예제 #1
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()
예제 #2
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)
예제 #3
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()
예제 #4
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)
예제 #5
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)
예제 #6
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())
예제 #7
0
class AuthServer(QtCore.QObject):
    finished = QtCore.pyqtSignal()
    response = QtCore.pyqtSignal(dict)

    @QtCore.pyqtSlot()
    @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()
예제 #8
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, '')
예제 #9
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())
예제 #10
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()))
예제 #11
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)
예제 #12
0
class DateLink(QtWidgets.QCheckBox):
    new_link = QtCore.pyqtSignal(six.text_type)

    def __init__(self, name, *arg, **kw):
        super(DateLink, self).__init__(*arg, **kw)
        self.name = name
        self.clicked.connect(self._clicked)

    @QtCore.pyqtSlot()
    @catch_all
    def _clicked(self):
        self.new_link.emit(self.name)
예제 #13
0
class GoogleUploadConfig(QtWidgets.QWidget):
    new_set = QtCore.pyqtSignal()

    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 clear_sets(self):
        for child in self.sets_widget.children():
            if child.isWidgetType():
                self.sets_widget.layout().removeWidget(child)
                child.setParent(None)

    def checked_albums(self):
        result = []
        for child in self.sets_widget.children():
            if child.isWidgetType() and child.isChecked():
                result.append(child.property('id'))
        return result

    def add_album(self, album, index=-1):
        widget = QtWidgets.QCheckBox(album['title'].replace('&', '&&'))
        widget.setProperty('id', album['id'])
        widget.setEnabled(album['isWriteable'])
        if index >= 0:
            self.sets_widget.layout().insertWidget(index, widget)
        else:
            self.sets_widget.layout().addWidget(widget)
        return widget
예제 #14
0
class FileWriter(QtCore.QObject):
    output = QtCore.pyqtSignal(dict, object, six.text_type)

    @QtCore.pyqtSlot(dict, object, six.text_type)
    @catch_all
    def input(self, info, camera_file, status):
        if camera_file:
            try:
                camera_file.save(info['dest_path'])
            except gp.GPhoto2Error as ex:
                logger.error(str(ex))
                status = str(ex)
        self.output.emit(info, camera_file, status)
예제 #15
0
class UploaderSession(QtCore.QObject):
    connection_changed = QtCore.pyqtSignal(bool)

    @QtCore.pyqtSlot()
    @catch_all
    def log_out(self):
        keyring.delete_password('photini', self.name)
        self.disconnect()

    def get_password(self):
        return keyring.get_password('photini', self.name)

    def set_password(self, password):
        keyring.set_password('photini', self.name, password)
예제 #16
0
class DropdownEdit(ComboBox):
    new_value = QtCore.pyqtSignal(object)

    def __init__(self, *arg, **kw):
        super(DropdownEdit, self).__init__(*arg, **kw)
        self.addItem(self.tr('<clear>'), None)
        self.addItem('', None)
        self.setItemData(1, 0, Qt.UserRole - 1)
        self.addItem(multiple_values(), None)
        self.setItemData(2, 0, Qt.UserRole - 1)
        self.currentIndexChanged.connect(self.current_index_changed)

    @QtCore.pyqtSlot(int)
    @catch_all
    def current_index_changed(self, int):
        self.new_value.emit(self.get_value())

    def add_item(self, text, data):
        blocked = self.blockSignals(True)
        self.insertItem(self.count() - 3, text, six.text_type(data))
        self.set_dropdown_width()
        self.blockSignals(blocked)

    def remove_item(self, data):
        blocked = self.blockSignals(True)
        self.removeItem(self.findData(six.text_type(data)))
        self.set_dropdown_width()
        self.blockSignals(blocked)

    def known_value(self, value):
        if not value:
            return True
        return self.findData(six.text_type(value)) >= 0

    def set_value(self, value):
        blocked = self.blockSignals(True)
        if not value:
            self.setCurrentIndex(self.count() - 2)
        else:
            self.setCurrentIndex(self.findData(six.text_type(value)))
        self.blockSignals(blocked)

    def get_value(self):
        return self.itemData(self.currentIndex())

    def set_multiple(self):
        blocked = self.blockSignals(True)
        self.setCurrentIndex(self.count() - 1)
        self.blockSignals(blocked)
예제 #17
0
class DateAndTimeWidget(QtWidgets.QGridLayout):
    new_value = QtCore.pyqtSignal(six.text_type, dict)

    def __init__(self, name, *arg, **kw):
        super(DateAndTimeWidget, self).__init__(*arg, **kw)
        self.name = name
        self.setVerticalSpacing(0)
        self.setColumnStretch(3, 1)
        self.members = {}
        # date & time
        self.members['datetime'] = DateTimeEdit()
        self.addWidget(self.members['datetime'], 0, 0, 1, 2)
        # time zone
        self.members['tz_offset'] = TimeZoneWidget()
        self.addWidget(self.members['tz_offset'], 0, 2)
        # precision
        self.addWidget(
            QtWidgets.QLabel(translate('TechnicalTab', 'Precision:')), 1, 0)
        self.members['precision'] = Slider(Qt.Horizontal)
        self.members['precision'].setRange(1, 7)
        self.members['precision'].setPageStep(1)
        self.addWidget(self.members['precision'], 1, 1)
        # connections
        self.members['precision'].valueChanged.connect(
            self.members['datetime'].set_precision)
        self.members['datetime'].editingFinished.connect(self.editing_finished)
        self.members['tz_offset'].editingFinished.connect(
            self.editing_finished)
        self.members['precision'].editing_finished.connect(
            self.editing_finished)

    def set_enabled(self, enabled):
        for widget in self.members.values():
            widget.setEnabled(enabled)

    def get_value(self):
        new_value = {}
        for key in self.members:
            if self.members[key].is_multiple():
                continue
            new_value[key] = self.members[key].get_value()
            if key == 'datetime' and new_value[key]:
                new_value[key] = new_value[key].toPyDateTime()
        return new_value

    @QtCore.pyqtSlot()
    @catch_all
    def editing_finished(self):
        self.new_value.emit(self.name, self.get_value())
예제 #18
0
class UploadWorker(QtCore.QObject):
    upload_progress = QtCore.pyqtSignal(float)
    upload_file_done = QtCore.pyqtSignal(object, str)

    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)

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

    @QtCore.pyqtSlot(object, object)
    def upload_file(self, image, convert):
        if not self.session.permitted('write'):
            self.upload_file_done.emit(image, 'not permitted')
            return
        if convert:
            path = convert(image)
        else:
            path = image.path
        with open(path, 'rb') as f:
            self.fileobj = FileObjWithCallback(f, self.upload_progress.emit)
            error = self.session.do_upload(self.fileobj, imghdr.what(path),
                                           image, self.params)
        if convert:
            os.unlink(path)
        if self.fileobj:
            self.fileobj = None
            # upload wasn't aborted
            self.upload_file_done.emit(image, error)
예제 #19
0
class DropdownEdit(QtWidgets.QComboBox):
    new_value = QtCore.pyqtSignal()

    def __init__(self, *arg, **kw):
        super(DropdownEdit, self).__init__(*arg, **kw)
        self.addItem(self.tr('<clear>'), '<clear>')
        self.addItem('', None)
        self.setItemData(1, 0, Qt.UserRole - 1)
        self.addItem(multiple(), None)
        self.setItemData(2, 0, Qt.UserRole - 1)
        self.currentIndexChanged.connect(self._new_value)

    @QtCore.pyqtSlot(int)
    def _new_value(self, index):
        if index >= 0:
            self.new_value.emit()

    def add_item(self, text, data):
        blocked = self.blockSignals(True)
        self.insertItem(self.count() - 3, text, str(data))
        self.blockSignals(blocked)

    def remove_item(self, data):
        blocked = self.blockSignals(True)
        self.removeItem(self.findData(str(data)))
        self.blockSignals(blocked)

    def known_value(self, value):
        if not value:
            return True
        return self.findData(str(value)) >= 0

    def set_value(self, value):
        if not value:
            self.setCurrentIndex(self.count() - 2)
        else:
            self.setCurrentIndex(self.findData(str(value)))

    def get_value(self):
        return self.itemData(self.currentIndex())

    def set_multiple(self):
        self.setCurrentIndex(self.count() - 1)

    def is_multiple(self):
        return self.currentIndex() == self.count() - 1
예제 #20
0
class LatLongDisplay(SingleLineEdit):
    changed = QtCore.pyqtSignal()

    def __init__(self, image_list, *args, **kwds):
        super(LatLongDisplay, self).__init__(*args, **kwds)
        self.image_list = image_list
        self.label = QtWidgets.QLabel(translate('MapTabsAll', 'Lat, long'))
        self.label.setAlignment(Qt.AlignRight)
        self.setFixedWidth(170)
        self.setEnabled(False)
        self.editingFinished.connect(self.editing_finished)

    @QtCore.pyqtSlot()
    @catch_all
    def editing_finished(self):
        text = self.get_value().strip()
        if text:
            try:
                new_value = list(map(float, text.split(',')))
            except Exception:
                # user typed in an invalid value
                self.refresh()
                return
        else:
            new_value = None
        for image in self.image_list.get_selected_images():
            image.metadata.latlong = new_value
        self.refresh()
        self.changed.emit()

    def refresh(self):
        images = self.image_list.get_selected_images()
        if not images:
            self.set_value(None)
            self.setEnabled(False)
            return
        values = []
        for image in images:
            value = image.metadata.latlong
            if value not in values:
                values.append(value)
        if len(values) > 1:
            self.set_multiple(choices=filter(None, values))
        else:
            self.set_value(values[0])
        self.setEnabled(True)
예제 #21
0
class AuthServer(QtCore.QObject):
    response = QtCore.pyqtSignal(dict)

    def __init__(self, *args, **kwds):
        super(AuthServer, self).__init__(*args, **kwds)
        self.server = HTTPServer(('127.0.0.1', 0), RequestHandler)
        self.port = self.server.server_port
        self.server.timeout = 1
        self.server.response = self.response
        self.running = True

    @QtCore.pyqtSlot()
    @catch_all
    def start(self):
        while self.running:
            self.server.handle_request()
        self.server.server_close()
예제 #22
0
class FileReader(QtCore.QObject):
    output = QtCore.pyqtSignal(dict, object, six.text_type)

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

    @QtCore.pyqtSlot()
    @catch_all
    def start(self):
        status = 'ok'
        for info, camera_file, status in self.source.read_files(self.copy_list):
            if status != 'ok' or not self.running:
                break
            self.output.emit(info, camera_file, status)
        self.output.emit({}, None, status)
예제 #23
0
class WebView(WebViewBase):
    drop_text = QtCore.pyqtSignal(int, int, six.text_type)

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

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

    def dropEvent(self, event):
        if not event.mimeData().hasFormat(DRAG_MIMETYPE):
            return super(WebView, 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)
예제 #24
0
class LocationInfo(QtWidgets.QWidget):
    new_value = QtCore.pyqtSignal(object, dict)

    def __init__(self, *args, **kw):
        super(LocationInfo, self).__init__(*args, **kw)
        layout = QtWidgets.QGridLayout()
        self.setLayout(layout)
        layout.setContentsMargins(0, 0, 0, 0)
        self.members = {}
        for key in ('sublocation', 'city', 'province_state', 'country_name',
                    'country_code', 'world_region'):
            self.members[key] = SingleLineEdit()
            self.members[key].editingFinished.connect(self.editing_finished)
        self.members['country_code'].setMaximumWidth(40)
        for j, text in enumerate((
                translate('AddressTab', 'Street'),
                translate('AddressTab', 'City'),
                translate('AddressTab', 'Province'),
                translate('AddressTab', 'Country'),
                translate('AddressTab', 'Region'),
        )):
            label = QtWidgets.QLabel(text)
            label.setAlignment(Qt.AlignRight)
            layout.addWidget(label, j, 0)
        layout.addWidget(self.members['sublocation'], 0, 1, 1, 2)
        layout.addWidget(self.members['city'], 1, 1, 1, 2)
        layout.addWidget(self.members['province_state'], 2, 1, 1, 2)
        layout.addWidget(self.members['country_name'], 3, 1)
        layout.addWidget(self.members['country_code'], 3, 2)
        layout.addWidget(self.members['world_region'], 4, 1, 1, 2)
        layout.setRowStretch(5, 1)

    def get_value(self):
        new_value = {}
        for key in self.members:
            if self.members[key].is_multiple():
                continue
            new_value[key] = self.members[key].get_value().strip() or None
        return new_value

    @QtCore.pyqtSlot()
    @catch_all
    def editing_finished(self):
        self.new_value.emit(self, self.get_value())
예제 #25
0
class SpellCheck(QtCore.QObject):
    new_dict = QtCore.pyqtSignal()

    def __init__(self, *arg, **kw):
        super(SpellCheck, self).__init__(*arg, **kw)
        self.config_store = QtWidgets.QApplication.instance().config_store
        self.enable(eval(self.config_store.get('spelling', 'enabled', 'True')))
        self.set_dict(self.config_store.get('spelling', 'language'))

    @staticmethod
    def available_languages():
        if not enchant:
            return []
        result = enchant.list_languages()
        result.sort()
        return result

    def current_language(self):
        if self.dict:
            return self.dict.tag
        return ''

    @QtCore.pyqtSlot(bool)
    def enable(self, enabled):
        self.enabled = bool(enchant) and enabled
        self.config_store.set('spelling', 'enabled', str(self.enabled))
        self.new_dict.emit()

    @QtCore.pyqtSlot(QtWidgets.QAction)
    def set_language(self, action):
        self.set_dict(action.text().replace('&', ''))

    def set_dict(self, tag):
        if tag:
            logger.info('Setting dictionary %s', tag)
        if tag and enchant and enchant.dict_exists(tag):
            self.dict = enchant.Dict(tag)
        else:
            if tag:
                logger.warning('Failed to set dictionary %s', tag)
            self.dict = None
        self.config_store.set('spelling', 'language', self.current_language())
        self.new_dict.emit()
예제 #26
0
class ScrollArea(QtWidgets.QScrollArea):
    dropped_images = QtCore.pyqtSignal(list)

    def __init__(self, parent=None):
        super(ScrollArea, self).__init__(parent)
        self.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOn)
        self.setWidgetResizable(True)
        self.setAcceptDrops(True)

    def dropEvent(self, event):
        file_list = []
        for uri in event.mimeData().urls():
            file_list.append(uri.toLocalFile())
        if file_list:
            self.dropped_images.emit(file_list)

    def dragEnterEvent(self, event):
        if event.mimeData().hasFormat('text/uri-list'):
            event.acceptProposedAction()
예제 #27
0
class NameMangler(QtCore.QObject):
    number_parser = re.compile('(\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)
    @catch_all
    def new_format(self, format_string):
        self.format_string = format_string
        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}
        numbers = self.number_parser.findall(name)
        if numbers:
            subst['number'] = numbers[-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(' ', '_')
        # process {...} parts first
        try:
            result = self.format_string.format(**subst)
        except (KeyError, ValueError):
            result = self.format_string
        # then do timestamp
        return file_data['timestamp'].strftime(result)
예제 #28
0
class FileCopier(QtCore.QObject):
    output = QtCore.pyqtSignal(dict, six.text_type)

    def __init__(self, source, copy_list, move, *args, **kwds):
        super(FileCopier, self).__init__(*args, **kwds)
        self.source = source
        self.copy_list = copy_list
        self.move = move
        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):
                self.output.emit(info, status)
                if not self.running:
                    break
        except Exception as ex:
            status = str(ex)
            logger.error(status)
        self.output.emit({}, status)
예제 #29
0
class OffsetWidget(QtWidgets.QWidget):
    apply_offset = QtCore.pyqtSignal(timedelta)

    def __init__(self, *arg, **kw):
        super(OffsetWidget, self).__init__(*arg, **kw)
        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)
        # 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)

    @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)

    @QtCore.pyqtSlot()
    def sub(self):
        value = self.offset.time()
        offset = timedelta(hours=value.hour(),
                           minutes=value.minute(),
                           seconds=value.second())
        self.apply_offset.emit(-offset)
예제 #30
0
파일: spelling.py 프로젝트: aseques/Photini
class SpellCheck(QtCore.QObject):
    new_dict = QtCore.pyqtSignal()

    def __init__(self, *arg, **kw):
        super(SpellCheck, self).__init__(*arg, **kw)
        self.config_store = QtWidgets.QApplication.instance().config_store
        self.enable(eval(self.config_store.get('spelling', 'enabled', 'True')))
        self.set_language(self.config_store.get('spelling', 'language'))

    @staticmethod
    def available_languages():
        result = []
        if Gspell:
            for lang in Gspell.Language.get_available():
                result.append((lang.get_name(), lang.get_code()))
        elif enchant:
            languages = enchant.list_languages()
            languages.sort()
            for lang in languages:
                result.append((lang, lang))
        else:
            return None
        return result

    def current_language(self):
        if not self.dict:
            return ''
        if Gspell:
            language = self.dict.get_language()
            if language:
                return language.get_code()
        elif enchant:
            return self.dict.tag
        return ''

    @QtCore.pyqtSlot(bool)
    @catch_all
    def enable(self, enabled):
        self.enabled = enabled and bool(Gspell or enchant)
        self.config_store.set('spelling', 'enabled', str(self.enabled))
        self.new_dict.emit()

    def set_language(self, code):
        if code:
            logger.debug('Setting dictionary %s', code)
        self.dict = None
        if Gspell:
            if code:
                self.dict = Gspell.Checker.new(Gspell.Language.lookup(code))
        elif enchant:
            if code and enchant.dict_exists(code):
                self.dict = enchant.Dict(code)
        if code and not self.dict:
            logger.warning('Failed to set dictionary %s', code)
        self.config_store.set('spelling', 'language', self.current_language())
        self.new_dict.emit()

    words = re.compile(r"\w+([-'’]\w+)*", flags=re.IGNORECASE | re.UNICODE)

    def find_words(self, text):
        for word in self.words.finditer(text):
            yield word.group(), word.start(), word.end()

    def check(self, word):
        if not (word and self.enabled and self.dict):
            return True
        if Gspell:
            return self.dict.check_word(word, -1)
        if enchant:
            return self.dict.check(word)
        return True

    def suggest(self, word):
        if self.check(word):
            return []
        if Gspell:
            return GSListPtr_to_list(self.dict.get_suggestions(word, -1))
        if enchant:
            return self.dict.suggest(word)
        return []