def __init__(self, *arg, **kw): super(FlickrUploadConfig, self).__init__(*arg, **kw) self.setLayout(QtWidgets.QGridLayout()) self.layout().setContentsMargins(0, 0, 0, 0) # privacy settings self.privacy = {} privacy_group = QtWidgets.QGroupBox(self.tr('Who can see the photos?')) privacy_group.setLayout(QtWidgets.QVBoxLayout()) self.privacy['private'] = QtWidgets.QRadioButton(self.tr('Only you')) privacy_group.layout().addWidget(self.privacy['private']) ff_group = QtWidgets.QGroupBox() ff_group.setFlat(True) ff_group.setLayout(QtWidgets.QVBoxLayout()) ff_group.layout().setContentsMargins(10, 0, 0, 0) self.privacy['friends'] = QtWidgets.QCheckBox(self.tr('Your friends')) ff_group.layout().addWidget(self.privacy['friends']) self.privacy['family'] = QtWidgets.QCheckBox(self.tr('Your family')) ff_group.layout().addWidget(self.privacy['family']) privacy_group.layout().addWidget(ff_group) self.privacy['public'] = QtWidgets.QRadioButton(self.tr('Anyone')) self.privacy['public'].toggled.connect(self.enable_ff) self.privacy['public'].setChecked(True) privacy_group.layout().addWidget(self.privacy['public']) self.hidden = QtWidgets.QCheckBox(self.tr('Hidden from search')) privacy_group.layout().addWidget(self.hidden) privacy_group.layout().addStretch(1) self.layout().addWidget(privacy_group, 0, 0, 2, 1) # content type self.content_type = {} content_group = QtWidgets.QGroupBox(self.tr('Content type')) content_group.setLayout(QtWidgets.QVBoxLayout()) self.content_type['photo'] = QtWidgets.QRadioButton(self.tr('Photo')) self.content_type['photo'].setChecked(True) content_group.layout().addWidget(self.content_type['photo']) self.content_type['screenshot'] = QtWidgets.QRadioButton(self.tr('Screenshot')) content_group.layout().addWidget(self.content_type['screenshot']) self.content_type['other'] = QtWidgets.QRadioButton(self.tr('Art/Illustration')) content_group.layout().addWidget(self.content_type['other']) content_group.layout().addStretch(1) self.layout().addWidget(content_group, 0, 1) # create new set new_set_button = QtWidgets.QPushButton(self.tr('New album')) new_set_button.clicked.connect(self.new_set) self.layout().addWidget(new_set_button, 1, 1) # list of sets widget sets_group = QtWidgets.QGroupBox(self.tr('Add to albums')) sets_group.setLayout(QtWidgets.QVBoxLayout()) scrollarea = QtWidgets.QScrollArea() scrollarea.setFrameStyle(QtWidgets.QFrame.NoFrame) scrollarea.setStyleSheet("QScrollArea { background-color: transparent }") self.sets_widget = QtWidgets.QWidget() self.sets_widget.setLayout(QtWidgets.QVBoxLayout()) self.sets_widget.layout().setSpacing(0) self.sets_widget.layout().setSizeConstraint( QtWidgets.QLayout.SetMinAndMaxSize) scrollarea.setWidget(self.sets_widget) self.sets_widget.setAutoFillBackground(False) sets_group.layout().addWidget(scrollarea) self.layout().addWidget(sets_group, 0, 2, 2, 1) self.layout().setColumnStretch(2, 1)
def __init__(self, *arg, **kw): super(GoogleUploadConfig, self).__init__(*arg, **kw) self.setLayout(QtWidgets.QGridLayout()) self.layout().setContentsMargins(0, 0, 0, 0) # create new set new_set_button = QtWidgets.QPushButton( translate('GooglePhotosTab', 'New album')) new_set_button.clicked.connect(self.new_set) self.layout().addWidget(new_set_button, 2, 1) # list of sets widget sets_group = QtWidgets.QGroupBox( translate('GooglePhotosTab', 'Add to albums')) sets_group.setLayout(QtWidgets.QVBoxLayout()) scrollarea = QtWidgets.QScrollArea() scrollarea.setFrameStyle(QtWidgets.QFrame.NoFrame) scrollarea.setStyleSheet( "QScrollArea { background-color: transparent }") self.sets_widget = QtWidgets.QWidget() self.sets_widget.setLayout(QtWidgets.QVBoxLayout()) self.sets_widget.layout().setSpacing(0) self.sets_widget.layout().setSizeConstraint( QtWidgets.QLayout.SetMinAndMaxSize) scrollarea.setWidget(self.sets_widget) self.sets_widget.setAutoFillBackground(False) sets_group.layout().addWidget(scrollarea) self.layout().addWidget(sets_group, 0, 2, 3, 1) self.layout().setColumnStretch(2, 1)
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
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)
def __init__(self, image_list, *arg, **kw): super(TabWidget, self).__init__(*arg, **kw) self.config_store = QtWidgets.QApplication.instance().config_store self.image_list = image_list self.setLayout(QtWidgets.QHBoxLayout()) self.layout().setContentsMargins(0, 0, 0, 0) # construct widgets self.enableable = [] ## data fields form, self.widgets = self.data_form() self.enableable.append(form.widget()) for key in self.widgets: self.widgets[key].editingFinished.connect( getattr(self, 'new_' + key)) self.layout().addWidget(form) ## buttons buttons = QtWidgets.QVBoxLayout() buttons.addStretch(1) edit_template = QtWidgets.QPushButton( translate('OwnerTab', 'Edit\ntemplate')) edit_template.clicked.connect(self.edit_template) buttons.addWidget(edit_template) apply_template = QtWidgets.QPushButton( translate('OwnerTab', 'Apply\ntemplate')) apply_template.clicked.connect(self.apply_template) self.enableable.append(apply_template) buttons.addWidget(apply_template) self.layout().addLayout(buttons) # disable data entry until an image is selected self.set_enabled(False)
def show_terms(self): # return widget to display map terms and conditions layout = QtWidgets.QVBoxLayout() widget = QtWidgets.QPushButton(self.tr('Terms of Use')) widget.clicked.connect(self.load_tou) widget.setStyleSheet('QPushButton { font-size: 10px }') layout.addWidget(widget) return layout
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)
def initialize_finished(self): self.map_loaded = True self.layout().removeWidget(self.load_map) self.load_map.setParent(None) show_terms = QtWidgets.QVBoxLayout() for widget in self.show_terms(): widget.setStyleSheet('QPushButton, QLabel { font-size: 10px }') show_terms.addWidget(widget) self.layout().addLayout(show_terms, 7, 0) self.edit_box.setEnabled(True) self.map.setAcceptDrops(True) self.image_list_changed() self.image_list.set_drag_to_map(self.drag_icon)
def __init__(self, upload_config_widget, image_list, *arg, **kw): super(PhotiniUploader, self).__init__(*arg, **kw) self.app = QtWidgets.QApplication.instance() self.app.aboutToQuit.connect(self.shutdown) logger.debug('using %s', keyring.get_keyring().__module__) self.image_list = image_list self.setLayout(QtWidgets.QGridLayout()) self.session = self.session_factory() self.session.connection_changed.connect(self.connection_changed) self.upload_worker = None # user details self.user = {} user_group = QtWidgets.QGroupBox(translate('UploaderTabsAll', 'User')) user_group.setLayout(QtWidgets.QVBoxLayout()) self.user_photo = QtWidgets.QLabel() self.user_photo.setAlignment(Qt.AlignHCenter | Qt.AlignTop) user_group.layout().addWidget(self.user_photo) self.user_name = QtWidgets.QLabel() self.user_name.setWordWrap(True) self.user_name.setFixedWidth(80) user_group.layout().addWidget(self.user_name) user_group.layout().addStretch(1) self.layout().addWidget(user_group, 0, 0, 1, 2) # connect / disconnect button self.user_connect = StartStopButton( translate('UploaderTabsAll', 'Log in'), translate('UploaderTabsAll', 'Log out')) self.user_connect.click_start.connect(self.log_in) self.user_connect.click_stop.connect(self.session.log_out) self.layout().addWidget(self.user_connect, 1, 0, 1, 2) # 'service' specific widget self.layout().addWidget(upload_config_widget, 0, 2, 2, 2) # upload button self.upload_button = StartStopButton( translate('UploaderTabsAll', 'Start upload'), translate('UploaderTabsAll', 'Stop upload')) self.upload_button.setEnabled(False) self.upload_button.click_start.connect(self.start_upload) self.upload_button.click_stop.connect(self.stop_upload) self.layout().addWidget(self.upload_button, 2, 3) # progress bar self.layout().addWidget( QtWidgets.QLabel(translate('UploaderTabsAll', 'Progress')), 2, 0) self.total_progress = QtWidgets.QProgressBar() self.layout().addWidget(self.total_progress, 2, 1, 1, 2) # adjust spacing self.layout().setColumnStretch(2, 1) self.layout().setRowStretch(0, 1) # initialise as not connected self.connection_changed(False)
def __init__(self, upload_config_widget, image_list, *arg, **kw): super(PhotiniUploader, self).__init__(*arg, **kw) QtWidgets.QApplication.instance().aboutToQuit.connect(self.shutdown) self.logger = logging.getLogger(self.__class__.__name__) self.image_list = image_list self.setLayout(QtWidgets.QGridLayout()) self.session = self.session_factory() self.upload_worker = None self.connected = False # user details self.user = {} user_group = QtWidgets.QGroupBox(self.tr('User')) user_group.setLayout(QtWidgets.QVBoxLayout()) self.user_photo = QtWidgets.QLabel() self.user_photo.setAlignment(Qt.AlignHCenter | Qt.AlignTop) user_group.layout().addWidget(self.user_photo) self.user_name = QtWidgets.QLabel() self.user_name.setWordWrap(True) self.user_name.setFixedWidth(80) user_group.layout().addWidget(self.user_name) user_group.layout().addStretch(1) self.layout().addWidget(user_group, 0, 0, 1, 2) # connect / disconnect button self.user_connect = QtWidgets.QPushButton() self.user_connect.setCheckable(True) self.user_connect.clicked.connect(self.connect_user) self.layout().addWidget(self.user_connect, 1, 0, 1, 2) # 'service' specific widget self.layout().addWidget(upload_config_widget, 0, 2, 2, 2) # upload button self.upload_button = StartStopButton(self.tr('Start upload'), self.tr('Stop upload')) self.upload_button.setEnabled(False) self.upload_button.click_start.connect(self.start_upload) self.upload_button.click_stop.connect(self.stop_upload) self.layout().addWidget(self.upload_button, 2, 3) # progress bar self.layout().addWidget(QtWidgets.QLabel(self.tr('Progress')), 2, 0) self.total_progress = QtWidgets.QProgressBar() self.layout().addWidget(self.total_progress, 2, 1, 1, 2) # adjust spacing self.layout().setColumnStretch(2, 1) self.layout().setRowStretch(0, 1)
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)
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)
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)
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()
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])))
def __init__(self, image_list, parent=None): super(TabWidget, self).__init__(parent) app = QtWidgets.QApplication.instance() app.aboutToQuit.connect(self.shutdown) if gp and app.test_mode: self.gp_log = gp.check_result(gp.use_python_logging()) self.config_store = app.config_store self.image_list = image_list self.setLayout(QtWidgets.QGridLayout()) form = QtWidgets.QFormLayout() form.setFieldGrowthPolicy(QtWidgets.QFormLayout.AllNonFixedFieldsGrow) self.nm = NameMangler() self.file_data = {} self.file_list = [] self.source = None self.file_reader = None self.file_writer = None # source selector box = QtWidgets.QHBoxLayout() box.setContentsMargins(0, 0, 0, 0) self.source_selector = QtWidgets.QComboBox() self.source_selector.currentIndexChanged.connect(self.new_source) box.addWidget(self.source_selector) refresh_button = QtWidgets.QPushButton(self.tr('refresh')) refresh_button.clicked.connect(self.refresh) box.addWidget(refresh_button) box.setStretch(0, 1) form.addRow(self.tr('Source'), box) # path format self.path_format = QtWidgets.QLineEdit() self.path_format.setValidator(PathFormatValidator()) self.path_format.textChanged.connect(self.nm.new_format) self.path_format.editingFinished.connect(self.path_format_finished) form.addRow(self.tr('Target format'), self.path_format) # path example self.path_example = QtWidgets.QLabel() self.nm.new_example.connect(self.path_example.setText) form.addRow('=>', self.path_example) self.layout().addLayout(form, 0, 0) # file list self.file_list_widget = QtWidgets.QListWidget() self.file_list_widget.setSelectionMode( QtWidgets.QAbstractItemView.ExtendedSelection) self.file_list_widget.itemSelectionChanged.connect(self.selection_changed) self.layout().addWidget(self.file_list_widget, 1, 0) # selection buttons buttons = QtWidgets.QVBoxLayout() buttons.addStretch(1) self.selected_count = QtWidgets.QLabel() self.selection_changed() buttons.addWidget(self.selected_count) select_all = QtWidgets.QPushButton(self.tr('Select\nall')) select_all.clicked.connect(self.select_all) buttons.addWidget(select_all) select_new = QtWidgets.QPushButton(self.tr('Select\nnew')) select_new.clicked.connect(self.select_new) buttons.addWidget(select_new) self.copy_button = StartStopButton(self.tr('Copy\nphotos'), self.tr('Stop\nimport')) self.copy_button.click_start.connect(self.copy_selected) self.copy_button.click_stop.connect(self.stop_copy) buttons.addWidget(self.copy_button) self.layout().addLayout(buttons, 0, 1, 2, 1) # final initialisation self.image_list.sort_order_changed.connect(self.sort_file_list) path = os.path.expanduser('~/Pictures') if not os.path.isdir(path) and sys.platform == 'win32': try: import win32com.shell as ws path = ws.shell.SHGetFolderPath( 0, ws.shellcon.CSIDL_MYPICTURES, None, 0) except ImportError: pass self.path_format.setText( os.path.join(path, '%Y', '%Y_%m_%d', '{name}')) self.refresh() self.list_files()
def __init__(self, image_list, *arg, **kw): super(TabWidget, self).__init__(*arg, **kw) self.config_store = QtWidgets.QApplication.instance().config_store self.image_list = image_list self.form = QtWidgets.QFormLayout() self.setLayout(QtWidgets.QVBoxLayout()) self.layout().addLayout(self.form) self.layout().addStretch(1) # construct widgets self.widgets = {} # title self.widgets['title'] = SingleLineEdit( spell_check=True, length_check=ImageMetadata.max_bytes('title')) self.widgets['title'].setToolTip( translate( 'DescriptiveTab', 'Enter a short verbal and human readable name' ' for the image, this may be the file name.')) self.widgets['title'].editingFinished.connect(self.new_title) self.form.addRow(translate('DescriptiveTab', 'Title / Object Name'), self.widgets['title']) # description self.widgets['description'] = MultiLineEdit( spell_check=True, length_check=ImageMetadata.max_bytes('description')) self.widgets['description'].setToolTip( translate( 'DescriptiveTab', 'Enter a "caption" describing the who, what,' ' and why of what is happening in this image,\nthis might include' ' names of people, and/or their role in the action that is taking' ' place within the image.')) self.widgets['description'].editingFinished.connect( self.new_description) self.form.addRow(translate('DescriptiveTab', 'Description / Caption'), self.widgets['description']) # keywords self.widgets['keywords'] = KeywordsEditor( spell_check=True, length_check=ImageMetadata.max_bytes('keywords'), multi_string=True) self.widgets['keywords'].setToolTip( translate( 'DescriptiveTab', 'Enter any number of keywords, terms or phrases' ' used to express the subject matter in the image.' '\nSeparate them with ";" characters.')) self.widgets['keywords'].editingFinished.connect(self.new_keywords) self.form.addRow(translate('DescriptiveTab', 'Keywords'), self.widgets['keywords']) self.image_list.image_list_changed.connect(self.image_list_changed) # rating self.widgets['rating'] = RatingWidget() self.widgets['rating'].editing_finished.connect(self.new_rating) self.form.addRow(translate('DescriptiveTab', 'Rating'), self.widgets['rating']) # copyright self.widgets['copyright'] = LineEditWithAuto( length_check=ImageMetadata.max_bytes('copyright')) self.widgets['copyright'].setToolTip( translate( 'OwnerTab', 'Enter a notice on the current owner of the' ' copyright for this image, such as "©2008 Jane Doe".')) self.widgets['copyright'].editingFinished.connect(self.new_copyright) self.widgets['copyright'].autoComplete.connect(self.auto_copyright) self.form.addRow(translate('DescriptiveTab', 'Copyright'), self.widgets['copyright']) # creator self.widgets['creator'] = LineEditWithAuto( length_check=ImageMetadata.max_bytes('creator'), multi_string=True) self.widgets['creator'].setToolTip( translate('OwnerTab', 'Enter the name of the person that created this image.')) self.widgets['creator'].editingFinished.connect(self.new_creator) self.widgets['creator'].autoComplete.connect(self.auto_creator) self.form.addRow(translate('DescriptiveTab', 'Creator / Artist'), self.widgets['creator']) # disable until an image is selected self.setEnabled(False)
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)
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()
def __init__(self, *arg, **kw): super(FacebookUploadConfig, self).__init__(*arg, **kw) self.setLayout(QtWidgets.QHBoxLayout()) self.layout().setContentsMargins(0, 0, 0, 0) self.widgets = {} ## upload config config_group = QtWidgets.QGroupBox(self.tr('Options')) config_group.setLayout(QtWidgets.QFormLayout()) self.layout().addWidget(config_group) # suppress feed story self.widgets['no_story'] = QtWidgets.QCheckBox() config_group.layout().addRow(self.tr('Suppress news feed story'), self.widgets['no_story']) label = config_group.layout().labelForField(self.widgets['no_story']) label.setWordWrap(True) label.setFixedWidth(90) # geotagging self.widgets['geo_tag'] = QtWidgets.QCheckBox() config_group.layout().addRow( self.tr('Set "city" from map coordinates'), self.widgets['geo_tag']) self.widgets['geo_tag'].setChecked(True) label = config_group.layout().labelForField(self.widgets['geo_tag']) label.setWordWrap(True) label.setFixedWidth(90) # optimise self.widgets['optimise'] = QtWidgets.QCheckBox() config_group.layout().addRow(self.tr('Optimise image size'), self.widgets['optimise']) label = config_group.layout().labelForField(self.widgets['optimise']) label.setWordWrap(True) label.setFixedWidth(90) if PIL: self.widgets['optimise'].setChecked(True) else: self.widgets['optimise'].setEnabled(False) label.setEnabled(False) ## album details album_group = QtWidgets.QGroupBox(self.tr('Album')) album_group.setLayout(QtWidgets.QHBoxLayout()) # left hand side album_form_left = QtWidgets.QFormLayout() album_form_left.setFieldGrowthPolicy( QtWidgets.QFormLayout.AllNonFixedFieldsGrow) album_group.layout().addLayout(album_form_left) # album title / selector self.widgets['album_choose'] = QtWidgets.QComboBox() self.widgets['album_choose'].activated.connect(self.select_album) album_form_left.addRow(self.tr('Title'), self.widgets['album_choose']) # album description self.widgets['album_description'] = QtWidgets.QPlainTextEdit() self.widgets['album_description'].setReadOnly(True) policy = self.widgets['album_description'].sizePolicy() policy.setVerticalStretch(1) self.widgets['album_description'].setSizePolicy(policy) album_form_left.addRow(self.tr('Description'), self.widgets['album_description']) # album location self.widgets['album_location'] = QtWidgets.QLineEdit() self.widgets['album_location'].setReadOnly(True) album_form_left.addRow(self.tr('Location'), self.widgets['album_location']) # right hand side album_form_right = QtWidgets.QVBoxLayout() album_group.layout().addLayout(album_form_right) # album thumbnail self.widgets['album_thumb'] = QtWidgets.QLabel() self.widgets['album_thumb'].setFixedSize(150, 150) self.widgets['album_thumb'].setAlignment(Qt.AlignHCenter | Qt.AlignTop) album_form_right.addWidget(self.widgets['album_thumb']) album_form_right.addStretch(1) # new album new_album_button = QtWidgets.QPushButton(self.tr('New album')) new_album_button.clicked.connect(self.new_album) album_form_right.addWidget(new_album_button) self.layout().addWidget(album_group, stretch=1)
def __init__(self, image_list, parent=None): super(TabWidget, self).__init__(parent) app = QtWidgets.QApplication.instance() app.aboutToQuit.connect(self.shutdown) if gp and app.test_mode: self.gp_log = gp.check_result(gp.use_python_logging()) self.config_store = app.config_store self.image_list = image_list self.setLayout(QtWidgets.QGridLayout()) form = QtWidgets.QFormLayout() form.setFieldGrowthPolicy(QtWidgets.QFormLayout.AllNonFixedFieldsGrow) self.nm = NameMangler() self.file_data = {} self.file_list = [] self.source = None self.file_copier = None # source selector box = QtWidgets.QHBoxLayout() box.setContentsMargins(0, 0, 0, 0) self.source_selector = QtWidgets.QComboBox() self.source_selector.currentIndexChanged.connect(self.new_source) box.addWidget(self.source_selector) refresh_button = QtWidgets.QPushButton(self.tr('refresh')) refresh_button.clicked.connect(self.refresh) box.addWidget(refresh_button) box.setStretch(0, 1) form.addRow(self.tr('Source'), box) # path format self.path_format = QtWidgets.QLineEdit() self.path_format.setValidator(PathFormatValidator()) self.path_format.textChanged.connect(self.nm.new_format) self.path_format.editingFinished.connect(self.path_format_finished) form.addRow(self.tr('Target format'), self.path_format) # path example self.path_example = QtWidgets.QLabel() self.nm.new_example.connect(self.path_example.setText) form.addRow('=>', self.path_example) self.layout().addLayout(form, 0, 0) # file list self.file_list_widget = QtWidgets.QListWidget() self.file_list_widget.setSelectionMode( QtWidgets.QAbstractItemView.ExtendedSelection) self.file_list_widget.itemSelectionChanged.connect( self.selection_changed) self.layout().addWidget(self.file_list_widget, 1, 0) # selection buttons buttons = QtWidgets.QVBoxLayout() buttons.addStretch(1) self.selected_count = QtWidgets.QLabel() buttons.addWidget(self.selected_count) select_all = QtWidgets.QPushButton(self.tr('Select\nall')) select_all.clicked.connect(self.select_all) buttons.addWidget(select_all) select_new = QtWidgets.QPushButton(self.tr('Select\nnew')) select_new.clicked.connect(self.select_new) buttons.addWidget(select_new) # copy buttons self.move_button = StartStopButton(self.tr('Move\nphotos'), self.tr('Stop\nmove')) self.move_button.click_start.connect(self.move_selected) self.move_button.click_stop.connect(self.stop_copy) buttons.addWidget(self.move_button) self.copy_button = StartStopButton(self.tr('Copy\nphotos'), self.tr('Stop\ncopy')) self.copy_button.click_start.connect(self.copy_selected) self.copy_button.click_stop.connect(self.stop_copy) buttons.addWidget(self.copy_button) self.layout().addLayout(buttons, 0, 1, 2, 1) self.selection_changed() # final initialisation self.image_list.sort_order_changed.connect(self.sort_file_list) if qt_version_info >= (5, 0): path = QtCore.QStandardPaths.writableLocation( QtCore.QStandardPaths.PicturesLocation) else: path = QtGui.QDesktopServices.storageLocation( QtGui.QDesktopServices.PicturesLocation) self.path_format.setText(os.path.join(path, '%Y', '%Y_%m_%d', '{name}')) self.refresh() self.list_files()
def __init__(self, image_list, parent=None): super(TabWidget, self).__init__(parent) self.app = QtWidgets.QApplication.instance() self.app.aboutToQuit.connect(self.stop_copy) if gp and self.app.options.test: self.gp_log = gp.check_result(gp.use_python_logging()) self.config_store = self.app.config_store self.image_list = image_list self.setLayout(QtWidgets.QGridLayout()) form = QtWidgets.QFormLayout() form.setFieldGrowthPolicy(QtWidgets.QFormLayout.AllNonFixedFieldsGrow) self.nm = NameMangler() self.file_data = {} self.file_list = [] self.source = None self.file_copier = None self.updating = QtCore.QMutex() # source selector box = QtWidgets.QHBoxLayout() box.setContentsMargins(0, 0, 0, 0) self.source_selector = QtWidgets.QComboBox() self.source_selector.currentIndexChanged.connect(self.new_source) self.source_selector.setContextMenuPolicy(Qt.CustomContextMenu) self.source_selector.customContextMenuRequested.connect( self.remove_folder) box.addWidget(self.source_selector) refresh_button = QtWidgets.QPushButton( translate('ImporterTab', 'refresh')) refresh_button.clicked.connect(self.refresh) box.addWidget(refresh_button) box.setStretch(0, 1) form.addRow(translate('ImporterTab', 'Source'), box) # update config self.config_store.delete('importer', 'folders') for section in self.config_store.config.sections(): if not section.startswith('importer'): continue path_format = self.config_store.get(section, 'path_format') if not (path_format and '(' in path_format): continue path_format = path_format.replace('(', '{').replace(')', '}') self.config_store.set(section, 'path_format', path_format) # path format self.path_format = QtWidgets.QLineEdit() self.path_format.setValidator(PathFormatValidator()) self.path_format.textChanged.connect(self.nm.new_format) self.path_format.editingFinished.connect(self.path_format_finished) form.addRow(translate('ImporterTab', 'Target format'), self.path_format) # path example self.path_example = QtWidgets.QLabel() self.nm.new_example.connect(self.path_example.setText) form.addRow('=>', self.path_example) self.layout().addLayout(form, 0, 0) # file list self.file_list_widget = QtWidgets.QListWidget() self.file_list_widget.setSelectionMode( QtWidgets.QAbstractItemView.ExtendedSelection) self.file_list_widget.itemSelectionChanged.connect( self.selection_changed) self.layout().addWidget(self.file_list_widget, 1, 0) # selection buttons buttons = QtWidgets.QVBoxLayout() buttons.addStretch(1) self.selected_count = QtWidgets.QLabel() buttons.addWidget(self.selected_count) select_all = QtWidgets.QPushButton( translate('ImporterTab', 'Select\nall')) select_all.clicked.connect(self.select_all) buttons.addWidget(select_all) select_new = QtWidgets.QPushButton( translate('ImporterTab', 'Select\nnew')) select_new.clicked.connect(self.select_new) buttons.addWidget(select_new) # copy buttons self.move_button = StartStopButton( translate('ImporterTab', 'Move\nphotos'), translate('ImporterTab', 'Stop\nmove')) self.move_button.click_start.connect(self.move_selected) self.move_button.click_stop.connect(self.stop_copy) buttons.addWidget(self.move_button) self.copy_button = StartStopButton( translate('ImporterTab', 'Copy\nphotos'), translate('ImporterTab', 'Stop\ncopy')) self.copy_button.click_start.connect(self.copy_selected) self.copy_button.click_stop.connect(self.stop_copy) buttons.addWidget(self.copy_button) self.layout().addLayout(buttons, 0, 1, 2, 1) self.selection_changed() # final initialisation self.image_list.sort_order_changed.connect(self.sort_file_list) path = QtCore.QStandardPaths.writableLocation( QtCore.QStandardPaths.PicturesLocation) self.path_format.setText(os.path.join(path, '%Y', '%Y_%m_%d', '{name}'))
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)
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])