Ejemplo n.º 1
0
 def __init__(self, *arg, **kw):
     super(NewItemDialog, self).__init__(*arg, **kw)
     self.setLayout(QtWidgets.QVBoxLayout())
     # main dialog area
     scroll_area = QtWidgets.QScrollArea()
     scroll_area.setWidgetResizable(True)
     self.layout().addWidget(scroll_area)
     self.panel = QtWidgets.QWidget()
     self.panel.setLayout(QtWidgets.QFormLayout())
     self.panel.layout().setFieldGrowthPolicy(
         QtWidgets.QFormLayout.AllNonFixedFieldsGrow)
     # ok & cancel buttons
     button_box = QtWidgets.QDialogButtonBox(
         QtWidgets.QDialogButtonBox.Ok | QtWidgets.QDialogButtonBox.Cancel)
     button_box.accepted.connect(self.accept)
     button_box.rejected.connect(self.reject)
     self.layout().addWidget(button_box)
     # common data items
     self.model_widgets = {}
     for key, label in (
             ('make', translate('TechnicalTab', "Maker's name")),
             ('model', translate('TechnicalTab', 'Model name')),
             ('serial_no', translate('TechnicalTab', 'Serial number')),
             ):
         self.model_widgets[key] = QtWidgets.QLineEdit()
         self.model_widgets[key].setMinimumWidth(
             width_for_text(self.model_widgets[key], 'x' * 35))
         self.panel.layout().addRow(label, self.model_widgets[key])
     # add any other data items
     self.extend_data()
     # add panel to scroll area now its size is known
     scroll_area.setWidget(self.panel)
Ejemplo n.º 2
0
 def new_set(self):
     dialog = QtWidgets.QDialog(parent=self)
     dialog.setWindowTitle(self.tr('Create new Flickr album'))
     dialog.setLayout(QtWidgets.QFormLayout())
     title = SingleLineEdit(spell_check=True)
     dialog.layout().addRow(self.tr('Title'), title)
     description = MultiLineEdit(spell_check=True)
     dialog.layout().addRow(self.tr('Description'), description)
     dialog.layout().addRow(QtWidgets.QLabel(
         self.tr('Album will be created when photos are uploaded')))
     button_box = QtWidgets.QDialogButtonBox(
         QtWidgets.QDialogButtonBox.Ok | QtWidgets.QDialogButtonBox.Cancel)
     button_box.accepted.connect(dialog.accept)
     button_box.rejected.connect(dialog.reject)
     dialog.layout().addRow(button_box)
     if dialog.exec_() != QtWidgets.QDialog.Accepted:
         return
     title = title.toPlainText()
     if not title:
         return
     description = description.toPlainText()
     widget = self.upload_config.add_set(title, description, index=0)
     widget.setChecked(True)
     self.photosets.insert(0, {
         'id'          : None,
         'title'       : title,
         'description' : description,
         'widget'      : widget,
         })
Ejemplo n.º 3
0
 def _replace_dialog(self, image):
     # has image already been uploaded?
     for keyword in image.metadata.keywords or []:
         name_pred, sep, photo_id = keyword.partition('=')
         if name_pred == ID_TAG:
             break
     else:
         # new upload
         return {
             'set_metadata'  : True,
             'set_visibility': True,
             'set_type'      : True,
             'set_albums'    : True,
             'replace_image' : False,
             'new_photo'     : True,
             }, None
     # get user preferences
     dialog = QtWidgets.QDialog(parent=self)
     dialog.setWindowTitle(self.tr('Replace photo'))
     dialog.setLayout(QtWidgets.QVBoxLayout())
     message = QtWidgets.QLabel(self.tr(
         'File {0} has already been uploaded to Flickr.' +
         ' How would you like to update it?').format(
             os.path.basename(image.path)))
     message.setWordWrap(True)
     dialog.layout().addWidget(message)
     widget = {}
     widget['set_metadata'] = QtWidgets.QCheckBox(
         self.tr('Replace metadata'))
     widget['set_visibility'] = QtWidgets.QCheckBox(
         self.tr('Change who can see it'))
     widget['set_type'] = QtWidgets.QCheckBox(
         self.tr('Change content type'))
     widget['set_albums'] = QtWidgets.QCheckBox(
         self.tr('Change album membership'))
     widget['replace_image'] = QtWidgets.QCheckBox(
         self.tr('Replace image'))
     widget['new_photo'] = QtWidgets.QCheckBox(
         self.tr('Upload as new photo'))
     no_upload = QtWidgets.QCheckBox(self.tr('No image upload'))
     no_upload.setChecked(True)
     button_group = QtWidgets.QButtonGroup()
     button_group.addButton(widget['replace_image'])
     button_group.addButton(widget['new_photo'])
     button_group.addButton(no_upload)
     for key in ('set_metadata', 'set_visibility', 'set_type',
                 'set_albums', 'replace_image', 'new_photo'):
         dialog.layout().addWidget(widget[key])
         widget[key].setChecked(self.replace_prefs[key])
     dialog.layout().addWidget(no_upload)
     button_box = QtWidgets.QDialogButtonBox(
         QtWidgets.QDialogButtonBox.Ok | QtWidgets.QDialogButtonBox.Cancel)
     button_box.accepted.connect(dialog.accept)
     button_box.rejected.connect(dialog.reject)
     dialog.layout().addWidget(button_box)
     if dialog.exec_() != QtWidgets.QDialog.Accepted:
         return None, photo_id
     for key in self.replace_prefs:
         self.replace_prefs[key] = widget[key].isChecked()
     return dict(self.replace_prefs), photo_id
Ejemplo n.º 4
0
 def __init__(self, *arg, **kw):
     super(FacebookLoginPopup, self).__init__(*arg, **kw)
     self.setSizePolicy(QtWidgets.QSizePolicy.Maximum,
                        QtWidgets.QSizePolicy.Maximum)
     self.setLayout(QtWidgets.QVBoxLayout())
     self.browser = WebView()
     self.browser.urlChanged.connect(self.auth_url_changed)
     self.layout().addWidget(self.browser)
     buttons = QtWidgets.QDialogButtonBox(QtWidgets.QDialogButtonBox.Cancel)
     buttons.rejected.connect(self.reject)
     self.layout().addWidget(buttons)
Ejemplo n.º 5
0
 def new_album(self):
     dialog = QtWidgets.QDialog(parent=self)
     dialog.setWindowTitle(self.tr('Create new Facebook album'))
     dialog.setLayout(QtWidgets.QFormLayout())
     name = SingleLineEdit(spell_check=True)
     dialog.layout().addRow(self.tr('Title'), name)
     message = MultiLineEdit(spell_check=True)
     dialog.layout().addRow(self.tr('Description'), message)
     location = SingleLineEdit(spell_check=True)
     dialog.layout().addRow(self.tr('Location'), location)
     privacy = QtWidgets.QComboBox()
     for display_name, value in (
         (self.tr('Only me'), '{value: "SELF"}'),
         (self.tr('All friends'), '{value: "ALL_FRIENDS"}'),
         (self.tr('Friends of friends'), '{value: "FRIENDS_OF_FRIENDS"}'),
         (self.tr('Friends + networks'), '{value: "NETWORKS_FRIENDS"}'),
         (self.tr('Everyone'), '{value: "EVERYONE"}'),
     ):
         privacy.addItem(display_name, value)
     dialog.layout().addRow(self.tr('Privacy'), privacy)
     button_box = QtWidgets.QDialogButtonBox(
         QtWidgets.QDialogButtonBox.Ok | QtWidgets.QDialogButtonBox.Cancel)
     button_box.accepted.connect(dialog.accept)
     button_box.rejected.connect(dialog.reject)
     dialog.layout().addRow(button_box)
     if dialog.exec_() != QtWidgets.QDialog.Accepted:
         return
     if not self.authorise('write'):
         self.refresh(force=True)
         return
     name = name.toPlainText().strip()
     if not name:
         return
     data = {'name': name}
     message = message.toPlainText().strip()
     if message:
         data['message'] = message
     location = location.toPlainText().strip()
     if location:
         data['location'] = location
     data['privacy'] = privacy.itemData(privacy.currentIndex())
     try:
         album = self.session.post('https://graph.facebook.com/me/albums',
                                   data=data)
     except Exception as ex:
         self.logger.error(str(ex))
         self.refresh(force=True)
         return
     self.load_user_data(album_id=album['id'])
Ejemplo n.º 6
0
 def edit_template(self):
     dialog = QtWidgets.QDialog(parent=self)
     width = width_for_text(dialog, 'x' * 120)
     dialog.setFixedSize(min(width,
                             self.window().width()),
                         min(width * 3 // 4,
                             self.window().height()))
     dialog.setWindowTitle(self.tr('Photini: ownership template'))
     dialog.setLayout(QtWidgets.QVBoxLayout())
     # main dialog area
     form, widgets = self.data_form()
     widgets['copyright'].setToolTip(
         widgets['copyright'].toolTip() + ' ' +
         translate('OwnerTab',
                   'Use %Y to insert the year the photograph was taken.'))
     for key in widgets:
         value = self.config_store.get('ownership', key)
         if key == 'copyright' and not value:
             name = self.config_store.get('user', 'copyright_name') or ''
             text = (self.config_store.get('user', 'copyright_text')
                     or translate(
                         'DescriptiveTab', 'Copyright ©{year} {name}.'
                         ' All rights reserved.'))
             value = text.format(year='%Y', name=name)
         elif key == 'creator' and not value:
             value = self.config_store.get('user', 'creator_name')
         widgets[key].set_value(value)
     dialog.layout().addWidget(form)
     # apply & cancel buttons
     button_box = QtWidgets.QDialogButtonBox(
         QtWidgets.QDialogButtonBox.Ok | QtWidgets.QDialogButtonBox.Cancel)
     button_box.accepted.connect(dialog.accept)
     button_box.rejected.connect(dialog.reject)
     dialog.layout().addWidget(button_box)
     if dialog.exec_() != QtWidgets.QDialog.Accepted:
         return
     for key in widgets:
         value = widgets[key].get_value()
         if value:
             self.config_store.set('ownership', key, value)
         else:
             self.config_store.delete('ownership', key)
Ejemplo n.º 7
0
 def __init__(self, verbose, *arg, **kw):
     super(LoggerWindow, self).__init__(*arg, **kw)
     QtWidgets.QApplication.instance().aboutToQuit.connect(self.shutdown)
     self.setWindowTitle(self.tr("Photini error logging"))
     self.setLayout(QtWidgets.QVBoxLayout())
     # main dialog area
     self.text = QtWidgets.QTextEdit()
     self.text.setReadOnly(True)
     self.text.setMinimumWidth(width_for_text(self.text, 'x' * 70))
     self.layout().addWidget(self.text)
     # buttons
     button_box = QtWidgets.QDialogButtonBox(
         QtWidgets.QDialogButtonBox.Save | QtWidgets.QDialogButtonBox.Close)
     button_box.button(QtWidgets.QDialogButtonBox.Save).clicked.connect(
         self.save)
     button_box.button(QtWidgets.QDialogButtonBox.Close).clicked.connect(
         self.hide)
     self.layout().addWidget(button_box)
     # Python logger
     self.logger = logging.getLogger('')
     for handler in list(self.logger.handlers):
         self.logger.removeHandler(handler)
     threshold = logging.ERROR - (verbose * 10)
     self.logger.setLevel(max(threshold, 1))
     self.stream_proxy = StreamProxy(self)
     self.stream_proxy.write_text.connect(self.write)
     self.stream_proxy.flush_text.connect(self.flush)
     handler = logging.StreamHandler(self.stream_proxy)
     handler.setFormatter(
         logging.Formatter(
             '%(asctime)s: %(levelname)s: %(name)s: %(message)s',
             datefmt='%H:%M:%S'))
     handler.addFilter(LoggerFilter(threshold))
     self.logger.addHandler(handler)
     # intercept stdout and stderr, if they exist
     if sys.stderr:
         sys.stderr = OutputInterceptor('stderr', sys.stderr)
     if sys.stdout:
         sys.stdout = OutputInterceptor('stdout', sys.stdout)
Ejemplo n.º 8
0
 def __init__(self, *arg, **kw):
     super(EditSettings, self).__init__(*arg, **kw)
     self.config_store = QtWidgets.QApplication.instance().config_store
     self.setWindowTitle(self.tr('Photini: settings'))
     self.setLayout(QtWidgets.QVBoxLayout())
     # main dialog area
     scroll_area = QtWidgets.QScrollArea()
     self.layout().addWidget(scroll_area)
     panel = QtWidgets.QWidget()
     panel.setLayout(QtWidgets.QFormLayout())
     panel.layout().setRowWrapPolicy(
         max(QtWidgets.QFormLayout.WrapLongRows,
             panel.layout().rowWrapPolicy()))
     # apply & cancel buttons
     self.button_box = QtWidgets.QDialogButtonBox(
         QtWidgets.QDialogButtonBox.Apply
         | QtWidgets.QDialogButtonBox.Cancel)
     self.button_box.clicked.connect(self.button_clicked)
     self.layout().addWidget(self.button_box)
     # copyright holder name
     self.copyright_name = SingleLineEdit(spell_check=True)
     self.copyright_name.set_value(
         self.config_store.get('user', 'copyright_name', ''))
     panel.layout().addRow(self.tr('Copyright holder name'),
                           self.copyright_name)
     # copyright text
     self.copyright_text = SingleLineEdit(spell_check=True)
     self.copyright_text.set_value(
         self.config_store.get('user', 'copyright_text', ''))
     self.copyright_text.setMinimumWidth(
         width_for_text(self.copyright_text, 'x' * 50))
     panel.layout().addRow(self.tr('Copyright text'), self.copyright_text)
     # creator name
     self.creator_name = SingleLineEdit(spell_check=True)
     self.creator_name.set_value(
         self.config_store.get('user', 'creator_name', ''))
     panel.layout().addRow(self.tr('Creator name'), self.creator_name)
     # IPTC data
     force_iptc = eval(self.config_store.get('files', 'force_iptc',
                                             'False'))
     self.write_iptc = QtWidgets.QCheckBox(self.tr('Always write'))
     self.write_iptc.setChecked(force_iptc)
     panel.layout().addRow(self.tr('IPTC metadata'), self.write_iptc)
     # sidecar files
     if_mode = eval(self.config_store.get('files', 'image', 'True'))
     sc_mode = self.config_store.get('files', 'sidecar', 'auto')
     if not if_mode:
         sc_mode = 'always'
     self.sc_always = QtWidgets.QRadioButton(self.tr('Always create'))
     self.sc_always.setChecked(sc_mode == 'always')
     panel.layout().addRow(self.tr('Sidecar files'), self.sc_always)
     self.sc_auto = QtWidgets.QRadioButton(self.tr('Create if necessary'))
     self.sc_auto.setChecked(sc_mode == 'auto')
     self.sc_auto.setEnabled(if_mode)
     panel.layout().addRow('', self.sc_auto)
     self.sc_delete = QtWidgets.QRadioButton(
         self.tr('Delete when possible'))
     self.sc_delete.setChecked(sc_mode == 'delete')
     self.sc_delete.setEnabled(if_mode)
     panel.layout().addRow('', self.sc_delete)
     # image file locking
     self.write_if = QtWidgets.QCheckBox(self.tr('(when possible)'))
     self.write_if.setChecked(if_mode)
     self.write_if.clicked.connect(self.new_write_if)
     panel.layout().addRow(self.tr('Write to image file'), self.write_if)
     # preserve file timestamps
     keep_time = eval(
         self.config_store.get('files', 'preserve_timestamps', 'False'))
     self.keep_time = QtWidgets.QCheckBox()
     self.keep_time.setChecked(keep_time)
     panel.layout().addRow(self.tr('Preserve file timestamps'),
                           self.keep_time)
     # add panel to scroll area after its size is known
     scroll_area.setWidget(panel)
Ejemplo n.º 9
0
 def __init__(self, parent):
     QtWidgets.QDialog.__init__(self, parent)
     self.config_store = QtWidgets.QApplication.instance().config_store
     self.setWindowTitle(self.tr('Photini: settings'))
     self.setLayout(QtWidgets.QVBoxLayout())
     # main dialog area
     scroll_area = QtWidgets.QScrollArea()
     self.layout().addWidget(scroll_area)
     panel = QtWidgets.QWidget()
     panel.setLayout(QtWidgets.QFormLayout())
     # apply & cancel buttons
     self.button_box = QtWidgets.QDialogButtonBox(
         QtWidgets.QDialogButtonBox.Apply
         | QtWidgets.QDialogButtonBox.Cancel)
     self.button_box.clicked.connect(self.button_clicked)
     self.layout().addWidget(self.button_box)
     # copyright holder name
     self.copyright_name = QtWidgets.QLineEdit()
     self.copyright_name.setText(
         self.config_store.get('user', 'copyright_name', ''))
     self.copyright_name.setMinimumWidth(200)
     panel.layout().addRow(self.tr('Copyright holder'), self.copyright_name)
     # creator name
     self.creator_name = QtWidgets.QLineEdit()
     self.creator_name.setText(
         self.config_store.get('user', 'creator_name', ''))
     panel.layout().addRow(self.tr('Creator'), self.creator_name)
     # reset flickr
     self.reset_flickr = QtWidgets.QCheckBox()
     panel.layout().addRow(self.tr('Disconnect from Flickr'),
                           self.reset_flickr)
     if not keyring or keyring.get_password('photini', 'flickr') is None:
         self.reset_flickr.setDisabled(True)
         panel.layout().labelForField(self.reset_flickr).setDisabled(True)
     # reset picasa
     self.reset_picasa = QtWidgets.QCheckBox()
     panel.layout().addRow(self.tr('Disconnect from Google Photos'),
                           self.reset_picasa)
     if not keyring or keyring.get_password('photini', 'picasa') is None:
         self.reset_picasa.setDisabled(True)
         panel.layout().labelForField(self.reset_picasa).setDisabled(True)
     # reset facebook
     self.reset_facebook = QtWidgets.QCheckBox()
     panel.layout().addRow(self.tr('Disconnect from Facebook'),
                           self.reset_facebook)
     if not keyring or keyring.get_password('photini', 'facebook') is None:
         self.reset_facebook.setDisabled(True)
         panel.layout().labelForField(self.reset_facebook).setDisabled(True)
     # IPTC data
     force_iptc = eval(self.config_store.get('files', 'force_iptc',
                                             'False'))
     self.write_iptc = QtWidgets.QCheckBox(self.tr('Write unconditionally'))
     self.write_iptc.setChecked(force_iptc)
     panel.layout().addRow(self.tr('IPTC metadata'), self.write_iptc)
     # sidecar files
     if_mode = eval(self.config_store.get('files', 'image', 'True'))
     sc_mode = self.config_store.get('files', 'sidecar', 'auto')
     if not if_mode:
         sc_mode = 'always'
     self.sc_always = QtWidgets.QRadioButton(self.tr('Always create'))
     self.sc_always.setChecked(sc_mode == 'always')
     panel.layout().addRow(self.tr('Sidecar files'), self.sc_always)
     self.sc_auto = QtWidgets.QRadioButton(self.tr('Create if necessary'))
     self.sc_auto.setChecked(sc_mode == 'auto')
     self.sc_auto.setEnabled(if_mode)
     panel.layout().addRow('', self.sc_auto)
     self.sc_delete = QtWidgets.QRadioButton(
         self.tr('Delete when possible'))
     self.sc_delete.setChecked(sc_mode == 'delete')
     self.sc_delete.setEnabled(if_mode)
     panel.layout().addRow('', self.sc_delete)
     # image file locking
     self.write_if = QtWidgets.QCheckBox(self.tr('(when possible)'))
     self.write_if.setChecked(if_mode)
     self.write_if.clicked.connect(self.new_write_if)
     panel.layout().addRow(self.tr('Write to image'), self.write_if)
     # add panel to scroll area after its size is known
     scroll_area.setWidget(panel)
Ejemplo n.º 10
0
 def diff_metadata(self):
     dialog = QtWidgets.QDialog(parent=self)
     dialog.setWindowTitle(translate('ImageList', 'Metadata differences'))
     dialog.setLayout(QtWidgets.QVBoxLayout())
     table = TableWidget()
     table.setSizePolicy(QtWidgets.QSizePolicy.Expanding,
                         QtWidgets.QSizePolicy.Expanding)
     table.setColumnCount(3)
     table.setHorizontalHeaderLabels([
         translate('ImageList', 'new value'),
         translate('ImageList', 'undo'),
         translate('ImageList', 'old value')
     ])
     labels = []
     row = 0
     undo = {}
     new_md = self.metadata
     old_md = Metadata(self.path)
     for key in ('title', 'description', 'keywords', 'rating', 'copyright',
                 'creator', 'date_taken', 'date_digitised', 'date_modified',
                 'orientation', 'lens_model', 'lens_make', 'lens_serial',
                 'lens_spec', 'focal_length', 'focal_length_35', 'aperture',
                 'latlong', 'altitude', 'location_taken', 'location_shown',
                 'thumbnail'):
         values = getattr(new_md, key), getattr(old_md, key)
         if values[0] == values[1]:
             continue
         table.setRowCount(row + 1)
         for n, value in enumerate(values):
             if not value:
                 value = ''
             elif isinstance(value, MultiString):
                 value = '\n'.join(value)
             else:
                 value = six.text_type(value)
             item = QtWidgets.QTableWidgetItem(value)
             table.setItem(row, n * 2, item)
         undo[key] = QtWidgets.QTableWidgetItem()
         undo[key].setFlags(undo[key].flags() | Qt.ItemIsUserCheckable)
         undo[key].setCheckState(False)
         table.setItem(row, 1, undo[key])
         labels.append(key)
         row += 1
     table.setVerticalHeaderLabels(labels)
     table.resizeColumnsToContents()
     table.resizeRowsToContents()
     dialog.layout().addWidget(table)
     button_box = QtWidgets.QDialogButtonBox(
         QtWidgets.QDialogButtonBox.Ok | QtWidgets.QDialogButtonBox.Cancel)
     button_box.accepted.connect(dialog.accept)
     button_box.rejected.connect(dialog.reject)
     dialog.layout().addWidget(button_box)
     if dialog.exec_() != QtWidgets.QDialog.Accepted:
         return
     changed = False
     dirty = False
     for key, widget in undo.items():
         if widget.checkState() == Qt.Checked:
             setattr(new_md, key, getattr(old_md, key))
             changed = True
         else:
             dirty = True
     if not dirty:
         self.reload_metadata()
     elif changed:
         self.image_list.emit_selection()
Ejemplo n.º 11
0
 def __init__(self, images, *arg, **kw):
     super(NewLensDialog, self).__init__(*arg, **kw)
     self.setWindowTitle(self.tr('Photini: define lens'))
     self.setLayout(QtWidgets.QVBoxLayout())
     # main dialog area
     scroll_area = QtWidgets.QScrollArea()
     scroll_area.setWidgetResizable(True)
     self.layout().addWidget(scroll_area)
     panel = QtWidgets.QWidget()
     panel.setLayout(QtWidgets.QFormLayout())
     # ok & cancel buttons
     button_box = QtWidgets.QDialogButtonBox(
         QtWidgets.QDialogButtonBox.Ok | QtWidgets.QDialogButtonBox.Cancel)
     button_box.accepted.connect(self.accept)
     button_box.rejected.connect(self.reject)
     self.layout().addWidget(button_box)
     # model
     self.lens_model = QtWidgets.QLineEdit()
     self.lens_model.setMinimumWidth(250)
     panel.layout().addRow(self.tr('Model name'), self.lens_model)
     # maker
     self.lens_make = QtWidgets.QLineEdit()
     panel.layout().addRow(self.tr("Maker's name"), self.lens_make)
     # serial number
     self.lens_serial = QtWidgets.QLineEdit()
     panel.layout().addRow(self.tr('Serial number'), self.lens_serial)
     ## spec has four items
     self.lens_spec = {}
     # min focal length
     self.lens_spec['min_fl'] = QtWidgets.QLineEdit()
     self.lens_spec['min_fl'].setValidator(
         QtGui.QDoubleValidator(bottom=0.0))
     panel.layout().addRow(self.tr('Minimum focal length (mm)'),
                           self.lens_spec['min_fl'])
     # min focal length aperture
     self.lens_spec['min_fl_fn'] = QtWidgets.QLineEdit()
     self.lens_spec['min_fl_fn'].setValidator(DoubleValidator(bottom=0.0))
     panel.layout().addRow(self.tr('Aperture at min. focal length f/'),
                           self.lens_spec['min_fl_fn'])
     # max focal length
     self.lens_spec['max_fl'] = QtWidgets.QLineEdit()
     self.lens_spec['max_fl'].setValidator(
         QtGui.QDoubleValidator(bottom=0.0))
     panel.layout().addRow(self.tr('Maximum focal length (mm)'),
                           self.lens_spec['max_fl'])
     # max focal length aperture
     self.lens_spec['max_fl_fn'] = QtWidgets.QLineEdit()
     self.lens_spec['max_fl_fn'].setValidator(DoubleValidator(bottom=0.0))
     panel.layout().addRow(self.tr('Aperture at max. focal length f/'),
                           self.lens_spec['max_fl_fn'])
     # add panel to scroll area after its size is known
     scroll_area.setWidget(panel)
     # fill in any values we can from existing metadata
     for image in images:
         if image.metadata.lens_model:
             self.lens_model.setText(image.metadata.lens_model.value)
         if image.metadata.lens_make:
             self.lens_make.setText(image.metadata.lens_make.value)
         if image.metadata.lens_serial:
             self.lens_serial.setText(image.metadata.lens_serial.value)
         spec = image.metadata.lens_spec
         for key in self.lens_spec:
             if spec and spec.value[key]:
                 self.lens_spec[key].setText('{:g}'.format(
                     float(spec.value[key])))
Ejemplo n.º 12
0
 def do_import(self, parent):
     args = [
         parent,
         self.tr('Import GPX file'),
         parent.app.config_store.get('paths', 'gpx', ''),
         self.tr("GPX files (*.gpx *.GPX *.Gpx);;All files (*)")
     ]
     if eval(parent.app.config_store.get('pyqt', 'native_dialog', 'True')):
         pass
     else:
         args += [None, QtWidgets.QFileDialog.DontUseNativeDialog]
     path = QtWidgets.QFileDialog.getOpenFileName(*args)
     path = path[0]
     if not path:
         return
     parent.app.config_store.set('paths', 'gpx',
                                 os.path.dirname(os.path.abspath(path)))
     # get user options
     config_store = QtWidgets.QApplication.instance().config_store
     dialog = QtWidgets.QDialog(parent=parent)
     dialog.setWindowTitle(self.tr('GPX options'))
     dialog.setLayout(QtWidgets.QFormLayout())
     max_interval = QtWidgets.QSpinBox()
     max_interval.setRange(60, 300)
     max_interval.setValue(
         int(config_store.get('gpx_importer', 'interval', '120')))
     max_interval.setSuffix(self.tr(' secs'))
     dialog.layout().addRow(self.tr('Max time between points'),
                            max_interval)
     max_dilution = QtWidgets.QDoubleSpinBox()
     max_dilution.setRange(1.0, 100.0)
     max_dilution.setValue(
         float(config_store.get('gpx_importer', 'dilution', '2.5')))
     max_dilution.setSingleStep(0.1)
     dialog.layout().addRow(self.tr('Max dilution of precision'),
                            max_dilution)
     if hasattr(parent.tabs.currentWidget(), 'plot_track'):
         plot_track = QtWidgets.QCheckBox()
         plot_track.setChecked(
             bool(config_store.get('gpx_importer', 'plot', 'True')))
         dialog.layout().addRow(self.tr('Plot track on map'), plot_track)
     else:
         plot_track = False
     button_box = QtWidgets.QDialogButtonBox(QtWidgets.QDialogButtonBox.Ok)
     button_box.accepted.connect(dialog.accept)
     dialog.layout().addWidget(button_box)
     dialog.exec_()
     max_interval = max_interval.value()
     max_dilution = max_dilution.value()
     config_store.set('gpx_importer', 'interval', max_interval)
     config_store.set('gpx_importer', 'dilution', max_dilution)
     if plot_track:
         plot_track = plot_track.isChecked()
         config_store.set('gpx_importer', 'plot', plot_track)
     # make a list of all points in the file
     points = []
     discards = 0
     for p in self.read_file(path):
         if p.horizontal_dilution and p.horizontal_dilution > max_dilution:
             discards += 1
             continue
         time_stamp = p.time
         if time_stamp.tzinfo is not None:
             # convert timestamp to UTC
             utc_offset = time_stamp.utcoffset()
             time_stamp = (time_stamp - utc_offset).replace(tzinfo=None)
         # add point to list
         points.append((time_stamp, p.latitude, p.longitude))
     if discards:
         logger.warning('Discarded %d low accuracy points', discards)
     if not points:
         logger.warning('No points found in file "%s"', path)
         return
     logger.warning('Using %d points', len(points))
     # sort points by timestamp
     points.sort(key=lambda x: x[0])
     # display on map
     if plot_track:
         # divide points into contiguous tracks
         tracks = []
         t = []
         for p in points:
             if t and (p[0] - t[-1][0]).total_seconds() > max_interval:
                 tracks.append(t)
                 t = []
             t.append(p)
         if t:
             tracks.append(t)
         parent.tabs.currentWidget().plot_track(tracks)
     # set image coordinates
     max_interval = max_interval / 2.0
     for image in parent.image_list.get_selected_images():
         if not image.metadata.date_taken:
             continue
         time_stamp = image.metadata.date_taken.to_utc()
         if len(points) < 2:
             lo, hi = 0, 0
         elif time_stamp < points[0][0]:
             lo, hi = 0, 1
         elif time_stamp > points[-1][0]:
             lo, hi = -2, -1
         else:
             # binary search for points with nearest timestamps
             lo, hi = 0, len(points) - 1
             while hi - lo > 1:
                 mid = (lo + hi) // 2
                 if time_stamp >= points[mid][0]:
                     lo = mid
                 elif time_stamp <= points[mid][0]:
                     hi = mid
         # use linear interpolation (or extrapolation) to set lat & long
         dt_lo = (time_stamp - points[lo][0]).total_seconds()
         dt_hi = (time_stamp - points[hi][0]).total_seconds()
         if abs(dt_lo) > max_interval and abs(dt_hi) > max_interval:
             logger.info('No point for time %s', image.metadata.date_taken)
             continue
         if dt_lo == dt_hi:
             beta = 0.5
         else:
             beta = dt_lo / (dt_lo - dt_hi)
         lat = points[lo][1] + (beta * (points[hi][1] - points[lo][1]))
         lng = points[lo][2] + (beta * (points[hi][2] - points[lo][2]))
         image.metadata.latlong = lat, lng
     parent.image_list.emit_selection()
Ejemplo n.º 13
0
 def diff_selected_metadata(self):
     dialog = QtWidgets.QDialog(parent=self)
     dialog.setLayout(QtWidgets.QVBoxLayout())
     dialog.setFixedSize(min(800,
                             self.window().width()),
                         min(400,
                             self.window().height()))
     table = QtWidgets.QTableWidget()
     table.setColumnCount(3)
     table.setHorizontalHeaderLabels([
         translate('ImageList', 'new value'),
         translate('ImageList', 'undo'),
         translate('ImageList', 'old value')
     ])
     table.horizontalHeader().setSectionResizeMode(
         0, QtWidgets.QHeaderView.Stretch)
     table.horizontalHeader().setSectionResizeMode(
         2, QtWidgets.QHeaderView.Stretch)
     dialog.layout().addWidget(table)
     button_box = QtWidgets.QDialogButtonBox(
         QtWidgets.QDialogButtonBox.Ok | QtWidgets.QDialogButtonBox.Cancel)
     button_box.accepted.connect(dialog.accept)
     button_box.rejected.connect(dialog.reject)
     dialog.layout().addWidget(button_box)
     changed = False
     position = None
     for image in self.get_selected_images():
         if not image.metadata.changed():
             continue
         dialog.setWindowTitle(
             translate('ImageList',
                       'Metadata differences: {}').format(image.name))
         labels = []
         row = 0
         undo = {}
         table.clearContents()
         new_md = image.metadata
         old_md = Metadata(image.path)
         for key in ('title', 'description', 'keywords', 'rating',
                     'copyright', 'creator', 'date_taken', 'date_digitised',
                     'date_modified', 'orientation', 'camera_model',
                     'lens_model', 'lens_spec', 'focal_length',
                     'focal_length_35', 'aperture', 'latlong', 'altitude',
                     'location_taken', 'location_shown', 'thumbnail'):
             values = getattr(new_md, key), getattr(old_md, key)
             if values[0] == values[1]:
                 continue
             values = [str(x or '') for x in values]
             table.setRowCount(row + 1)
             for n, value in enumerate(values):
                 item = QtWidgets.QTableWidgetItem(value)
                 table.setItem(row, n * 2, item)
             undo[key] = QtWidgets.QTableWidgetItem()
             undo[key].setFlags(undo[key].flags() | Qt.ItemIsUserCheckable)
             undo[key].setCheckState(Qt.Unchecked)
             table.setItem(row, 1, undo[key])
             labels.append(key)
             row += 1
         if not row:
             continue
         table.setVerticalHeaderLabels(labels)
         table.resizeColumnsToContents()
         table.resizeRowsToContents()
         if position:
             dialog.move(position)
         if dialog.exec_() != QtWidgets.QDialog.Accepted:
             return
         position = dialog.pos()
         undo_all = True
         for key, widget in undo.items():
             if widget.checkState() == Qt.Checked:
                 setattr(new_md, key, getattr(old_md, key))
                 changed = True
             else:
                 undo_all = False
         if undo_all:
             image.reload_metadata()
     if changed:
         self.emit_selection()
Ejemplo n.º 14
0
 def __init__(self, images, *arg, **kw):
     super(NewLensDialog, self).__init__(*arg, **kw)
     self.setWindowTitle(translate('TechnicalTab', 'Photini: define lens'))
     self.setLayout(QtWidgets.QVBoxLayout())
     # main dialog area
     scroll_area = QtWidgets.QScrollArea()
     scroll_area.setWidgetResizable(True)
     self.layout().addWidget(scroll_area)
     panel = QtWidgets.QWidget()
     panel.setLayout(QtWidgets.QFormLayout())
     panel.layout().setFieldGrowthPolicy(
         QtWidgets.QFormLayout.AllNonFixedFieldsGrow)
     # ok & cancel buttons
     button_box = QtWidgets.QDialogButtonBox(
         QtWidgets.QDialogButtonBox.Ok | QtWidgets.QDialogButtonBox.Cancel)
     button_box.accepted.connect(self.accept)
     button_box.rejected.connect(self.reject)
     self.layout().addWidget(button_box)
     # model
     self.lens_model = QtWidgets.QLineEdit()
     self.lens_model.setMinimumWidth(
         width_for_text(self.lens_model, 'x' * 35))
     panel.layout().addRow(translate('TechnicalTab', 'Model name'),
                           self.lens_model)
     # maker
     self.lens_make = QtWidgets.QLineEdit()
     panel.layout().addRow(translate('TechnicalTab', "Maker's name"),
                           self.lens_make)
     # serial number
     self.lens_serial = QtWidgets.QLineEdit()
     panel.layout().addRow(translate('TechnicalTab', 'Serial number'),
                           self.lens_serial)
     ## spec has four items
     self.lens_spec = {}
     # min focal length
     self.lens_spec['min_fl'] = DoubleSpinBox()
     self.lens_spec['min_fl'].setMinimum(0.0)
     self.lens_spec['min_fl'].setSingleStep(1.0)
     self.lens_spec['min_fl'].setSuffix(' mm')
     panel.layout().addRow(
         translate('TechnicalTab', 'Minimum focal length'),
         self.lens_spec['min_fl'])
     # min focal length aperture
     self.lens_spec['min_fl_fn'] = DoubleSpinBox()
     self.lens_spec['min_fl_fn'].setMinimum(0.0)
     self.lens_spec['min_fl_fn'].setPrefix('ƒ/')
     panel.layout().addRow(
         translate('TechnicalTab', 'Aperture at min. focal length'),
         self.lens_spec['min_fl_fn'])
     # max focal length
     self.lens_spec['max_fl'] = DoubleSpinBox()
     self.lens_spec['max_fl'].setMinimum(0.0)
     self.lens_spec['max_fl'].setSingleStep(1.0)
     self.lens_spec['max_fl'].setSuffix(' mm')
     panel.layout().addRow(
         translate('TechnicalTab', 'Maximum focal length'),
         self.lens_spec['max_fl'])
     # max focal length aperture
     self.lens_spec['max_fl_fn'] = DoubleSpinBox()
     self.lens_spec['max_fl_fn'].setMinimum(0.0)
     self.lens_spec['max_fl_fn'].setPrefix('ƒ/')
     panel.layout().addRow(
         translate('TechnicalTab', 'Aperture at max. focal length'),
         self.lens_spec['max_fl_fn'])
     # add panel to scroll area after its size is known
     scroll_area.setWidget(panel)
     # fill in any values we can from existing metadata
     for image in images:
         if image.metadata.lens_model:
             self.lens_model.setText(image.metadata.lens_model)
         if image.metadata.lens_make:
             self.lens_make.setText(image.metadata.lens_make)
         if image.metadata.lens_serial:
             self.lens_serial.setText(image.metadata.lens_serial)
         spec = image.metadata.lens_spec
         for key in self.lens_spec:
             if spec and spec[key]:
                 self.lens_spec[key].set_value(spec[key])
Ejemplo n.º 15
0
 def __init__(self, *arg, **kw):
     super(EditSettings, self).__init__(*arg, **kw)
     self.config_store = QtWidgets.QApplication.instance().config_store
     self.setWindowTitle(self.tr('Photini: settings'))
     self.setLayout(QtWidgets.QVBoxLayout())
     # main dialog area
     scroll_area = QtWidgets.QScrollArea()
     self.layout().addWidget(scroll_area)
     panel = QtWidgets.QWidget()
     panel.setLayout(QtWidgets.QFormLayout())
     panel.layout().setRowWrapPolicy(
         max(QtWidgets.QFormLayout.WrapLongRows,
             panel.layout().rowWrapPolicy()))
     # apply & cancel buttons
     self.button_box = QtWidgets.QDialogButtonBox(
         QtWidgets.QDialogButtonBox.Apply
         | QtWidgets.QDialogButtonBox.Cancel)
     self.button_box.clicked.connect(self.button_clicked)
     self.layout().addWidget(self.button_box)
     # copyright holder name
     self.copyright_name = SingleLineEdit(spell_check=True)
     self.copyright_name.set_value(
         self.config_store.get('user', 'copyright_name', ''))
     panel.layout().addRow(self.tr('Copyright holder name'),
                           self.copyright_name)
     # copyright text
     self.copyright_text = SingleLineEdit(spell_check=True)
     self.copyright_text.set_value(
         self.config_store.get('user', 'copyright_text', ''))
     self.copyright_text.setMinimumWidth(
         width_for_text(self.copyright_text, 'x' * 50))
     panel.layout().addRow(self.tr('Copyright text'), self.copyright_text)
     # creator name
     self.creator_name = SingleLineEdit(spell_check=True)
     self.creator_name.set_value(
         self.config_store.get('user', 'creator_name', ''))
     panel.layout().addRow(self.tr('Creator name'), self.creator_name)
     # IPTC data
     force_iptc = self.config_store.get('files', 'force_iptc', False)
     self.write_iptc = QtWidgets.QCheckBox(self.tr('Always write'))
     self.write_iptc.setChecked(force_iptc)
     panel.layout().addRow(self.tr('IPTC-IIM metadata'), self.write_iptc)
     # show IPTC-IIM length limits
     length_warning = self.config_store.get('files', 'length_warning', True)
     self.length_warning = QtWidgets.QCheckBox(
         self.tr('Show IPTC-IIM length limits'))
     self.length_warning.setChecked(length_warning)
     panel.layout().addRow('', self.length_warning)
     # sidecar files
     if_mode = self.config_store.get('files', 'image', True)
     sc_mode = self.config_store.get('files', 'sidecar', 'auto')
     if not if_mode:
         sc_mode = 'always'
     button_group = QtWidgets.QButtonGroup(parent=self)
     self.sc_always = QtWidgets.QRadioButton(self.tr('Always create'))
     button_group.addButton(self.sc_always)
     self.sc_always.setChecked(sc_mode == 'always')
     panel.layout().addRow(self.tr('Sidecar files'), self.sc_always)
     self.sc_auto = QtWidgets.QRadioButton(self.tr('Create if necessary'))
     button_group.addButton(self.sc_auto)
     self.sc_auto.setChecked(sc_mode == 'auto')
     self.sc_auto.setEnabled(if_mode)
     panel.layout().addRow('', self.sc_auto)
     self.sc_delete = QtWidgets.QRadioButton(
         self.tr('Delete when possible'))
     button_group.addButton(self.sc_delete)
     self.sc_delete.setChecked(sc_mode == 'delete')
     self.sc_delete.setEnabled(if_mode)
     panel.layout().addRow('', self.sc_delete)
     # image file locking
     self.write_if = QtWidgets.QCheckBox(self.tr('(when possible)'))
     self.write_if.setChecked(if_mode)
     self.write_if.clicked.connect(self.new_write_if)
     panel.layout().addRow(self.tr('Write to image file'), self.write_if)
     # preserve file timestamps
     keep_time = self.config_store.get('files', 'preserve_timestamps',
                                       'now')
     if isinstance(keep_time, bool):
         # old config format
         keep_time = ('now', 'keep')[keep_time]
     button_group = QtWidgets.QButtonGroup(parent=self)
     self.keep_time = QtWidgets.QRadioButton(self.tr('Keep original'))
     button_group.addButton(self.keep_time)
     self.keep_time.setChecked(keep_time == 'keep')
     panel.layout().addRow(self.tr('File timestamps'), self.keep_time)
     self.time_taken = QtWidgets.QRadioButton(
         self.tr('Set to when photo was taken'))
     button_group.addButton(self.time_taken)
     self.time_taken.setChecked(keep_time == 'taken')
     panel.layout().addRow('', self.time_taken)
     button = QtWidgets.QRadioButton(self.tr('Set to when file is saved'))
     button_group.addButton(button)
     button.setChecked(keep_time == 'now')
     panel.layout().addRow('', button)
     # add panel to scroll area after its size is known
     scroll_area.setWidget(panel)