Esempio n. 1
0
 def __init__(self, image_list, parent=None):
     super(PhotiniMap, self).__init__(parent)
     self.app = QtWidgets.QApplication.instance()
     self.image_list = image_list
     self.geocode_cache = OrderedDict()
     name = self.__class__.__name__.lower()
     self.api_key = key_store.get(name, 'api_key')
     self.search_key = key_store.get('opencage', 'api_key')
     self.script_dir = pkg_resources.resource_filename(
         'photini', 'data/' + name + '/')
     self.drag_icon = QtGui.QPixmap(
         os.path.join(self.script_dir, '../map_pin_grey.png'))
     self.drag_hotspot = 10, 35
     self.search_string = None
     self.map_loaded = False
     self.marker_info = {}
     self.map_status = {}
     self.dropped_images = []
     self.setChildrenCollapsible(False)
     left_side = QtWidgets.QWidget()
     self.addWidget(left_side)
     left_side.setLayout(QtWidgets.QFormLayout())
     left_side.layout().setContentsMargins(0, 0, 0, 0)
     left_side.layout().setFieldGrowthPolicy(
         QtWidgets.QFormLayout.AllNonFixedFieldsGrow)
     # map
     self.map = WebView()
     self.map.setPage(WebPage(parent=self.map))
     self.call_handler = CallHandler(parent=self)
     if QtWebEngineWidgets:
         self.web_channel = QtWebChannel.QWebChannel(parent=self)
         self.map.page().setWebChannel(self.web_channel)
         self.web_channel.registerObject('python', self.call_handler)
         self.map.settings().setAttribute(
             WebSettings.Accelerated2dCanvasEnabled, False)
     else:
         self.map.page().setLinkDelegationPolicy(
             QtWebKitWidgets.QWebPage.DelegateAllLinks)
         self.map.page().linkClicked.connect(self.link_clicked)
         self.map.page().mainFrame().javaScriptWindowObjectCleared.connect(
             self.java_script_window_object_cleared)
     self.map.settings().setAttribute(
         WebSettings.LocalContentCanAccessRemoteUrls, True)
     self.map.settings().setAttribute(
         WebSettings.LocalContentCanAccessFileUrls, True)
     self.map.setAcceptDrops(False)
     self.map.drop_text.connect(self.drop_text)
     self.addWidget(self.map)
     # search
     search_layout = QtWidgets.QFormLayout()
     search_layout.setContentsMargins(0, 0, 0, 0)
     search_layout.setVerticalSpacing(0)
     search_layout.setFieldGrowthPolicy(
         QtWidgets.QFormLayout.AllNonFixedFieldsGrow)
     self.edit_box = ComboBox()
     self.edit_box.setEditable(True)
     self.edit_box.setInsertPolicy(QtWidgets.QComboBox.NoInsert)
     self.edit_box.lineEdit().setPlaceholderText(
         translate('PhotiniMap', '<new search>'))
     self.edit_box.lineEdit().returnPressed.connect(self.search)
     self.edit_box.activated.connect(self.goto_search_result)
     self.clear_search()
     self.edit_box.setEnabled(False)
     search_layout.addRow(translate('PhotiniMap', 'Search'), self.edit_box)
     # search terms and conditions
     terms = self.search_terms()
     if terms:
         search_layout.addRow(*terms)
     left_side.layout().addRow(search_layout)
     if terms:
         divider = QtWidgets.QFrame()
         divider.setFrameStyle(QtWidgets.QFrame.HLine)
         left_side.layout().addRow(divider)
     left_side.layout().addItem(
         QtWidgets.QSpacerItem(1,
                               1000,
                               vPolicy=QtWidgets.QSizePolicy.Expanding))
     # latitude & longitude
     layout = QtWidgets.QHBoxLayout()
     self.coords = SingleLineEdit()
     self.coords.editingFinished.connect(self.new_coords)
     self.coords.setEnabled(False)
     layout.addWidget(self.coords)
     # convert lat/lng to location info
     self.auto_location = QtWidgets.QPushButton(
         translate('PhotiniMap',
                   six.unichr(0x21e8) + ' address'))
     self.auto_location.setFixedHeight(self.coords.height())
     self.auto_location.setEnabled(False)
     self.auto_location.clicked.connect(self.get_address)
     layout.addWidget(self.auto_location)
     left_side.layout().addRow(translate('PhotiniMap', 'Lat, long'), layout)
     # location info
     self.location_widgets = []
     self.location_info = QtWidgets.QTabWidget()
     tab_bar = QTabBar()
     self.location_info.setTabBar(tab_bar)
     tab_bar.context_menu.connect(self.location_tab_context_menu)
     tab_bar.tabMoved.connect(self.location_tab_moved)
     self.location_info.setElideMode(Qt.ElideLeft)
     self.location_info.setMovable(True)
     self.location_info.setEnabled(False)
     left_side.layout().addRow(self.location_info)
     # address lookup (and default search) terms and conditions
     layout = QtWidgets.QHBoxLayout()
     if terms:
         widget = CompactButton(
             self.tr('Address lookup\npowered by OpenCage'))
     else:
         widget = CompactButton(
             self.tr('Search && lookup\npowered by OpenCage'))
     widget.clicked.connect(self.load_tou_opencage)
     layout.addWidget(widget)
     widget = CompactButton(
         self.tr('Geodata © OpenStreetMap\ncontributors'))
     widget.clicked.connect(self.load_tou_osm)
     layout.addWidget(widget)
     left_side.layout().addRow(layout)
     # other init
     self.image_list.image_list_changed.connect(self.image_list_changed)
     self.splitterMoved.connect(self.new_split)
     self.block_timer = QtCore.QTimer(self)
     self.block_timer.setInterval(5000)
     self.block_timer.setSingleShot(True)
     self.block_timer.timeout.connect(self.enable_search)
Esempio n. 2
0
 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
     # 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},
         )
     for tab in self.tab_list:
         if tab['class']:
             tab['object'] = tab['class'](self.image_list)
         else:
             tab['object'] = None
     # 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)
Esempio n. 3
0
 def __init__(self, options, initial_files):
     super(MainWindow, self).__init__()
     self.setWindowTitle(
         translate('MenuBar', "Photini photo metadata editor"))
     pixmap = QtGui.QPixmap()
     pixmap.loadFromData(
         pkg_resources.resource_string('photini',
                                       'data/icons/photini_48.png'))
     icon = QtGui.QIcon(pixmap)
     self.setWindowIcon(icon)
     self.selection = list()
     # logger window
     self.loggerwindow = LoggerWindow(options.verbose)
     self.loggerwindow.setWindowIcon(icon)
     # set network proxy
     proxies = urllib.request.getproxies()
     if 'http' in proxies:
         parsed = urllib.parse.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.open_cage = OpenCage(parent=self)
     self.app.options = options
     # 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)
     # update config file
     if self.app.config_store.config.has_section('tabs'):
         conv = {
             'descriptive_metadata': 'photini.descriptive',
             'technical_metadata': 'photini.technical',
             'map_google': 'photini.googlemap',
             'map_bing': 'photini.bingmap',
             'map_mapbox': 'photini.mapboxmap',
             'map_osm': 'photini.openstreetmap',
             'address': 'photini.address',
             'flickr_upload': 'photini.flickr',
             'import_photos': 'photini.importer',
         }
         for key in self.app.config_store.config.options('tabs'):
             if key in conv:
                 self.app.config_store.set(
                     'tabs', conv[key],
                     self.app.config_store.get('tabs', key))
                 self.app.config_store.config.remove_option('tabs', key)
     # prepare list of tabs and associated stuff
     self.tab_list = []
     default_modules = [
         'photini.descriptive', 'photini.technical', 'photini.googlemap',
         'photini.bingmap', 'photini.mapboxmap', 'photini.openstreetmap',
         'photini.address', 'photini.flickr', 'photini.googlephotos',
         'photini.importer'
     ]
     modules = eval(
         self.app.config_store.get('tabs', 'modules',
                                   pprint.pformat(default_modules)))
     for n, module in enumerate(default_modules):
         if module not in modules:
             modules = list(modules)
             modules.insert(n, module)
             self.app.config_store.set('tabs', 'modules',
                                       pprint.pformat(modules))
     for module in modules:
         tab = {'module': module}
         try:
             mod = importlib.import_module(tab['module'])
             tab['class'] = mod.TabWidget
             tab['name'] = tab['class'].tab_name()
         except ImportError as ex:
             print(str(ex))
             tab['class'] = None
         self.tab_list.append(tab)
     # file menu
     file_menu = self.menuBar().addMenu(translate('MenuBar', 'File'))
     action = file_menu.addAction(translate('MenuBar', 'Open files'))
     action.setShortcuts(QtGui.QKeySequence.Open)
     action.triggered.connect(self.image_list.open_files)
     self.save_action = file_menu.addAction(
         translate('MenuBar', 'Save changes'))
     self.save_action.setShortcuts(QtGui.QKeySequence.Save)
     self.save_action.setEnabled(False)
     self.save_action.triggered.connect(self.image_list.save_files)
     action = file_menu.addAction(translate('MenuBar', 'Close all files'))
     action.triggered.connect(self.image_list.close_all_files)
     sep = file_menu.addAction(translate('MenuBar', 'Selected images'))
     sep.setSeparator(True)
     self.selected_actions = self.image_list.add_selected_actions(file_menu)
     if GpxImporter:
         self.import_gpx_action = file_menu.addAction(
             translate('MenuBar', 'Import GPX file'))
         self.import_gpx_action.triggered.connect(self.import_pgx_file)
     else:
         self.import_gpx_action = None
     file_menu.addSeparator()
     action = file_menu.addAction(translate('MenuBar', 'Quit'))
     action.setShortcuts(
         [QtGui.QKeySequence.Quit, QtGui.QKeySequence.Close])
     action.triggered.connect(
         QtWidgets.QApplication.instance().closeAllWindows)
     # options menu
     options_menu = self.menuBar().addMenu(translate('MenuBar', 'Options'))
     action = options_menu.addAction(translate('MenuBar', 'Settings'))
     action.triggered.connect(self.edit_settings)
     options_menu.addSeparator()
     for tab in self.tab_list:
         if tab['class']:
             name = tab['name'].replace('&', '')
         else:
             name = tab['module']
         tab['action'] = options_menu.addAction(name)
         tab['action'].setCheckable(True)
         if tab['class']:
             tab['action'].setChecked(
                 eval(
                     self.app.config_store.get('tabs', tab['module'],
                                               'True')))
         else:
             tab['action'].setEnabled(False)
         tab['action'].triggered.connect(self.add_tabs)
     # spelling menu
     languages = self.app.spell_check.available_languages()
     spelling_menu = self.menuBar().addMenu(translate(
         'MenuBar', 'Spelling'))
     action = spelling_menu.addAction(
         translate('MenuBar', 'Enable spell check'))
     action.setEnabled(languages is not None)
     action.setCheckable(True)
     action.setChecked(self.app.spell_check.enabled)
     action.toggled.connect(self.app.spell_check.enable)
     language_menu = spelling_menu.addMenu(
         translate('MenuBar', 'Choose language'))
     language_menu.setEnabled(languages is not None)
     current_language = self.app.spell_check.current_language()
     if languages:
         language_group = QtWidgets.QActionGroup(self)
         for name, code in languages:
             if name != code:
                 name = code + ': ' + name
             action = language_menu.addAction(name)
             action.setCheckable(True)
             action.setChecked(code == current_language)
             action.setData(code)
             action.setActionGroup(language_group)
         language_group.triggered.connect(self.set_language)
     else:
         action = language_menu.addAction(
             translate('MenuBar', 'No dictionary installed'))
         action.setEnabled(False)
     # help menu
     help_menu = self.menuBar().addMenu(translate('MenuBar', 'Help'))
     action = help_menu.addAction(translate('MenuBar', 'About Photini'))
     action.triggered.connect(self.about)
     help_menu.addSeparator()
     action = help_menu.addAction(
         translate('MenuBar', 'Photini documentation'))
     action.triggered.connect(self.open_docs)
     # 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(False)
     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)