class SelectNames(QDialog): # {{{ def __init__(self, names, txt, parent=None): QDialog.__init__(self, parent) self.l = l = QVBoxLayout(self) self.setLayout(l) self.la = la = QLabel(_('Create a Virtual library based on %s') % txt) l.addWidget(la) self.filter = f = QLineEdit(self) f.setPlaceholderText(_('Filter {}').format(txt)) f.setClearButtonEnabled(True) l.addWidget(f) self.model = QStringListModel(sorted(names, key=sort_key)) self.pmodel = QSortFilterProxyModel(self) self.pmodel.setFilterCaseSensitivity( Qt.CaseSensitivity.CaseInsensitive) f.textChanged.connect(self.pmodel.setFilterFixedString) self.pmodel.setSourceModel(self.model) self._names = QListView(self) self._names.setModel(self.pmodel) self._names.setSelectionMode( QAbstractItemView.SelectionMode.MultiSelection) l.addWidget(self._names) self._or = QRadioButton(_('Match any of the selected %s') % txt) self._and = QRadioButton(_('Match all of the selected %s') % txt) self._or.setChecked(True) l.addWidget(self._or) l.addWidget(self._and) self.bb = QDialogButtonBox(QDialogButtonBox.StandardButton.Ok | QDialogButtonBox.StandardButton.Cancel) self.bb.accepted.connect(self.accept) self.bb.rejected.connect(self.reject) l.addWidget(self.bb) self.resize(self.sizeHint()) @property def names(self): for index in self._names.selectedIndexes(): yield index.data(Qt.ItemDataRole.DisplayRole) or '' @property def match_type(self): return ' and ' if self._and.isChecked() else ' or '
def __init__(self, tts_client, initial_backend_settings=None, parent=None): QWidget.__init__(self, parent) self.l = l = QFormLayout(self) self.tts_client = tts_client with BusyCursor(): self.voice_data = self.tts_client.get_voice_data() self.default_system_rate = self.tts_client.default_system_rate self.all_sound_outputs = self.tts_client.get_sound_outputs() self.speed = s = QSlider(Qt.Orientation.Horizontal, self) s.setMinimumWidth(200) l.addRow(_('&Speed of speech (words per minute):'), s) s.setRange(self.tts_client.min_rate, self.tts_client.max_rate) s.setSingleStep(1) s.setPageStep(2) self.voices = v = QTableView(self) self.voices_model = VoicesModel(self.voice_data, parent=v) self.proxy_model = p = QSortFilterProxyModel(self) p.setFilterCaseSensitivity(Qt.CaseSensitivity.CaseInsensitive) p.setSourceModel(self.voices_model) v.setModel(p) v.setSelectionBehavior(QAbstractItemView.SelectionBehavior.SelectRows) v.setSortingEnabled(True) v.horizontalHeader().resizeSection( 0, QFontMetrics(self.font()).averageCharWidth() * 25) v.horizontalHeader().resizeSection( 1, QFontMetrics(self.font()).averageCharWidth() * 30) v.verticalHeader().close() v.verticalHeader().close() v.setSelectionMode(QAbstractItemView.SelectionMode.SingleSelection) v.sortByColumn(0, Qt.SortOrder.AscendingOrder) l.addRow(v) self.sound_outputs = so = QComboBox(self) so.addItem(_('System default'), '') for x in self.all_sound_outputs: so.addItem(x.get('description') or x['id'], x['id']) l.addRow(_('Sound output:'), so) self.backend_settings = initial_backend_settings or {}
def __init__(self, tts_client, initial_backend_settings=None, parent=None): QWidget.__init__(self, parent) self.l = l = QFormLayout(self) self.tts_client = tts_client self.speed = s = QSlider(Qt.Orientation.Horizontal, self) s.setTickPosition(QSlider.TickPosition.TicksAbove) s.setMinimumWidth(200) l.addRow(_('&Speed of speech:'), s) s.setRange(self.tts_client.min_rate, self.tts_client.max_rate) s.setSingleStep(10) s.setTickInterval((s.maximum() - s.minimum()) // 2) self.output_modules = om = QComboBox(self) with BusyCursor(): self.voice_data = self.tts_client.get_voice_data() self.system_default_output_module = self.tts_client.system_default_output_module om.addItem(_('System default'), self.system_default_output_module) for x in self.voice_data: om.addItem(x, x) l.addRow(_('Speech s&ynthesizer:'), om) self.voices = v = QTableView(self) self.voices_model = VoicesModel(self.voice_data, self.system_default_output_module, parent=v) self.proxy_model = p = QSortFilterProxyModel(self) p.setFilterCaseSensitivity(Qt.CaseSensitivity.CaseInsensitive) p.setSourceModel(self.voices_model) v.setModel(p) v.setSelectionBehavior(QAbstractItemView.SelectionBehavior.SelectRows) v.setSortingEnabled(True) h = v.horizontalHeader() h.resizeSection(0, QFontMetrics(self.font()).averageCharWidth() * 30) v.verticalHeader().close() v.setSelectionMode(QAbstractItemView.SelectionMode.SingleSelection) v.sortByColumn(0, Qt.SortOrder.AscendingOrder) om.currentIndexChanged.connect(self.output_module_changed) l.addRow(v) self.backend_settings = initial_backend_settings or {}
def __init__(self, tts_client, initial_backend_settings=None, parent=None): QWidget.__init__(self, parent) self.l = l = QFormLayout(self) self.tts_client = tts_client with BusyCursor(): self.voice_data = self.tts_client.get_voice_data() self.default_system_rate = self.tts_client.default_system_rate self.speed = s = QSlider(Qt.Orientation.Horizontal, self) s.setMinimumWidth(200) l.addRow(_('&Speed of speech (words per minute):'), s) s.setRange(self.tts_client.min_rate, self.tts_client.max_rate) s.setTickPosition(QSlider.TickPosition.TicksAbove) s.setTickInterval((s.maximum() - s.minimum()) // 2) s.setSingleStep(10) self.voices = v = QTableView(self) self.voices_model = VoicesModel(self.voice_data, parent=v) self.proxy_model = p = QSortFilterProxyModel(self) p.setFilterCaseSensitivity(Qt.CaseSensitivity.CaseInsensitive) p.setSourceModel(self.voices_model) v.setModel(p) v.setSelectionBehavior(QAbstractItemView.SelectionBehavior.SelectRows) v.setSortingEnabled(True) v.horizontalHeader().resizeSection( 0, QFontMetrics(self.font()).averageCharWidth() * 20) v.horizontalHeader().resizeSection( 1, QFontMetrics(self.font()).averageCharWidth() * 30) v.verticalHeader().close() v.setSelectionMode(QAbstractItemView.SelectionMode.SingleSelection) v.sortByColumn(0, Qt.SortOrder.AscendingOrder) l.addRow(v) self.backend_settings = initial_backend_settings or {}
def __init__(self, window, db, id_=None, key=None, current_tags=None): QDialog.__init__(self, window) Ui_TagEditor.__init__(self) self.setupUi(self) self.db = db self.sep = ',' self.is_names = False if key: # Assume that if given a key then it is a custom column try: fm = db.field_metadata[key] self.is_names = fm['display'].get('is_names', False) if self.is_names: self.sep = '&' self.setWindowTitle(self.windowTitle() + ': ' + fm['name']) except Exception: pass key = db.field_metadata.key_to_label(key) else: self.setWindowTitle(self.windowTitle() + ': ' + db.field_metadata['tags']['name']) if self.sep == '&': self.add_tag_input.setToolTip( '<p>' + _('If the item you want is not in the available list, ' 'you can add it here. Accepts an ampersand-separated ' 'list of items. The items will be applied to ' 'the book.') + '</p>') else: self.add_tag_input.setToolTip( '<p>' + _('If the item you want is not in the available list, ' 'you can add it here. Accepts a comma-separated ' 'list of items. The items will be applied to ' 'the book.') + '</p>') self.key = key self.index = db.row(id_) if id_ is not None else None if self.index is not None: if key is None: tags = self.db.tags(self.index) if tags: tags = [ tag.strip() for tag in tags.split(',') if tag.strip() ] else: tags = self.db.get_custom(self.index, label=key) else: tags = [] if current_tags is not None: tags = sorted(set(current_tags), key=sort_key) if tags: if not self.is_names: tags.sort(key=sort_key) else: tags = [] self.applied_model = QStringListModel(tags) p = QSortFilterProxyModel() p.setFilterCaseSensitivity(Qt.CaseSensitivity.CaseInsensitive) p.setSourceModel(self.applied_model) self.applied_tags.setModel(p) if self.is_names: self.applied_tags.setDragDropMode( QAbstractItemView.DragDropMode.InternalMove) self.applied_tags.setSelectionMode( QAbstractItemView.SelectionMode.ExtendedSelection) if key: all_tags = [tag for tag in self.db.all_custom(label=key)] else: all_tags = [tag for tag in self.db.all_tags()] all_tags = sorted(set(all_tags) - set(tags), key=sort_key) self.all_tags_model = QStringListModel(all_tags) p = QSortFilterProxyModel() p.setFilterCaseSensitivity(Qt.CaseSensitivity.CaseInsensitive) p.setSourceModel(self.all_tags_model) self.available_tags.setModel(p) connect_lambda(self.apply_button.clicked, self, lambda self: self.apply_tags()) connect_lambda(self.unapply_button.clicked, self, lambda self: self.unapply_tags()) self.add_tag_button.clicked.connect(self.add_tag) connect_lambda(self.delete_button.clicked, self, lambda self: self.delete_tags()) self.add_tag_input.returnPressed[()].connect(self.add_tag) # add the handlers for the filter input fields connect_lambda(self.available_filter_input.textChanged, self, lambda self, text: self.filter_tags(text)) connect_lambda( self.applied_filter_input.textChanged, self, lambda self, text: self.filter_tags(text, which='applied_tags')) # Restore the focus to the last input box used (typed into) for x in ('add_tag_input', 'available_filter_input', 'applied_filter_input'): ibox = getattr(self, x) ibox.setObjectName(x) connect_lambda( ibox.textChanged, self, lambda self: self.edit_box_changed(self.sender().objectName())) getattr(self, gprefs.get('tag_editor_last_filter', 'add_tag_input')).setFocus() self.available_tags.setEditTriggers( QAbstractItemView.EditTrigger.NoEditTriggers) self.applied_tags.setEditTriggers( QAbstractItemView.EditTrigger.NoEditTriggers) if islinux: self.available_tags.doubleClicked.connect(self.apply_tags) self.applied_tags.doubleClicked.connect(self.unapply_tags) else: self.available_tags.activated.connect(self.apply_tags) self.applied_tags.activated.connect(self.unapply_tags) geom = gprefs.get('tag_editor_geometry', None) if geom is not None: QApplication.instance().safe_restore_geometry(self, geom)
def __init__(self, parent): QSortFilterProxyModel.__init__(self, parent) self.search_filter = None
def __init__(self, parent): QSortFilterProxyModel.__init__(self, parent) self.setSortRole(Qt.ItemDataRole.UserRole) self.setSortCaseSensitivity(Qt.CaseSensitivity.CaseInsensitive) self.filter_criteria = FILTER_ALL self.filter_text = ""
def setup_ui(self): self.l = l = QGridLayout(self) self.setLayout(l) self.la1 = la = QLabel(_('&Existing images in the book')) la.setSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Fixed) l.addWidget(la, 0, 0, 1, 2) if self.for_browsing: la.setVisible(False) self.view = v = QListView(self) v.setViewMode(QListView.ViewMode.IconMode) v.setFlow(QListView.Flow.LeftToRight) v.setSpacing(4) v.setResizeMode(QListView.ResizeMode.Adjust) v.setUniformItemSizes(True) set_no_activate_on_click(v) v.activated.connect(self.activated) v.doubleClicked.connect(self.activated) self.d = ImageDelegate(v) v.setItemDelegate(self.d) self.model = Images(self.view) self.fm = fm = QSortFilterProxyModel(self.view) self.fm.setDynamicSortFilter(self.for_browsing) fm.setSourceModel(self.model) fm.setFilterCaseSensitivity(False) v.setModel(fm) l.addWidget(v, 1, 0, 1, 2) v.pressed.connect(self.pressed) la.setBuddy(v) self.filter = f = QLineEdit(self) f.setPlaceholderText(_('Search for image by file name')) l.addWidget(f, 2, 0) self.cb = b = QToolButton(self) b.setIcon(QIcon(I('clear_left.png'))) b.clicked.connect(f.clear) l.addWidget(b, 2, 1) f.textChanged.connect(self.filter_changed) if self.for_browsing: self.bb.clear() self.bb.addButton(QDialogButtonBox.StandardButton.Close) b = self.refresh_button = self.bb.addButton(_('&Refresh'), QDialogButtonBox.ButtonRole.ActionRole) b.clicked.connect(self.refresh) b.setIcon(QIcon(I('view-refresh.png'))) b.setToolTip(_('Refresh the displayed images')) self.setAttribute(Qt.WidgetAttribute.WA_DeleteOnClose, False) else: b = self.import_button = self.bb.addButton(_('&Import image'), QDialogButtonBox.ButtonRole.ActionRole) b.clicked.connect(self.import_image) b.setIcon(QIcon(I('view-image.png'))) b.setToolTip(_('Import an image from elsewhere in your computer')) b = self.paste_button = self.bb.addButton(_('&Paste image'), QDialogButtonBox.ButtonRole.ActionRole) b.clicked.connect(self.paste_image) b.setIcon(QIcon(I('edit-paste.png'))) b.setToolTip(_('Paste an image from the clipboard')) self.fullpage = f = QCheckBox(_('Full page image'), self) f.setToolTip(_('Insert the image so that it takes up an entire page when viewed in a reader')) f.setChecked(tprefs['insert_full_screen_image']) self.preserve_aspect_ratio = a = QCheckBox(_('Preserve aspect ratio')) a.setToolTip(_('Preserve the aspect ratio of the inserted image when rendering it full paged')) a.setChecked(tprefs['preserve_aspect_ratio_when_inserting_image']) f.toggled.connect(self.full_page_image_toggled) a.toggled.connect(self.par_toggled) a.setVisible(f.isChecked()) h = QHBoxLayout() l.addLayout(h, 3, 0, 1, -1) h.addWidget(f), h.addStretch(10), h.addWidget(a) b = self.bb.addButton(_('&Zoom in'), QDialogButtonBox.ButtonRole.ActionRole) b.clicked.connect(self.zoom_in) b.setIcon(QIcon(I('plus.png'))) b = self.bb.addButton(_('Zoom &out'), QDialogButtonBox.ButtonRole.ActionRole) b.clicked.connect(self.zoom_out) b.setIcon(QIcon(I('minus.png'))) l.addWidget(self.bb, 4, 0, 1, 2)