#!/usr/bin/env python
# coding=utf8
from subprocess import call
def messageerreur(message):
  call(["zenity","--error","--text=%s"%message])
  exit(0)

try:
  import pygtk
  pygtk.require('2.0')
except:
  messageerreur("La bibliothèque PyGTK n’a pas pu être chargée, vérifiez son installation")

try:
  import gtk,gobject
except:
  messageerreur("Les bibliothèques GTK ou gobject n’ont pas pu être chargées, vérifiez leur installation")

from os.path import basename,dirname,join
from subprocess import PIPE,Popen
from os import unlink,getenv
from time import sleep
from tempfile import mkstemp

try:
  from odf.opendocument import OpenDocumentPresentation
  from odf.style import Style, MasterPage, PageLayout, PageLayoutProperties, TextProperties, GraphicProperties, ParagraphProperties, DrawingPageProperties
  from odf.text import P
  from odf.draw  import Page, Frame, TextBox
  import odf.draw
except:
  messageerreur("La bibliothèque Odfpy n’a pas pu être chargée, vérifiez son installation")

try:
  import Image
except:
  messageerreur("La bibliothèque PIL n’a pas pu être chargée, vérifiez son installation")

try:
  call(["convert","--version"])
except:
  messageerreur("L’utilitaire convert d’Image Magick n’est pas accessible, vérifiez son installation")

def pool_execute(commandes,nb_max_process,progress):
  pool=[False]*nb_max_process

  while len(commandes)>0:
    commande=commandes.pop(0)

    commande_lancee=False
    while commande_lancee==False:
      progress.stdin.write("-")
      sleep(0.05)

      for i in range(0,nb_max_process):
        if not pool[i] or pool[i].poll()!=None:
          pool[i]=Popen(commande,shell=(type(commande)==str))
          commande_lancee=True
          break

  commande_restante=True
  while commande_restante:
    progress.stdin.write("-")
    sleep(0.05)

    commande_restante=False
    for i in range(0,nb_max_process):
      if pool[i] and pool[i].poll()==None:
        commande_restante=True
        break

def getdimensions():
  commande=["zenity","--list","--width=340","--height=380",
    "--title=Résolution","--text=Sélectionnez la résolution","--hide-column=1",
    "--column=Valeur","--column=Dimensions","--column=Rapport","--column=Pour",
    "512x384","512×384","4/3","Internet",
    "640x480","640×480","4/3","Internet",
    "800x600","800×600","4/3","Vidéo-projecteur",
    "1024x768","1024×768","4/3","Vidéo-projecteur",
    "1024x576","1024×576","16/9","Vidéo-projecteur",
    "1280x960","1280×960","4/3","Vidéo-projecteur",
    "1280x720","1280×720","16/9","HD Ready",
    "1920x1080","1920×1080","16/9","Full HD"]

  return Popen(commande,stdout=PIPE).communicate()[0]

def generatethumbnails(images):
  thumbnails={}
  progress   =Popen(["zenity","--title","Préparation","--text","Génération des vignettes…","--progress","--pulsate","--auto-close"],stdin=PIPE)
  processes=[]

  for image in images:
    (fd,fname)=mkstemp(".jpg")
    processes.append(["convert",image,"-quality","70%","-thumbnail","96x72",fname])

    thumbnails[image]=fname

  pool_execute(processes,8,progress)
  progress.stdin.close()

  return thumbnails

def generatereduced(images,dimensions):
  reduceds={}
  progress   =Popen(["zenity","--title","Préparation","--text","Reduction des images…","--progress","--pulsate","--auto-close"],stdin=PIPE)
  processes=[]
  for image in images:
    # File must be an image
    (fd,fname)=mkstemp(".jpg")
    processes.append(["convert",image,"-quality","65%","-resize",dimensions,fname])

    # Add thumbnails to images list
    reduceds[image]=fname

  pool_execute(processes,8,progress)
  progress.stdin.close()

  return reduceds

def deletetemps(thumbnails):
  for image in thumbnails: unlink(thumbnails[image])

class ListeImages:
  def __init__(self,window):
    # create a liststore to use as the model
    self.liststore=gtk.ListStore(
      gobject.TYPE_STRING, # Full path name of the original image
      gtk.gdk.Pixbuf,      # Thumbnail
      gobject.TYPE_STRING, # Base name of the original image
      gobject.TYPE_BOOLEAN # Selected or not
    )

    # create the TreeView using liststore
    self.treeview=gtk.TreeView(self.liststore)

    # create the TreeViewColumns to display the data
    self.imgcolumn =gtk.TreeViewColumn('Image'  )
    self.namecolumn=gtk.TreeViewColumn('Fichier')
    self.selcolumn =gtk.TreeViewColumn('Garder' )

    # add columns to treeview
    self.treeview.append_column(self.imgcolumn )
    self.treeview.append_column(self.namecolumn)
    self.treeview.append_column(self.selcolumn )

    # create a CellRenderers to render the data
    self.imgcell =gtk.CellRendererPixbuf()
    self.namecell=gtk.CellRendererText()
    self.selcell =gtk.CellRendererToggle()
    self.selcell.set_property("activatable",True)
    self.selcell.connect('toggled',self.seltoggle,self.liststore)

    # add the cells to the columns
    self.imgcolumn.pack_start(self.imgcell, False)
    self.namecolumn.pack_start(self.namecell,True)
    self.selcolumn.pack_start(self.selcell,True)

    # set the cell attributes to the appropriate liststore column
    self.imgcolumn.set_attributes(self.imgcell,pixbuf=1)
    self.namecolumn.set_attributes(self.namecell,text=2)
    self.selcolumn.set_attributes(self.selcell,active=3)

    # Allow drag and drop reordering of rows
    self.treeview.set_reorderable(True)

    scw=gtk.ScrolledWindow()
    scw.add(self.treeview)
    window.add(scw)

  def seltoggle(self,cell,path,model):
    model[path][3]=not model[path][3]
    return

  def addImage(self,image,thumbnail):
    self.liststore.append([
      image,
      gtk.gdk.pixbuf_new_from_file(thumbnail),
      basename(image),
      True
    ])

  def getlist(self):
    images=[]
    iter=self.liststore.get_iter_first()
    while iter!=None:
      name=self.liststore.get_value(iter,0)
      if self.liststore.get_value(iter,3)==True: images.append(name)
      iter=self.liststore.iter_next(iter)

    return images

class AlbumGenerator:
  def __init__(self,thumbnails,reduced,dimensions):
    self.window = gtk.Window(gtk.WINDOW_TOPLEVEL)
    self.window.set_position(gtk.WIN_POS_CENTER_ALWAYS)
    self.window.set_title("Générateur de présentation")
    self.window.set_size_request(440,600)
    self.window.connect("delete_event", self.on_delete)
    self.vbox=gtk.VBox()
    self.window.add(self.vbox)
    self.listeimages=ListeImages(self.vbox)
    self.boutonok=gtk.Button("Générer l’album")
    self.vbox.pack_end(self.boutonok,False,True, 0)
    self.boutonok.connect("clicked", self.on_boutonok_clicked)

    self.reduced=reduced
    self.dimensions=dimensions

    images=thumbnails.keys()
    images.sort()
    for image in images:
      self.listeimages.addImage(image,thumbnails[image])

    self.window.show_all()

  def on_boutonok_clicked(self,widget,data=None):
    images=self.listeimages.getlist()
    repertoire=dirname(images[0])
    fichiersortie=join(repertoire,"presentation.odp")
    generatealbum(fichiersortie,images,self.reduced,self.dimensions)
    gtk.main_quit()
    return False

  def on_delete(self,widget,event,data=None):
    gtk.main_quit()
    return False

def generatealbum(outputfile,images,reduced,dimensions):
  doc=OpenDocumentPresentation()

  (width,height)=dimensions.split("x")
  (width,height)=(int(width),int(height))

  # We must describe the dimensions of the page
  pagelayout=PageLayout(name="MyLayout")
  doc.automaticstyles.addElement(pagelayout)
  pagelayout.addElement(PageLayoutProperties(
    margin="0pt",
    pagewidth="%dpt"%(width),
    pageheight="%dpt"%(height),
    printorientation="landscape",
  ))

  # Style for the photo frame
  photostyle=Style(name="MyMaster-photo", family="presentation")
  doc.styles.addElement(photostyle)

  # Create automatic transition
  dpstyle=Style(name="dp1", family="drawing-page")
  dpstyle.addElement(DrawingPageProperties(fillcolor="#000000"))
  doc.automaticstyles.addElement(dpstyle)

  # Every drawing page must have a master page assigned to it.
  masterpage=MasterPage(name="MyMaster", pagelayoutname=pagelayout)
  doc.masterstyles.addElement(masterpage)

  for image in images:
    (w,h)=Image.open(reduced[image]).size
    page=Page(stylename=dpstyle, masterpagename=masterpage)
    doc.presentation.addElement(page)

    offsetx=(float(width )-float(w))/2.0
    offsety=(float(height)-float(h))/2.0
    photoframe=Frame(stylename=photostyle, width="%fpt" % w, height="%fpt" % h, x="%fpt" % offsetx, y="%fpt" % offsety)
    page.addElement(photoframe)
    href=doc.addPicture(reduced[image])
    photoframe.addElement(odf.draw.Image(href=href))

  doc.save(outputfile)

def main():
  gtk.main()

if __name__ == "__main__":
  dimensions=getdimensions()
  if 'x' in dimensions:
    thumbnails=generatethumbnails(getenv("NAUTILUS_SCRIPT_SELECTED_FILE_PATHS","").splitlines())
    reduceds  =generatereduced(getenv("NAUTILUS_SCRIPT_SELECTED_FILE_PATHS","").splitlines(),dimensions)
    albumgenerator=AlbumGenerator(thumbnails,reduceds,dimensions)
    deletetemps(thumbnails)
    main()
    deletetemps(reduceds)


