def __init__(self, horizontal=False, size=48, parent=None): QFrame.__init__(self, parent) if horizontal: size = 24 self.pi = ProgressIndicator(self, size) self._jobs = QLabel('<b>'+_('Jobs:')+' 0') self._jobs.mouseReleaseEvent = self.mouseReleaseEvent self.shortcut = 'Shift+Alt+J' if horizontal: self.setLayout(QHBoxLayout()) self.layout().setDirection(self.layout().RightToLeft) else: self.setLayout(QVBoxLayout()) self._jobs.setAlignment(Qt.AlignHCenter|Qt.AlignBottom) self.layout().addWidget(self.pi) self.layout().addWidget(self._jobs) if not horizontal: self.layout().setAlignment(self._jobs, Qt.AlignHCenter) self._jobs.setMargin(0) self.layout().setContentsMargins(0, 0, 0, 0) self._jobs.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Minimum) self.setCursor(Qt.PointingHandCursor) b = _('Click to see list of jobs') self.setToolTip(b + u' (%s)'%self.shortcut) self.action_toggle = QAction(b, parent) parent.addAction(self.action_toggle) self.action_toggle.setShortcut(self.shortcut) self.action_toggle.triggered.connect(self.toggle)
def _intialize_file_settings(self, layout): '''Initialize file creation/sending settings''' separator_a = QFrame() separator_a.setFrameStyle(QFrame.HLine) separator_a.setFrameShadow(QFrame.Sunken) layout.addWidget(separator_a) files_to_create = QGroupBox() files_to_create.setTitle('Files to create/send') files_to_create.setLayout(QGridLayout(files_to_create)) self._settings['create_send_xray'] = QCheckBox('X-Ray') self._settings['create_send_xray'].setChecked(__prefs__['create_send_xray']) files_to_create.layout().addWidget(self._settings['create_send_xray'], 0, 0) self._settings['create_send_author_profile'] = QCheckBox('Author Profile') self._settings['create_send_author_profile'].setChecked(__prefs__['create_send_author_profile']) files_to_create.layout().addWidget(self._settings['create_send_author_profile'], 1, 0) self._settings['create_send_start_actions'] = QCheckBox('Start Actions') self._settings['create_send_start_actions'].setChecked(__prefs__['create_send_start_actions']) files_to_create.layout().addWidget(self._settings['create_send_start_actions'], 0, 1) self._settings['create_send_end_actions'] = QCheckBox('End Actions') self._settings['create_send_end_actions'].setChecked(__prefs__['create_send_end_actions']) files_to_create.layout().addWidget(self._settings['create_send_end_actions'], 1, 1) layout.addWidget(files_to_create)
def _initialize_file_type_settings(self, layout): '''Initialize file creation/sending type settings''' separator_b = QFrame() separator_b.setFrameStyle(QFrame.HLine) separator_b.setFrameShadow(QFrame.Sunken) layout.addWidget(separator_b) book_types_to_create = QGroupBox() book_types_to_create.setTitle('Book types to create files for:') book_types_to_create.setLayout(QHBoxLayout(book_types_to_create)) self._settings['mobi'] = QCheckBox('MOBI') self._settings['mobi'].setChecked('mobi' in __prefs__['formats']) book_types_to_create.layout().addWidget(self._settings['mobi']) self._settings['azw3'] = QCheckBox('AZW3') self._settings['azw3'].setChecked('azw3' in __prefs__['formats']) book_types_to_create.layout().addWidget(self._settings['azw3']) layout.addWidget(book_types_to_create) file_preference_layout = QGroupBox() file_preference_layout.setTitle('If device has both (mobi and azw3) formats, prefer:') file_preference_layout.setLayout(QHBoxLayout(file_preference_layout)) file_preference_group = QButtonGroup() self._settings['file_preference_mobi'] = QRadioButton('MOBI') self._settings['file_preference_mobi'].setChecked(__prefs__['file_preference'] == 'mobi') file_preference_group.addButton(self._settings['file_preference_mobi']) file_preference_layout.layout().addWidget(self._settings['file_preference_mobi']) self._settings['file_preference_azw3'] = QRadioButton('AZW3') self._settings['file_preference_azw3'].setChecked(__prefs__['file_preference'] == 'azw3') file_preference_group.addButton(self._settings['file_preference_azw3']) file_preference_layout.layout().addWidget(self._settings['file_preference_azw3']) layout.addWidget(file_preference_layout)
def ui(self): """ Method build ui """ grid = QGridLayout(self) self.setLayout(grid) self.userLbl = QLabel(self) self.timeLbl = QLabel(self) self.timeLbl.setAlignment(Qt.AlignRight) self.line_1 = QFrame(self) self.line_1.setFrameShape(QFrame.HLine) self.line_1.setFrameShadow(QFrame.Sunken) self.line_2 = QFrame(self) self.line_2.setFrameShape(QFrame.HLine) self.line_2.setFrameShadow(QFrame.Sunken) self.msgLbl = QTextBrowser(self) # font = QFont() # font.setPointSize(12) # self.msgLbl.setFont(font) self.msgLbl.setFrameShape(QFrame.NoFrame) self.msgLbl.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff) self.msgLbl.setSizeAdjustPolicy(QAbstractScrollArea.AdjustToContents) self.msgLbl.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed) grid.addWidget(self.userLbl, 0, 0) grid.addWidget(self.timeLbl, 0, 1) grid.addWidget(self.line_1, 1, 0, 1, 2) grid.addWidget(self.msgLbl, 2, 0, 1, 2) grid.addWidget(self.line_2, 3, 0, 1, 2)
def __init__(self, horizontal=False, size=48, parent=None): QFrame.__init__(self, parent) if horizontal: size = 24 self.pi = ProgressIndicator(self, size) self._jobs = QLabel('<b>' + _('Jobs:') + ' 0') self._jobs.mouseReleaseEvent = self.mouseReleaseEvent self.shortcut = 'Shift+Alt+J' if horizontal: self.setLayout(QHBoxLayout()) self.layout().setDirection(self.layout().RightToLeft) else: self.setLayout(QVBoxLayout()) self._jobs.setAlignment(Qt.AlignHCenter | Qt.AlignBottom) self.layout().addWidget(self.pi) self.layout().addWidget(self._jobs) if not horizontal: self.layout().setAlignment(self._jobs, Qt.AlignHCenter) self._jobs.setMargin(0) self.layout().setContentsMargins(0, 0, 0, 0) self._jobs.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Minimum) self.setCursor(Qt.PointingHandCursor) b = _('Click to see list of jobs') self.setToolTip(b + u' (%s)' % self.shortcut) self.action_toggle = QAction(b, parent) parent.addAction(self.action_toggle) self.action_toggle.triggered.connect(self.toggle) if hasattr(parent, 'keyboard'): parent.keyboard.register_shortcut('toggle jobs list', _('Show/hide the Jobs List'), default_keys=(self.shortcut, ), action=self.action_toggle)
class TestWindow(MainWindow): def __init__(self, parent=None, show=True): MainWindow.__init__(self, parent) self.frame = QFrame() vlayout = QVBoxLayout() self.vtk_widget = QtInteractor(self.frame) vlayout.addWidget(self.vtk_widget.interactor) self.frame.setLayout(vlayout) self.setCentralWidget(self.frame) mainMenu = self.menuBar() fileMenu = mainMenu.addMenu('File') self.exit_action = QAction('Exit', self) self.exit_action.setShortcut('Ctrl+Q') self.exit_action.triggered.connect(self.close) fileMenu.addAction(self.exit_action) meshMenu = mainMenu.addMenu('Mesh') self.add_sphere_action = QAction('Add Sphere', self) self.exit_action.setShortcut('Ctrl+A') self.add_sphere_action.triggered.connect(self.add_sphere) meshMenu.addAction(self.add_sphere_action) self.signal_close.connect(self.vtk_widget.interactor.close) if show: self.show() def add_sphere(self): sphere = pyvista.Sphere() self.vtk_widget.add_mesh(sphere) self.vtk_widget.reset_camera()
def __init__(self, name, plugins, gui_name, parent=None): QWidget.__init__(self, parent) self._layout = QVBoxLayout() self.setLayout(self._layout) self.label = QLabel(gui_name) self.sep = QFrame(self) self.bf = QFont() self.bf.setBold(True) self.label.setFont(self.bf) self.sep.setFrameShape(QFrame.HLine) self._layout.addWidget(self.label) self._layout.addWidget(self.sep) self.plugins = plugins self.bar = QToolBar(self) self.bar.setStyleSheet('QToolBar { border: none; background: none }') lh = QApplication.instance().line_height self.bar.setIconSize(QSize(2 * lh, 2 * lh)) self.bar.setMovable(False) self.bar.setFloatable(False) self.bar.setToolButtonStyle(Qt.ToolButtonTextUnderIcon) self._layout.addWidget(self.bar) self.actions = [] for p in plugins: target = partial(self.triggered, p) ac = self.bar.addAction(QIcon(p.icon), p.gui_name, target) ac.setToolTip(textwrap.fill(p.description)) ac.setWhatsThis(textwrap.fill(p.description)) ac.setStatusTip(p.description) self.actions.append(ac) w = self.bar.widgetForAction(ac) w.setCursor(Qt.PointingHandCursor) w.setAutoRaise(True) w.setMinimumWidth(100)
def __init__(self, parent=None, show=True): QMainWindow.__init__(self, parent) self.frame = QFrame() vlayout = QVBoxLayout() self.vtk_widget = QtInteractor(self.frame) vlayout.addWidget(self.vtk_widget) self.frame.setLayout(vlayout) self.setCentralWidget(self.frame) mainMenu = self.menuBar() fileMenu = mainMenu.addMenu('File') exitButton = QAction('Exit', self) exitButton.setShortcut('Ctrl+Q') exitButton.triggered.connect(self.close) fileMenu.addAction(exitButton) meshMenu = mainMenu.addMenu('Mesh') self.add_sphere_action = QAction('Add Sphere', self) self.add_sphere_action.triggered.connect(self.add_sphere) meshMenu.addAction(self.add_sphere_action) if show: self.show()
def __init__(self, *args): QFrame.__init__(self, *args) self.setFrameStyle(QFrame.StyledPanel | QFrame.Sunken) self.edit = QTextBrowser() self.edit.setFrameStyle(QFrame.NoFrame) self.number_bar = self.NumberBar() self.number_bar.setTextEdit(self.edit) hbox = QHBoxLayout(self) hbox.setSpacing(0) margins = QMargins(0, 0, 0, 0) hbox.setContentsMargins(margins) hbox.addWidget(self.number_bar) hbox.addWidget(self.edit) self.edit.installEventFilter(self) self.edit.viewport().installEventFilter(self) config = Config() style_str = config.array_config_str('log_line_number_style') self.setStyleSheet(style_str)
def __init__(self, plugin, parent): QWidget.__init__(self, parent) self.plugin = plugin self.l = l = QVBoxLayout() self.setLayout(l) self.c = c = QLabel( _('<b>Configure %(name)s</b><br>%(desc)s') % dict(name=plugin.name, desc=plugin.description)) c.setAlignment(Qt.AlignHCenter) l.addWidget(c) self.config_widget = plugin.config_widget() self.l.addWidget(self.config_widget) self.bb = QDialogButtonBox(QDialogButtonBox.Save | QDialogButtonBox.Cancel, parent=self) self.bb.accepted.connect(self.finished) self.bb.rejected.connect(self.finished) self.bb.accepted.connect(self.commit) l.addWidget(self.bb) self.f = QFrame(self) self.f.setFrameShape(QFrame.HLine) l.addWidget(self.f)
def __init__(self, parent, closeButton=True): QFrame.__init__(self, parent) self.setMaximumSize(QSize(9999999,22)) self.setObjectName("windowTitle") self.hboxlayout = QHBoxLayout(self) self.hboxlayout.setSpacing(0) self.hboxlayout.setContentsMargins(0,0,4,0) self.label = QLabel(self) self.label.setObjectName("label") self.label.setStyleSheet("padding-left:4px; font:bold 11px; color: #FFFFFF;") self.hboxlayout.addWidget(self.label) spacerItem = QSpacerItem(40,20,QSizePolicy.Expanding,QSizePolicy.Minimum) self.hboxlayout.addItem(spacerItem) if closeButton: self.pushButton = QPushButton(self) self.pushButton.setFocusPolicy(Qt.NoFocus) self.pushButton.setObjectName("pushButton") self.pushButton.setStyleSheet("font:bold;") self.pushButton.setText("X") self.hboxlayout.addWidget(self.pushButton) self.dragPosition = None self.mainwidget = self.parent() self.setStyleSheet(""" QFrame#windowTitle {background-color:#222222;color:#FFF;} """) # Initial position to top left self.dragPosition = self.mainwidget.frameGeometry().topLeft()
class PluginConfig(QWidget): # {{{ finished = pyqtSignal() def __init__(self, plugin, parent): QWidget.__init__(self, parent) self.plugin = plugin self.l = l = QVBoxLayout() self.setLayout(l) self.c = c = QLabel(_('<b>Configure %(name)s</b><br>%(desc)s') % dict( name=plugin.name, desc=plugin.description)) c.setAlignment(Qt.AlignHCenter) l.addWidget(c) self.config_widget = plugin.config_widget() self.l.addWidget(self.config_widget) self.bb = QDialogButtonBox( QDialogButtonBox.Save|QDialogButtonBox.Cancel, parent=self) self.bb.accepted.connect(self.finished) self.bb.rejected.connect(self.finished) self.bb.accepted.connect(self.commit) l.addWidget(self.bb) self.f = QFrame(self) self.f.setFrameShape(QFrame.HLine) l.addWidget(self.f) def commit(self): self.plugin.save_settings(self.config_widget)
def __init__(self, parent=None, show=True, off_screen=True): MainWindow.__init__(self, parent) self.frame = QFrame() vlayout = QVBoxLayout() self.vtk_widget = QtInteractor(parent=self.frame, off_screen=off_screen) vlayout.addWidget(self.vtk_widget.interactor) self.frame.setLayout(vlayout) self.setCentralWidget(self.frame) mainMenu = _create_menu_bar(parent=self) fileMenu = mainMenu.addMenu('File') self.exit_action = QAction('Exit', self) self.exit_action.setShortcut('Ctrl+Q') self.exit_action.triggered.connect(self.close) fileMenu.addAction(self.exit_action) meshMenu = mainMenu.addMenu('Mesh') self.add_sphere_action = QAction('Add Sphere', self) self.exit_action.setShortcut('Ctrl+A') self.add_sphere_action.triggered.connect(self.add_sphere) meshMenu.addAction(self.add_sphere_action) self.signal_close.connect(self.vtk_widget.close) if show: self.show()
def _set_common_top_ui(self): top_frame = QFrame() top_frame.setMaximumHeight(60) top_layout = QVBoxLayout(top_frame) self.layout.addWidget(top_frame) common_top_frame = QFrame() common_top_frame.setMinimumHeight(50) common_top_frame.setMaximumHeight(50) common_top_layout = QHBoxLayout(common_top_frame) top_layout.addWidget(common_top_frame) common_top_layout.addStretch(0) label = QLabel(i18n[self.lang]['Type'] + ':') self.label_type = QLabel('') self.label_type.setStyleSheet('''color: gray;font:bold;''') common_top_layout.addWidget(label) common_top_layout.addWidget(self.label_type) label = QLabel(i18n[self.lang]['Mode'] + ':') self.label_mode = QLabel('') self.label_mode.setStyleSheet('''color: gray;font:bold;''') common_top_layout.addWidget(label) common_top_layout.addWidget(self.label_mode) label = QLabel(i18n[self.lang]['HardwareVersion'] + ':') self.label_hard_version = QLabel('') self.label_hard_version.setStyleSheet('''color: gray;font:bold;''') common_top_layout.addWidget(label) common_top_layout.addWidget(self.label_hard_version) label = QLabel(i18n[self.lang]['FirmwareVersion'] + ':') self.label_firm_version = QLabel('') self.label_firm_version.setStyleSheet('''color: gray;font:bold;''') common_top_layout.addWidget(label) common_top_layout.addWidget(self.label_firm_version) label_1 = QLabel(i18n[self.lang]['Connected'] + ':') self.label_connected = QLabel() img = QImage() self.label_connected.setMaximumHeight(20) self.label_connected.setMaximumWidth(20) self.label_connected.setScaledContents(True) if img.load(disconnect_icon_path): self.label_connected.setPixmap(QPixmap.fromImage(img)) self.lnt_addr = QLineEdit('COM12') self.lnt_addr.setMaximumWidth(50) self.lnt_addr.setMinimumWidth(30) self.btn_connect = QPushButton(i18n[self.lang]['Connect']) # self.btn_connect.setMaximumWidth(50) # common_top_layout.addStretch(0) common_top_layout.setSpacing(10) common_top_layout.addWidget(label_1) common_top_layout.addWidget(self.label_connected) common_top_layout.addWidget(self.lnt_addr) common_top_layout.addWidget(self.btn_connect)
def __init__(self, parent=None): """ Create menu object. `UndoMenu` class shows list of child items in the plain list, suitable for undo / redo operations. Items are inserted to menu with `setItems()` method. Methods `setMaxWidth()` and `setLength()` allow to limit the width (in pixels) and height (as a number of shown items) of menu. To customize summary label (shown in the bottom area of menu), use `setComment()` method. Top-most item can be obtained with `lastItem()` method. Arguments: parent (Optional[QWidget]): Parent widget. Defaults to None. """ QMenu.__init__(self, parent) v_layout = QVBoxLayout(self) v_layout.setContentsMargins(0, 0, 0, 0) frame = QFrame(self) frame.setFrameStyle(QFrame.Panel | QFrame.Plain) v_layout.addWidget(frame) v_layout = QVBoxLayout(frame) v_layout.setContentsMargins(0, 0, 0, 0) v_layout.setSpacing(1) self._list = QListWidget(frame) self._list.setFrameStyle(QListWidget.NoFrame) self._list.setSelectionMode(QListWidget.MultiSelection) self._list.setVerticalScrollMode(QListWidget.ScrollPerItem) self._list.setVerticalScrollBarPolicy(Qt.ScrollBarAsNeeded) self._list.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff) self._list.setResizeMode(QListWidget.Adjust) self._list.setFocusPolicy(Qt.NoFocus) self._list.viewport().installEventFilter(self) self._list.installEventFilter(self) self._list.viewport().setMouseTracking(True) self._label = QLabel(frame) self._label.setAlignment(Qt.AlignCenter) v_layout.addWidget(self._list) v_layout.addWidget(HLine(frame)) v_layout.addWidget(self._label) self._comment = "%d" self._length = 10 self._max_width = 0 self._updateComment()
def timerEvent(self, event): if event.timerId() == self.timer.timerId(): if self.isWaitingAfterLine: self.isWaitingAfterLine = False self.newPiece() else: self.oneLineDown() else: QFrame.timerEvent(self, event)
def __init__(self, parent=None): QFrame.__init__(self, parent) self.setFrameShape(self.StyledPanel) self.search_index = -1 self.search = {} self.original_name = None self.l = l = QVBoxLayout(self) self.title = la = QLabel('<h2>Edit...') self.ht = h = QHBoxLayout() l.addLayout(h) h.addWidget(la) self.cb = cb = QToolButton(self) cb.setIcon(QIcon(I('window-close.png'))) cb.setToolTip(_('Abort editing of search')) h.addWidget(cb) cb.clicked.connect(self.abort_editing) self.search_name = n = QLineEdit('', self) n.setPlaceholderText(_('The name with which to save this search')) self.la1 = la = QLabel(_('&Name:')) la.setBuddy(n) self.h3 = h = QHBoxLayout() h.addWidget(la), h.addWidget(n) l.addLayout(h) self.find = f = QPlainTextEdit('', self) self.la2 = la = QLabel(_('&Find:')) la.setBuddy(f) l.addWidget(la), l.addWidget(f) self.replace = r = QPlainTextEdit('', self) self.la3 = la = QLabel(_('&Replace:')) la.setBuddy(r) l.addWidget(la), l.addWidget(r) self.case_sensitive = c = QCheckBox(_('Case sensitive')) self.h = h = QHBoxLayout() l.addLayout(h) h.addWidget(c) self.dot_all = d = QCheckBox(_('Dot matches all')) h.addWidget(d), h.addStretch(2) self.h2 = h = QHBoxLayout() l.addLayout(h) self.mode_box = m = ModeBox(self) m.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed) self.la4 = la = QLabel(_('&Mode:')) la.setBuddy(m) h.addWidget(la), h.addWidget(m), h.addStretch(2) self.done_button = b = QPushButton(QIcon(I('ok.png')), _('&Done')) b.setToolTip(_('Finish editing of search')) h.addWidget(b) b.clicked.connect(self.emit_done)
def eventFilter(self, obj, event): if self.capture == 0 or obj not in (self.button1, self.button2): return QFrame.eventFilter(self, obj, event) t = event.type() if t == event.ShortcutOverride: event.accept() return True if t == event.KeyPress: self.key_press_event(event, 1 if obj is self.button1 else 2) return True return QFrame.eventFilter(self, obj, event)
def __init__(self, color_caption): TestableWidget.__init__(self) self.setWindowFlags(Qt.Popup) self._text = self.tr("Alignment text") main_layout = QVBoxLayout() main_layout.setContentsMargins(0, 0, 0, 0) b = "border: 1px solid #9b9b9b;" self._styles = { "border": b, "border_blue": "border: 0px solid blue;", "frame": 'QFrame[frameShape="4"]{color: #9b9b9b;}' } self.setStyleSheet(self._styles["frame"]) # -- CAPTION ---------------------------------- caption = QFrame(self, flags=Qt.WindowFlags()) caption_layout = QHBoxLayout() self._lbl_caption = QLabel(self._text) self._lbl_caption.setStyleSheet(self._styles["border_blue"]) caption_layout.addWidget(self._lbl_caption, alignment=Qt.Alignment()) caption.setLayout(caption_layout) caption_layout.setContentsMargins(9, 5, 9, 5) caption.setStyleSheet( f"background-color: {color_caption}; {self._styles['border']}") # -- CELLS GRID ------------------------------- cellsbox = QFrame(self, flags=Qt.WindowFlags()) cells = QGridLayout() cellsbox.setLayout(cells) cells.setContentsMargins(9, 0, 9, 9) self._clrbtn = [] for i in range(1, 4): for j in range(1, 5): self._clrbtn.append(QToolButton()) self._clrbtn[-1].clicked.connect( lambda z, y=i, x=j: self.select_align_(x, y)) self._clrbtn[-1].setAutoRaise(True) sz = 48 self._clrbtn[-1].setFixedSize(sz, sz) self._clrbtn[-1].setIconSize(QSize(sz, sz)) self._clrbtn[-1].setIcon(QIcon(img(f"editor/a{i}{j}.png"))) # noinspection PyArgumentList cells.addWidget(self._clrbtn[-1], i - 1, j - 1) # --------------------------------------------- main_layout.addWidget(caption, alignment=Qt.Alignment()) main_layout.addWidget(cellsbox, alignment=Qt.Alignment()) self.setLayout(main_layout)
def setup_select_libraries_panel(self): self.imported_lib_widgets = [] self.frames = [] l = self.slp.layout() for lpath in sorted(self.importer.metadata['libraries'], key=lambda x:numeric_sort_key(os.path.basename(x))): f = QFrame(self) self.frames.append(f) l.addWidget(f) f.setFrameShape(f.HLine) w = ImportLocation(lpath, self.slp) l.addWidget(w) self.imported_lib_widgets.append(w) l.addStretch()
def initSrcFiles(self): row = 0 f = QFrame() l = QGridLayout() f.setLayout(l) l.addWidget(QLabel('Source Files :'), row, 0) self.srcFilesList = QListWidget() self.srcFilesList.setSelectionMode(QAbstractItemView.MultiSelection) self.srcFilesList.setAlternatingRowColors(True) self.srcFilesList.model().rowsInserted.connect( self.handleSrcFilesChanged) self.srcFilesList.model().rowsRemoved.connect( self.handleSrcFilesChanged) selectionModel = self.srcFilesList.selectionModel() selectionModel.selectionChanged.connect( self.handleSrcFilesSelectionChanged) l.addWidget(self.srcFilesList, row, 1, 3, 1) self.srcFilesBtn = QPushButton('Select Files') self.srcFilesBtn.clicked.connect(self.handleSelectSrcFiles) self.srcFilesBtn.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Expanding) l.addWidget(self.srcFilesBtn, row, 2) row += 1 self.addFilesBtn = QPushButton('Add Files') self.addFilesBtn.clicked.connect(self.handleAddSrcFiles) self.addFilesBtn.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Expanding) l.addWidget(self.addFilesBtn, row, 2) row += 1 self.removeFilesBtn = QPushButton('Remove Files') self.removeFilesBtn.setEnabled(False) self.removeFilesBtn.clicked.connect(self.handleRemoveSrcFiles) self.removeFilesBtn.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Expanding) l.addWidget(self.removeFilesBtn, row, 2) row += 1 self.errorEdit = QPlainTextEdit() self.errorEdit.setReadOnly(True) l.addWidget(self.errorEdit, row, 1, 1, 2) self.comms.errorSignal.connect(self.errorEdit.appendPlainText) return f
def __init__(self): QWidget.__init__(self, ctx.mainScreen) self.setObjectName("InformationWindow") self.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) self.setFixedHeight(50) self.setMaximumWidth(800) self.setStyleSheet(""" QFrame#frame { border: 1px solid rgba(255,255,255,30); /*border-radius: 4px;*/ background-color: rgba(0,0,0,100);} QLabel { border:none; color:#FFFFFF;} QProgressBar { border: 1px solid white;} QProgressBar::chunk { background-color: #F1610D; width: 0.5px;} """) self.gridlayout = QGridLayout(self) self.frame = QFrame(self) self.frame.setObjectName("frame") self.horizontalLayout = QHBoxLayout(self.frame) self.horizontalLayout.setContentsMargins(10, 0, 10, 0) # Spinner self.spinner = QLabel(self.frame) self.spinner.setMinimumSize(QSize(16, 16)) self.spinner.setMaximumSize(QSize(16, 16)) self.spinner.setIndent(6) self.movie = QMovie(':/images/working.mng') self.spinner.setMovie(self.movie) self.movie.start() self.horizontalLayout.addWidget(self.spinner) # Message self.label = QLabel(self.frame) self.label.setAlignment(Qt.AlignCenter) self.label.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) self.icon = QLabel(self.frame) self.icon.setFixedWidth(16) self.icon.setFixedHeight(16) self.horizontalLayout.setSpacing(10) self.horizontalLayout.addWidget(self.icon) self.horizontalLayout.addWidget(self.label) self.gridlayout.addWidget(self.frame, 0, 0, 1, 1)
def __init__(self, name, is_checked=False, path='', restriction='', parent=None, is_first=False, enable_on_checked=True): QWidget.__init__(self, parent) self.name = name self.enable_on_checked = enable_on_checked self.l = l = QVBoxLayout(self) l.setSizeConstraint(l.SetMinAndMaxSize) if not is_first: self.border = b = QFrame(self) b.setFrameStyle(b.HLine) l.addWidget(b) self.cw = cw = QCheckBox(name.replace('&', '&&')) cw.setStyleSheet('QCheckBox { font-weight: bold }') cw.setChecked(is_checked) cw.stateChanged.connect(self.state_changed) if path: cw.setToolTip(path) l.addWidget(cw) self.la = la = QLabel(_('Further &restrict access to books in this library that match:')) l.addWidget(la) self.rw = rw = QLineEdit(self) rw.setPlaceholderText(_('A search expression')) rw.setToolTip(textwrap.fill(_( 'A search expression. If specified, access will be further restricted' ' to only those books that match this expression. For example:' ' tags:"=Share"'))) rw.setText(restriction or '') rw.textChanged.connect(self.on_rchange) la.setBuddy(rw) l.addWidget(rw) self.state_changed()
def _set_down_frame_ui(self): self.down_frame = QFrame() self.down_layout = QHBoxLayout(self.down_frame) self.layout.addWidget(self.down_frame) self.textEdit = QTextEdit() self.down_layout.addWidget(self.textEdit)
def keyPressEvent(self, ev): if ev.key() in (Qt.Key.Key_Enter, Qt.Key.Key_Return) and self.find_text: self.find() ev.accept() return return QFrame.keyPressEvent(self, ev)
def __init__(self, parent, label, extra_widgets=[], style=QFrame.HLine + QFrame.Raised, offset=16): QWidget.__init__(self, parent) lo = QHBoxLayout(self) lo.setContentsMargins(0, 0, 0, 0) lo.setSpacing(4) if offset: frame = QFrame(self) frame.setFrameStyle(style) frame.setMinimumWidth(offset) lo.addWidget(frame, 0) lo.addWidget(QLabel(label, self), 0) frame = QFrame(self) frame.setFrameStyle(style) lo.addWidget(frame, 1) for w in extra_widgets: lo.addWidget(w, 0)
def eventFilter(self, object, event): # Update the line numbers for all events on the text edit and the viewport. # This is easier than connecting all necessary singals. if object in (self.edit, self.edit.viewport()): self.number_bar.update() return False return QFrame.eventFilter(object, event)
def __init__(self, name, plugins, gui_name, parent=None): QWidget.__init__(self, parent) self._layout = QVBoxLayout() self.setLayout(self._layout) self.label = QLabel(gui_name) self.sep = QFrame(self) self.bf = QFont() self.bf.setBold(True) self.label.setFont(self.bf) self.sep.setFrameShape(QFrame.HLine) self._layout.addWidget(self.label) self._layout.addWidget(self.sep) self.plugins = plugins self.bar = QToolBar(self) self.bar.setStyleSheet( 'QToolBar { border: none; background: none }') self.bar.setIconSize(QSize(32, 32)) self.bar.setMovable(False) self.bar.setFloatable(False) self.bar.setToolButtonStyle(Qt.ToolButtonTextUnderIcon) self._layout.addWidget(self.bar) self.actions = [] for p in plugins: target = partial(self.triggered, p) ac = self.bar.addAction(QIcon(p.icon), p.gui_name, target) ac.setToolTip(textwrap.fill(p.description)) ac.setWhatsThis(textwrap.fill(p.description)) ac.setStatusTip(p.description) self.actions.append(ac) w = self.bar.widgetForAction(ac) w.setCursor(Qt.PointingHandCursor) w.setAutoRaise(True) w.setMinimumWidth(100)
def __init__(self, parent=None): QWidget.__init__(self, parent) self.l = l = QGridLayout(self) def add_row(*args): r = l.rowCount() if len(args) == 1: l.addWidget(args[0], r, 0, 1, 2) else: la = QLabel(args[0]) l.addWidget(la, r, 0, Qt.AlignmentFlag.AlignRight), l.addWidget(args[1], r, 1) la.setBuddy(args[1]) self.heading = la = QLabel('<h2>\xa0') add_row(la) self.helpl = la = QLabel(_('For help with snippets, see the <a href="%s">User Manual</a>') % localize_user_manual_link('https://manual.calibre-ebook.com/snippets.html')) la.setOpenExternalLinks(True) add_row(la) self.name = n = QLineEdit(self) n.setPlaceholderText(_('The name of this snippet')) add_row(_('&Name:'), n) self.trig = t = QLineEdit(self) t.setPlaceholderText(_('The text used to trigger this snippet')) add_row(_('Tri&gger:'), t) self.template = t = QPlainTextEdit(self) la.setBuddy(t) add_row(_('&Template:'), t) self.types = t = QListWidget(self) t.setFlow(QListView.Flow.LeftToRight) t.setWrapping(True), t.setResizeMode(QListView.ResizeMode.Adjust), t.setSpacing(5) fm = t.fontMetrics() t.setMaximumHeight(2*(fm.ascent() + fm.descent()) + 25) add_row(_('&File types:'), t) t.setToolTip(_('Which file types this snippet should be active in')) self.frame = f = QFrame(self) f.setFrameShape(f.HLine) add_row(f) self.test = d = SnippetTextEdit('', self) d.snippet_manager.snip_func = self.snip_func d.setToolTip(_('You can test your snippet here')) d.setMaximumHeight(t.maximumHeight() + 15) add_row(_('T&est:'), d) i = QListWidgetItem(_('All'), t) i.setData(Qt.ItemDataRole.UserRole, '*') i.setCheckState(Qt.CheckState.Checked) i.setFlags(i.flags() | Qt.ItemFlag.ItemIsUserCheckable) for ftype in sorted(all_text_syntaxes): i = QListWidgetItem(ftype, t) i.setData(Qt.ItemDataRole.UserRole, ftype) i.setCheckState(Qt.CheckState.Checked) i.setFlags(i.flags() | Qt.ItemFlag.ItemIsUserCheckable) self.creating_snippet = False
def initFileFrame(self): row = 0 f = QFrame() l = QGridLayout() f.setLayout(l) # f.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Expanding) l.addWidget(QLabel('Destination File :'), row, 0) self.destFilenameEdit = QLineEdit(self.destFilename) self.destFilenameEdit.setEnabled(False) self.destFilenameEdit.textChanged.connect( self.handleDestFilenameChanged) l.addWidget(self.destFilenameEdit, row, 1) row += 1 self.combineRoutesBox = QCheckBox('combine_routes') if self.config[FORMS]['combine_routes']: self.combineRoutesBox.setChecked(True) else: self.combineRoutesBox.setChecked(False) self.combineRoutesBox.clicked.connect(self.handleCombineRoutesClicked) self.combineRoutesBox.setEnabled(False) l.addWidget(self.combineRoutesBox, row, 0) row += 1 addDateInNameBox = QCheckBox('Add date to filename') addDateInNameBox.clicked.connect(self.handleAddDateClicked) l.addWidget(addDateInNameBox, row, 0) if self.config[FORMS]['prefix_date']: self.prefixDateInNameBox = QPushButton('prefix_date') self.prefixDateInNameBox.setEnabled(False) else: self.prefixDateInNameBox = QPushButton('Suffix date') self.prefixDateInNameBox.setEnabled(False) self.prefixDateInNameBox.setToolTip('Click to change to prefix date.') self.prefixDateInNameBox.clicked.connect(self.handlePrefixDateClicked) l.addWidget(self.prefixDateInNameBox, row, 1) row += 1 addRouteInNameBox = QCheckBox('Add route to filename') addRouteInNameBox.clicked.connect(self.handleAddRouteClicked) l.addWidget(addRouteInNameBox, row, 0) # row += 1 return f
def initResultPage(self): f = QFrame() l = QHBoxLayout() f.setLayout(l) self.convertedTabs = QTabWidget() l.addWidget(self.convertedTabs) ''' This just adds a blank page with an empty tab widget. Pages are added on the fly when the files are converted as this could involve one or many pages depending on combine_route flag and number of routes. self.convertedTabs is the empty tab widget ''' return f
def __init__(self, parent=None): QFrame.__init__(self, parent) self.setFocusPolicy(Qt.FocusPolicy.StrongFocus) self.setAutoFillBackground(True) self.capture = 0 self.setFrameShape(self.StyledPanel) self.setFrameShadow(self.Raised) self._layout = l = QGridLayout(self) self.setLayout(l) self.header = QLabel('') l.addWidget(self.header, 0, 0, 1, 2) self.use_default = QRadioButton('') self.use_custom = QRadioButton(_('&Custom')) l.addWidget(self.use_default, 1, 0, 1, 3) l.addWidget(self.use_custom, 2, 0, 1, 3) self.use_custom.toggled.connect(self.custom_toggled) off = 2 for which in (1, 2): text = _('&Shortcut:') if which == 1 else _('&Alternate shortcut:') la = QLabel(text) la.setStyleSheet('QLabel { margin-left: 1.5em }') l.addWidget(la, off + which, 0, 1, 3) setattr(self, 'label%d' % which, la) button = QPushButton(_('None'), self) button.clicked.connect(partial(self.capture_clicked, which=which)) button.installEventFilter(self) setattr(self, 'button%d' % which, button) clear = QToolButton(self) clear.setIcon(QIcon(I('clear_left.png'))) clear.clicked.connect(partial(self.clear_clicked, which=which)) setattr(self, 'clear%d' % which, clear) l.addWidget(button, off + which, 1, 1, 1) l.addWidget(clear, off + which, 2, 1, 1) la.setBuddy(button) self.done_button = doneb = QPushButton(_('Done'), self) l.addWidget(doneb, 0, 2, 1, 1) doneb.clicked.connect(lambda: self.editing_done.emit(self)) l.setColumnStretch(0, 100) self.custom_toggled(False)
def __init__(self, parent=None): QFrame.__init__(self, parent) self.setFocusPolicy(Qt.StrongFocus) self.setAutoFillBackground(True) self.capture = 0 self.setFrameShape(self.StyledPanel) self.setFrameShadow(self.Raised) self._layout = l = QGridLayout(self) self.setLayout(l) self.header = QLabel('') l.addWidget(self.header, 0, 0, 1, 2) self.use_default = QRadioButton('') self.use_custom = QRadioButton(_('Custom')) l.addWidget(self.use_default, 1, 0, 1, 3) l.addWidget(self.use_custom, 2, 0, 1, 3) self.use_custom.toggled.connect(self.custom_toggled) off = 2 for which in (1, 2): text = _('&Shortcut:') if which == 1 else _('&Alternate shortcut:') la = QLabel(text) la.setStyleSheet('QLabel { margin-left: 1.5em }') l.addWidget(la, off+which, 0, 1, 3) setattr(self, 'label%d'%which, la) button = QPushButton(_('None'), self) button.clicked.connect(partial(self.capture_clicked, which=which)) button.keyPressEvent = partial(self.key_press_event, which=which) setattr(self, 'button%d'%which, button) clear = QToolButton(self) clear.setIcon(QIcon(I('clear_left.png'))) clear.clicked.connect(partial(self.clear_clicked, which=which)) setattr(self, 'clear%d'%which, clear) l.addWidget(button, off+which, 1, 1, 1) l.addWidget(clear, off+which, 2, 1, 1) la.setBuddy(button) self.done_button = doneb = QPushButton(_('Done'), self) l.addWidget(doneb, 0, 2, 1, 1) doneb.clicked.connect(lambda : self.editing_done.emit(self)) l.setColumnStretch(0, 100) self.custom_toggled(False)
def __init__(self, index, dup_check, parent=None): QFrame.__init__(self, parent) self.setupUi(self) self.data_model = index.model() self.setFocusPolicy(Qt.StrongFocus) self.setAutoFillBackground(True) self.custom.toggled.connect(self.custom_toggled) self.custom_toggled(False) self.capture = 0 self.key = None self.shorcut1 = self.shortcut2 = None self.dup_check = dup_check for x in (1, 2): button = getattr(self, "button%d" % x) button.clicked.connect(partial(self.capture_clicked, which=x)) button.keyPressEvent = partial(self.key_press_event, which=x) clear = getattr(self, "clear%d" % x) clear.clicked.connect(partial(self.clear_clicked, which=x))
def __init__(self, index, dup_check, parent=None): QFrame.__init__(self, parent) self.setupUi(self) self.data_model = index.model() self.setFocusPolicy(Qt.StrongFocus) self.setAutoFillBackground(True) self.custom.toggled.connect(self.custom_toggled) self.custom_toggled(False) self.capture = 0 self.key = None self.shorcut1 = self.shortcut2 = None self.dup_check = dup_check for x in (1, 2): button = getattr(self, 'button%d' % x) button.clicked.connect(partial(self.capture_clicked, which=x)) button.keyPressEvent = partial(self.key_press_event, which=x) clear = getattr(self, 'clear%d' % x) clear.clicked.connect(partial(self.clear_clicked, which=x))
class Category(QWidget): # {{{ plugin_activated = pyqtSignal(object) def __init__(self, name, plugins, gui_name, parent=None): QWidget.__init__(self, parent) self._layout = QVBoxLayout() self.setLayout(self._layout) self.label = QLabel(gui_name) self.sep = QFrame(self) self.bf = QFont() self.bf.setBold(True) self.label.setFont(self.bf) self.sep.setFrameShape(QFrame.HLine) self._layout.addWidget(self.label) self._layout.addWidget(self.sep) self.plugins = plugins self.bar = QToolBar(self) self.bar.setStyleSheet( 'QToolBar { border: none; background: none }') lh = QApplication.instance().line_height self.bar.setIconSize(QSize(2*lh, 2*lh)) self.bar.setMovable(False) self.bar.setFloatable(False) self.bar.setToolButtonStyle(Qt.ToolButtonTextUnderIcon) self._layout.addWidget(self.bar) self.actions = [] for p in plugins: target = partial(self.triggered, p) ac = self.bar.addAction(QIcon(p.icon), p.gui_name.replace('&', '&&'), target) ac.setToolTip(textwrap.fill(p.description)) ac.setWhatsThis(textwrap.fill(p.description)) ac.setStatusTip(p.description) self.actions.append(ac) w = self.bar.widgetForAction(ac) w.setCursor(Qt.PointingHandCursor) if hasattr(w, 'setAutoRaise'): w.setAutoRaise(True) w.setMinimumWidth(100) def triggered(self, plugin, *args): self.plugin_activated.emit(plugin)
def get_frame_separator(vertical=False): """ Return a frame separator :param vertical: define if separator is vertical or horizontal :type vertical: bool :return: frame separator :rtype: QFrame """ line = QFrame() if vertical: line.setObjectName('vseparator') line.setFrameShape(QFrame.VLine) else: line.setObjectName('hseparator') line.setFrameShape(QFrame.HLine) return line
def __init__(self, *args): QFrame.__init__(self, *args) self.setFrameStyle(QFrame.StyledPanel | QFrame.Sunken) self.edit = QPlainTextEdit() self.edit.setFrameStyle(QFrame.NoFrame) self.number_bar = self.NumberBar() self.number_bar.setTextEdit(self.edit) hbox = QHBoxLayout(self) hbox.setSpacing(0) #hbox.setMargin(0) hbox.addWidget(self.number_bar) hbox.addWidget(self.edit) self.edit.installEventFilter(self) self.edit.viewport().installEventFilter(self)
def create_template_widget(title, which, button): attr = which + '_template' heading = QLabel('<h2>' + title) setattr(tp, attr + '_heading', heading) l.addWidget(heading) la = QLabel() setattr(self, attr, la) l.addWidget(la), la.setTextFormat(Qt.TextFormat.PlainText), la.setStyleSheet('QLabel {font-family: monospace}') la.setWordWrap(True) b = QPushButton(button) b.setSizePolicy(QSizePolicy.Policy.Fixed, QSizePolicy.Policy.Fixed) connect_lambda(b.clicked, self, lambda self: self.change_template(which)) setattr(self, attr + '_button', b) l.addWidget(b) if which != 'footer': f = QFrame(tp) setattr(tp, attr + '_sep', f), f.setFrameShape(QFrame.Shape.HLine) l.addWidget(f) l.addSpacing(10)
def __init__(self, parent): QFrame.__init__(self, parent) self.timer = QBasicTimer() self.isWaitingAfterLine = False self.curPiece = Shape() self.nextPiece = Shape() self.curX = 0 self.curY = 0 self.numLinesRemoved = 0 self.board = [] self.setFocusPolicy(Qt.StrongFocus) self.isStarted = False self.isPaused = False self.clearBoard() self.nextPiece.setRandomShape() self._parent = parent
def create_template_widget(title, which, button): attr = which + '_template' heading = QLabel('<h2>' + title) setattr(tp, attr + '_heading', heading) l.addWidget(heading) la = QLabel() setattr(self, attr, la) l.addWidget(la), la.setTextFormat(Qt.PlainText), la.setStyleSheet('QLabel {font-family: monospace}') la.setWordWrap(True) b = QPushButton(button) b.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed) b.clicked.connect(partial(self.change_template, which)) setattr(self, attr + '_button', b) l.addWidget(b) if which != 'footer': f = QFrame(tp) setattr(tp, attr + '_sep', f), f.setFrameShape(QFrame.HLine) l.addWidget(f) l.addSpacing(10)
def __init__(self, index, dup_check, parent=None): QFrame.__init__(self, parent) self.setFrameShape(self.StyledPanel) self.setFrameShadow(self.Raised) self.setFocusPolicy(Qt.StrongFocus) self.setAutoFillBackground(True) self.l = l = QVBoxLayout(self) self.header = la = QLabel(self) la.setWordWrap(True) l.addWidget(la) self.default_shortcuts = QRadioButton(_("&Default"), self) self.custom = QRadioButton(_("&Custom"), self) self.custom.toggled.connect(self.custom_toggled) l.addWidget(self.default_shortcuts) l.addWidget(self.custom) for which in 1, 2: la = QLabel(_("&Shortcut:") if which == 1 else _("&Alternate shortcut:")) setattr(self, 'label%d' % which, la) h = QHBoxLayout() l.addLayout(h) h.setContentsMargins(25, -1, -1, -1) h.addWidget(la) b = QPushButton(_("Click to change"), self) la.setBuddy(b) b.clicked.connect(partial(self.capture_clicked, which=which)) b.installEventFilter(self) setattr(self, 'button%d' % which, b) h.addWidget(b) c = QToolButton(self) c.setIcon(QIcon(I('clear_left.png'))) c.setToolTip(_('Clear')) h.addWidget(c) c.clicked.connect(partial(self.clear_clicked, which=which)) setattr(self, 'clear%d' % which, c) self.data_model = index.model() self.capture = 0 self.key = None self.shorcut1 = self.shortcut2 = None self.dup_check = dup_check self.custom_toggled(False)
def __init__(self): QWidget.__init__(self, ctx.mainScreen) self.setObjectName("InformationWindow") self.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) self.setFixedHeight(50) self.setMaximumWidth(800) self.setStyleSheet(""" QFrame#frame { border: 1px solid rgba(255,255,255,30); /*border-radius: 4px;*/ background-color: rgba(0,0,0,100);} QLabel { border:none; color:#FFFFFF;} QProgressBar { border: 1px solid white;} QProgressBar::chunk { background-color: #F1610D; width: 0.5px;} """) self.gridlayout = QGridLayout(self) self.frame = QFrame(self) self.frame.setObjectName("frame") self.horizontalLayout = QHBoxLayout(self.frame) self.horizontalLayout.setContentsMargins(10, 0, 10, 0) # Spinner self.spinner = QLabel(self.frame) self.spinner.setMinimumSize(QSize(16, 16)) self.spinner.setMaximumSize(QSize(16, 16)) self.spinner.setIndent(6) self.movie = QMovie(':/images/working.mng') self.spinner.setMovie(self.movie) self.movie.start() self.horizontalLayout.addWidget(self.spinner) # Message self.label = QLabel(self.frame) self.label.setAlignment(Qt.AlignCenter) self.label.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) self.icon = QLabel(self.frame) self.icon.setFixedWidth(16) self.icon.setFixedHeight(16) self.horizontalLayout.setSpacing(10) self.horizontalLayout.addWidget(self.icon) self.horizontalLayout.addWidget(self.label) self.gridlayout.addWidget(self.frame,0,0,1,1)
def __init__(self, parent): QFrame.__init__(self, parent) self.setFrameStyle(QFrame.NoFrame if gprefs['tag_browser_old_look'] else QFrame.StyledPanel) self._parent = parent self._layout = QVBoxLayout(self) self._layout.setContentsMargins(0,0,0,0) # Set up the find box & button self.tb_bar = tbb = TagBrowserBar(self) self.alter_tb, self.item_search, self.search_button = tbb.alter_tb, tbb.item_search, tbb.search_button self.toggle_search_button = tbb.toggle_search_button self._layout.addWidget(tbb) self.current_find_position = None self.search_button.clicked.connect(self.find) self.item_search.lineEdit().textEdited.connect(self.find_text_changed) self.item_search.activated[str].connect(self.do_find) # The tags view parent.tags_view = TagsView(parent) self.tags_view = parent.tags_view self._layout.insertWidget(0, parent.tags_view) # Now the floating 'not found' box l = QLabel(self.tags_view) self.not_found_label = l l.setFrameStyle(QFrame.StyledPanel) l.setAutoFillBackground(True) l.setText('<p><b>'+_('No More Matches.</b><p> Click Find again to go to first match')) l.setAlignment(Qt.AlignVCenter) l.setWordWrap(True) l.resize(l.sizeHint()) l.move(10,20) l.setVisible(False) self.not_found_label_timer = QTimer() self.not_found_label_timer.setSingleShot(True) self.not_found_label_timer.timeout.connect(self.not_found_label_timer_event, type=Qt.QueuedConnection) # The Alter Tag Browser button l = self.alter_tb self.collapse_all_action = ac = QAction(parent) parent.addAction(ac) parent.keyboard.register_shortcut('tag browser collapse all', _('Collapse all'), default_keys=(), action=ac, group=_('Tag browser')) connect_lambda(ac.triggered, self, lambda self: self.tags_view.collapseAll()) ac = QAction(parent) parent.addAction(ac) parent.keyboard.register_shortcut('tag browser alter', _('Configure Tag browser'), default_keys=(), action=ac, group=_('Tag browser')) ac.triggered.connect(l.showMenu) sb = l.m.addAction(_('Sort by')) sb.m = l.sort_menu = QMenu(l.m) sb.setMenu(sb.m) sb.bg = QActionGroup(sb) # Must be in the same order as db2.CATEGORY_SORTS for i, x in enumerate((_('Name'), _('Number of books'), _('Average rating'))): a = sb.m.addAction(x) sb.bg.addAction(a) a.setCheckable(True) if i == 0: a.setChecked(True) sb.setToolTip( _('Set the sort order for entries in the Tag browser')) sb.setStatusTip(sb.toolTip()) ma = l.m.addAction(_('Search type when selecting multiple items')) ma.m = l.match_menu = QMenu(l.m) ma.setMenu(ma.m) ma.ag = QActionGroup(ma) # Must be in the same order as db2.MATCH_TYPE for i, x in enumerate((_('Match any of the items'), _('Match all of the items'))): a = ma.m.addAction(x) ma.ag.addAction(a) a.setCheckable(True) if i == 0: a.setChecked(True) ma.setToolTip( _('When selecting multiple entries in the Tag browser ' 'match any or all of them')) ma.setStatusTip(ma.toolTip()) mt = l.m.addAction(_('Manage authors, tags, etc.')) mt.setToolTip(_('All of these category_managers are available by right-clicking ' 'on items in the tag browser above')) mt.m = l.manage_menu = QMenu(l.m) mt.setMenu(mt.m) ac = QAction(parent) parent.addAction(ac) parent.keyboard.register_shortcut('tag browser toggle item', _("'Click' found item"), default_keys=(), action=ac, group=_('Tag browser')) ac.triggered.connect(self.toggle_item)
def add_hline(): f = QFrame() fp.f.append(f) f.setFrameShape(f.HLine) l.addRow(f)
class InformationWindow(QWidget): def __init__(self): QWidget.__init__(self, ctx.mainScreen) self.setObjectName("InformationWindow") self.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) self.setFixedHeight(50) self.setMaximumWidth(800) self.setStyleSheet(""" QFrame#frame { border: 1px solid rgba(255,255,255,30); /*border-radius: 4px;*/ background-color: rgba(0,0,0,100);} QLabel { border:none; color:#FFFFFF;} QProgressBar { border: 1px solid white;} QProgressBar::chunk { background-color: #F1610D; width: 0.5px;} """) self.gridlayout = QGridLayout(self) self.frame = QFrame(self) self.frame.setObjectName("frame") self.horizontalLayout = QHBoxLayout(self.frame) self.horizontalLayout.setContentsMargins(10, 0, 10, 0) # Spinner self.spinner = QLabel(self.frame) self.spinner.setMinimumSize(QSize(16, 16)) self.spinner.setMaximumSize(QSize(16, 16)) self.spinner.setIndent(6) self.movie = QMovie(':/images/working.mng') self.spinner.setMovie(self.movie) self.movie.start() self.horizontalLayout.addWidget(self.spinner) # Message self.label = QLabel(self.frame) self.label.setAlignment(Qt.AlignCenter) self.label.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) self.icon = QLabel(self.frame) self.icon.setFixedWidth(16) self.icon.setFixedHeight(16) self.horizontalLayout.setSpacing(10) self.horizontalLayout.addWidget(self.icon) self.horizontalLayout.addWidget(self.label) self.gridlayout.addWidget(self.frame,0,0,1,1) def update(self, message, type=None, spinner=False): fontMetric = self.label.fontMetrics() textWidth = fontMetric.width(message) if type: self.icon.show() if type == "error": self.icon.setPixmap(QPixmap(":/gui/pics/dialog-error.png")) self.setStyleSheet(" QFrame#frame {background-color: rgba(255,0,0,100);} ") elif type == "warning": self.icon.setPixmap(QPixmap(":/gui/pics/dialog-warning.png")) self.setStyleSheet(" QFrame#frame {background-color: rgba(0,0,0,100);} ") self.setFixedWidth(textWidth + self.icon.width() + 50) self.label.setText(message) else: self.icon.hide() self.setStyleSheet(" QFrame#frame {background-color: rgba(0,0,0,100);} ") self.setFixedWidth(textWidth + self.icon.width() + 100) self.label.setText(message) self.spinner.setVisible(spinner) self.move(ctx.mainScreen.width()/2 - self.width()/2, ctx.mainScreen.height() - self.height()/2 - 50) self.show() def refresh(self): ctx.mainScreen.processEvents() def show(self): QWidget.show(self) self.refresh() def hide(self): QWidget.hide(self) self.refresh()
def __init__(self, opts): self.matched_ids = set() self.opts = opts self.prefs = opts.prefs super(FindAnnotationsDialog, self).__init__(self.opts.gui, 'find_annotations_dialog') self.setWindowTitle('Find Annotations') self.setWindowIcon(self.opts.icon) self.l = QVBoxLayout(self) self.setLayout(self.l) self.search_criteria_gb = QGroupBox(self) self.search_criteria_gb.setTitle("Search criteria") self.scgl = QGridLayout(self.search_criteria_gb) self.l.addWidget(self.search_criteria_gb) # addWidget(widget, row, col, rowspan, colspan) row = 0 # ~~~~~~~~ Create the Readers comboBox ~~~~~~~~ self.reader_label = QLabel('Reader') self.reader_label.setAlignment(Qt.AlignRight|Qt.AlignVCenter) self.scgl.addWidget(self.reader_label, row, 0, 1, 1) self.find_annotations_reader_comboBox = QComboBox() self.find_annotations_reader_comboBox.setObjectName('find_annotations_reader_comboBox') self.find_annotations_reader_comboBox.setToolTip('Reader annotations to search for') self.find_annotations_reader_comboBox.addItem(self.GENERIC_READER) racs = ReaderApp.get_reader_app_classes() for ra in sorted(racs.keys()): self.find_annotations_reader_comboBox.addItem(ra) self.scgl.addWidget(self.find_annotations_reader_comboBox, row, 1, 1, 4) row += 1 # ~~~~~~~~ Create the Styles comboBox ~~~~~~~~ self.style_label = QLabel('Style') self.style_label.setAlignment(Qt.AlignRight|Qt.AlignVCenter) self.scgl.addWidget(self.style_label, row, 0, 1, 1) self.find_annotations_color_comboBox = QComboBox() self.find_annotations_color_comboBox.setObjectName('find_annotations_color_comboBox') self.find_annotations_color_comboBox.setToolTip('Annotation style to search for') self.find_annotations_color_comboBox.addItem(self.GENERIC_STYLE) all_colors = COLOR_MAP.keys() all_colors.remove('Default') for color in sorted(all_colors): self.find_annotations_color_comboBox.addItem(color) self.scgl.addWidget(self.find_annotations_color_comboBox, row, 1, 1, 4) row += 1 # ~~~~~~~~ Create the Text LineEdit control ~~~~~~~~ self.text_label = QLabel('Text') self.text_label.setAlignment(Qt.AlignRight|Qt.AlignVCenter) self.scgl.addWidget(self.text_label, row, 0, 1, 1) self.find_annotations_text_lineEdit = MyLineEdit() self.find_annotations_text_lineEdit.setObjectName('find_annotations_text_lineEdit') self.scgl.addWidget(self.find_annotations_text_lineEdit, row, 1, 1, 3) self.reset_text_tb = QToolButton() self.reset_text_tb.setObjectName('reset_text_tb') self.reset_text_tb.setToolTip('Clear search criteria') self.reset_text_tb.setIcon(QIcon(I('trash.png'))) self.reset_text_tb.clicked.connect(self.clear_text_field) self.scgl.addWidget(self.reset_text_tb, row, 4, 1, 1) row += 1 # ~~~~~~~~ Create the Note LineEdit control ~~~~~~~~ self.note_label = QLabel('Note') self.note_label.setAlignment(Qt.AlignRight|Qt.AlignVCenter) self.scgl.addWidget(self.note_label, row, 0, 1, 1) self.find_annotations_note_lineEdit = MyLineEdit() self.find_annotations_note_lineEdit.setObjectName('find_annotations_note_lineEdit') self.scgl.addWidget(self.find_annotations_note_lineEdit, row, 1, 1, 3) self.reset_note_tb = QToolButton() self.reset_note_tb.setObjectName('reset_note_tb') self.reset_note_tb.setToolTip('Clear search criteria') self.reset_note_tb.setIcon(QIcon(I('trash.png'))) self.reset_note_tb.clicked.connect(self.clear_note_field) self.scgl.addWidget(self.reset_note_tb, row, 4, 1, 1) row += 1 # ~~~~~~~~ Create the Date range controls ~~~~~~~~ self.date_range_label = QLabel('Date range') self.date_range_label.setAlignment(Qt.AlignRight|Qt.AlignVCenter) self.scgl.addWidget(self.date_range_label, row, 0, 1, 1) # Date 'From' self.find_annotations_date_from_dateEdit = MyDateEdit(self, datetime(1970,1,1)) self.find_annotations_date_from_dateEdit.setObjectName('find_annotations_date_from_dateEdit') #self.find_annotations_date_from_dateEdit.current_val = datetime(1970,1,1) self.find_annotations_date_from_dateEdit.clear_button.clicked.connect(self.find_annotations_date_from_dateEdit.reset_from_date) self.scgl.addWidget(self.find_annotations_date_from_dateEdit, row, 1, 1, 1) self.scgl.addWidget(self.find_annotations_date_from_dateEdit.clear_button, row, 2, 1, 1) # Date 'To' self.find_annotations_date_to_dateEdit = MyDateEdit(self, datetime.today()) self.find_annotations_date_to_dateEdit.setObjectName('find_annotations_date_to_dateEdit') #self.find_annotations_date_to_dateEdit.current_val = datetime.today() self.find_annotations_date_to_dateEdit.clear_button.clicked.connect(self.find_annotations_date_to_dateEdit.reset_to_date) self.scgl.addWidget(self.find_annotations_date_to_dateEdit, row, 3, 1, 1) self.scgl.addWidget(self.find_annotations_date_to_dateEdit.clear_button, row, 4, 1, 1) row += 1 # ~~~~~~~~ Create a horizontal line ~~~~~~~~ self.hl = QFrame(self) self.hl.setGeometry(QRect(0, 0, 1, 3)) self.hl.setFrameShape(QFrame.HLine) self.hl.setFrameShadow(QFrame.Raised) self.scgl.addWidget(self.hl, row, 0, 1, 5) row += 1 # ~~~~~~~~ Create the results label field ~~~~~~~~ self.result_label = QLabel('<p style="color:red">scanning…</p>') self.result_label.setAlignment(Qt.AlignCenter) self.result_label.setWordWrap(False) sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Maximum) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth(self.result_label.sizePolicy().hasHeightForWidth()) self.result_label.setSizePolicy(sizePolicy) self.result_label.setMinimumSize(QtCore.QSize(250, 0)) self.scgl.addWidget(self.result_label, row, 0, 1, 5) row += 1 # ~~~~~~~~ Create the ButtonBox ~~~~~~~~ self.dialogButtonBox = QDialogButtonBox(self) self.dialogButtonBox.setOrientation(Qt.Horizontal) if False: self.update_button = QPushButton('Update results') self.update_button.setDefault(True) self.update_button.setVisible(False) self.dialogButtonBox.addButton(self.update_button, QDialogButtonBox.ActionRole) self.cancel_button = self.dialogButtonBox.addButton(self.dialogButtonBox.Cancel) self.find_button = self.dialogButtonBox.addButton(self.dialogButtonBox.Ok) self.find_button.setText('Find Matching Books') self.l.addWidget(self.dialogButtonBox) self.dialogButtonBox.clicked.connect(self.find_annotations_dialog_clicked) # ~~~~~~~~ Add a spacer ~~~~~~~~ self.spacerItem = QtGui.QSpacerItem(20, 40, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding) self.l.addItem(self.spacerItem) # ~~~~~~~~ Restore previously saved settings ~~~~~~~~ self.restore_settings() # ~~~~~~~~ Declare sizing ~~~~~~~~ sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Preferred, QtGui.QSizePolicy.Preferred) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth(self.sizePolicy().hasHeightForWidth()) self.setSizePolicy(sizePolicy) self.resize_dialog() # ~~~~~~~~ Connect all signals ~~~~~~~~ self.find_annotations_reader_comboBox.currentIndexChanged.connect(partial(self.update_results, 'reader')) self.find_annotations_color_comboBox.currentIndexChanged.connect(partial(self.update_results, 'color')) self.find_annotations_text_lineEdit.editingFinished.connect(partial(self.update_results, 'text')) self.find_annotations_note_lineEdit.editingFinished.connect(partial(self.update_results, 'note')) # self.connect(self.find_annotations_text_lineEdit, pyqtSignal("return_pressed"), self.return_pressed) self.find_annotations_text_lineEdit.return_pressed.connect(self.return_pressed) # self.connect(self.find_annotations_note_lineEdit, pyqtSignal("return_pressed"), self.return_pressed) self.find_annotations_note_lineEdit.return_pressed.connect(self.return_pressed) # Date range signals connected in inventory_available() # ~~~~~~~~ Allow dialog to render before doing inventory ~~~~~~~~ #field = self.prefs.get('cfg_annotations_destination_field', None) field = get_cc_mapping('annotations', 'field', None) self.annotated_books_scanner = InventoryAnnotatedBooks(self.opts.gui, field, get_date_range=True) self.annotated_books_scanner.signal.connect(self.inventory_available) QTimer.singleShot(1, self.start_inventory_scan)
class FindAnnotationsDialog(SizePersistedDialog, Logger): GENERIC_STYLE = 'Any style' GENERIC_READER = 'Any reader' def __init__(self, opts): self.matched_ids = set() self.opts = opts self.prefs = opts.prefs super(FindAnnotationsDialog, self).__init__(self.opts.gui, 'find_annotations_dialog') self.setWindowTitle('Find Annotations') self.setWindowIcon(self.opts.icon) self.l = QVBoxLayout(self) self.setLayout(self.l) self.search_criteria_gb = QGroupBox(self) self.search_criteria_gb.setTitle("Search criteria") self.scgl = QGridLayout(self.search_criteria_gb) self.l.addWidget(self.search_criteria_gb) # addWidget(widget, row, col, rowspan, colspan) row = 0 # ~~~~~~~~ Create the Readers comboBox ~~~~~~~~ self.reader_label = QLabel('Reader') self.reader_label.setAlignment(Qt.AlignRight|Qt.AlignVCenter) self.scgl.addWidget(self.reader_label, row, 0, 1, 1) self.find_annotations_reader_comboBox = QComboBox() self.find_annotations_reader_comboBox.setObjectName('find_annotations_reader_comboBox') self.find_annotations_reader_comboBox.setToolTip('Reader annotations to search for') self.find_annotations_reader_comboBox.addItem(self.GENERIC_READER) racs = ReaderApp.get_reader_app_classes() for ra in sorted(racs.keys()): self.find_annotations_reader_comboBox.addItem(ra) self.scgl.addWidget(self.find_annotations_reader_comboBox, row, 1, 1, 4) row += 1 # ~~~~~~~~ Create the Styles comboBox ~~~~~~~~ self.style_label = QLabel('Style') self.style_label.setAlignment(Qt.AlignRight|Qt.AlignVCenter) self.scgl.addWidget(self.style_label, row, 0, 1, 1) self.find_annotations_color_comboBox = QComboBox() self.find_annotations_color_comboBox.setObjectName('find_annotations_color_comboBox') self.find_annotations_color_comboBox.setToolTip('Annotation style to search for') self.find_annotations_color_comboBox.addItem(self.GENERIC_STYLE) all_colors = COLOR_MAP.keys() all_colors.remove('Default') for color in sorted(all_colors): self.find_annotations_color_comboBox.addItem(color) self.scgl.addWidget(self.find_annotations_color_comboBox, row, 1, 1, 4) row += 1 # ~~~~~~~~ Create the Text LineEdit control ~~~~~~~~ self.text_label = QLabel('Text') self.text_label.setAlignment(Qt.AlignRight|Qt.AlignVCenter) self.scgl.addWidget(self.text_label, row, 0, 1, 1) self.find_annotations_text_lineEdit = MyLineEdit() self.find_annotations_text_lineEdit.setObjectName('find_annotations_text_lineEdit') self.scgl.addWidget(self.find_annotations_text_lineEdit, row, 1, 1, 3) self.reset_text_tb = QToolButton() self.reset_text_tb.setObjectName('reset_text_tb') self.reset_text_tb.setToolTip('Clear search criteria') self.reset_text_tb.setIcon(QIcon(I('trash.png'))) self.reset_text_tb.clicked.connect(self.clear_text_field) self.scgl.addWidget(self.reset_text_tb, row, 4, 1, 1) row += 1 # ~~~~~~~~ Create the Note LineEdit control ~~~~~~~~ self.note_label = QLabel('Note') self.note_label.setAlignment(Qt.AlignRight|Qt.AlignVCenter) self.scgl.addWidget(self.note_label, row, 0, 1, 1) self.find_annotations_note_lineEdit = MyLineEdit() self.find_annotations_note_lineEdit.setObjectName('find_annotations_note_lineEdit') self.scgl.addWidget(self.find_annotations_note_lineEdit, row, 1, 1, 3) self.reset_note_tb = QToolButton() self.reset_note_tb.setObjectName('reset_note_tb') self.reset_note_tb.setToolTip('Clear search criteria') self.reset_note_tb.setIcon(QIcon(I('trash.png'))) self.reset_note_tb.clicked.connect(self.clear_note_field) self.scgl.addWidget(self.reset_note_tb, row, 4, 1, 1) row += 1 # ~~~~~~~~ Create the Date range controls ~~~~~~~~ self.date_range_label = QLabel('Date range') self.date_range_label.setAlignment(Qt.AlignRight|Qt.AlignVCenter) self.scgl.addWidget(self.date_range_label, row, 0, 1, 1) # Date 'From' self.find_annotations_date_from_dateEdit = MyDateEdit(self, datetime(1970,1,1)) self.find_annotations_date_from_dateEdit.setObjectName('find_annotations_date_from_dateEdit') #self.find_annotations_date_from_dateEdit.current_val = datetime(1970,1,1) self.find_annotations_date_from_dateEdit.clear_button.clicked.connect(self.find_annotations_date_from_dateEdit.reset_from_date) self.scgl.addWidget(self.find_annotations_date_from_dateEdit, row, 1, 1, 1) self.scgl.addWidget(self.find_annotations_date_from_dateEdit.clear_button, row, 2, 1, 1) # Date 'To' self.find_annotations_date_to_dateEdit = MyDateEdit(self, datetime.today()) self.find_annotations_date_to_dateEdit.setObjectName('find_annotations_date_to_dateEdit') #self.find_annotations_date_to_dateEdit.current_val = datetime.today() self.find_annotations_date_to_dateEdit.clear_button.clicked.connect(self.find_annotations_date_to_dateEdit.reset_to_date) self.scgl.addWidget(self.find_annotations_date_to_dateEdit, row, 3, 1, 1) self.scgl.addWidget(self.find_annotations_date_to_dateEdit.clear_button, row, 4, 1, 1) row += 1 # ~~~~~~~~ Create a horizontal line ~~~~~~~~ self.hl = QFrame(self) self.hl.setGeometry(QRect(0, 0, 1, 3)) self.hl.setFrameShape(QFrame.HLine) self.hl.setFrameShadow(QFrame.Raised) self.scgl.addWidget(self.hl, row, 0, 1, 5) row += 1 # ~~~~~~~~ Create the results label field ~~~~~~~~ self.result_label = QLabel('<p style="color:red">scanning…</p>') self.result_label.setAlignment(Qt.AlignCenter) self.result_label.setWordWrap(False) sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Maximum) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth(self.result_label.sizePolicy().hasHeightForWidth()) self.result_label.setSizePolicy(sizePolicy) self.result_label.setMinimumSize(QtCore.QSize(250, 0)) self.scgl.addWidget(self.result_label, row, 0, 1, 5) row += 1 # ~~~~~~~~ Create the ButtonBox ~~~~~~~~ self.dialogButtonBox = QDialogButtonBox(self) self.dialogButtonBox.setOrientation(Qt.Horizontal) if False: self.update_button = QPushButton('Update results') self.update_button.setDefault(True) self.update_button.setVisible(False) self.dialogButtonBox.addButton(self.update_button, QDialogButtonBox.ActionRole) self.cancel_button = self.dialogButtonBox.addButton(self.dialogButtonBox.Cancel) self.find_button = self.dialogButtonBox.addButton(self.dialogButtonBox.Ok) self.find_button.setText('Find Matching Books') self.l.addWidget(self.dialogButtonBox) self.dialogButtonBox.clicked.connect(self.find_annotations_dialog_clicked) # ~~~~~~~~ Add a spacer ~~~~~~~~ self.spacerItem = QtGui.QSpacerItem(20, 40, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding) self.l.addItem(self.spacerItem) # ~~~~~~~~ Restore previously saved settings ~~~~~~~~ self.restore_settings() # ~~~~~~~~ Declare sizing ~~~~~~~~ sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Preferred, QtGui.QSizePolicy.Preferred) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth(self.sizePolicy().hasHeightForWidth()) self.setSizePolicy(sizePolicy) self.resize_dialog() # ~~~~~~~~ Connect all signals ~~~~~~~~ self.find_annotations_reader_comboBox.currentIndexChanged.connect(partial(self.update_results, 'reader')) self.find_annotations_color_comboBox.currentIndexChanged.connect(partial(self.update_results, 'color')) self.find_annotations_text_lineEdit.editingFinished.connect(partial(self.update_results, 'text')) self.find_annotations_note_lineEdit.editingFinished.connect(partial(self.update_results, 'note')) # self.connect(self.find_annotations_text_lineEdit, pyqtSignal("return_pressed"), self.return_pressed) self.find_annotations_text_lineEdit.return_pressed.connect(self.return_pressed) # self.connect(self.find_annotations_note_lineEdit, pyqtSignal("return_pressed"), self.return_pressed) self.find_annotations_note_lineEdit.return_pressed.connect(self.return_pressed) # Date range signals connected in inventory_available() # ~~~~~~~~ Allow dialog to render before doing inventory ~~~~~~~~ #field = self.prefs.get('cfg_annotations_destination_field', None) field = get_cc_mapping('annotations', 'field', None) self.annotated_books_scanner = InventoryAnnotatedBooks(self.opts.gui, field, get_date_range=True) self.annotated_books_scanner.signal.connect(self.inventory_available) QTimer.singleShot(1, self.start_inventory_scan) def clear_note_field(self): if str(self.find_annotations_note_lineEdit.text()) > '': self.find_annotations_note_lineEdit.setText('') self.update_results('clear_note_field') def clear_text_field(self): if str(self.find_annotations_text_lineEdit.text()) > '': self.find_annotations_text_lineEdit.setText('') self.update_results('clear_text_field') def find_annotations_dialog_clicked(self, button): if self.dialogButtonBox.buttonRole(button) == QDialogButtonBox.AcceptRole: self.save_settings() self.accept() elif self.dialogButtonBox.buttonRole(button) == QDialogButtonBox.RejectRole: self.close() def inventory_available(self): ''' Update the Date range widgets with the rounded oldest, newest dates Don't connect date signals until date range available ''' self._log_location() # Reset the date range based on available annotations oldest = QDateTime(datetime.fromtimestamp(self.annotated_books_scanner.oldest_annotation)) oldest_day = QDateTime(datetime.fromtimestamp(self.annotated_books_scanner.oldest_annotation).replace(hour=0, minute=0, second=0)) newest = QDateTime(datetime.fromtimestamp(self.annotated_books_scanner.newest_annotation)) newest_day = QDateTime(datetime.fromtimestamp(self.annotated_books_scanner.newest_annotation).replace(hour=23, minute=59, second=59)) # Set 'From' date limits to inventory values self.find_annotations_date_from_dateEdit.setMinimumDateTime(oldest_day) self.find_annotations_date_from_dateEdit.current_val = oldest self.find_annotations_date_from_dateEdit.setMaximumDateTime(newest_day) # Set 'To' date limits to inventory values self.find_annotations_date_to_dateEdit.setMinimumDateTime(oldest_day) self.find_annotations_date_to_dateEdit.current_val = newest_day self.find_annotations_date_to_dateEdit.setMaximumDateTime(newest_day) # Connect the signals for date range changes self.find_annotations_date_from_dateEdit.dateTimeChanged.connect(partial(self.update_results, 'from_date')) self.find_annotations_date_to_dateEdit.dateTimeChanged.connect(partial(self.update_results, 'to_date')) self.update_results('inventory_available') def restore_settings(self): self.blockSignals(True) ra = self.prefs.get('find_annotations_reader_comboBox', self.GENERIC_READER) ra_index = self.find_annotations_reader_comboBox.findText(ra) self.find_annotations_reader_comboBox.setCurrentIndex(ra_index) color = self.prefs.get('find_annotations_color_comboBox', self.GENERIC_STYLE) color_index = self.find_annotations_color_comboBox.findText(color) self.find_annotations_color_comboBox.setCurrentIndex(color_index) text = self.prefs.get('find_annotations_text_lineEdit', '') self.find_annotations_text_lineEdit.setText(text) note = self.prefs.get('find_annotations_note_lineEdit', '') self.find_annotations_note_lineEdit.setText(note) if False: from_date = self.prefs.get('find_annotations_date_from_dateEdit', datetime(1970,1,1)) self.find_annotations_date_from_dateEdit.current_val = from_date to_date = self.prefs.get('find_annotations_date_to_dateEdit', datetime.today()) self.find_annotations_date_to_dateEdit.current_val = to_date self.blockSignals(False) def return_pressed(self): self.update_results("return_pressed") def save_settings(self): ra = str(self.find_annotations_reader_comboBox.currentText()) self.prefs.set('find_annotations_reader_comboBox', ra) color = str(self.find_annotations_color_comboBox.currentText()) self.prefs.set('find_annotations_color_comboBox', color) text = str(self.find_annotations_text_lineEdit.text()) self.prefs.set('find_annotations_text_lineEdit', text) note = str(self.find_annotations_note_lineEdit.text()) self.prefs.set('find_annotations_note_lineEdit', note) if False: from_date = self.find_annotations_date_from_dateEdit.current_val self.prefs.set('find_annotations_date_from_dateEdit', from_date) to_date = self.find_annotations_date_to_dateEdit.current_val self.prefs.set('find_annotations_date_to_dateEdit', to_date) def start_inventory_scan(self): self._log_location() self.annotated_books_scanner.start() def update_results(self, trigger): #self._log_location(trigger) reader_to_match = str(self.find_annotations_reader_comboBox.currentText()) color_to_match = str(self.find_annotations_color_comboBox.currentText()) text_to_match = str(self.find_annotations_text_lineEdit.text()) note_to_match = str(self.find_annotations_note_lineEdit.text()) from_date = self.find_annotations_date_from_dateEdit.dateTime().toTime_t() to_date = self.find_annotations_date_to_dateEdit.dateTime().toTime_t() annotation_map = self.annotated_books_scanner.annotation_map #field = self.prefs.get("cfg_annotations_destination_field", None) field = get_cc_mapping('annotations', 'field', None) db = self.opts.gui.current_db matched_titles = [] self.matched_ids = set() for cid in annotation_map: mi = db.get_metadata(cid, index_is_id=True) soup = None if field == 'Comments': if mi.comments: soup = BeautifulSoup(mi.comments) else: if mi.get_user_metadata(field, False)['#value#'] is not None: soup = BeautifulSoup(mi.get_user_metadata(field, False)['#value#']) if soup: uas = soup.findAll('div', 'annotation') for ua in uas: # Are we already logged? if cid in self.matched_ids: continue # Check reader if reader_to_match != self.GENERIC_READER: this_reader = ua['reader'] if this_reader != reader_to_match: continue # Check color if color_to_match != self.GENERIC_STYLE: this_color = ua.find('table')['color'] if this_color != color_to_match: continue # Check date range, allow for mangled timestamp try: timestamp = float(ua.find('td', 'timestamp')['uts']) if timestamp < from_date or timestamp > to_date: continue except: continue highlight_text = '' try: pels = ua.findAll('p', 'highlight') for pel in pels: highlight_text += pel.string + '\n' except: pass if text_to_match > '': if not re.search(text_to_match, highlight_text, flags=re.IGNORECASE): continue note_text = '' try: nels = ua.findAll('p', 'note') for nel in nels: note_text += nel.string + '\n' except: pass if note_to_match > '': if not re.search(note_to_match, note_text, flags=re.IGNORECASE): continue # If we made it this far, add the id to matched_ids self.matched_ids.add(cid) matched_titles.append(mi.title) # Update the results box matched_titles.sort() if len(annotation_map): if len(matched_titles): first_match = ("<i>%s</i>" % matched_titles[0]) if len(matched_titles) == 1: results = first_match else: results = first_match + (" and %d more." % (len(matched_titles) - 1)) self.result_label.setText('<p style="color:blue">{0}</p>'.format(results)) else: self.result_label.setText('<p style="color:red">no matches</p>') else: self.result_label.setText('<p style="color:red">no annotated books in library</p>') self.resize_dialog()
def __init__(self, parent): QFrame.__init__(self, parent) self.setFrameShape(QFrame.StyledPanel) self.setMinimumWidth(250) self.stack = s = QStackedWidget(self) self.l = l = QVBoxLayout() self.setLayout(l) l.addWidget(s) self.root_pane = rp = QWidget(self) self.item_pane = ip = QWidget(self) self.current_item = None s.addWidget(rp) s.addWidget(ip) self.l1 = la = QLabel('<p>'+_( 'You can edit existing entries in the Table of Contents by clicking them' ' in the panel to the left.')+'<p>'+_( 'Entries with a green tick next to them point to a location that has ' 'been verified to exist. Entries with a red dot are broken and may need' ' to be fixed.')) la.setStyleSheet('QLabel { margin-bottom: 20px }') la.setWordWrap(True) l = rp.l = QVBoxLayout() rp.setLayout(l) l.addWidget(la) self.add_new_to_root_button = b = QPushButton(_('Create a &new entry')) b.clicked.connect(self.add_new_to_root) l.addWidget(b) l.addStretch() self.cfmhb = b = QPushButton(_('Generate ToC from &major headings')) b.clicked.connect(self.create_from_major_headings) b.setToolTip(textwrap.fill(_( 'Generate a Table of Contents from the major headings in the book.' ' This will work if the book identifies its headings using HTML' ' heading tags. Uses the <h1>, <h2> and <h3> tags.'))) l.addWidget(b) self.cfmab = b = QPushButton(_('Generate ToC from &all headings')) b.clicked.connect(self.create_from_all_headings) b.setToolTip(textwrap.fill(_( 'Generate a Table of Contents from all the headings in the book.' ' This will work if the book identifies its headings using HTML' ' heading tags. Uses the <h1-6> tags.'))) l.addWidget(b) self.lb = b = QPushButton(_('Generate ToC from &links')) b.clicked.connect(self.create_from_links) b.setToolTip(textwrap.fill(_( 'Generate a Table of Contents from all the links in the book.' ' Links that point to destinations that do not exist in the book are' ' ignored. Also multiple links with the same destination or the same' ' text are ignored.' ))) l.addWidget(b) self.cfb = b = QPushButton(_('Generate ToC from &files')) b.clicked.connect(self.create_from_files) b.setToolTip(textwrap.fill(_( 'Generate a Table of Contents from individual files in the book.' ' Each entry in the ToC will point to the start of the file, the' ' text of the entry will be the "first line" of text from the file.' ))) l.addWidget(b) self.xpb = b = QPushButton(_('Generate ToC from &XPath')) b.clicked.connect(self.create_from_user_xpath) b.setToolTip(textwrap.fill(_( 'Generate a Table of Contents from arbitrary XPath expressions.' ))) l.addWidget(b) self.fal = b = QPushButton(_('&Flatten the ToC')) b.clicked.connect(self.flatten_toc) b.setToolTip(textwrap.fill(_( 'Flatten the Table of Contents, putting all entries at the top level' ))) l.addWidget(b) l.addStretch() self.w1 = la = QLabel(_('<b>WARNING:</b> calibre only supports the ' 'creation of linear ToCs in AZW3 files. In a ' 'linear ToC every entry must point to a ' 'location after the previous entry. If you ' 'create a non-linear ToC it will be ' 'automatically re-arranged inside the AZW3 file.' )) la.setWordWrap(True) l.addWidget(la) l = ip.l = QGridLayout() ip.setLayout(l) la = ip.heading = QLabel('') l.addWidget(la, 0, 0, 1, 2) la.setWordWrap(True) la = ip.la = QLabel(_( 'You can move this entry around the Table of Contents by drag ' 'and drop or using the up and down buttons to the left')) la.setWordWrap(True) l.addWidget(la, 1, 0, 1, 2) # Item status ip.hl1 = hl = QFrame() hl.setFrameShape(hl.HLine) l.addWidget(hl, l.rowCount(), 0, 1, 2) self.icon_label = QLabel() self.status_label = QLabel() self.status_label.setWordWrap(True) l.addWidget(self.icon_label, l.rowCount(), 0) l.addWidget(self.status_label, l.rowCount()-1, 1) ip.hl2 = hl = QFrame() hl.setFrameShape(hl.HLine) l.addWidget(hl, l.rowCount(), 0, 1, 2) # Edit/remove item rs = l.rowCount() ip.b1 = b = QPushButton(QIcon(I('edit_input.png')), _('Change the &location this entry points to'), self) b.clicked.connect(self.edit_item) l.addWidget(b, l.rowCount()+1, 0, 1, 2) ip.b2 = b = QPushButton(QIcon(I('trash.png')), _('&Remove this entry'), self) l.addWidget(b, l.rowCount(), 0, 1, 2) b.clicked.connect(self.delete_item) ip.hl3 = hl = QFrame() hl.setFrameShape(hl.HLine) l.addWidget(hl, l.rowCount(), 0, 1, 2) l.setRowMinimumHeight(rs, 20) # Add new item rs = l.rowCount() ip.b3 = b = QPushButton(QIcon(I('plus.png')), _('New entry &inside this entry')) b.clicked.connect(partial(self.add_new, 'inside')) l.addWidget(b, l.rowCount()+1, 0, 1, 2) ip.b4 = b = QPushButton(QIcon(I('plus.png')), _('New entry &above this entry')) b.clicked.connect(partial(self.add_new, 'before')) l.addWidget(b, l.rowCount(), 0, 1, 2) ip.b5 = b = QPushButton(QIcon(I('plus.png')), _('New entry &below this entry')) b.clicked.connect(partial(self.add_new, 'after')) l.addWidget(b, l.rowCount(), 0, 1, 2) # Flatten entry ip.b3 = b = QPushButton(QIcon(I('heuristics.png')), _('&Flatten this entry')) b.clicked.connect(self.flatten_item) b.setToolTip(_('All children of this entry are brought to the same ' 'level as this entry.')) l.addWidget(b, l.rowCount()+1, 0, 1, 2) ip.hl4 = hl = QFrame() hl.setFrameShape(hl.HLine) l.addWidget(hl, l.rowCount(), 0, 1, 2) l.setRowMinimumHeight(rs, 20) # Return to welcome rs = l.rowCount() ip.b4 = b = QPushButton(QIcon(I('back.png')), _('&Return to welcome screen')) b.clicked.connect(self.go_to_root) b.setToolTip(_('Go back to the top level view')) l.addWidget(b, l.rowCount()+1, 0, 1, 2) l.setRowMinimumHeight(rs, 20) l.addWidget(QLabel(), l.rowCount(), 0, 1, 2) l.setColumnStretch(1, 10) l.setRowStretch(l.rowCount()-1, 10) self.w2 = la = QLabel(self.w1.text()) self.w2.setWordWrap(True) l.addWidget(la, l.rowCount(), 0, 1, 2)
class UnpackBook(QDialog): def __init__(self, parent, book_id, fmts, db): QDialog.__init__(self, parent) self.setWindowIcon(QIcon(I('unpack-book.png'))) self.book_id, self.fmts, self.db_ref = book_id, fmts, weakref.ref(db) self._exploded = None self._cleanup_dirs = [] self._cleanup_files = [] self.setup_ui() self.setWindowTitle(_('Unpack Book') + ' - ' + db.title(book_id, index_is_id=True)) button = self.fmt_choice_buttons[0] button_map = {unicode(x.text()):x for x in self.fmt_choice_buttons} of = prefs['output_format'].upper() df = tweaks.get('default_tweak_format', None) lf = gprefs.get('last_tweak_format', None) if df and df.lower() == 'remember' and lf in button_map: button = button_map[lf] elif df and df.upper() in button_map: button = button_map[df.upper()] elif of in button_map: button = button_map[of] button.setChecked(True) self.init_state() for button in self.fmt_choice_buttons: button.toggled.connect(self.init_state) def init_state(self, *args): self._exploded = None self.preview_button.setEnabled(False) self.rebuild_button.setEnabled(False) self.explode_button.setEnabled(True) def setup_ui(self): # {{{ self._g = g = QHBoxLayout(self) self.setLayout(g) self._l = l = QVBoxLayout() g.addLayout(l) fmts = sorted(x.upper() for x in self.fmts) self.fmt_choice_box = QGroupBox(_('Choose the format to unpack:'), self) self._fl = fl = QHBoxLayout() self.fmt_choice_box.setLayout(self._fl) self.fmt_choice_buttons = [QRadioButton(y, self) for y in fmts] for x in self.fmt_choice_buttons: fl.addWidget(x, stretch=10 if x is self.fmt_choice_buttons[-1] else 0) l.addWidget(self.fmt_choice_box) self.fmt_choice_box.setVisible(len(fmts) > 1) self.help_label = QLabel(_('''\ <h2>About Unpack Book</h2> <p>Unpack Book allows you to fine tune the appearance of an ebook by making small changes to its internals. In order to use Unpack Book, you need to know a little bit about HTML and CSS, technologies that are used in ebooks. Follow the steps:</p> <br> <ol> <li>Click "Explode Book": This will "explode" the book into its individual internal components.<br></li> <li>Right click on any individual file and select "Open with..." to edit it in your favorite text editor.<br></li> <li>When you are done: <b>close the file browser window and the editor windows you used to make your tweaks</b>. Then click the "Rebuild Book" button, to update the book in your calibre library.</li> </ol>''')) self.help_label.setWordWrap(True) self._fr = QFrame() self._fr.setFrameShape(QFrame.VLine) g.addWidget(self._fr) g.addWidget(self.help_label) self._b = b = QGridLayout() left, top, right, bottom = b.getContentsMargins() top += top b.setContentsMargins(left, top, right, bottom) l.addLayout(b, stretch=10) self.explode_button = QPushButton(QIcon(I('wizard.png')), _('&Explode Book')) self.preview_button = QPushButton(QIcon(I('view.png')), _('&Preview Book')) self.cancel_button = QPushButton(QIcon(I('window-close.png')), _('&Cancel')) self.rebuild_button = QPushButton(QIcon(I('exec.png')), _('&Rebuild Book')) self.explode_button.setToolTip( _('Explode the book to edit its components')) self.preview_button.setToolTip( _('Preview the result of your changes')) self.cancel_button.setToolTip( _('Abort without saving any changes')) self.rebuild_button.setToolTip( _('Save your changes and update the book in the calibre library')) a = b.addWidget a(self.explode_button, 0, 0, 1, 1) a(self.preview_button, 0, 1, 1, 1) a(self.cancel_button, 1, 0, 1, 1) a(self.rebuild_button, 1, 1, 1, 1) for x in ('explode', 'preview', 'cancel', 'rebuild'): getattr(self, x+'_button').clicked.connect(getattr(self, x)) self.msg = QLabel('dummy', self) self.msg.setVisible(False) self.msg.setStyleSheet(''' QLabel { text-align: center; background-color: white; color: black; border-width: 1px; border-style: solid; border-radius: 20px; font-size: x-large; font-weight: bold; } ''') self.resize(self.sizeHint() + QSize(40, 10)) # }}} def show_msg(self, msg): self.msg.setText(msg) self.msg.resize(self.size() - QSize(50, 25)) self.msg.move((self.width() - self.msg.width())//2, (self.height() - self.msg.height())//2) self.msg.setVisible(True) def hide_msg(self): self.msg.setVisible(False) def explode(self): self.show_msg(_('Exploding, please wait...')) if len(self.fmt_choice_buttons) > 1: gprefs.set('last_tweak_format', self.current_format.upper()) QTimer.singleShot(5, self.do_explode) def ask_question(self, msg): return question_dialog(self, _('Are you sure?'), msg) def do_explode(self): from calibre.ebooks.tweak import get_tools, Error, WorkerError tdir = PersistentTemporaryDirectory('_tweak_explode') self._cleanup_dirs.append(tdir) det_msg = None try: src = self.db.format(self.book_id, self.current_format, index_is_id=True, as_path=True) self._cleanup_files.append(src) exploder = get_tools(self.current_format)[0] opf = exploder(src, tdir, question=self.ask_question) except WorkerError as e: det_msg = e.orig_tb except Error as e: return error_dialog(self, _('Failed to unpack'), (_('Could not explode the %s file.')%self.current_format) + ' ' + as_unicode(e), show=True) except: import traceback det_msg = traceback.format_exc() finally: self.hide_msg() if det_msg is not None: return error_dialog(self, _('Failed to unpack'), _('Could not explode the %s file. Click "Show Details" for ' 'more information.')%self.current_format, det_msg=det_msg, show=True) if opf is None: # The question was answered with No return self._exploded = tdir self.explode_button.setEnabled(False) self.preview_button.setEnabled(True) self.rebuild_button.setEnabled(True) open_local_file(tdir) def rebuild_it(self): from calibre.ebooks.tweak import get_tools, WorkerError src_dir = self._exploded det_msg = None of = PersistentTemporaryFile('_tweak_rebuild.'+self.current_format.lower()) of.close() of = of.name self._cleanup_files.append(of) try: rebuilder = get_tools(self.current_format)[1] rebuilder(src_dir, of) except WorkerError as e: det_msg = e.orig_tb except: import traceback det_msg = traceback.format_exc() finally: self.hide_msg() if det_msg is not None: error_dialog(self, _('Failed to rebuild file'), _('Failed to rebuild %s. For more information, click ' '"Show details".')%self.current_format, det_msg=det_msg, show=True) return None return of def preview(self): self.show_msg(_('Rebuilding, please wait...')) QTimer.singleShot(5, self.do_preview) def do_preview(self): rebuilt = self.rebuild_it() if rebuilt is not None: self.parent().iactions['View']._view_file(rebuilt) def rebuild(self): self.show_msg(_('Rebuilding, please wait...')) QTimer.singleShot(5, self.do_rebuild) def do_rebuild(self): rebuilt = self.rebuild_it() if rebuilt is not None: fmt = os.path.splitext(rebuilt)[1][1:].upper() with open(rebuilt, 'rb') as f: self.db.add_format(self.book_id, fmt, f, index_is_id=True) self.accept() def cancel(self): self.reject() def cleanup(self): if isosx and self._exploded: try: import appscript self.finder = appscript.app('Finder') self.finder.Finder_windows[os.path.basename(self._exploded)].close() except: pass for f in self._cleanup_files: try: os.remove(f) except: pass for d in self._cleanup_dirs: try: shutil.rmtree(d) except: pass @property def db(self): return self.db_ref() @property def current_format(self): for b in self.fmt_choice_buttons: if b.isChecked(): return unicode(b.text())
class ProgressWindow(QWidget): def __init__(self, message): QWidget.__init__(self, ctx.mainScreen) self.setObjectName("ProgressWindow") self.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) self.setFixedHeight(50) self.setMaximumWidth(800) self.setStyleSheet(""" QFrame#frame { border: 1px solid rgba(255,255,255,30); /*border-radius: 4px;*/ background-color: rgba(255,0,0,100);} QLabel { border:none; color:#FFFFFF;} QProgressBar { border: 1px solid white;} QProgressBar::chunk { background-color: #F1610D; width: 0.5px;} """) self.gridlayout = QGridLayout(self) self.frame = QFrame(self) self.frame.setObjectName("frame") self.horizontalLayout = QHBoxLayout(self.frame) self.horizontalLayout.setContentsMargins(6, 0, 0, 0) # Spinner self.spinner = QLabel(self.frame) self.spinner.setMinimumSize(QSize(16, 16)) self.spinner.setMaximumSize(QSize(16, 16)) self.spinner.setIndent(6) self.movie = QMovie(':/images/working.mng') self.spinner.setMovie(self.movie) self.movie.start() self.horizontalLayout.addWidget(self.spinner) # Message self.label = QLabel(self.frame) self.label.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) self.horizontalLayout.addWidget(self.label) self.gridlayout.addWidget(self.frame,0,0,1,1) self.update(message) def update(self, message): self.spinner.setVisible(True) fontMetric = self.label.fontMetrics() textWidth = fontMetric.width(message) self.setFixedWidth(textWidth + 100) self.label.setText(message) self.move(ctx.mainScreen.width()/2 - self.width()/2, ctx.mainScreen.height() - self.height()/2 - 50) self.show() def refresh(self): ctx.mainScreen.processEvents() def show(self): QWidget.show(self) self.refresh() def pop(self): QWidget.hide(self) self.refresh()
class RuleEditor(QDialog): # {{{ @property def doing_multiple(self): return hasattr(self, 'multiple_icon_cb') and self.multiple_icon_cb.isChecked() def __init__(self, fm, pref_name, parent=None): QDialog.__init__(self, parent) self.fm = fm if pref_name == 'column_color_rules': self.rule_kind = 'color' rule_text = _('column coloring') elif pref_name == 'column_icon_rules': self.rule_kind = 'icon' rule_text = _('column icon') elif pref_name == 'cover_grid_icon_rules': self.rule_kind = 'emblem' rule_text = _('Cover grid emblem') self.setWindowIcon(QIcon(I('format-fill-color.png'))) self.setWindowTitle(_('Create/edit a {0} rule').format(rule_text)) self.l = l = QGridLayout(self) self.setLayout(l) self.l1 = l1 = QLabel(_('Create a {0} rule by' ' filling in the boxes below').format(rule_text)) l.addWidget(l1, 0, 0, 1, 8) self.f1 = QFrame(self) self.f1.setFrameShape(QFrame.HLine) l.addWidget(self.f1, 1, 0, 1, 8) self.l2 = l2 = QLabel(_('Add the emblem:') if self.rule_kind == 'emblem' else _('Set the')) l.addWidget(l2, 2, 0) if self.rule_kind == 'color': l.addWidget(QLabel(_('color'))) elif self.rule_kind == 'icon': self.kind_box = QComboBox(self) for tt, t in icon_rule_kinds: self.kind_box.addItem(tt, t) l.addWidget(self.kind_box, 2, 1) self.kind_box.setToolTip(textwrap.fill(_( 'If you choose composed icons and multiple rules match, then all the' ' matching icons will be combined, otherwise the icon from the' ' first rule to match will be used.'))) else: pass self.l3 = l3 = QLabel(_('of the column:')) l.addWidget(l3, 2, 2) self.column_box = QComboBox(self) l.addWidget(self.column_box, 2, 3) self.l4 = l4 = QLabel(_('to')) l.addWidget(l4, 2, 4) if self.rule_kind == 'emblem': l3.setVisible(False), self.column_box.setVisible(False), l4.setVisible(False) def create_filename_box(): self.filename_box = f = QComboBox() self.filenamebox_view = v = QListView() v.setIconSize(QSize(32, 32)) self.filename_box.setView(v) self.orig_filenamebox_view = f.view() f.setMinimumContentsLength(20), f.setSizeAdjustPolicy(f.AdjustToMinimumContentsLengthWithIcon) self.populate_icon_filenames() if self.rule_kind == 'color': self.color_box = ColorButton(parent=self) self.color_label = QLabel('Sample text Sample text') self.color_label.setTextFormat(Qt.RichText) l.addWidget(self.color_box, 2, 5) l.addWidget(self.color_label, 2, 6) l.addItem(QSpacerItem(10, 10, QSizePolicy.Expanding), 2, 7) elif self.rule_kind == 'emblem': create_filename_box() self.update_filename_box() self.filename_button = QPushButton(QIcon(I('document_open.png')), _('&Add new image')) l.addWidget(self.filename_box) l.addWidget(self.filename_button, 2, 6) l.addWidget(QLabel(_('(Images should be square-ish)')), 2, 7) l.setColumnStretch(7, 10) else: create_filename_box() vb = QVBoxLayout() self.multiple_icon_cb = QCheckBox(_('Choose &more than one icon')) vb.addWidget(self.multiple_icon_cb) self.update_filename_box() self.multiple_icon_cb.clicked.connect(self.multiple_box_clicked) vb.addWidget(self.filename_box) l.addLayout(vb, 2, 5) self.filename_button = QPushButton(QIcon(I('document_open.png')), _('&Add icon')) l.addWidget(self.filename_button, 2, 6) l.addWidget(QLabel(_('Icons should be square or landscape')), 2, 7) l.setColumnStretch(7, 10) self.l5 = l5 = QLabel( _('Only if the following conditions are all satisfied:')) l.addWidget(l5, 3, 0, 1, 7) self.scroll_area = sa = QScrollArea(self) sa.setMinimumHeight(300) sa.setMinimumWidth(950) sa.setWidgetResizable(True) l.addWidget(sa, 4, 0, 1, 8) self.add_button = b = QPushButton(QIcon(I('plus.png')), _('Add &another condition')) l.addWidget(b, 5, 0, 1, 8) b.clicked.connect(self.add_blank_condition) self.l6 = l6 = QLabel(_('You can disable a condition by' ' blanking all of its boxes')) l.addWidget(l6, 6, 0, 1, 8) self.bb = bb = QDialogButtonBox( QDialogButtonBox.Ok|QDialogButtonBox.Cancel) bb.accepted.connect(self.accept) bb.rejected.connect(self.reject) l.addWidget(bb, 7, 0, 1, 8) if self.rule_kind != 'color': self.remove_button = b = bb.addButton(_('&Remove icon'), bb.ActionRole) b.setIcon(QIcon(I('minus.png'))) b.setMenu(QMenu()) b.setToolTip('<p>' + _('Remove a previously added icon. Note that doing so will cause rules that use it to stop working.')) self.update_remove_button() self.conditions_widget = QWidget(self) sa.setWidget(self.conditions_widget) self.conditions_widget.setLayout(QVBoxLayout()) self.conditions_widget.layout().setAlignment(Qt.AlignTop) self.conditions = [] if self.rule_kind == 'color': for b in (self.column_box, ): b.setSizeAdjustPolicy(b.AdjustToMinimumContentsLengthWithIcon) b.setMinimumContentsLength(15) for key in sorted(displayable_columns(fm), key=lambda(k): sort_key(fm[k]['name']) if k != color_row_key else 0): if key == color_row_key and self.rule_kind != 'color': continue name = all_columns_string if key == color_row_key else fm[key]['name'] if name: self.column_box.addItem(name, key) self.column_box.setCurrentIndex(0) if self.rule_kind == 'color': self.color_box.color = '#000' self.update_color_label() self.color_box.color_changed.connect(self.update_color_label) else: self.rule_icon_files = [] self.filename_button.clicked.connect(self.filename_button_clicked) self.resize(self.sizeHint()) def multiple_box_clicked(self): self.update_filename_box() self.update_icon_filenames_in_box() @property def icon_folder(self): return os.path.join(config_dir, 'cc_icons') def populate_icon_filenames(self): d = self.icon_folder self.icon_file_names = [] if os.path.exists(d): for icon_file in os.listdir(d): icon_file = lower(icon_file) if os.path.exists(os.path.join(d, icon_file)) and icon_file.endswith('.png'): self.icon_file_names.append(icon_file) self.icon_file_names.sort(key=sort_key) def update_filename_box(self): doing_multiple = self.doing_multiple model = QStandardItemModel() self.filename_box.setModel(model) self.icon_file_names.sort(key=sort_key) if doing_multiple: item = QStandardItem(_('Open to see checkboxes')) item.setIcon(QIcon(I('blank.png'))) else: item = QStandardItem('') item.setFlags(Qt.ItemFlag(0)) model.appendRow(item) for i,filename in enumerate(self.icon_file_names): item = QStandardItem(filename) if doing_multiple: item.setFlags(Qt.ItemIsUserCheckable | Qt.ItemIsEnabled) item.setData(Qt.Unchecked, Qt.CheckStateRole) else: item.setFlags(Qt.ItemIsEnabled | Qt.ItemIsSelectable) icon = QIcon(os.path.join(self.icon_folder, filename)) item.setIcon(icon) model.appendRow(item) def update_color_label(self): pal = QApplication.palette() bg1 = unicode(pal.color(pal.Base).name()) bg2 = unicode(pal.color(pal.AlternateBase).name()) c = self.color_box.color self.color_label.setText(''' <span style="color: {c}; background-color: {bg1}"> {st} </span> <span style="color: {c}; background-color: {bg2}"> {st} </span> '''.format(c=c, bg1=bg1, bg2=bg2, st=_('Sample text'))) def sanitize_icon_file_name(self, icon_path): n = lower(sanitize_file_name_unicode( os.path.splitext( os.path.basename(icon_path))[0]+'.png')) return n.replace("'", '_') def filename_button_clicked(self): try: path = choose_files(self, 'choose_category_icon', _('Select Icon'), filters=[ (_('Images'), ['png', 'gif', 'jpg', 'jpeg'])], all_files=False, select_only_single_file=True) if path: icon_path = path[0] icon_name = self.sanitize_icon_file_name(icon_path) if icon_name not in self.icon_file_names: self.icon_file_names.append(icon_name) try: p = QIcon(icon_path).pixmap(QSize(128, 128)) d = self.icon_folder if not os.path.exists(os.path.join(d, icon_name)): if not os.path.exists(d): os.makedirs(d) with open(os.path.join(d, icon_name), 'wb') as f: f.write(pixmap_to_data(p, format='PNG')) except: import traceback traceback.print_exc() self.update_filename_box() self.update_remove_button() if self.doing_multiple: if icon_name not in self.rule_icon_files: self.rule_icon_files.append(icon_name) self.update_icon_filenames_in_box() else: self.filename_box.setCurrentIndex(self.filename_box.findText(icon_name)) self.filename_box.adjustSize() except: import traceback traceback.print_exc() return def get_filenames_from_box(self): if self.doing_multiple: model = self.filename_box.model() fnames = [] for i in range(1, model.rowCount()): item = model.item(i, 0) if item.checkState() == Qt.Checked: fnames.append(lower(unicode(item.text()))) fname = ' : '.join(fnames) else: fname = lower(unicode(self.filename_box.currentText())) return fname def update_icon_filenames_in_box(self): if self.rule_icon_files: if not self.doing_multiple: idx = self.filename_box.findText(self.rule_icon_files[0]) if idx >= 0: self.filename_box.setCurrentIndex(idx) else: self.filename_box.setCurrentIndex(0) else: model = self.filename_box.model() for icon in self.rule_icon_files: idx = self.filename_box.findText(icon) if idx >= 0: item = model.item(idx) item.setCheckState(Qt.Checked) def update_remove_button(self): m = self.remove_button.menu() m.clear() for name in self.icon_file_names: m.addAction(QIcon(os.path.join(self.icon_folder, name)), name).triggered.connect(partial( self.remove_image, name)) def remove_image(self, name): try: os.remove(os.path.join(self.icon_folder, name)) except EnvironmentError: pass else: self.populate_icon_filenames() self.update_remove_button() self.update_filename_box() self.update_icon_filenames_in_box() def add_blank_condition(self): c = ConditionEditor(self.fm, parent=self.conditions_widget) self.conditions.append(c) self.conditions_widget.layout().addWidget(c) def apply_rule(self, kind, col, rule): if kind == 'color': if rule.color: self.color_box.color = rule.color else: if self.rule_kind == 'icon': for i, tup in enumerate(icon_rule_kinds): if kind == tup[1]: self.kind_box.setCurrentIndex(i) break self.rule_icon_files = [ic.strip() for ic in rule.color.split(':')] if len(self.rule_icon_files) > 1: self.multiple_icon_cb.setChecked(True) self.update_filename_box() self.update_icon_filenames_in_box() for i in range(self.column_box.count()): c = unicode(self.column_box.itemData(i) or '') if col == c: self.column_box.setCurrentIndex(i) break for c in rule.conditions: ce = ConditionEditor(self.fm, parent=self.conditions_widget) self.conditions.append(ce) self.conditions_widget.layout().addWidget(ce) try: ce.condition = c except: import traceback traceback.print_exc() def accept(self): if self.rule_kind != 'color': fname = self.get_filenames_from_box() if not fname: error_dialog(self, _('No icon selected'), _('You must choose an icon for this rule'), show=True) return if self.validate(): QDialog.accept(self) def validate(self): r = Rule(self.fm) for c in self.conditions: condition = c.condition if condition is not None: try: r.add_condition(*condition) except Exception as e: import traceback error_dialog(self, _('Invalid condition'), _('One of the conditions for this rule is' ' invalid: <b>%s</b>')%e, det_msg=traceback.format_exc(), show=True) return False if len(r.conditions) < 1: error_dialog(self, _('No conditions'), _('You must specify at least one non-empty condition' ' for this rule'), show=True) return False return True @property def rule(self): r = Rule(self.fm) if self.rule_kind != 'color': r.color = self.get_filenames_from_box() else: r.color = self.color_box.color idx = self.column_box.currentIndex() col = unicode(self.column_box.itemData(idx) or '') for c in self.conditions: condition = c.condition if condition is not None: r.add_condition(*condition) if self.rule_kind == 'icon': kind = unicode(self.kind_box.itemData( self.kind_box.currentIndex()) or '') else: kind = self.rule_kind return kind, col, r
def __init__(self, fm, pref_name, parent=None): QDialog.__init__(self, parent) self.fm = fm if pref_name == 'column_color_rules': self.rule_kind = 'color' rule_text = _('column coloring') elif pref_name == 'column_icon_rules': self.rule_kind = 'icon' rule_text = _('column icon') elif pref_name == 'cover_grid_icon_rules': self.rule_kind = 'emblem' rule_text = _('Cover grid emblem') self.setWindowIcon(QIcon(I('format-fill-color.png'))) self.setWindowTitle(_('Create/edit a {0} rule').format(rule_text)) self.l = l = QGridLayout(self) self.setLayout(l) self.l1 = l1 = QLabel(_('Create a {0} rule by' ' filling in the boxes below').format(rule_text)) l.addWidget(l1, 0, 0, 1, 8) self.f1 = QFrame(self) self.f1.setFrameShape(QFrame.HLine) l.addWidget(self.f1, 1, 0, 1, 8) self.l2 = l2 = QLabel(_('Add the emblem:') if self.rule_kind == 'emblem' else _('Set the')) l.addWidget(l2, 2, 0) if self.rule_kind == 'color': l.addWidget(QLabel(_('color'))) elif self.rule_kind == 'icon': self.kind_box = QComboBox(self) for tt, t in icon_rule_kinds: self.kind_box.addItem(tt, t) l.addWidget(self.kind_box, 2, 1) self.kind_box.setToolTip(textwrap.fill(_( 'If you choose composed icons and multiple rules match, then all the' ' matching icons will be combined, otherwise the icon from the' ' first rule to match will be used.'))) else: pass self.l3 = l3 = QLabel(_('of the column:')) l.addWidget(l3, 2, 2) self.column_box = QComboBox(self) l.addWidget(self.column_box, 2, 3) self.l4 = l4 = QLabel(_('to')) l.addWidget(l4, 2, 4) if self.rule_kind == 'emblem': l3.setVisible(False), self.column_box.setVisible(False), l4.setVisible(False) def create_filename_box(): self.filename_box = f = QComboBox() self.filenamebox_view = v = QListView() v.setIconSize(QSize(32, 32)) self.filename_box.setView(v) self.orig_filenamebox_view = f.view() f.setMinimumContentsLength(20), f.setSizeAdjustPolicy(f.AdjustToMinimumContentsLengthWithIcon) self.populate_icon_filenames() if self.rule_kind == 'color': self.color_box = ColorButton(parent=self) self.color_label = QLabel('Sample text Sample text') self.color_label.setTextFormat(Qt.RichText) l.addWidget(self.color_box, 2, 5) l.addWidget(self.color_label, 2, 6) l.addItem(QSpacerItem(10, 10, QSizePolicy.Expanding), 2, 7) elif self.rule_kind == 'emblem': create_filename_box() self.update_filename_box() self.filename_button = QPushButton(QIcon(I('document_open.png')), _('&Add new image')) l.addWidget(self.filename_box) l.addWidget(self.filename_button, 2, 6) l.addWidget(QLabel(_('(Images should be square-ish)')), 2, 7) l.setColumnStretch(7, 10) else: create_filename_box() vb = QVBoxLayout() self.multiple_icon_cb = QCheckBox(_('Choose &more than one icon')) vb.addWidget(self.multiple_icon_cb) self.update_filename_box() self.multiple_icon_cb.clicked.connect(self.multiple_box_clicked) vb.addWidget(self.filename_box) l.addLayout(vb, 2, 5) self.filename_button = QPushButton(QIcon(I('document_open.png')), _('&Add icon')) l.addWidget(self.filename_button, 2, 6) l.addWidget(QLabel(_('Icons should be square or landscape')), 2, 7) l.setColumnStretch(7, 10) self.l5 = l5 = QLabel( _('Only if the following conditions are all satisfied:')) l.addWidget(l5, 3, 0, 1, 7) self.scroll_area = sa = QScrollArea(self) sa.setMinimumHeight(300) sa.setMinimumWidth(950) sa.setWidgetResizable(True) l.addWidget(sa, 4, 0, 1, 8) self.add_button = b = QPushButton(QIcon(I('plus.png')), _('Add &another condition')) l.addWidget(b, 5, 0, 1, 8) b.clicked.connect(self.add_blank_condition) self.l6 = l6 = QLabel(_('You can disable a condition by' ' blanking all of its boxes')) l.addWidget(l6, 6, 0, 1, 8) self.bb = bb = QDialogButtonBox( QDialogButtonBox.Ok|QDialogButtonBox.Cancel) bb.accepted.connect(self.accept) bb.rejected.connect(self.reject) l.addWidget(bb, 7, 0, 1, 8) if self.rule_kind != 'color': self.remove_button = b = bb.addButton(_('&Remove icon'), bb.ActionRole) b.setIcon(QIcon(I('minus.png'))) b.setMenu(QMenu()) b.setToolTip('<p>' + _('Remove a previously added icon. Note that doing so will cause rules that use it to stop working.')) self.update_remove_button() self.conditions_widget = QWidget(self) sa.setWidget(self.conditions_widget) self.conditions_widget.setLayout(QVBoxLayout()) self.conditions_widget.layout().setAlignment(Qt.AlignTop) self.conditions = [] if self.rule_kind == 'color': for b in (self.column_box, ): b.setSizeAdjustPolicy(b.AdjustToMinimumContentsLengthWithIcon) b.setMinimumContentsLength(15) for key in sorted(displayable_columns(fm), key=lambda(k): sort_key(fm[k]['name']) if k != color_row_key else 0): if key == color_row_key and self.rule_kind != 'color': continue name = all_columns_string if key == color_row_key else fm[key]['name'] if name: self.column_box.addItem(name, key) self.column_box.setCurrentIndex(0) if self.rule_kind == 'color': self.color_box.color = '#000' self.update_color_label() self.color_box.color_changed.connect(self.update_color_label) else: self.rule_icon_files = [] self.filename_button.clicked.connect(self.filename_button_clicked) self.resize(self.sizeHint())
def setup_ui(self): # {{{ self._g = g = QHBoxLayout(self) self.setLayout(g) self._l = l = QVBoxLayout() g.addLayout(l) fmts = sorted(x.upper() for x in self.fmts) self.fmt_choice_box = QGroupBox(_('Choose the format to unpack:'), self) self._fl = fl = QHBoxLayout() self.fmt_choice_box.setLayout(self._fl) self.fmt_choice_buttons = [QRadioButton(y, self) for y in fmts] for x in self.fmt_choice_buttons: fl.addWidget(x, stretch=10 if x is self.fmt_choice_buttons[-1] else 0) l.addWidget(self.fmt_choice_box) self.fmt_choice_box.setVisible(len(fmts) > 1) self.help_label = QLabel(_('''\ <h2>About Unpack Book</h2> <p>Unpack Book allows you to fine tune the appearance of an ebook by making small changes to its internals. In order to use Unpack Book, you need to know a little bit about HTML and CSS, technologies that are used in ebooks. Follow the steps:</p> <br> <ol> <li>Click "Explode Book": This will "explode" the book into its individual internal components.<br></li> <li>Right click on any individual file and select "Open with..." to edit it in your favorite text editor.<br></li> <li>When you are done: <b>close the file browser window and the editor windows you used to make your tweaks</b>. Then click the "Rebuild Book" button, to update the book in your calibre library.</li> </ol>''')) self.help_label.setWordWrap(True) self._fr = QFrame() self._fr.setFrameShape(QFrame.VLine) g.addWidget(self._fr) g.addWidget(self.help_label) self._b = b = QGridLayout() left, top, right, bottom = b.getContentsMargins() top += top b.setContentsMargins(left, top, right, bottom) l.addLayout(b, stretch=10) self.explode_button = QPushButton(QIcon(I('wizard.png')), _('&Explode Book')) self.preview_button = QPushButton(QIcon(I('view.png')), _('&Preview Book')) self.cancel_button = QPushButton(QIcon(I('window-close.png')), _('&Cancel')) self.rebuild_button = QPushButton(QIcon(I('exec.png')), _('&Rebuild Book')) self.explode_button.setToolTip( _('Explode the book to edit its components')) self.preview_button.setToolTip( _('Preview the result of your changes')) self.cancel_button.setToolTip( _('Abort without saving any changes')) self.rebuild_button.setToolTip( _('Save your changes and update the book in the calibre library')) a = b.addWidget a(self.explode_button, 0, 0, 1, 1) a(self.preview_button, 0, 1, 1, 1) a(self.cancel_button, 1, 0, 1, 1) a(self.rebuild_button, 1, 1, 1, 1) for x in ('explode', 'preview', 'cancel', 'rebuild'): getattr(self, x+'_button').clicked.connect(getattr(self, x)) self.msg = QLabel('dummy', self) self.msg.setVisible(False) self.msg.setStyleSheet(''' QLabel { text-align: center; background-color: white; color: black; border-width: 1px; border-style: solid; border-radius: 20px; font-size: x-large; font-weight: bold; } ''') self.resize(self.sizeHint() + QSize(40, 10))
def keyPressEvent(self, ev): if ev.key() in (Qt.Key_Enter, Qt.Key_Return) and self.find_text: self.find() ev.accept() return return QFrame.keyPressEvent(self, ev)