def __init__(self, verbose): QtGui.QMainWindow.__init__(self) self.setWindowTitle("Photini photo metadata editor") self.selection = list() # logger window self.loggerwindow = LoggerWindow(verbose) self.logger = logging.getLogger(self.__class__.__name__) # config store self.config_store = ConfigStore() # set network proxy proxies = urllib2.getproxies() if 'http' in proxies: scheme, host, port = proxies['http'].split(':') QNetworkProxy.setApplicationProxy( QNetworkProxy(QNetworkProxy.HttpProxy, host[2:], int(port))) # restore size size = self.width(), self.height() self.resize(*eval( self.config_store.get('main_window', 'size', str(size)))) # image selector self.image_list = ImageList(self.config_store) self.image_list.selection_changed.connect(self.new_selection) self.image_list.new_metadata.connect(self.new_metadata) # prepare list of tabs and associated stuff self.tab_list = ( {'name' : '&Descriptive metadata', 'class' : Descriptive}, {'name' : '&Technical metadata', 'class' : Technical}, {'name' : 'Map (&Google)', 'class' : GoogleMap}, {'name' : 'Map (&Bing)', 'class' : BingMap}, {'name' : 'Map (&OSM)', 'class' : OpenStreetMap}, {'name' : '&Flickr uploader', 'class' : FlickrUploader}, {'name' : '&Picasa uploader', 'class' : PicasaUploader}, ) for tab in self.tab_list: tab['key'] = tab['name'].replace('&', '').replace(' ', '_') tab['key'] = tab['key'].replace('(', '').replace(')', '').lower() if tab['class']: tab['object'] = tab['class'](self.config_store, self.image_list) else: tab['object'] = None # file menu file_menu = self.menuBar().addMenu('File') open_action = QtGui.QAction('Open images', self) open_action.setShortcuts(['Ctrl+O']) open_action.triggered.connect(self.image_list.open_files) file_menu.addAction(open_action) self.save_action = QtGui.QAction('Save images with new data', self) self.save_action.setShortcuts(['Ctrl+S']) self.save_action.setEnabled(False) self.save_action.triggered.connect(self.image_list.save_files) file_menu.addAction(self.save_action) self.close_action = QtGui.QAction('Close selected images', self) self.close_action.setEnabled(False) self.close_action.triggered.connect(self.close_files) file_menu.addAction(self.close_action) close_all_action = QtGui.QAction('Close all images', self) close_all_action.triggered.connect(self.close_all_files) file_menu.addAction(close_all_action) file_menu.addSeparator() quit_action = QtGui.QAction('Quit', self) quit_action.setShortcuts(['Ctrl+Q', 'Ctrl+W']) quit_action.triggered.connect(QtGui.qApp.closeAllWindows) file_menu.addAction(quit_action) # options menu options_menu = self.menuBar().addMenu('Options') settings_action = QtGui.QAction('Settings', self) settings_action.triggered.connect(self.edit_settings) options_menu.addAction(settings_action) options_menu.addSeparator() for tab in self.tab_list: tab['action'] = QtGui.QAction(tab['name'].replace('&', ''), self) tab['action'].setCheckable(True) if tab['class']: tab['action'].setChecked( eval(self.config_store.get('tabs', tab['key'], 'True'))) else: tab['action'].setEnabled(False) tab['action'].triggered.connect(self.add_tabs) options_menu.addAction(tab['action']) # help menu help_menu = self.menuBar().addMenu('Help') about_action = QtGui.QAction('About Photini', self) about_action.triggered.connect(self.about) help_menu.addAction(about_action) help_menu.addSeparator() help_action = QtGui.QAction('Photini documentation', self) help_action.triggered.connect(self.open_docs) help_menu.addAction(help_action) # main application area self.central_widget = QtGui.QSplitter() self.central_widget.setOrientation(Qt.Vertical) self.central_widget.setChildrenCollapsible(False) self.tabs = QtGui.QTabWidget() self.add_tabs() self.tabs.currentChanged.connect(self.new_tab) self.central_widget.addWidget(self.tabs) self.central_widget.addWidget(self.image_list) size = self.central_widget.sizes() self.central_widget.setSizes(eval( self.config_store.get('main_window', 'split', str(size)))) self.central_widget.splitterMoved.connect(self.new_split) self.setCentralWidget(self.central_widget)
def __init__(self, options, initial_files): super(MainWindow, self).__init__() self.setWindowTitle(self.tr("Photini photo metadata editor")) pixmap = QtGui.QPixmap() pixmap.loadFromData( pkg_resources.resource_string('photini', 'data/icons/48/photini.png')) icon = QtGui.QIcon(pixmap) self.setWindowIcon(icon) self.selection = list() # logger window self.loggerwindow = LoggerWindow(options.verbose) self.loggerwindow.setWindowIcon(icon) self.logger = logging.getLogger(self.__class__.__name__) # set network proxy proxies = getproxies() if 'http' in proxies: parsed = urlparse(proxies['http']) QNetworkProxy.setApplicationProxy( QNetworkProxy(QNetworkProxy.HttpProxy, parsed.hostname, parsed.port)) # create shared global objects self.app = QtWidgets.QApplication.instance() self.app.config_store = ConfigStore('editor', parent=self) self.app.spell_check = SpellCheck(parent=self) self.app.test_mode = options.test # set debug mode if self.app.test_mode: debug_metadata() # restore size size = self.width(), self.height() self.resize( *eval(self.app.config_store.get('main_window', 'size', str(size)))) # image selector self.image_list = ImageList() self.image_list.selection_changed.connect(self.new_selection) self.image_list.new_metadata.connect(self.new_metadata) # prepare list of tabs and associated stuff self.tab_list = ( { 'name': self.tr('&Descriptive metadata'), 'key': 'descriptive_metadata', 'class': Descriptive }, { 'name': self.tr('&Technical metadata'), 'key': 'technical_metadata', 'class': Technical }, { 'name': self.tr('Map (&Google)'), 'key': 'map_google', 'class': GoogleMap }, { 'name': self.tr('Map (&Bing)'), 'key': 'map_bing', 'class': BingMap }, { 'name': self.tr('Map (&OSM)'), 'key': 'map_osm', 'class': OpenStreetMap }, { 'name': self.tr('&Flickr upload'), 'key': 'flickr_upload', 'class': FlickrUploader }, { 'name': self.tr('Google &Photos upload'), 'key': 'picasa_upload', 'class': PicasaUploader }, { 'name': self.tr('Faceboo&k upload'), 'key': 'facebook_upload', 'class': FacebookUploader }, { 'name': self.tr('&Import photos'), 'key': 'import_photos', 'class': Importer }, ) # file menu file_menu = self.menuBar().addMenu(self.tr('File')) open_action = QtWidgets.QAction(self.tr('Open images'), self) open_action.setShortcuts(QtGui.QKeySequence.Open) open_action.triggered.connect(self.image_list.open_files) file_menu.addAction(open_action) self.save_action = QtWidgets.QAction( self.tr('Save images with new data'), self) self.save_action.setShortcuts(QtGui.QKeySequence.Save) self.save_action.setEnabled(False) self.save_action.triggered.connect(self.image_list.save_files) file_menu.addAction(self.save_action) self.close_action = QtWidgets.QAction(self.tr('Close selected images'), self) self.close_action.setEnabled(False) self.close_action.triggered.connect(self.close_files) file_menu.addAction(self.close_action) close_all_action = QtWidgets.QAction(self.tr('Close all images'), self) close_all_action.triggered.connect(self.close_all_files) file_menu.addAction(close_all_action) file_menu.addSeparator() quit_action = QtWidgets.QAction(self.tr('Quit'), self) quit_action.setShortcuts( [QtGui.QKeySequence.Quit, QtGui.QKeySequence.Close]) quit_action.triggered.connect( QtWidgets.QApplication.instance().closeAllWindows) file_menu.addAction(quit_action) # options menu options_menu = self.menuBar().addMenu(self.tr('Options')) settings_action = QtWidgets.QAction(self.tr('Settings'), self) settings_action.triggered.connect(self.edit_settings) options_menu.addAction(settings_action) options_menu.addSeparator() for tab in self.tab_list: name = tab['name'].replace('&', '') tab['action'] = QtWidgets.QAction(name, self) tab['action'].setCheckable(True) if tab['class']: tab['action'].setChecked( eval(self.app.config_store.get('tabs', tab['key'], 'True'))) else: tab['action'].setEnabled(False) tab['action'].triggered.connect(self.add_tabs) options_menu.addAction(tab['action']) # spelling menu languages = self.app.spell_check.available_languages() spelling_menu = self.menuBar().addMenu(self.tr('Spelling')) enable_action = QtWidgets.QAction(self.tr('Enable spell check'), self) enable_action.setEnabled(bool(languages)) enable_action.setCheckable(True) enable_action.setChecked(self.app.spell_check.enabled) enable_action.toggled.connect(self.app.spell_check.enable) spelling_menu.addAction(enable_action) language_menu = QtWidgets.QMenu(self.tr('Choose language'), self) language_menu.setEnabled(bool(languages)) language_group = QtWidgets.QActionGroup(self) current_language = self.app.spell_check.current_language() for tag in languages: language_action = QtWidgets.QAction(tag, self) language_action.setCheckable(True) language_action.setChecked(tag == current_language) language_action.setActionGroup(language_group) language_menu.addAction(language_action) language_group.triggered.connect(self.app.spell_check.set_language) spelling_menu.addMenu(language_menu) # help menu help_menu = self.menuBar().addMenu(self.tr('Help')) about_action = QtWidgets.QAction(self.tr('About Photini'), self) about_action.triggered.connect(self.about) help_menu.addAction(about_action) help_menu.addSeparator() help_action = QtWidgets.QAction(self.tr('Photini documentation'), self) help_action.triggered.connect(self.open_docs) help_menu.addAction(help_action) # main application area self.central_widget = QtWidgets.QSplitter() self.central_widget.setOrientation(Qt.Vertical) self.central_widget.setChildrenCollapsible(False) self.tabs = QtWidgets.QTabWidget() self.tabs.setTabBar(QTabBar()) self.tabs.setElideMode(Qt.ElideRight) self.tabs.currentChanged.connect(self.new_tab) self.add_tabs() self.central_widget.addWidget(self.tabs) self.central_widget.addWidget(self.image_list) size = self.central_widget.sizes() self.central_widget.setSizes( eval(self.app.config_store.get('main_window', 'split', str(size)))) self.central_widget.splitterMoved.connect(self.new_split) self.setCentralWidget(self.central_widget) # open files given on command line, after GUI is displayed self.initial_files = initial_files if self.initial_files: QtCore.QTimer.singleShot(0, self.open_initial_files)
class MainWindow(QtGui.QMainWindow): def __init__(self, verbose): QtGui.QMainWindow.__init__(self) self.setWindowTitle("Photini photo metadata editor") self.selection = list() # logger window self.loggerwindow = LoggerWindow(verbose) self.logger = logging.getLogger(self.__class__.__name__) # config store self.config_store = ConfigStore() # set network proxy proxies = urllib2.getproxies() if 'http' in proxies: scheme, host, port = proxies['http'].split(':') QNetworkProxy.setApplicationProxy( QNetworkProxy(QNetworkProxy.HttpProxy, host[2:], int(port))) # restore size size = self.width(), self.height() self.resize(*eval( self.config_store.get('main_window', 'size', str(size)))) # image selector self.image_list = ImageList(self.config_store) self.image_list.selection_changed.connect(self.new_selection) self.image_list.new_metadata.connect(self.new_metadata) # prepare list of tabs and associated stuff self.tab_list = ( {'name' : '&Descriptive metadata', 'class' : Descriptive}, {'name' : '&Technical metadata', 'class' : Technical}, {'name' : 'Map (&Google)', 'class' : GoogleMap}, {'name' : 'Map (&Bing)', 'class' : BingMap}, {'name' : 'Map (&OSM)', 'class' : OpenStreetMap}, {'name' : '&Flickr uploader', 'class' : FlickrUploader}, {'name' : '&Picasa uploader', 'class' : PicasaUploader}, ) for tab in self.tab_list: tab['key'] = tab['name'].replace('&', '').replace(' ', '_') tab['key'] = tab['key'].replace('(', '').replace(')', '').lower() if tab['class']: tab['object'] = tab['class'](self.config_store, self.image_list) else: tab['object'] = None # file menu file_menu = self.menuBar().addMenu('File') open_action = QtGui.QAction('Open images', self) open_action.setShortcuts(['Ctrl+O']) open_action.triggered.connect(self.image_list.open_files) file_menu.addAction(open_action) self.save_action = QtGui.QAction('Save images with new data', self) self.save_action.setShortcuts(['Ctrl+S']) self.save_action.setEnabled(False) self.save_action.triggered.connect(self.image_list.save_files) file_menu.addAction(self.save_action) self.close_action = QtGui.QAction('Close selected images', self) self.close_action.setEnabled(False) self.close_action.triggered.connect(self.close_files) file_menu.addAction(self.close_action) close_all_action = QtGui.QAction('Close all images', self) close_all_action.triggered.connect(self.close_all_files) file_menu.addAction(close_all_action) file_menu.addSeparator() quit_action = QtGui.QAction('Quit', self) quit_action.setShortcuts(['Ctrl+Q', 'Ctrl+W']) quit_action.triggered.connect(QtGui.qApp.closeAllWindows) file_menu.addAction(quit_action) # options menu options_menu = self.menuBar().addMenu('Options') settings_action = QtGui.QAction('Settings', self) settings_action.triggered.connect(self.edit_settings) options_menu.addAction(settings_action) options_menu.addSeparator() for tab in self.tab_list: tab['action'] = QtGui.QAction(tab['name'].replace('&', ''), self) tab['action'].setCheckable(True) if tab['class']: tab['action'].setChecked( eval(self.config_store.get('tabs', tab['key'], 'True'))) else: tab['action'].setEnabled(False) tab['action'].triggered.connect(self.add_tabs) options_menu.addAction(tab['action']) # help menu help_menu = self.menuBar().addMenu('Help') about_action = QtGui.QAction('About Photini', self) about_action.triggered.connect(self.about) help_menu.addAction(about_action) help_menu.addSeparator() help_action = QtGui.QAction('Photini documentation', self) help_action.triggered.connect(self.open_docs) help_menu.addAction(help_action) # main application area self.central_widget = QtGui.QSplitter() self.central_widget.setOrientation(Qt.Vertical) self.central_widget.setChildrenCollapsible(False) self.tabs = QtGui.QTabWidget() self.add_tabs() self.tabs.currentChanged.connect(self.new_tab) self.central_widget.addWidget(self.tabs) self.central_widget.addWidget(self.image_list) size = self.central_widget.sizes() self.central_widget.setSizes(eval( self.config_store.get('main_window', 'split', str(size)))) self.central_widget.splitterMoved.connect(self.new_split) self.setCentralWidget(self.central_widget) def add_tabs(self): current = self.tabs.currentWidget() self.tabs.clear() for tab in self.tab_list: use_tab = tab['action'].isChecked() self.config_store.set('tabs', tab['key'], str(use_tab)) if tab['object'] and use_tab: self.tabs.addTab(tab['object'], tab['name']) if current: self.tabs.setCurrentWidget(current) def open_docs(self): webbrowser.open_new('http://jim-easterbrook.github.com/Photini/') def close_files(self): self._close_files(False) def close_all_files(self): self._close_files(True) def _close_files(self, all_files): if self.image_list.unsaved_files_dialog(all_files=all_files): self.image_list.close_files(all_files) def closeEvent(self, event): self.image_list.unsaved_files_dialog(with_cancel=False) QtGui.QMainWindow.closeEvent(self, event) def edit_settings(self): dialog = EditSettings(self, self.config_store) dialog.exec_() @QtCore.pyqtSlot() def about(self): dialog = QtGui.QMessageBox() dialog.setWindowTitle('Photini: about') dialog.setText( open(os.path.join(data_dir, 'about.html')).read() % (version)) dialog.setDetailedText( open(os.path.join(data_dir, 'LICENSE.txt')).read()) dialog.exec_() @QtCore.pyqtSlot(int, int) def new_split(self, pos, index): self.config_store.set( 'main_window', 'split', str(self.central_widget.sizes())) @QtCore.pyqtSlot(int) def new_tab(self, index): current = self.tabs.currentWidget() if current: current.refresh() self.image_list.emit_selection() @QtCore.pyqtSlot(list) def new_selection(self, selection): self.close_action.setEnabled(len(selection) > 0) self.tabs.currentWidget().new_selection(selection) @QtCore.pyqtSlot(bool) def new_metadata(self, unsaved_data): self.save_action.setEnabled(unsaved_data) def resizeEvent(self, event): size = self.width(), self.height() self.config_store.set('main_window', 'size', str(size))