def __init__(self, parent=None): QWidget.__init__(self, parent) self.ui = Ui_trimage() self.ui.setupUi(self) self.showapp = True self.verbose = True self.imagelist = [] QCoreApplication.setOrganizationName("Kilian Valkhof") QCoreApplication.setOrganizationDomain("trimage.org") QCoreApplication.setApplicationName("Trimage") self.settings = QSettings() self.restoreGeometry(self.settings.value("geometry").toByteArray()) # check if apps are installed if self.checkapps(): quit() #add quit shortcut if hasattr(QKeySequence, "Quit"): self.quit_shortcut = QShortcut(QKeySequence(QKeySequence.Quit), self) else: self.quit_shortcut = QShortcut(QKeySequence("Ctrl+Q"), self) # disable recompress self.ui.recompress.setEnabled(False) #self.ui.recompress.hide() # make a worker thread self.thread = Worker() # connect signals with slots QObject.connect(self.ui.addfiles, SIGNAL("clicked()"), self.file_dialog) QObject.connect(self.ui.recompress, SIGNAL("clicked()"), self.recompress_files) QObject.connect(self.quit_shortcut, SIGNAL("activated()"), qApp, SLOT('quit()')) QObject.connect(self.ui.processedfiles, SIGNAL("fileDropEvent"), self.file_drop) QObject.connect(self.thread, SIGNAL("finished()"), self.update_table) QObject.connect(self.thread, SIGNAL("terminated()"), self.update_table) QObject.connect(self.thread, SIGNAL("updateUi"), self.update_table) self.compressing_icon = QIcon(QPixmap(self.ui.get_image("pixmaps/compressing.gif"))) # activate command line options self.commandline_options() if QSystemTrayIcon.isSystemTrayAvailable() and not self.cli: self.systemtray = Systray(self)
def __init__(self, parent=None): QWidget.__init__(self, parent) self.ui = Ui_trimage() self.ui.setupUi(self) self.showapp = True self.verbose = True self.imagelist = [] QCoreApplication.setOrganizationName("Kilian Valkhof") QCoreApplication.setOrganizationDomain("trimage.org") QCoreApplication.setApplicationName("Trimage") self.settings = QSettings() if self.settings.value("geometry"): self.restoreGeometry(self.settings.value("geometry")) # check if dependencies are installed if not check_dependencies(): quit() # add quit shortcut if hasattr(QKeySequence, "Quit"): self.quit_shortcut = QShortcut(QKeySequence(QKeySequence.Quit), self) else: self.quit_shortcut = QShortcut(QKeySequence("Ctrl+Q"), self) # disable recompress self.ui.recompress.setEnabled(False) # make a worker thread self.thread = Worker() # connect signals with slots self.ui.addfiles.clicked.connect(self.file_dialog) self.ui.recompress.clicked.connect(self.recompress_files) self.quit_shortcut.activated.connect(self.close) self.ui.processedfiles.drop_event_signal.connect(self.file_drop) self.thread.finished.connect(self.update_table) self.thread.update_ui_signal.connect(self.update_table) self.compressing_icon = QIcon( QPixmap(self.ui.get_image("pixmaps/compressing.gif"))) # activate command line options self.commandline_options() if QSystemTrayIcon.isSystemTrayAvailable() and not self.cli: self.systemtray = Systray(self)
def __init__(self, parent=None): QWidget.__init__(self, parent) self.ui = Ui_trimage() self.ui.setupUi(self) self.showapp = True self.verbose = True self.imagelist = [] QCoreApplication.setOrganizationName("Kilian Valkhof") QCoreApplication.setOrganizationDomain("trimage.org") QCoreApplication.setApplicationName("Trimage") self.settings = QSettings() if self.settings.value("geometry"): self.restoreGeometry(self.settings.value("geometry")) # check if dependencies are installed if not check_dependencies(): quit() # add quit shortcut if hasattr(QKeySequence, "Quit"): self.quit_shortcut = QShortcut(QKeySequence(QKeySequence.Quit), self) else: self.quit_shortcut = QShortcut(QKeySequence("Ctrl+Q"), self) # disable recompress self.ui.recompress.setEnabled(False) # make a worker thread self.thread = Worker() # connect signals with slots self.ui.addfiles.clicked.connect(self.file_dialog) self.ui.recompress.clicked.connect(self.recompress_files) self.quit_shortcut.activated.connect(self.close) self.ui.processedfiles.drop_event_signal.connect(self.file_drop) self.thread.finished.connect(self.update_table) self.thread.update_ui_signal.connect(self.update_table) self.compressing_icon = QIcon(QPixmap(self.ui.get_image("pixmaps/compressing.gif"))) # activate command line options self.commandline_options() if QSystemTrayIcon.isSystemTrayAvailable() and not self.cli: self.systemtray = Systray(self)
class StartQT4(QMainWindow): def __init__(self, parent=None): QWidget.__init__(self, parent) self.ui = Ui_trimage() self.ui.setupUi(self) if QSystemTrayIcon.isSystemTrayAvailable(): self.systemtray = Systray(self) self.showapp = True self.verbose = True self.imagelist = [] QCoreApplication.setOrganizationName("Kilian Valkhof") QCoreApplication.setOrganizationDomain("trimage.org") QCoreApplication.setApplicationName("Trimage") self.settings = QSettings() self.restoreGeometry(self.settings.value("geometry").toByteArray()) # check if apps are installed if self.checkapps(): quit() #add quit shortcut if hasattr(QKeySequence, "Quit"): self.quit_shortcut = QShortcut(QKeySequence(QKeySequence.Quit), self) else: self.quit_shortcut = QShortcut(QKeySequence("Ctrl+Q"), self) # disable recompress self.ui.recompress.setEnabled(False) #self.ui.recompress.hide() # make a worker thread self.thread = Worker() # connect signals with slots QObject.connect(self.ui.addfiles, SIGNAL("clicked()"), self.file_dialog) QObject.connect(self.ui.recompress, SIGNAL("clicked()"), self.recompress_files) QObject.connect(self.quit_shortcut, SIGNAL("activated()"), qApp, SLOT('quit()')) QObject.connect(self.ui.processedfiles, SIGNAL("fileDropEvent"), self.file_drop) QObject.connect(self.thread, SIGNAL("finished()"), self.update_table) QObject.connect(self.thread, SIGNAL("terminated()"), self.update_table) QObject.connect(self.thread, SIGNAL("updateUi"), self.update_table) # activate command line options self.commandline_options() def commandline_options(self): """Set up the command line options.""" parser = OptionParser(version="%prog " + VERSION, description="GUI front-end to compress png and jpg images via " "optipng, advpng and jpegoptim") parser.set_defaults(verbose=True) parser.add_option("-v", "--verbose", action="store_true", dest="verbose", help="Verbose mode (default)") parser.add_option("-q", "--quiet", action="store_false", dest="verbose", help="Quiet mode") parser.add_option("-f", "--file", action="store", type="string", dest="filename", help="compresses image and exit") parser.add_option("-d", "--directory", action="store", type="string", dest="directory", help="compresses images in directory and exit") options, args = parser.parse_args() # make sure we quit after processing finished if using cli if options.filename or options.directory: QObject.connect(self.thread, SIGNAL("finished()"), quit) # send to correct function if options.filename: self.file_from_cmd(options.filename.decode("utf-8")) if options.directory: self.dir_from_cmd(options.directory.decode("utf-8")) self.verbose = options.verbose """ Input functions """ def dir_from_cmd(self, directory): """ Read the files in the directory and send all files to compress_file. """ self.showapp = False dirpath = path.abspath(directory) imagedir = listdir(directory) filelist = [path.join(dirpath, image) for image in imagedir] self.delegator(filelist) def file_from_cmd(self, image): """Get the file and send it to compress_file""" self.showapp = False filelist = [path.abspath(image)] self.delegator(filelist) def file_drop(self, images): """ Get a file from the drag and drop handler and send it to compress_file. """ self.delegator(images) def file_dialog(self): """Open a file dialog and send the selected images to compress_file.""" fd = QFileDialog(self) fd.restoreState(self.settings.value("fdstate").toByteArray()) directory = self.settings.value("directory", QVariant("")).toString() fd.setDirectory(directory) images = fd.getOpenFileNames(self, "Select one or more image files to compress", directory, # this is a fix for file dialog differentiating between cases "Image files (*.png *.jpg *.jpeg *.PNG *.JPG *.JPEG)") self.settings.setValue("fdstate", QVariant(fd.saveState())) if images: self.settings.setValue("directory", QVariant(path.dirname(unicode(images[0])))) self.delegator([unicode(fullpath) for fullpath in images]) def recompress_files(self): """Send each file in the current file list to compress_file again.""" self.delegator([row.image.fullpath for row in self.imagelist]) """ Compress functions """ def delegator(self, images): """ Recieve all images, check them and send them to the worker thread. """ delegatorlist = [] for fullpath in images: try: # recompress images already in the list image = (i.image for i in self.imagelist if i.image.fullpath == fullpath).next() if image.compressed: image.reset() image.recompression = True delegatorlist.append(image) except StopIteration: image = Image(fullpath) if image.valid: delegatorlist.append(image) icon = QIcon(QPixmap(self.ui.get_image("pixmaps/compressing.gif"))) self.imagelist.append(ImageRow(image, icon)) else: print >> sys.stderr, u"[error] %s not a supported image file" % image.fullpath self.update_table() self.systemtray.trayIcon.setToolTip("Trimage image compressor (" + str(len(self.imagelist)) + " files)") self.setWindowTitle("Trimage image compressor (" + str(len(self.imagelist)) + " files)") self.thread.compress_file(delegatorlist, self.showapp, self.verbose, self.imagelist) """ UI Functions """ def update_table(self): """Update the table view with the latest file data.""" tview = self.ui.processedfiles # set table model tmodel = TriTableModel(self, self.imagelist, ["Filename", "Old Size", "New Size", "Compressed"]) tview.setModel(tmodel) # set minimum size of table vh = tview.verticalHeader() vh.setVisible(False) # set horizontal header properties hh = tview.horizontalHeader() hh.setStretchLastSection(True) # set all row heights nrows = len(self.imagelist) for row in range(nrows): tview.setRowHeight(row, 25) # set the second column to be longest tview.setColumnWidth(0, 300) # enable recompress button self.enable_recompress() """ Helper functions """ def enable_recompress(self): """Enable the recompress button.""" self.ui.recompress.setEnabled(True) self.systemtray.recompress.setEnabled(True) def checkapps(self): """Check if the required command line apps exist.""" exe = ".exe" if (sys.platform == "win32") else "" status = False retcode = self.safe_call("jpegoptim" + exe + " --version") if retcode != 0: status = True sys.stderr.write("[error] please install jpegoptim") retcode = self.safe_call("optipng" + exe + " -v") if retcode != 0: status = True sys.stderr.write("[error] please install optipng") retcode = self.safe_call("advpng" + exe + " --version") if retcode != 0: status = True sys.stderr.write("[error] please install advancecomp") return status def safe_call(self, command): """ cross-platform command-line check """ while True: try: return call(command, shell=True, stdout=PIPE) except OSError, e: if e.errno == errno.EINTR: continue else: raise
class StartQt(QMainWindow): def __init__(self, parent=None): QWidget.__init__(self, parent) self.ui = Ui_trimage() self.ui.setupUi(self) self.showapp = True self.verbose = True self.imagelist = [] QCoreApplication.setOrganizationName("Kilian Valkhof") QCoreApplication.setOrganizationDomain("trimage.org") QCoreApplication.setApplicationName("Trimage") self.settings = QSettings() if self.settings.value("geometry"): self.restoreGeometry(self.settings.value("geometry")) # check if dependencies are installed if not check_dependencies(): quit() # add quit shortcut if hasattr(QKeySequence, "Quit"): self.quit_shortcut = QShortcut(QKeySequence(QKeySequence.Quit), self) else: self.quit_shortcut = QShortcut(QKeySequence("Ctrl+Q"), self) # disable recompress self.ui.recompress.setEnabled(False) # make a worker thread self.thread = Worker() # connect signals with slots self.ui.addfiles.clicked.connect(self.file_dialog) self.ui.recompress.clicked.connect(self.recompress_files) self.quit_shortcut.activated.connect(self.close) self.ui.processedfiles.drop_event_signal.connect(self.file_drop) self.thread.finished.connect(self.update_table) self.thread.update_ui_signal.connect(self.update_table) self.compressing_icon = QIcon( QPixmap(self.ui.get_image("pixmaps/compressing.gif"))) # activate command line options self.commandline_options() if QSystemTrayIcon.isSystemTrayAvailable() and not self.cli: self.systemtray = Systray(self) def commandline_options(self): """Set up the command line options.""" self.cli = False parser = OptionParser( version="%prog " + VERSION, description="GUI front-end to compress png and jpg images via " "advpng, jpegoptim, optipng and pngcrush") parser.set_defaults(verbose=True) parser.add_option("-v", "--verbose", action="store_true", dest="verbose", help="Verbose mode (default)") parser.add_option("-q", "--quiet", action="store_false", dest="verbose", help="Quiet mode") parser.add_option("-f", "--file", action="store", type="string", dest="filename", help="compresses image and exit") parser.add_option("-d", "--directory", action="store", type="string", dest="directory", help="compresses images in directory and exit") options, args = parser.parse_args() # make sure we quit after processing finished if using cli if options.filename or options.directory: self.thread.finished.connect(quit) self.cli = True # send to correct function if options.filename: self.file_from_cmd(options.filename) if options.directory: self.dir_from_cmd(options.directory) self.verbose = options.verbose """ Input functions """ def dir_from_cmd(self, directory): """ Read the files in the directory and send all files to compress_file. """ self.showapp = False dirpath = path.abspath(directory) imagedir = listdir(directory) filelist = [path.join(dirpath, image) for image in imagedir] self.delegator(filelist) def file_from_cmd(self, image): """Get the file and send it to compress_file""" self.showapp = False filelist = [path.abspath(image)] self.delegator(filelist) def file_drop(self, images): """ Get a file from the drag and drop handler and send it to compress_file. """ self.delegator(images) def file_dialog(self): """Open a file dialog and send the selected images to compress_file.""" fd = QFileDialog(self) if (self.settings.value("fdstate")): fd.restoreState(self.settings.value("fdstate")) directory = self.settings.value("directory", QVariant("")) fd.setDirectory(directory) images, _ = fd.getOpenFileNames( self, "Select one or more image files to compress", directory, # this is a fix for file dialog differentiating between cases "Image files (*.png *.jpg *.jpeg *.PNG *.JPG *.JPEG)") self.settings.setValue("fdstate", QVariant(fd.saveState())) if images: self.settings.setValue("directory", QVariant(path.dirname(images[0]))) self.delegator([fullpath for fullpath in images]) def recompress_files(self): """Send each file in the current file list to compress_file again.""" self.delegator([row.image.fullpath for row in self.imagelist]) """ Compress functions """ def delegator(self, images): """ Receive all images, check them and send them to the worker thread. """ delegatorlist = [] for fullpath in images: try: # recompress images already in the list image = next(i.image for i in self.imagelist if i.image.fullpath == fullpath) if image.compressed: image.reset() image.recompression = True delegatorlist.append(image) except StopIteration: if not path.isdir(fullpath): self.add_image(fullpath, delegatorlist) else: self.walk(fullpath, delegatorlist) self.update_table() self.thread.compress_file(delegatorlist, self.showapp, self.verbose, self.imagelist) def walk(self, dir, delegatorlist): """ Walks a directory, and executes a callback on each file. """ dir = path.abspath(dir) for file in [ file for file in listdir(dir) if not file in [".", "..", ".svn", ".git", ".hg", ".bzr", ".cvs"] ]: nfile = path.join(dir, file) if path.isdir(nfile): self.walk(nfile, delegatorlist) else: self.add_image(nfile, delegatorlist) def add_image(self, fullpath, delegatorlist): """ Adds an image file to the delegator list and update the tray and the title of the window. """ image = Image(fullpath) if image.valid: delegatorlist.append(image) self.imagelist.append(ImageRow(image, self.compressing_icon)) if QSystemTrayIcon.isSystemTrayAvailable() and not self.cli: self.systemtray.trayIcon.setToolTip( "Trimage image compressor (" + str(len(self.imagelist)) + " files)") self.setWindowTitle("Trimage image compressor (" + str(len(self.imagelist)) + " files)") else: print("[error] {} not a supported image file and/or not writable". format(image.fullpath), file=sys.stderr) """ UI Functions """ def update_table(self): """Update the table view with the latest file data.""" tview = self.ui.processedfiles # set table model tmodel = TriTableModel( self, self.imagelist, ["Filename", "Old Size", "New Size", "Compressed"]) tview.setModel(tmodel) # set minimum size of table vh = tview.verticalHeader() vh.setVisible(False) # set horizontal header properties hh = tview.horizontalHeader() hh.setStretchLastSection(True) # set all row heights nrows = len(self.imagelist) for row in range(nrows): tview.setRowHeight(row, 25) # set the second column to be longest tview.setColumnWidth(0, 300) # enable recompress button self.enable_recompress() def enable_recompress(self): """Enable the recompress button.""" self.ui.recompress.setEnabled(True) if QSystemTrayIcon.isSystemTrayAvailable() and not self.cli: self.systemtray.recompress.setEnabled(True) def hide_main_window(self): if self.isVisible(): self.hide() if QSystemTrayIcon.isSystemTrayAvailable(): self.systemtray.hideMain.setText("&Show window") else: self.show() if QSystemTrayIcon.isSystemTrayAvailable(): self.systemtray.hideMain.setText("&Hide window") def closeEvent(self, event): self.settings.setValue("geometry", QVariant(self.saveGeometry())) event.accept()
class StartQT4(QMainWindow): def __init__(self, parent=None): QWidget.__init__(self, parent) self.ui = Ui_trimage() self.ui.setupUi(self) self.showapp = True self.verbose = True self.imagelist = [] QCoreApplication.setOrganizationName("Kilian Valkhof") QCoreApplication.setOrganizationDomain("trimage.org") QCoreApplication.setApplicationName("Trimage") self.settings = QSettings() self.restoreGeometry(self.settings.value("geometry").toByteArray()) # check if apps are installed if self.checkapps(): quit() #add quit shortcut if hasattr(QKeySequence, "Quit"): self.quit_shortcut = QShortcut(QKeySequence(QKeySequence.Quit), self) else: self.quit_shortcut = QShortcut(QKeySequence("Ctrl+Q"), self) # disable recompress self.ui.recompress.setEnabled(False) #self.ui.recompress.hide() # make a worker thread self.thread = Worker() # connect signals with slots QObject.connect(self.ui.addfiles, SIGNAL("clicked()"), self.file_dialog) QObject.connect(self.ui.recompress, SIGNAL("clicked()"), self.recompress_files) QObject.connect(self.quit_shortcut, SIGNAL("activated()"), qApp, SLOT('quit()')) QObject.connect(self.ui.processedfiles, SIGNAL("fileDropEvent"), self.file_drop) QObject.connect(self.thread, SIGNAL("finished()"), self.update_table) QObject.connect(self.thread, SIGNAL("terminated()"), self.update_table) QObject.connect(self.thread, SIGNAL("updateUi"), self.update_table) self.compressing_icon = QIcon(QPixmap(self.ui.get_image("pixmaps/compressing.gif"))) # activate command line options self.commandline_options() if QSystemTrayIcon.isSystemTrayAvailable() and not self.cli: self.systemtray = Systray(self) def commandline_options(self): self.cli = False """Set up the command line options.""" parser = OptionParser(version="%prog " + VERSION, description="GUI front-end to compress png and jpg images via " "optipng, advpng and jpegoptim") parser.set_defaults(verbose=True) parser.add_option("-v", "--verbose", action="store_true", dest="verbose", help="Verbose mode (default)") parser.add_option("-q", "--quiet", action="store_false", dest="verbose", help="Quiet mode") parser.add_option("-f", "--file", action="store", type="string", dest="filename", help="compresses image and exit") parser.add_option("-d", "--directory", action="store", type="string", dest="directory", help="compresses images in directory and exit") options, args = parser.parse_args() # make sure we quit after processing finished if using cli if options.filename or options.directory: QObject.connect(self.thread, SIGNAL("finished()"), quit) self.cli = True # send to correct function if options.filename: self.file_from_cmd(options.filename.decode("utf-8")) if options.directory: self.dir_from_cmd(options.directory.decode("utf-8")) self.verbose = options.verbose """ Input functions """ def dir_from_cmd(self, directory): """ Read the files in the directory and send all files to compress_file. """ self.showapp = False dirpath = path.abspath(directory) imagedir = listdir(directory) filelist = [path.join(dirpath, image) for image in imagedir] self.delegator(filelist) def file_from_cmd(self, image): """Get the file and send it to compress_file""" self.showapp = False filelist = [path.abspath(image)] self.delegator(filelist) def file_drop(self, images): """ Get a file from the drag and drop handler and send it to compress_file. """ self.delegator(images) def file_dialog(self): """Open a file dialog and send the selected images to compress_file.""" fd = QFileDialog(self) fd.restoreState(self.settings.value("fdstate").toByteArray()) directory = self.settings.value("directory", QVariant("")).toString() fd.setDirectory(directory) images = fd.getOpenFileNames(self, "Select one or more image files to compress", directory, # this is a fix for file dialog differentiating between cases "Image files (*.png *.jpg *.jpeg *.PNG *.JPG *.JPEG)") self.settings.setValue("fdstate", QVariant(fd.saveState())) if images: self.settings.setValue("directory", QVariant(path.dirname(unicode(images[0])))) self.delegator([unicode(fullpath) for fullpath in images]) def recompress_files(self): """Send each file in the current file list to compress_file again.""" self.delegator([row.image.fullpath for row in self.imagelist]) """ Compress functions """ def delegator(self, images): """ Receive all images, check them and send them to the worker thread. """ delegatorlist = [] for fullpath in images: try: # recompress images already in the list image = (i.image for i in self.imagelist if i.image.fullpath == fullpath).next() if image.compressed: image.reset() image.recompression = True delegatorlist.append(image) except StopIteration: if not path.isdir(fullpath): self. add_image(fullpath, delegatorlist) else: self.walk(fullpath, delegatorlist) self.update_table() self.thread.compress_file(delegatorlist, self.showapp, self.verbose, self.imagelist) def walk(self, dir, delegatorlist): """ Walks a directory, and executes a callback on each file """ dir = path.abspath(dir) for file in [file for file in listdir(dir) if not file in [".","..",".svn",".git",".hg",".bzr",".cvs"]]: nfile = path.join(dir, file) if path.isdir(nfile): self.walk(nfile, delegatorlist) else: self.add_image(nfile, delegatorlist) def add_image(self, fullpath, delegatorlist): """ Adds an image file to the delegator list and update the tray and the title of the window """ image = Image(fullpath) if image.valid: delegatorlist.append(image) self.imagelist.append(ImageRow(image, self.compressing_icon)) if QSystemTrayIcon.isSystemTrayAvailable() and not self.cli: self.systemtray.trayIcon.setToolTip("Trimage image compressor (" + str(len(self.imagelist)) + " files)") self.setWindowTitle("Trimage image compressor (" + str(len(self.imagelist)) + " files)") else: print >> sys.stderr, u"[error] %s not a supported image file and/or not writeable" % image.fullpath """ UI Functions """ def update_table(self): """Update the table view with the latest file data.""" tview = self.ui.processedfiles # set table model tmodel = TriTableModel(self, self.imagelist, ["Filename", "Old Size", "New Size", "Compressed"]) tview.setModel(tmodel) # set minimum size of table vh = tview.verticalHeader() vh.setVisible(False) # set horizontal header properties hh = tview.horizontalHeader() hh.setStretchLastSection(True) # set all row heights nrows = len(self.imagelist) for row in range(nrows): tview.setRowHeight(row, 25) # set the second column to be longest tview.setColumnWidth(0, 300) # enable recompress button self.enable_recompress() """ Helper functions """ def enable_recompress(self): """Enable the recompress button.""" self.ui.recompress.setEnabled(True) if QSystemTrayIcon.isSystemTrayAvailable() and not self.cli: self.systemtray.recompress.setEnabled(True) def checkapps(self): """Check if the required command line apps exist.""" exe = ".exe" if (sys.platform == "win32") else "" status = False retcode = self.safe_call("jpegoptim" + exe + " --version") if retcode != 0: status = True sys.stderr.write("[error] please install jpegoptim") retcode = self.safe_call("optipng" + exe + " -v") if retcode != 0: status = True sys.stderr.write("[error] please install optipng") retcode = self.safe_call("advpng" + exe + " --version") if retcode != 0: status = True sys.stderr.write("[error] please install advancecomp") retcode = self.safe_call("pngcrush" + exe + " -version") if retcode != 0: status = True sys.stderr.write("[error] please install pngcrush") return status def safe_call(self, command): """ cross-platform command-line check """ while True: try: return call(command, shell=True, stdout=PIPE) except OSError, e: if e.errno == errno.EINTR: continue else: raise
class StartQt(QMainWindow): def __init__(self, parent=None): QWidget.__init__(self, parent) self.ui = Ui_trimage() self.ui.setupUi(self) self.showapp = True self.verbose = True self.imagelist = [] QCoreApplication.setOrganizationName("Kilian Valkhof") QCoreApplication.setOrganizationDomain("trimage.org") QCoreApplication.setApplicationName("Trimage") self.settings = QSettings() if self.settings.value("geometry"): self.restoreGeometry(self.settings.value("geometry")) # check if dependencies are installed if not check_dependencies(): quit() # add quit shortcut if hasattr(QKeySequence, "Quit"): self.quit_shortcut = QShortcut(QKeySequence(QKeySequence.Quit), self) else: self.quit_shortcut = QShortcut(QKeySequence("Ctrl+Q"), self) # disable recompress self.ui.recompress.setEnabled(False) # make a worker thread self.thread = Worker() # connect signals with slots self.ui.addfiles.clicked.connect(self.file_dialog) self.ui.recompress.clicked.connect(self.recompress_files) self.quit_shortcut.activated.connect(self.close) self.ui.processedfiles.drop_event_signal.connect(self.file_drop) self.thread.finished.connect(self.update_table) self.thread.update_ui_signal.connect(self.update_table) self.compressing_icon = QIcon(QPixmap(self.ui.get_image("pixmaps/compressing.gif"))) # activate command line options self.commandline_options() if QSystemTrayIcon.isSystemTrayAvailable() and not self.cli: self.systemtray = Systray(self) def commandline_options(self): """Set up the command line options.""" self.cli = False parser = OptionParser(version="%prog " + VERSION, description="GUI front-end to compress png and jpg images via " "advpng, jpegoptim, optipng and pngcrush") parser.set_defaults(verbose=True) parser.add_option("-v", "--verbose", action="store_true", dest="verbose", help="Verbose mode (default)") parser.add_option("-q", "--quiet", action="store_false", dest="verbose", help="Quiet mode") parser.add_option("-f", "--file", action="store", type="string", dest="filename", help="compresses image and exit") parser.add_option("-d", "--directory", action="store", type="string", dest="directory", help="compresses images in directory and exit") options, args = parser.parse_args() # make sure we quit after processing finished if using cli if options.filename or options.directory: self.thread.finished.connect(quit) self.cli = True # send to correct function if options.filename: self.file_from_cmd(options.filename) if options.directory: self.dir_from_cmd(options.directory) self.verbose = options.verbose """ Input functions """ def dir_from_cmd(self, directory): """ Read the files in the directory and send all files to compress_file. """ self.showapp = False dirpath = path.abspath(directory) imagedir = listdir(directory) filelist = [path.join(dirpath, image) for image in imagedir] self.delegator(filelist) def file_from_cmd(self, image): """Get the file and send it to compress_file""" self.showapp = False filelist = [path.abspath(image)] self.delegator(filelist) def file_drop(self, images): """ Get a file from the drag and drop handler and send it to compress_file. """ self.delegator(images) def file_dialog(self): """Open a file dialog and send the selected images to compress_file.""" fd = QFileDialog(self) if (self.settings.value("fdstate")): fd.restoreState(self.settings.value("fdstate")) directory = self.settings.value("directory", QVariant("")) fd.setDirectory(directory) images, _ = fd.getOpenFileNames(self, "Select one or more image files to compress", directory, # this is a fix for file dialog differentiating between cases "Image files (*.png *.jpg *.jpeg *.PNG *.JPG *.JPEG)") self.settings.setValue("fdstate", QVariant(fd.saveState())) if images: self.settings.setValue("directory", QVariant(path.dirname(images[0]))) self.delegator([fullpath for fullpath in images]) def recompress_files(self): """Send each file in the current file list to compress_file again.""" self.delegator([row.image.fullpath for row in self.imagelist]) """ Compress functions """ def delegator(self, images): """ Receive all images, check them and send them to the worker thread. """ delegatorlist = [] for fullpath in images: try: # recompress images already in the list image = next(i.image for i in self.imagelist if i.image.fullpath == fullpath) if image.compressed: image.reset() image.recompression = True delegatorlist.append(image) except StopIteration: if not path.isdir(fullpath): self.add_image(fullpath, delegatorlist) else: self.walk(fullpath, delegatorlist) self.update_table() self.thread.compress_file(delegatorlist, self.showapp, self.verbose, self.imagelist) def walk(self, dir, delegatorlist): """ Walks a directory, and executes a callback on each file. """ dir = path.abspath(dir) for file in [file for file in listdir(dir) if not file in [".","..",".svn",".git",".hg",".bzr",".cvs"]]: nfile = path.join(dir, file) if path.isdir(nfile): self.walk(nfile, delegatorlist) else: self.add_image(nfile, delegatorlist) def add_image(self, fullpath, delegatorlist): """ Adds an image file to the delegator list and update the tray and the title of the window. """ image = Image(fullpath) if image.valid: delegatorlist.append(image) self.imagelist.append(ImageRow(image, self.compressing_icon)) if QSystemTrayIcon.isSystemTrayAvailable() and not self.cli: self.systemtray.trayIcon.setToolTip("Trimage image compressor (" + str(len(self.imagelist)) + " files)") self.setWindowTitle("Trimage image compressor (" + str(len(self.imagelist)) + " files)") else: print("[error] {} not a supported image file and/or not writable".format(image.fullpath), file=sys.stderr) """ UI Functions """ def update_table(self): """Update the table view with the latest file data.""" tview = self.ui.processedfiles # set table model tmodel = TriTableModel(self, self.imagelist, ["Filename", "Old Size", "New Size", "Compressed"]) tview.setModel(tmodel) # set minimum size of table vh = tview.verticalHeader() vh.setVisible(False) # set horizontal header properties hh = tview.horizontalHeader() hh.setStretchLastSection(True) # set all row heights nrows = len(self.imagelist) for row in range(nrows): tview.setRowHeight(row, 25) # set the second column to be longest tview.setColumnWidth(0, 300) # enable recompress button self.enable_recompress() def enable_recompress(self): """Enable the recompress button.""" self.ui.recompress.setEnabled(True) if QSystemTrayIcon.isSystemTrayAvailable() and not self.cli: self.systemtray.recompress.setEnabled(True) def hide_main_window(self): if self.isVisible(): self.hide() if QSystemTrayIcon.isSystemTrayAvailable(): self.systemtray.hideMain.setText("&Show window") else: self.show() if QSystemTrayIcon.isSystemTrayAvailable(): self.systemtray.hideMain.setText("&Hide window") def closeEvent(self, event): self.settings.setValue("geometry", QVariant(self.saveGeometry())) event.accept()