示例#1
0
 def minimumSize(self):
     size = QtCore.QSize()
     for item in self.item_list:
         size = size.expandedTo(item.minimumSize())
     left, top, right, bottom = self.getContentsMargins()
     size += QtCore.QSize(left + right, top + bottom)
     return size
示例#2
0
 def _do_layout(self, origin):
     left, top, right, bottom = self.getContentsMargins()
     width_hint = left + right
     height_hint = top + bottom
     if self.item_list:
         item_size = self.item_list[0].sizeHint()
         item_h = item_size.height()
         item_w = item_size.width()
         multi_row = self.viewport_size.height() - height_hint > item_h
         if multi_row:
             columns = max(
                 (self.viewport_size.width() - width_hint) // item_w, 1)
             rows = (len(self.item_list) + columns - 1) // columns
         else:
             columns = len(self.item_list)
             rows = 1
         width_hint += columns * item_w
         height_hint += rows * item_h
     self.size_hint = QtCore.QSize(width_hint, height_hint)
     if not self.item_list:
         return
     x = origin.x() + left
     y = origin.y() + top
     for n, item in enumerate(self.item_list):
         i, j = n % columns, n // columns
         item.setGeometry(
             QtCore.QRect(QtCore.QPoint(x + (i * item_w), y + (j * item_h)),
                          item_size))
     self.scroll_area.set_multi_row(multi_row)
示例#3
0
 def convert(value):
     if value['data'] and not value['image']:
         buf = QtCore.QBuffer()
         buf.setData(value['data'])
         reader = QtGui.QImageReader(buf)
         reader.setAutoTransform(False)
         value['fmt'] = reader.format().data().decode().upper()
         value['image'] = reader.read()
         if value['image'].isNull():
             logger.error('thumbnail: %s', reader.errorString())
             value['image'] = None
         # don't keep reference to what might be an entire image file
         value['data'] = None
     if value['image'] and not value['data']:
         buf = QtCore.QBuffer()
         buf.open(buf.WriteOnly)
         value['fmt'] = 'JPEG'
         value['image'].save(buf, value['fmt'])
         value['data'] = buf.data().data()
     if value['image']:
         value['w'] = value['image'].width()
         value['h'] = value['image'].height()
     else:
         value['w'] = 0
         value['h'] = 0
     return value
示例#4
0
def main(argv=None):
    if argv:
        sys.argv = argv
    # let PyQt handle its options (need at least one argument after options)
    sys.argv.append('xxx')
    app = QtWidgets.QApplication(sys.argv)
    del sys.argv[-1]
    # install translation
    if qt_version_info < (5, 0):
        QtCore.QTextCodec.setCodecForTr(
            QtCore.QTextCodec.codecForName('utf-8'))
    locale = QtCore.QLocale.system()
    translator = QtCore.QTranslator(parent=app)
    translator.load(locale, 'photini', '.',
                    pkg_resources.resource_filename('photini', 'data/lang'),
                    '.qm')
    app.installTranslator(translator)
    qt_translator = QtCore.QTranslator(parent=app)
    qt_translator.load(
        locale, 'qt', '_',
        QtCore.QLibraryInfo.location(QtCore.QLibraryInfo.TranslationsPath))
    app.installTranslator(qt_translator)
    # parse remaining arguments
    version = 'Photini ' + __version__ + ', build ' + build
    version += '\n  Python ' + sys.version
    version += '\n  ' + gexiv2_version
    version += '\n  PyQt {}, Qt {}'.format(QtCore.PYQT_VERSION_STR,
                                           QtCore.QT_VERSION_STR)
    if QtWebEngineWidgets:
        version += ', using QtWebEngineWidgets'
    if enchant_version:
        version += '\n  ' + enchant_version
    if FlickrUploader:
        from photini.flickr import flickr_version
        version += '\n  ' + flickr_version
    parser = OptionParser(usage=six.text_type(
        QtCore.QCoreApplication.translate(
            'main', 'Usage: %prog [options] [file_name, ...]')),
                          version=version,
                          description=six.text_type(
                              QtCore.QCoreApplication.translate(
                                  'main', 'Photini photo metadata editor')))
    parser.add_option('-t',
                      '--test',
                      action='store_true',
                      help=six.text_type(
                          QtCore.QCoreApplication.translate(
                              'main', 'test new features or API versions')))
    parser.add_option('-v',
                      '--verbose',
                      action='count',
                      default=0,
                      help=six.text_type(
                          QtCore.QCoreApplication.translate(
                              'main', 'increase number of logging messages')))
    options, args = parser.parse_args()
    # create GUI and run application event loop
    main = MainWindow(options, args)
    main.show()
    return app.exec_()
示例#5
0
 def mouseMoveEvent(self, event):
     if not self.image_list.drag_icon:
         return
     if qt_version_info >= (6, 0):
         pos = event.position()
     else:
         pos = event.pos()
     if ((pos - self.drag_start_pos).manhattanLength() <
             QtWidgets.QApplication.startDragDistance()):
         return
     if not self.get_selected():
         # user has started dragging an unselected image
         self.image_list.select_image(self)
     paths = []
     for image in self.image_list.get_selected_images():
         paths.append(image.path)
     if not paths:
         return
     drag = QtGui.QDrag(self)
     # construct icon
     count = min(len(paths), 8)
     src_icon = self.image_list.drag_icon
     src_w = src_icon.width()
     src_h = src_icon.height()
     margin = (count - 1) * 4
     if count == 1:
         icon = src_icon
     else:
         icon = QtGui.QPixmap(src_w + margin, src_h + margin)
         icon.fill(Qt.transparent)
         try:
             paint = QtGui.QPainter(icon)
             for i in range(count):
                 paint.drawPixmap(QtCore.QPoint(margin - (i * 4), i * 4),
                                  src_icon)
         finally:
             del paint
     drag.setPixmap(icon)
     if self.image_list.drag_hotspot:
         x, y = self.image_list.drag_hotspot
     else:
         x, y = src_w // 2, src_h
     drag.setHotSpot(QtCore.QPoint(x, y + margin))
     mimeData = QtCore.QMimeData()
     mimeData.setData(DRAG_MIMETYPE, repr(paths).encode('utf-8'))
     drag.setMimeData(mimeData)
     if qt_version_info >= (6, 0):
         drag.exec(Qt.CopyAction)
     else:
         drag.exec_(Qt.CopyAction)
示例#6
0
class StreamProxy(QtCore.QObject):
    # only the GUI thread is allowed to write messages in the
    # LoggerWindow, so this class acts as a proxy, passing messages
    # over Qt signal/slot for thread safety
    flush_text = QtCore.pyqtSignal()
    write_text = QtCore.pyqtSignal(str)

    def write(self, msg):
        msg = msg.strip()
        if msg:
            self.write_text.emit(msg)

    def flush(self):
        self.flush_text.emit()
示例#7
0
 def __init__(self, *arg, **kw):
     self.default_value = QtCore.QDateTime(
         QtCore.QDate.currentDate(), QtCore.QTime())
     self.multiple = multiple_values()
     # rename some methods for compatibility with AugmentSpinBox
     self.minimum = self.minimumDateTime
     self.setValue = self.setDateTime
     self.textFromValue = self.textFromDateTime
     self.value = self.dateTime
     super(DateTimeEdit, self).__init__(*arg, **kw)
     self.init_augment()
     self.setCalendarPopup(True)
     self.setCalendarWidget(CalendarWidget())
     self.precision = 1
     self.set_precision(7)
def main(argv=None):
    root = os.path.dirname(os.path.dirname(os.path.realpath(__file__)))
    lang_dir = os.path.join(root, 'src', 'photini', 'data', 'lang')
    translator = QtCore.QTranslator()
    cmd = []
    for name in os.listdir(lang_dir):
        lang = name.split('.')[1]
        if lang == 'en':
            continue
        if not translator.load('photini.' + lang, lang_dir):
            print('load failed:', lang)
            continue
        text = translator.translate('MenuBar', 'Photini photo metadata editor')
        if text:
            cmd += ['--set-key=GenericName[{}]'.format(lang),
                    '--set-value={}'.format(text.strip())]
        text = translator.translate('MenuBar',
                                    'An easy to use digital photograph metadata'
                                    ' (Exif, IPTC, XMP) editing application.')
        if text:
            cmd += ['--set-key=Comment[{}]'.format(lang),
                    '--set-value={}'.format(text.strip())]
    if not cmd:
        return 0
    desktop_file = os.path.join(
        root, 'src', 'photini', 'data', 'linux', 'photini.desktop')
    cmd = ['desktop-file-edit'] + cmd + [desktop_file]
    return subprocess.call(cmd)
示例#9
0
 def __init__(self, *args, **kwds):
     super(GeocoderBase, self).__init__(*args, **kwds)
     self.app = QtWidgets.QApplication.instance()
     self.block_timer = QtCore.QTimer(self)
     self.block_timer.setInterval(self.interval)
     self.block_timer.setSingleShot(True)
     self.query_cache = OrderedDict()
示例#10
0
 def start_upload(self):
     if not self.image_list.unsaved_files_dialog(with_discard=False):
         return
     # make list of items to upload
     upload_list = []
     for image in self.image_list.get_selected_images():
         params = self.get_upload_params(image)
         if not params:
             continue
         convert = self.get_conversion_function(image, params)
         if convert == 'omit':
             continue
         upload_list.append((image, convert, params))
     if not upload_list:
         self.upload_button.setChecked(False)
         return
     self.upload_button.set_checked(True)
     self.upload_config.setEnabled(False)
     self.user_connect.setEnabled(False)
     # do uploading in separate thread, so GUI can continue
     self.upload_worker = UploadWorker(self.session_factory, upload_list)
     thread = QtCore.QThread(self)
     self.upload_worker.moveToThread(thread)
     self.upload_worker.upload_error.connect(
         self.upload_error, Qt.BlockingQueuedConnection)
     self.abort_upload.connect(
         self.upload_worker.abort_upload, Qt.DirectConnection)
     self.upload_worker.upload_progress.connect(self.upload_progress)
     thread.started.connect(self.upload_worker.start)
     self.upload_worker.finished.connect(self.uploader_finished)
     self.upload_worker.finished.connect(thread.quit)
     self.upload_worker.finished.connect(self.upload_worker.deleteLater)
     thread.finished.connect(thread.deleteLater)
     thread.start()
示例#11
0
class NumberEdit(QtWidgets.QLineEdit):
    new_value = QtCore.pyqtSignal(six.text_type)

    def __init__(self, *arg, **kw):
        super(NumberEdit, self).__init__(*arg, **kw)
        self.multiple = multiple_values()
        self.textEdited.connect(self.text_edited)
        self.editingFinished.connect(self.editing_finished)

    @QtCore.pyqtSlot(six.text_type)
    @catch_all
    def text_edited(self, text):
        self.setPlaceholderText('')

    @QtCore.pyqtSlot()
    @catch_all
    def editing_finished(self):
        if self.placeholderText() != self.multiple:
            self.new_value.emit(self.text())

    def set_value(self, value):
        self.setPlaceholderText('')
        if value:
            self.setText(str(value))
        else:
            self.clear()

    def set_multiple(self):
        self.setPlaceholderText(self.multiple)
        self.clear()
示例#12
0
文件: importer.py 项目: jcl78/Photini
 def copy_selected(self, move=False):
     copy_list = []
     for item in self.file_list_widget.selectedItems():
         name = item.data(Qt.UserRole)
         info = self.file_data[name]
         if (move and 'path' in info
                 and self.image_list.get_image(info['path'])):
             # don't rename an open file
             logger.warning('Please close image %s before moving it',
                            info['name'])
         else:
             copy_list.append(info)
     if not copy_list:
         return
     if move:
         self.move_button.set_checked(True)
         self.copy_button.setEnabled(False)
     else:
         self.copy_button.set_checked(True)
         self.move_button.setEnabled(False)
     self.last_file_copied = None, datetime.min
     # start file copier in a separate thread
     self.file_copier = FileCopier(self.source, copy_list, move,
                                   self.updating)
     self.file_copier_thread = QtCore.QThread(self)
     self.file_copier.moveToThread(self.file_copier_thread)
     self.file_copier.output.connect(self.file_copied)
     self.file_copier_thread.started.connect(self.file_copier.start)
     self.file_copier_thread.start()
示例#13
0
文件: importer.py 项目: jcl78/Photini
class FileCopier(QtCore.QObject):
    output = QtCore.pyqtSignal(dict, six.text_type)

    def __init__(self, source, copy_list, move, updating, *args, **kwds):
        super(FileCopier, self).__init__(*args, **kwds)
        self.source = source
        self.copy_list = copy_list
        self.move = move
        self.updating = updating
        self.running = True

    @QtCore.pyqtSlot()
    @catch_all
    def start(self):
        status = 'ok'
        try:
            for info in self.source.copy_files(self.copy_list, self.move):
                # don't display image until previous one has been displayed
                self.updating.lock()
                self.output.emit(info, status)
                self.updating.unlock()
                if not self.running:
                    break
        except Exception as ex:
            status = str(ex)
            logger.error(status)
        self.output.emit({}, status)
示例#14
0
 def __init__(self, *arg, **kw):
     super(OpenStreetMap, self).__init__(*arg, **kw)
     self.block_timer = QtCore.QTimer(self)
     self.block_timer.setInterval(10000)
     self.block_timer.setSingleShot(True)
     self.block_timer.timeout.connect(self.enable_search)
     self.api_key = key_store.get('opencagedata', 'api_key')
示例#15
0
class MapWebView(QWebView):
    drop_text = QtCore.pyqtSignal(int, int, six.text_type)

    def __init__(self, call_handler, *args, **kwds):
        super(MapWebView, self).__init__(*args, **kwds)
        # set view's page
        if using_qtwebengine:
            self.setPage(MapWebEnginePage(call_handler, parent=self))
            self.settings().setAttribute(
                QWebSettings.Accelerated2dCanvasEnabled, False)
        else:
            self.setPage(MapWebKitPage(call_handler, parent=self))
        self.settings().setAttribute(
            QWebSettings.LocalContentCanAccessRemoteUrls, True)
        self.settings().setAttribute(
            QWebSettings.LocalContentCanAccessFileUrls, True)

    @catch_all
    def dragEnterEvent(self, event):
        if not event.mimeData().hasFormat(DRAG_MIMETYPE):
            return super(MapWebView, self).dragEnterEvent(event)
        event.acceptProposedAction()

    @catch_all
    def dragMoveEvent(self, event):
        if not event.mimeData().hasFormat(DRAG_MIMETYPE):
            return super(MapWebView, self).dragMoveEvent(event)

    @catch_all
    def dropEvent(self, event):
        if not event.mimeData().hasFormat(DRAG_MIMETYPE):
            return super(MapWebView, self).dropEvent(event)
        text = event.mimeData().data(DRAG_MIMETYPE).data().decode('utf-8')
        if text:
            self.drop_text.emit(event.pos().x(), event.pos().y(), text)
示例#16
0
 def start_upload(self):
     if not self.image_list.unsaved_files_dialog(with_discard=False):
         return
     # make list of items to upload
     self.upload_list = []
     for image in self.image_list.get_selected_images():
         params = self.get_upload_params(image)
         if not params:
             continue
         convert = self.get_conversion_function(image, params)
         if convert == 'omit':
             continue
         self.upload_list.append((image, convert, params))
     if not self.upload_list:
         self.upload_button.setChecked(False)
         return
     self.upload_button.set_checked(True)
     # start uploading in separate thread, so GUI can continue
     self.upload_worker = UploadWorker(self.session_factory)
     self.upload_worker_thread = QtCore.QThread(self)
     self.upload_worker.moveToThread(self.upload_worker_thread)
     self.upload_file.connect(self.upload_worker.upload_file)
     self.upload_worker.upload_progress.connect(
         self.total_progress.setValue)
     self.upload_worker.upload_file_done.connect(self.upload_file_done)
     self.upload_worker_thread.started.connect(self.upload_worker.start)
     self.upload_worker_thread.start()
     self.upload_config.setEnabled(False)
     self.user_connect.setEnabled(False)
     self.uploads_done = 0
     self.next_upload()
示例#17
0
 def available_languages():
     result = defaultdict(list)
     if Gspell:
         for lang in Gspell.Language.get_available():
             code = lang.get_code()
             name = lang.get_name()
             match = re.match('(.+)\s+\((.+?)\)', name)
             if match:
                 language = match.group(1)
                 country = match.group(2)
                 if country == 'any':
                     country = ''
             else:
                 language = name
                 country = ''
             result[language].append((country, code))
     elif enchant:
         for code in enchant.list_languages():
             locale = QtCore.QLocale(code)
             language = locale.languageToString(locale.language())
             if '_' in code and '_ANY' not in code:
                 country = locale.countryToString(locale.country())
             else:
                 country = ''
             result[language].append((country, code))
     else:
         return None
     for value in result.values():
         value.sort()
     return dict(result) or None
示例#18
0
 def __init__(self, *arg, **kw):
     super(OffsetWidget, self).__init__(*arg, **kw)
     self.config_store = QtWidgets.QApplication.instance().config_store
     self.setLayout(QtWidgets.QHBoxLayout())
     self.layout().setContentsMargins(0, 0, 0, 0)
     # offset value
     self.offset = QtWidgets.QTimeEdit()
     self.offset.setDisplayFormat("'h:'hh 'm:'mm 's:'ss")
     self.layout().addWidget(self.offset)
     # time zone
     self.time_zone = TimeZoneWidget()
     self.time_zone.set_value(None)
     self.layout().addWidget(self.time_zone)
     # add offset button
     add_button = SquareButton('+')
     add_button.clicked.connect(self.add)
     self.layout().addWidget(add_button)
     # subtract offset button
     sub_button = SquareButton('-')
     sub_button.clicked.connect(self.sub)
     self.layout().addWidget(sub_button)
     self.layout().addStretch(1)
     # restore stored values
     value = eval(self.config_store.get('technical', 'offset', 'None'))
     if value:
         self.offset.setTime(QtCore.QTime(*value[0:3]))
         self.time_zone.set_value(value[3])
     # connections
     self.offset.editingFinished.connect(self.new_value)
     self.time_zone.editingFinished.connect(self.new_value)
示例#19
0
文件: editor.py 项目: dirten/Photini
 def __init__(self, name, *arg, **kw):
     super(ConfigStore, self).__init__(name, *arg, **kw)
     QtCore.QCoreApplication.instance().aboutToQuit.connect(self.save)
     self.timer = QtCore.QTimer(self)
     self.timer.setSingleShot(True)
     self.timer.setInterval(3000)
     self.timer.timeout.connect(self.save)
示例#20
0
 def __init__(self, session_factory, params):
     super(UploadWorker, self).__init__()
     self.session = session_factory(auto_refresh=False)
     self.params = params
     self.fileobj = None
     self.thread = QtCore.QThread(self)
     self.moveToThread(self.thread)
示例#21
0
class OffsetWidget(QtWidgets.QWidget):
    apply_offset = QtCore.pyqtSignal(timedelta, object)

    def __init__(self, *arg, **kw):
        super(OffsetWidget, self).__init__(*arg, **kw)
        self.config_store = QtWidgets.QApplication.instance().config_store
        self.setLayout(QtWidgets.QHBoxLayout())
        self.layout().setContentsMargins(0, 0, 0, 0)
        # offset value
        self.offset = QtWidgets.QTimeEdit()
        self.offset.setDisplayFormat("'h:'hh 'm:'mm 's:'ss")
        self.layout().addWidget(self.offset)
        # time zone
        self.time_zone = TimeZoneWidget()
        self.time_zone.set_value(None)
        self.layout().addWidget(self.time_zone)
        # add offset button
        add_button = SquareButton('+')
        add_button.clicked.connect(self.add)
        self.layout().addWidget(add_button)
        # subtract offset button
        sub_button = SquareButton('-')
        sub_button.clicked.connect(self.sub)
        self.layout().addWidget(sub_button)
        self.layout().addStretch(1)
        # restore stored values
        value = eval(self.config_store.get('technical', 'offset', 'None'))
        if value:
            self.offset.setTime(QtCore.QTime(*value[0:3]))
            self.time_zone.set_value(value[3])
        # connections
        self.offset.editingFinished.connect(self.new_value)
        self.time_zone.editingFinished.connect(self.new_value)

    @QtCore.pyqtSlot()
    def new_value(self):
        value = self.offset.time()
        value = (value.hour(), value.minute(), value.second(),
                 self.time_zone.get_value())
        self.config_store.set('technical', 'offset', str(value))

    @QtCore.pyqtSlot()
    def add(self):
        value = self.offset.time()
        offset = timedelta(hours=value.hour(),
                           minutes=value.minute(),
                           seconds=value.second())
        self.apply_offset.emit(offset, self.time_zone.get_value())

    @QtCore.pyqtSlot()
    def sub(self):
        value = self.offset.time()
        offset = timedelta(hours=value.hour(),
                           minutes=value.minute(),
                           seconds=value.second())
        tz_offset = self.time_zone.get_value()
        if isinstance(tz_offset, int):
            tz_offset = -tz_offset
        self.apply_offset.emit(-offset, tz_offset)
示例#22
0
 def _do_layout(self, rect, test_only):
     left, top, right, bottom = self.getContentsMargins()
     effective_rect = rect.adjusted(left, top, -right, -bottom)
     x = effective_rect.x()
     y = effective_rect.y()
     row_height = 0
     for item in self.item_list:
         item_size = item.sizeHint()
         if x + item_size.width() > effective_rect.right() and row_height > 0:
             x = effective_rect.x()
             y += row_height
             row_height = 0
         if not test_only:
             item.setGeometry(QtCore.QRect(QtCore.QPoint(x, y), item_size))
         x += item_size.width()
         row_height = max(row_height, item_size.height())
     return y + row_height - rect.y() + bottom
示例#23
0
class MultiLineEdit(QtWidgets.QPlainTextEdit):
    editingFinished = QtCore.pyqtSignal()

    def __init__(self, spell_check=False, *arg, **kw):
        super(MultiLineEdit, self).__init__(*arg, **kw)
        self.multiple_values = multiple_values()
        self.setTabChangesFocus(True)
        self._is_multiple = False
        if spell_check:
            self.spell_check = SpellingHighlighter(self.document())
        else:
            self.spell_check = None

    def focusOutEvent(self, event):
        self.editingFinished.emit()
        super(MultiLineEdit, self).focusOutEvent(event)

    def contextMenuEvent(self, event):
        menu = self.createStandardContextMenu()
        suggestion_group = QtWidgets.QActionGroup(menu)
        if self.spell_check:
            cursor = self.cursorForPosition(event.pos())
            cursor.select(QtGui.QTextCursor.WordUnderCursor)
            word = cursor.selectedText()
            suggestions = self.spell_check.suggestions(word)
            if suggestions:
                sep = menu.insertSeparator(menu.actions()[0])
                for suggestion in suggestions:
                    action = QtWidgets.QAction(suggestion, suggestion_group)
                    menu.insertAction(sep, action)
        action = menu.exec_(event.globalPos())
        if action and action.actionGroup() == suggestion_group:
            cursor = self.cursorForPosition(event.pos())
            cursor.select(QtGui.QTextCursor.WordUnderCursor)
            cursor.insertText(action.text())

    def set_value(self, value):
        self._is_multiple = False
        if not value:
            self.clear()
            if qt_version_info >= (5, 3):
                self.setPlaceholderText('')
        else:
            self.setPlainText(six.text_type(value))

    def get_value(self):
        return self.toPlainText()

    def set_multiple(self):
        self._is_multiple = True
        if qt_version_info >= (5, 3):
            self.setPlaceholderText(self.multiple_values)
            self.clear()
        else:
            self.setPlainText(self.multiple_values)

    def is_multiple(self):
        return self._is_multiple and not bool(self.get_value())
示例#24
0
class AuthServer(QtCore.QObject):
    finished = QtCore.Signal()
    response = QtCore.Signal(dict)

    @QtCore.Slot()
    @catch_all
    def handle_requests(self):
        self.server.timeout = 10
        self.server.result = None
        # allow user 5 minutes to finish the process
        timeout = time.time() + 300
        while time.time() < timeout:
            self.server.handle_request()
            if self.server.result:
                self.response.emit(self.server.result)
                break
        self.server.server_close()
        self.finished.emit()
示例#25
0
 def authorise(self):
     with Busy():
         # do full authentication procedure
         if self.auth_server:
             self.auth_server.running = False
             self.auth_server_thread.quit()
         self.auth_server = AuthServer()
         self.auth_server_thread = QtCore.QThread(self)
         self.auth_server.moveToThread(self.auth_server_thread)
         self.auth_server.response.connect(self.auth_response)
         self.auth_server_thread.started.connect(self.auth_server.start)
         self.auth_server_thread.start()
         redirect_uri = 'http://127.0.0.1:' + str(self.auth_server.port)
         auth_url = self.session.get_auth_url(redirect_uri)
         if not QtGui.QDesktopServices.openUrl(QtCore.QUrl(auth_url)):
             logger.error('Failed to open web browser')
             self.auth_server.running = False
             self.auth_server = None
             self.auth_server_thread.quit()
示例#26
0
class UploadWorker(QtCore.QObject):
    upload_progress = QtCore.pyqtSignal(float)
    upload_file_done = QtCore.pyqtSignal(object, six.text_type)

    def __init__(self, session_factory, *args, **kwds):
        super(UploadWorker, self).__init__(*args, **kwds)
        self.session_factory = session_factory
        self.session = None
        self.fileobj = None

    @QtCore.pyqtSlot()
    @catch_all
    def start(self):
        self.session = self.session_factory()
        self.session.connect()

    def abort_upload(self):
        if self.fileobj:
            self.fileobj.close()
            self.fileobj = None

    @QtCore.pyqtSlot(object, object, object)
    @catch_all
    def upload_file(self, image, convert, params):
        if convert:
            path = convert(image)
        else:
            path = image.path
        with open(path, 'rb') as f:
            self.fileobj = FileObjWithCallback(f, self.upload_progress.emit)
            try:
                error = self.session.do_upload(self.fileobj, imghdr.what(path),
                                               image, params)
            except Exception as ex:
                error = str(ex)
        if convert:
            os.unlink(path)
        if self.fileobj:
            self.fileobj = None
            self.upload_file_done.emit(image, error)
        else:
            # upload was aborted
            self.upload_file_done.emit(None, '')
示例#27
0
class LocationWidgets(QtCore.QObject):
    new_value = QtCore.pyqtSignal(str, str)

    def __init__(self, *args, **kw):
        super(LocationWidgets, self).__init__(*args, **kw)
        self.members = {
            'sublocation': SingleLineEdit(),
            'city': SingleLineEdit(),
            'province_state': SingleLineEdit(),
            'country_name': SingleLineEdit(),
            'country_code': SingleLineEdit(),
            'world_region': SingleLineEdit(),
        }
        self.members['sublocation'].editingFinished.connect(
            self.new_sublocation)
        self.members['city'].editingFinished.connect(self.new_city)
        self.members['province_state'].editingFinished.connect(
            self.new_province_state)
        self.members['country_name'].editingFinished.connect(
            self.new_country_name)
        self.members['country_code'].editingFinished.connect(
            self.new_country_code)
        self.members['world_region'].editingFinished.connect(
            self.new_world_region)
        self.members['country_code'].setMaximumWidth(40)

    def __getitem__(self, key):
        return self.members[key]

    @QtCore.pyqtSlot()
    def new_sublocation(self):
        self.send_value('sublocation')

    @QtCore.pyqtSlot()
    def new_city(self):
        self.send_value('city')

    @QtCore.pyqtSlot()
    def new_province_state(self):
        self.send_value('province_state')

    @QtCore.pyqtSlot()
    def new_country_name(self):
        self.send_value('country_name')

    @QtCore.pyqtSlot()
    def new_country_code(self):
        self.send_value('country_code')

    @QtCore.pyqtSlot()
    def new_world_region(self):
        self.send_value('world_region')

    def send_value(self, key):
        self.new_value.emit(key, self.members[key].get_value())
示例#28
0
class NameMangler(QtCore.QObject):
    number_parser = re.compile('\D*(\d+)')
    new_example = QtCore.pyqtSignal(str)

    def __init__(self, parent=None):
        super(NameMangler, self).__init__(parent)
        self.example = None
        self.format_string = None

    @QtCore.pyqtSlot(str)
    def new_format(self, format_string):
        self.format_string = format_string
        # extract bracket delimited words from string
        self.parts = []
        while format_string:
            parts = format_string.split('(', 1)
            if len(parts) > 1:
                parts[1:] = parts[1].split(')', 1)
            if len(parts) < 3:
                self.parts.append((format_string, ''))
                break
            self.parts.append((parts[0], parts[1]))
            format_string = parts[2]
        self.refresh_example()

    def set_example(self, example):
        self.example = example
        self.refresh_example()

    def refresh_example(self):
        if self.format_string and self.example:
            self.new_example.emit(self.transform(self.example))

    def transform(self, file_data):
        name = file_data['name']
        subst = {'name': name}
        match = self.number_parser.match(name)
        if match:
            subst['number'] = match.group(1)
        else:
            subst['number'] = ''
        subst['root'], subst['ext'] = os.path.splitext(name)
        subst['camera'] = file_data['camera'] or 'unknown_camera'
        subst['camera'] = subst['camera'].replace(' ', '_')
        result = ''
        # process (...) parts first
        for left, right in self.parts:
            result += left
            if right in subst:
                result += subst[right]
            else:
                result += right
        # then do timestamp
        return file_data['timestamp'].strftime(result)
示例#29
0
 def resizeEvent(self, event):
     super(ScrollArea, self).resizeEvent(event)
     width = event.size().width()
     height = event.size().height()
     if not self.multi_row:
         scrollbar = self.verticalScrollBar()
         width -= scrollbar.width()
     scrollbar = self.horizontalScrollBar()
     if not scrollbar.isVisible():
         height -= scrollbar.height()
     self.thumbs.set_viewport_size(QtCore.QSize(width, height))
示例#30
0
class DateAndTimeWidget(QtWidgets.QGridLayout):
    new_value = QtCore.pyqtSignal(object)

    def __init__(self, *arg, **kw):
        super(DateAndTimeWidget, self).__init__(*arg, **kw)
        self.setContentsMargins(0, 0, 0, 0)
        self.setColumnStretch(3, 1)
        # date & time
        self.datetime = DateTimeEdit()
        self.datetime.setCalendarPopup(True)
        self.addWidget(self.datetime, 0, 0, 1, 2)
        # time zone
        self.time_zone = TimeZoneWidget()
        self.addWidget(self.time_zone, 0, 2)
        # precision
        self.addWidget(QtWidgets.QLabel(self.tr('Precision:')), 1, 0)
        self.precision = Slider(Qt.Horizontal)
        self.precision.setRange(0, 7)
        self.precision.setPageStep(1)
        self.addWidget(self.precision, 1, 1)
        # connections
        self.datetime.editingFinished.connect(self.new_datetime)
        self.time_zone.editingFinished.connect(self.new_time_zone)
        self.precision.valueChanged.connect(self.datetime.set_precision)
        self.precision.editing_finished.connect(self.new_precision)

    def get_value(self):
        return (self.datetime.get_value(), self.precision.value(),
                self.time_zone.get_value())

    def set_value(self, date_time, precision, tz_offset):
        blocked = self.precision.blockSignals(True)
        self.precision.setValue(precision)
        self.precision.blockSignals(blocked)
        self.datetime.set_precision(precision)
        self.datetime.set_value(date_time)
        self.time_zone.set_value(tz_offset)

    def set_enabled(self, enabled):
        self.datetime.setEnabled(enabled)
        self.time_zone.setEnabled(enabled)
        self.precision.setEnabled(enabled)

    @QtCore.pyqtSlot()
    def new_precision(self):
        self.new_value.emit((MULTI, self.precision.value(), MULTI))

    @QtCore.pyqtSlot()
    def new_datetime(self):
        self.new_value.emit(self.get_value())

    @QtCore.pyqtSlot()
    def new_time_zone(self):
        self.new_value.emit((MULTI, MULTI, self.time_zone.get_value()))