class Comments(Base):

    def setup_ui(self, parent):
        self._box = QGroupBox(parent)
        self._box.setTitle('&'+self.col_metadata['name'])
        self._layout = QVBoxLayout()
        self._tb = CommentsEditor(self._box, toolbar_prefs_name=u'metadata-comments-editor-widget-hidden-toolbars')
        self._tb.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Minimum)
        # self._tb.setTabChangesFocus(True)
        self._layout.addWidget(self._tb)
        self._box.setLayout(self._layout)
        self.widgets = [self._box]

    def setter(self, val):
        if not val or not val.strip():
            val = ''
        else:
            val = comments_to_html(val)
        self._tb.html = val
        self._tb.wyswyg_dirtied()

    def getter(self):
        val = unicode(self._tb.html).strip()
        if not val:
            val = None
        return val

    @dynamic_property
    def tab(self):
        def fget(self):
            return self._tb.tab

        def fset(self, val):
            self._tb.tab = val
        return property(fget=fget, fset=fset)
    def _init_controls(self):
        layout = QVBoxLayout(self)
        self.setLayout(layout)

        ml = QHBoxLayout()
        layout.addLayout(ml, 1)

        self.keys_list = QListWidget(self)
        self.keys_list.setSelectionMode(QAbstractItemView.SingleSelection)
        self.keys_list.setFixedWidth(150)
        self.keys_list.setAlternatingRowColors(True)
        ml.addWidget(self.keys_list)
        self.value_text = QTextEdit(self)
        self.value_text.setTabStopWidth(24)
        self.value_text.setReadOnly(False)
        ml.addWidget(self.value_text, 1)

        button_box = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel)
        button_box.accepted.connect(self._apply_changes)
        button_box.rejected.connect(self.reject)
        self.clear_button = button_box.addButton('Clear', QDialogButtonBox.ResetRole)
        self.clear_button.setIcon(get_icon('trash.png'))
        self.clear_button.setToolTip('Clear all settings for this plugin')
        self.clear_button.clicked.connect(self._clear_settings)
        layout.addWidget(button_box)
Exemple #3
0
    def __init__(self, parent):
        orientation = Qt.Vertical
        if config['gui_layout'] == 'narrow':
            orientation = Qt.Horizontal if is_widescreen() else Qt.Vertical
        idx = 0 if orientation == Qt.Vertical else 1
        size = 300 if orientation == Qt.Vertical else 550
        Splitter.__init__(self, 'cover_browser_splitter', _('Cover browser'),
                I('cover_flow.png'),
                orientation=orientation, parent=parent,
                connect_button=not config['separate_cover_flow'],
                side_index=idx, initial_side_size=size, initial_show=False,
                shortcut='Shift+Alt+B')

        quickview_widget = QWidget()
        parent.quickview_splitter = QuickviewSplitter(
                parent=self, orientation=Qt.Vertical, qv_widget=quickview_widget)
        parent.library_view = BooksView(parent)
        parent.library_view.setObjectName('library_view')
        stack = QStackedWidget(self)
        av = parent.library_view.alternate_views
        av.set_stack(stack)
        parent.grid_view = GridView(parent)
        parent.grid_view.setObjectName('grid_view')
        av.add_view('grid', parent.grid_view)
        parent.quickview_splitter.addWidget(stack)

        l = QVBoxLayout()
        l.setContentsMargins(4, 0, 0, 0)
        quickview_widget.setLayout(l)
        parent.quickview_splitter.addWidget(quickview_widget)
        parent.quickview_splitter.hide_quickview_widget()

        self.addWidget(parent.quickview_splitter)
 def __init__(self, parent=None):
     self.loaded_ruleset = None
     QWidget.__init__(self, parent)
     self.PREFS_OBJECT = JSONConfig('style-transform-rules')
     l = QVBoxLayout(self)
     self.rules_widget = w = Rules(self)
     w.changed.connect(self.changed.emit)
     l.addWidget(w)
     self.h = h = QHBoxLayout()
     l.addLayout(h)
     self.export_button = b = QPushButton(_('E&xport'), self)
     b.setToolTip(_('Export these rules to a file'))
     b.clicked.connect(self.export_rules)
     h.addWidget(b)
     self.import_button = b = QPushButton(_('&Import'), self)
     b.setToolTip(_('Import previously exported rules'))
     b.clicked.connect(self.import_rules)
     h.addWidget(b)
     self.test_button = b = QPushButton(_('&Test rules'), self)
     b.clicked.connect(self.test_rules)
     h.addWidget(b)
     h.addStretch(10)
     self.save_button = b = QPushButton(_('&Save'), self)
     b.setToolTip(_('Save this ruleset for later re-use'))
     b.clicked.connect(self.save_ruleset)
     h.addWidget(b)
     self.export_button = b = QPushButton(_('&Load'), self)
     self.load_menu = QMenu(self)
     b.setMenu(self.load_menu)
     b.setToolTip(_('Load a previously saved ruleset'))
     b.clicked.connect(self.load_ruleset)
     h.addWidget(b)
     self.build_load_menu()
    def initialize(self):
        """
        Initialize History QWidget

        """

        main_layout = QVBoxLayout(self)
        main_layout.setContentsMargins(0, 0, 0, 0)

        # Title Window
        main_layout.addWidget(get_logo_widget(self, _('History')))

        # History QWidget
        history_widget = QWidget()
        history_layout = QVBoxLayout(history_widget)

        # History QTableWidget
        self.history_table.setObjectName('history')
        self.history_table.verticalHeader().hide()
        self.history_table.verticalHeader().setDefaultSectionSize(100)
        self.history_table.setColumnCount(len(self.table_headers))
        self.history_table.setColumnWidth(0, 600)
        self.history_table.setSortingEnabled(True)
        self.history_table.setHorizontalScrollMode(QAbstractItemView.ScrollPerItem)
        self.history_table.setHorizontalHeaderLabels(self.table_headers)
        self.history_table.setEditTriggers(QAbstractItemView.NoEditTriggers)
        self.history_table.horizontalHeader().setStretchLastSection(True)
        self.history_table.horizontalHeader().setMinimumHeight(30)
        history_layout.addWidget(self.history_table)

        main_layout.addWidget(history_widget)

        center_widget(self)
    def get_text_widget(self):
        """
        Return text QWidget with QTextEdit

        :return: text QWidget
        :rtype: QWidget
        """

        text_widget = QWidget()
        text_widget.setObjectName('dialog')
        text_layout = QVBoxLayout()
        text_widget.setLayout(text_layout)

        self.text_edit.setPlaceholderText(_('type your text...'))
        self.text_edit.setText(self.old_text)
        text_layout.addWidget(self.text_edit)

        # Accept button
        accept_btn = QPushButton(_('Confirm'), self)
        accept_btn.clicked.connect(self.accept_text)
        accept_btn.setObjectName('valid')
        accept_btn.setMinimumHeight(30)
        text_layout.addWidget(accept_btn)

        return text_widget
    def __init__(self, parent=None,):
        QDialog.__init__(self, parent)
        self.parent = parent
        self.setWindowTitle(u"{0} {1}: Add New EInk Kindle Serial Number".format(PLUGIN_NAME, PLUGIN_VERSION))
        layout = QVBoxLayout(self)
        self.setLayout(layout)

        data_group_box = QGroupBox(u"", self)
        layout.addWidget(data_group_box)
        data_group_box_layout = QVBoxLayout()
        data_group_box.setLayout(data_group_box_layout)

        key_group = QHBoxLayout()
        data_group_box_layout.addLayout(key_group)
        key_group.addWidget(QLabel(u"EInk Kindle Serial Number:", self))
        self.key_ledit = QLineEdit("", self)
        self.key_ledit.setToolTip(u"Enter an eInk Kindle serial number. EInk Kindle serial numbers are 16 characters long and usually start with a 'B' or a '9'. Kindle Serial Numbers are case-sensitive, so be sure to enter the upper and lower case letters unchanged.")
        key_group.addWidget(self.key_ledit)
        key_label = QLabel(_(''), self)
        key_label.setAlignment(Qt.AlignHCenter)
        data_group_box_layout.addWidget(key_label)

        self.button_box = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel)
        self.button_box.accepted.connect(self.accept)
        self.button_box.rejected.connect(self.reject)
        layout.addWidget(self.button_box)

        self.resize(self.sizeHint())
Exemple #8
0
def show_config_widget(category, name, gui=None, show_restart_msg=False,
        parent=None, never_shutdown=False):
    '''
    Show the preferences plugin identified by category and name

    :param gui: gui instance, if None a hidden gui is created
    :param show_restart_msg: If True and the preferences plugin indicates a
    restart is required, show a message box telling the user to restart
    :param parent: The parent of the displayed dialog

    :return: True iff a restart is required for the changes made by the user to
    take effect
    '''
    from calibre.gui2 import gprefs
    pl = get_plugin(category, name)
    d = ConfigDialog(parent)
    d.resize(750, 550)
    conf_name = 'config_widget_dialog_geometry_%s_%s'%(category, name)
    geom = gprefs.get(conf_name, None)
    d.setWindowTitle(_('Configure ') + name)
    d.setWindowIcon(QIcon(I('config.png')))
    bb = QDialogButtonBox(d)
    bb.setStandardButtons(bb.Apply|bb.Cancel|bb.RestoreDefaults)
    bb.accepted.connect(d.accept)
    bb.rejected.connect(d.reject)
    w = pl.create_widget(d)
    d.set_widget(w)
    bb.button(bb.RestoreDefaults).clicked.connect(w.restore_defaults)
    bb.button(bb.RestoreDefaults).setEnabled(w.supports_restoring_to_defaults)
    bb.button(bb.Apply).setEnabled(False)
    bb.button(bb.Apply).clicked.connect(d.accept)
    def onchange():
        b = bb.button(bb.Apply)
        b.setEnabled(True)
        b.setDefault(True)
        b.setAutoDefault(True)
    w.changed_signal.connect(onchange)
    bb.button(bb.Cancel).setFocus(True)
    l = QVBoxLayout()
    d.setLayout(l)
    l.addWidget(w)
    l.addWidget(bb)
    mygui = gui is None
    if gui is None:
        gui = init_gui()
        mygui = True
    w.genesis(gui)
    w.initialize()
    if geom is not None:
        d.restoreGeometry(geom)
    d.exec_()
    geom = bytearray(d.saveGeometry())
    gprefs[conf_name] = geom
    rr = getattr(d, 'restart_required', False)
    if show_restart_msg and rr:
        from calibre.gui2 import warning_dialog
        warning_dialog(gui, 'Restart required', 'Restart required', show=True)
    if mygui and not never_shutdown:
        gui.shutdown()
    return rr
    def __init__(self, parent=None,):
        QDialog.__init__(self, parent)
        self.parent = parent
        self.setWindowTitle(u"{0} {1}: Add New Mobipocket PID".format(PLUGIN_NAME, PLUGIN_VERSION))
        layout = QVBoxLayout(self)
        self.setLayout(layout)

        data_group_box = QGroupBox(u"", self)
        layout.addWidget(data_group_box)
        data_group_box_layout = QVBoxLayout()
        data_group_box.setLayout(data_group_box_layout)

        key_group = QHBoxLayout()
        data_group_box_layout.addLayout(key_group)
        key_group.addWidget(QLabel(u"PID:", self))
        self.key_ledit = QLineEdit("", self)
        self.key_ledit.setToolTip(u"Enter a Mobipocket PID. Mobipocket PIDs are 8 or 10 characters long. Mobipocket PIDs are case-sensitive, so be sure to enter the upper and lower case letters unchanged.")
        key_group.addWidget(self.key_ledit)
        key_label = QLabel(_(''), self)
        key_label.setAlignment(Qt.AlignHCenter)
        data_group_box_layout.addWidget(key_label)

        self.button_box = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel)
        self.button_box.accepted.connect(self.accept)
        self.button_box.rejected.connect(self.reject)
        layout.addWidget(self.button_box)

        self.resize(self.sizeHint())
Exemple #10
0
    def __init__(self, parent=None,):
        QDialog.__init__(self, parent)
        self.parent = parent
        self.setWindowTitle(u"{0} {1}: Add New Kindle for Android Serial Number".format(PLUGIN_NAME, PLUGIN_VERSION))
        layout = QVBoxLayout(self)
        self.setLayout(layout)

        data_group_box = QGroupBox(u"", self)
        layout.addWidget(data_group_box)
        data_group_box_layout = QVBoxLayout()
        data_group_box.setLayout(data_group_box_layout)

        key_group = QHBoxLayout()
        data_group_box_layout.addLayout(key_group)
        key_group.addWidget(QLabel(u"Kindle for Android Serial Number:", self))
        self.key_ledit = QLineEdit("", self)
        self.key_ledit.setToolTip(u"Enter a Kindle for ANdroid serial number. These can be found using the androidkindlekey.py script.")
        key_group.addWidget(self.key_ledit)
        key_label = QLabel(_(''), self)
        key_label.setAlignment(Qt.AlignHCenter)
        data_group_box_layout.addWidget(key_label)

        self.button_box = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel)
        self.button_box.accepted.connect(self.accept)
        self.button_box.rejected.connect(self.reject)
        layout.addWidget(self.button_box)

        self.resize(self.sizeHint())
Exemple #11
0
class LogDialog(QDialog):

    # GUI definition
    def __init__(self, log, icon):
        '''
        :param log: The text to show in the dialog
        :param icon: The window icon
        '''
        QDialog.__init__(self)

        self.setWindowTitle(_('Prince log'))
        self.setWindowIcon(icon)

        self.l = QVBoxLayout()
        self.setLayout(self.l)

        monofont = QFont('')
        monofont.setStyleHint(QFont.TypeWriter)

        self.box = QPlainTextEdit()
        self.box.setPlainText(log)
        self.box.setStyleSheet('* { font-family: monospace }')
        self.box.setMinimumWidth(500)
        self.box.setLineWrapMode(QPlainTextEdit.NoWrap)
        self.box.setReadOnly(True)
        self.box.setToolTip(_('<qt>Console output from the last Prince run</qt>'))
        self.l.addWidget(self.box)
         
        self.buttons = QDialogButtonBox(QDialogButtonBox.Ok)
        self.l.addWidget(self.buttons)
        self.buttons.accepted.connect(self.accept)

        self.adjustSize()
class PlotDialog(QDialog):
    
    def __init__(self, parent=None):
        super(PlotDialog, self).__init__(parent)
        
        self.resize(550, 350)

        #self.verticalLayout.addWidget(self.buttonBox)
        
    def init_plot(self, component, field):
        
        self.plot = DataPlot()
        self.plot.initData(component, field)
        self.plot.resize(500, 300)
        self.plot.show()
        
        self.verticalLayout = QVBoxLayout(self)
        self.verticalLayout.addWidget(self.plot)
    
    def get_plot(self):
        return self.plot
        
    def closeEvent(self, event):
        self.reject()
        super(PlotDialog, self).closeEvent(event)
    def __init__(self, parent, friendly_name, rac):
        #self.dialog = QDialog(parent.gui)
        QDialog.__init__(self, parent.gui)
        self.parent = parent
        self.opts = parent.opts
        self.rac = rac
        parent_loc = self.parent.gui.pos()
        self.move(parent_loc.x(), parent_loc.y())
        self.setWindowTitle(rac.import_dialog_title)
        self.setWindowIcon(self.opts.icon)

        l = QVBoxLayout()
        self.setLayout(l)

        self.pte = PlainTextEdit(self.parent)
        self.pte.setPlainText(rac.initial_dialog_text)
        self.pte.setMinimumWidth(400)
        l.addWidget(self.pte)

        self.dialogButtonBox = QDialogButtonBox(QDialogButtonBox.Cancel|QDialogButtonBox.Help)
        self.import_button = self.dialogButtonBox.addButton(self.dialogButtonBox.Ok)
        self.import_button.setText('Import')
        self.dialogButtonBox.clicked.connect(self.import_annotations_dialog_clicked)
        l.addWidget(self.dialogButtonBox)

        self.rejected.connect(self.close)

        self.exec_()
        self.text = str(self.pte.toPlainText())
Exemple #14
0
 def message_dialog(self, msg):
     self.clear_dialog()
     self.dialog = dialog = WindowModalDialog(self.top_level_window(), _("Ledger Status"))
     l = QLabel(msg)
     vbox = QVBoxLayout(dialog)
     vbox.addWidget(l)
     dialog.show()
Exemple #15
0
    def __init__(self, parent, icon, text, over=True):
        QDialog.__init__(self, parent)
        self.state=None

        layout = QVBoxLayout(self)
        self.setLayout(layout)
        self.setWindowTitle('UnMerge Epub')

        label = QLabel(text)
        label.setOpenExternalLinks(True)
        label.setWordWrap(True)
        layout.addWidget(label)

        button_box = QDialogButtonBox(self)
        button = button_box.addButton(_("Add"), button_box.AcceptRole)
        button.clicked.connect(self.add)

        if over:
            button = button_box.addButton(_("Overwrite"), button_box.AcceptRole)
            button.clicked.connect(self.over)

        button = button_box.addButton(_("Discard"), button_box.AcceptRole)
        button.clicked.connect(self.discard)
        button_box.accepted.connect(self.accept)

        layout.addWidget(button_box)
class HelpView(SizePersistedDialog):
    '''
    Modeless dialog for presenting HTML help content
    '''

    def __init__(self, parent, icon, prefs, html=None, page=None, title=''):
        self.prefs = prefs
        #QDialog.__init__(self, parent=parent)
        super(HelpView, self).__init__(parent, 'help_dialog')
        self.setWindowTitle(title)
        self.setWindowIcon(icon)
        self.l = QVBoxLayout(self)
        self.setLayout(self.l)

        self.wv = QWebView()
        if html is not None:
            self.wv.setHtml(html)
        elif page is not None:
            self.wv.load(QUrl(page))
        self.wv.setMinimumHeight(100)
        self.wv.setMaximumHeight(16777215)
        self.wv.setMinimumWidth(400)
        self.wv.setMaximumWidth(16777215)
        self.wv.setGeometry(0, 0, 400, 100)
        self.wv.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
        self.l.addWidget(self.wv)

        # Sizing
        sizePolicy = QSizePolicy(QSizePolicy.Preferred, QSizePolicy.Preferred)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(self.sizePolicy().hasHeightForWidth())
        self.setSizePolicy(sizePolicy)
        self.resize_dialog()
    def initialize(self):
        """
        Intialize QWidget

        """

        self.timer.setInterval(30000)
        self.timer.start()
        self.timer.timeout.connect(self.send_datamanager_events)

        layout = QVBoxLayout()
        layout.setContentsMargins(0, 0, 0, 0)
        self.setLayout(layout)

        self.events_list.setDragDropMode(QAbstractItemView.DragOnly)
        self.events_list.setSelectionMode(QAbstractItemView.ExtendedSelection)
        self.events_list.setDropIndicatorShown(True)
        self.events_list.doubleClicked.connect(self.remove_event)
        self.events_list.setWordWrap(True)
        self.events_list.setIconSize(QSize(16, 16))

        self.add_event(
            'OK',
            _('Welcome %s, you are connected to Alignak Backend') %
            data_manager.database['user'].name,
            timer=True
        )

        layout.addWidget(self.events_list)
class Comments(Base):

    def setup_ui(self, parent):
        self._box = QGroupBox(parent)
        self._box.setTitle('&'+self.col_metadata['name'])
        self._layout = QVBoxLayout()
        self._tb = CommentsEditor(self._box)
        self._tb.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Minimum)
        # self._tb.setTabChangesFocus(True)
        self._layout.addWidget(self._tb)
        self._box.setLayout(self._layout)
        self.widgets = [self._box]

    def setter(self, val):
        if not val or not val.strip():
            val = ''
        else:
            val = comments_to_html(val)
        self._tb.html = val
        self._tb.wyswyg_dirtied()

    def getter(self):
        val = unicode(self._tb.html).strip()
        if not val:
            val = None
        return val
Exemple #19
0
class ConfigWidget(QWidget):

    def __init__(self, plugin_action):
        QWidget.__init__(self)
        self.plugin_action = plugin_action
        
        self.l = QVBoxLayout()
        self.setLayout(self.l)

        tab_widget = QTabWidget(self)
        self.l.addWidget(tab_widget)

        self.basic_tab = BasicTab(self, plugin_action)
        tab_widget.addTab(self.basic_tab, _('Basic'))

        self.searches_tab = SearchesTab(self, plugin_action)
        tab_widget.addTab(self.searches_tab, _('Searches'))

    def save_settings(self):
        prefs['checkreadinglistsync'] = self.basic_tab.checkreadinglistsync.isChecked()
        prefs['checkdups'] = self.basic_tab.checkdups.isChecked()
        prefs['checknotinlibrary'] = self.basic_tab.checknotinlibrary.isChecked()
        prefs['checknotondevice'] = self.basic_tab.checknotondevice.isChecked()

        prefs['checkdups_search'] = unicode(self.searches_tab.checkdups_search.text())
        prefs['checknotinlibrary_search'] = unicode(self.searches_tab.checknotinlibrary_search.text())
        prefs['checknotondevice_search'] = unicode(self.searches_tab.checknotondevice_search.text())

        prefs.save_to_db()
        
    def edit_shortcuts(self):
        self.save_settings()
        d = KeyboardConfigDialog(self.plugin_action.gui, self.plugin_action.action_spec[0])
        if d.exec_() == d.Accepted:
            self.plugin_action.gui.keyboard.finalize()
Exemple #20
0
class ConfigWidget(QWidget):

    def __init__(self):
        QWidget.__init__(self)
        self.l = QVBoxLayout()
        self.setLayout(self.l)

        self.about_button = QPushButton('Help', self)
        self.about_button.clicked.connect(self.about)
        self.l.addWidget(self.about_button)

        self.notebookLabel = QLabel('evernote Notebook')
        self.l.addWidget(self.notebookLabel)

        self.notebookMsg = QLineEdit(self)
        self.notebookMsg.setText(prefs['notebook'])
        self.l.addWidget(self.notebookMsg)
        self.notebookLabel.setBuddy(self.notebookMsg)
        
        self.tagsCsvLabel = QLabel('evernote Tags CSV (ie calibre,mykindle)')
        self.l.addWidget(self.tagsCsvLabel)

        self.tagsCsvMsg = QLineEdit(self)
        self.tagsCsvMsg.setText(prefs['tagsCsv'])
        self.l.addWidget(self.tagsCsvMsg)
        self.tagsCsvLabel.setBuddy(self.tagsCsvMsg)

    def save_settings(self):
        prefs['notebook'] = unicode(self.notebookMsg.text())
        prefs['tagsCsv'] = unicode(self.tagsCsvMsg.text())

    def about(self):
        text = get_resources('about.txt')
        QMessageBox.about(self, 'About calibrebeam',
                text.decode('utf-8'))
Exemple #21
0
class CustomColumnsTab(QWidget):

    def __init__(self, parent_dialog, plugin_action):
        self.parent_dialog = parent_dialog
        self.plugin_action = plugin_action
        QWidget.__init__(self)
        
        self.l = QVBoxLayout()
        self.setLayout(self.l)

        label = QLabel(_("If you have custom columns defined, they will be listed below.  Choose how you would like these columns handled."))
        label.setWordWrap(True)
        self.l.addWidget(label)
        self.l.addSpacing(5)
        
        scrollable = QScrollArea()
        scrollcontent = QWidget()
        scrollable.setWidget(scrollcontent)
        scrollable.setWidgetResizable(True)
        self.l.addWidget(scrollable)

        self.sl = QVBoxLayout()
        scrollcontent.setLayout(self.sl)
        
        self.custcol_dropdowns = {}

        custom_columns = self.plugin_action.gui.library_view.model().custom_columns

        grid = QGridLayout()
        self.sl.addLayout(grid)
        row=0
        for key, column in custom_columns.iteritems():
            if column['datatype'] in permitted_values:
                # print("\n============== %s ===========\n"%key)
                # for (k,v) in column.iteritems():
                #     print("column['%s'] => %s"%(k,v))
                label = QLabel('%s(%s)'%(column['name'],key))
                label.setToolTip(_("Set this %s column on new merged books...")%column['datatype'])
                grid.addWidget(label,row,0)

                dropdown = QComboBox(self)
                dropdown.addItem('','none')
                for md in permitted_values[column['datatype']]:
                    # tags-like column also 'text'
                    if md == 'union' and not column['is_multiple']:
                        continue
                    if md == 'concat' and column['is_multiple']:
                        continue
                    dropdown.addItem(titleLabels[md],md)
                self.custcol_dropdowns[key] = dropdown
                if key in prefs['custom_cols']:
                    dropdown.setCurrentIndex(dropdown.findData(prefs['custom_cols'][key]))
                dropdown.setToolTip(_("How this column will be populated by default."))
                grid.addWidget(dropdown,row,1)
                row+=1
        
        self.sl.insertStretch(-1)
Exemple #22
0
class TabExtendedConfig(DeviceConfigTab):
    def __init__(self, parent, device):
        super(TabExtendedConfig, self).__init__(parent)

        self.l = QVBoxLayout(self)
        self.setLayout(self.l)

        self.extended_options = ExtendedGroupBox(self, device)
        self.l.addWidget(self.extended_options)
        self.addDeviceWidget(self.extended_options)
Exemple #23
0
    def __init__(self, info_str, parent=None):
        super(InfoDialog, self).__init__(parent)

        layout = QVBoxLayout(self)
        layout.addWidget(QLabel(info_str))

        buttons = QDialogButtonBox(QDialogButtonBox.Ok, Qt.Horizontal, self)
        buttons.accepted.connect(self.accept)

        layout.addWidget(buttons)
    def _init_controls(self):
        # Add the control set
        vbl = QVBoxLayout()
        self.move_element_up_tb = QToolButton()
        self.move_element_up_tb.setObjectName("move_element_up_tb")
        self.move_element_up_tb.setToolTip('Move element up')
        self.move_element_up_tb.setIcon(QIcon(I('arrow-up.png')))
        self.move_element_up_tb.clicked.connect(self.move_row_up)
        vbl.addWidget(self.move_element_up_tb)

        self.undo_css_tb = QToolButton()
        self.undo_css_tb.setObjectName("undo_css_tb")
        self.undo_css_tb.setToolTip('Restore CSS to last saved')
        self.undo_css_tb.setIcon(QIcon(I('edit-undo.png')))
        self.undo_css_tb.clicked.connect(partial(self.undo_reset_button_clicked, 'undo'))
        vbl.addWidget(self.undo_css_tb)

        self.reset_css_tb = QToolButton()
        self.reset_css_tb.setObjectName("reset_css_tb")
        self.reset_css_tb.setToolTip('Reset CSS to default')
        self.reset_css_tb.setIcon(QIcon(I('trash.png')))
        self.reset_css_tb.clicked.connect(partial(self.undo_reset_button_clicked, 'reset'))
        vbl.addWidget(self.reset_css_tb)

        self.move_element_down_tb = QToolButton()
        self.move_element_down_tb.setObjectName("move_element_down_tb")
        self.move_element_down_tb.setToolTip('Move element down')
        self.move_element_down_tb.setIcon(QIcon(I('arrow-down.png')))
        self.move_element_down_tb.clicked.connect(self.move_row_down)
        vbl.addWidget(self.move_element_down_tb)

        self.layout.addLayout(vbl)
Exemple #25
0
    def __init__(self, parent):
        super(MatrixDialog, self).__init__(parent)
        self.setWindowTitle(_("Trezor Matrix Recovery"))
        self.num = 9
        self.loop = QEventLoop()

        vbox = QVBoxLayout(self)
        vbox.addWidget(WWLabel(MATRIX_RECOVERY))

        grid = QGridLayout()
        grid.setSpacing(0)
        self.char_buttons = []
        for y in range(3):
            for x in range(3):
                button = QPushButton('?')
                button.clicked.connect(partial(self.process_key, ord('1') + y * 3 + x))
                grid.addWidget(button, 3 - y, x)
                self.char_buttons.append(button)
        vbox.addLayout(grid)

        self.backspace_button = QPushButton("<=")
        self.backspace_button.clicked.connect(partial(self.process_key, Qt.Key_Backspace))
        self.cancel_button = QPushButton(_("Cancel"))
        self.cancel_button.clicked.connect(partial(self.process_key, Qt.Key_Escape))
        buttons = Buttons(self.backspace_button, self.cancel_button)
        vbox.addSpacing(40)
        vbox.addLayout(buttons)
        self.refresh()
        self.show()
Exemple #26
0
    def __init__(self, parent):
        super(CharacterDialog, self).__init__(parent)
        self.setWindowTitle(_("KeepKey Seed Recovery"))
        self.character_pos = 0
        self.word_pos = 0
        self.loop = QEventLoop()
        self.word_help = QLabel()
        self.char_buttons = []

        vbox = QVBoxLayout(self)
        vbox.addWidget(WWLabel(CHARACTER_RECOVERY))
        hbox = QHBoxLayout()
        hbox.addWidget(self.word_help)
        for i in range(4):
            char_button = CharacterButton('*')
            char_button.setMaximumWidth(36)
            self.char_buttons.append(char_button)
            hbox.addWidget(char_button)
        self.accept_button = CharacterButton(_("Accept Word"))
        self.accept_button.clicked.connect(partial(self.process_key, 32))
        self.rejected.connect(partial(self.loop.exit, 1))
        hbox.addWidget(self.accept_button)
        hbox.addStretch(1)
        vbox.addLayout(hbox)

        self.finished_button = QPushButton(_("Seed Entered"))
        self.cancel_button = QPushButton(_("Cancel"))
        self.finished_button.clicked.connect(partial(self.process_key,
                                                     Qt.Key_Return))
        self.cancel_button.clicked.connect(self.rejected)
        buttons = Buttons(self.finished_button, self.cancel_button)
        vbox.addSpacing(40)
        vbox.addLayout(buttons)
        self.refresh()
        self.show()
Exemple #27
0
    def __init__(self, parent=None):
        QDialog.__init__(self, parent)
        self.parent = parent
        self.setWindowTitle(u"{0} {1}: Getting Default Adobe Digital Editions Key".format(PLUGIN_NAME, PLUGIN_VERSION))
        layout = QVBoxLayout(self)
        self.setLayout(layout)

        try:
            if iswindows or isosx:
                from calibre_plugins.dedrm.adobekey import adeptkeys

                defaultkeys = adeptkeys()
            else:  # linux
                from wineutils import WineGetKeys

                scriptpath = os.path.join(parent.parent.alfdir, u"adobekey.py")
                defaultkeys = WineGetKeys(scriptpath, u".der", parent.getwineprefix())

            self.default_key = defaultkeys[0]
        except:
            traceback.print_exc()
            self.default_key = u""

        self.button_box = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel)

        if len(self.default_key) > 0:
            data_group_box = QGroupBox(u"", self)
            layout.addWidget(data_group_box)
            data_group_box_layout = QVBoxLayout()
            data_group_box.setLayout(data_group_box_layout)

            key_group = QHBoxLayout()
            data_group_box_layout.addLayout(key_group)
            key_group.addWidget(QLabel(u"Unique Key Name:", self))
            self.key_ledit = QLineEdit(u"default_key", self)
            self.key_ledit.setToolTip(
                u"<p>Enter an identifying name for the current default Adobe Digital Editions key."
            )
            key_group.addWidget(self.key_ledit)

            self.button_box.accepted.connect(self.accept)
        else:
            default_key_error = QLabel(
                u"The default encryption key for Adobe Digital Editions could not be found.", self
            )
            default_key_error.setAlignment(Qt.AlignHCenter)
            layout.addWidget(default_key_error)
            # if no default, bot buttons do the same
            self.button_box.accepted.connect(self.reject)

        self.button_box.rejected.connect(self.reject)
        layout.addWidget(self.button_box)

        self.resize(self.sizeHint())
Exemple #28
0
class ConfigWidget(QWidget):

    def __init__(self, plugin_action):
        QWidget.__init__(self)
        self.plugin_action = plugin_action

        self.l = QVBoxLayout()
        self.setLayout(self.l)

        tab_widget = QTabWidget(self)
        self.l.addWidget(tab_widget)

        self.basic_tab = BasicTab(self, plugin_action)
        tab_widget.addTab(self.basic_tab, _('Basic'))

        self.columns_tab = CustomColumnsTab(self, plugin_action)
        tab_widget.addTab(self.columns_tab, _('Custom Columns'))

    def save_settings(self):
        prefs['editmetadata'] = self.basic_tab.editmetadata.isChecked()
        prefs['show_checkedalways'] = self.basic_tab.show_checkedalways.isChecked()
        prefs['copytoctitle'] = self.basic_tab.copytoctitle.isChecked()
        prefs['copytitle'] = self.basic_tab.copytitle.isChecked()
        prefs['copyauthors'] = self.basic_tab.copyauthors.isChecked()
        prefs['copytags'] = self.basic_tab.copytags.isChecked()
        prefs['copylanguages'] = self.basic_tab.copylanguages.isChecked()
        prefs['copyseries'] = self.basic_tab.copyseries.isChecked()
        prefs['copycomments'] = self.basic_tab.copycomments.isChecked()
        prefs['copycover'] = self.basic_tab.copycover.isChecked()
        prefs['copydate'] = self.basic_tab.copydate.isChecked()
        prefs['copyrating'] = self.basic_tab.copyrating.isChecked()
        prefs['copypubdate'] = self.basic_tab.copypubdate.isChecked()
        prefs['copyidentifiers'] = self.basic_tab.copyidentifiers.isChecked()
        prefs['copypublisher'] = self.basic_tab.copypublisher.isChecked()

        # Custom Columns tab
        colsmap = {}
        for (col,chkbx) in self.columns_tab.custcol_checkboxes.iteritems():
            if chkbx.isChecked():
                colsmap[col] = chkbx.isChecked()
            #print("colsmap[%s]:%s"%(col,colsmap[col]))
        prefs['custom_cols'] = colsmap

        prefs['sourcecol'] = unicode(convert_qvariant(self.columns_tab.sourcecol.itemData(self.columns_tab.sourcecol.currentIndex())))
        prefs['sourcetemplate'] = unicode(self.columns_tab.sourcetemplate.text())

        prefs.save_to_db()

    def edit_shortcuts(self):
        self.save_settings()
        d = KeyboardConfigDialog(self.plugin_action.gui, self.plugin_action.action_spec[0])
        if d.exec_() == d.Accepted:
            self.plugin_action.gui.keyboard.finalize()
Exemple #29
0
 def message_dialog(self, msg, on_cancel):
     # Called more than once during signing, to confirm output and fee
     self.clear_dialog()
     title = _('Please check your %s device') % self.device
     self.dialog = dialog = WindowModalDialog(self.top_level_window(), title)
     l = QLabel(msg)
     vbox = QVBoxLayout(dialog)
     vbox.addWidget(l)
     if on_cancel:
         dialog.rejected.connect(on_cancel)
         vbox.addLayout(Buttons(CancelButton(dialog)))
     dialog.show()
    def create_main_frame(self):        
        page = QWidget()        

        self.button = QPushButton('OK', page)
        self.textWindow = QTextEdit()

        vbox1 = QVBoxLayout()
        vbox1.addWidget(self.textWindow)
        vbox1.addWidget(self.button)
        page.setLayout(vbox1)
        self.setCentralWidget(page)

        self.button.clicked.connect(self.clicked)
Exemple #31
0
    def genesis(self, gui):
        self.gui = gui
        if not isosx and not iswindows:
            self.label_widget_style.setVisible(False)
            self.opt_ui_style.setVisible(False)

        db = gui.library_view.model().db

        r = self.register

        try:
            self.icon_theme_title = json.loads(I('icon-theme.json',
                                                 data=True))['name']
        except Exception:
            self.icon_theme_title = _('Default icons')
        self.icon_theme.setText(
            _('Icon theme: <b>%s</b>') % self.icon_theme_title)
        self.commit_icon_theme = None
        self.icon_theme_button.clicked.connect(self.choose_icon_theme)
        self.default_author_link = DefaultAuthorLink(
            self.default_author_link_container)
        self.default_author_link.changed_signal.connect(self.changed_signal)
        r('gui_layout',
          config,
          restart_required=True,
          choices=[(_('Wide'), 'wide'), (_('Narrow'), 'narrow')])
        r('hidpi',
          gprefs,
          restart_required=True,
          choices=[(_('Automatic'), 'auto'), (_('On'), 'on'),
                   (_('Off'), 'off')])
        if isosx:
            self.opt_hidpi.setVisible(False), self.label_hidpi.setVisible(
                False)
        r('ui_style',
          gprefs,
          restart_required=True,
          choices=[(_('System default'), 'system'),
                   (_('calibre style'), 'calibre')])
        r('book_list_tooltips', gprefs)
        r('show_layout_buttons', gprefs, restart_required=True)
        r('row_numbers_in_book_list', gprefs)
        r('tag_browser_old_look', gprefs)
        r('tag_browser_hide_empty_categories', gprefs)
        r('bd_show_cover', gprefs)
        r('bd_overlay_cover_size', gprefs)
        r('cover_grid_width', gprefs)
        r('cover_grid_height', gprefs)
        r('cover_grid_cache_size_multiple', gprefs)
        r('cover_grid_disk_cache_size', gprefs)
        r('cover_grid_spacing', gprefs)
        r('cover_grid_show_title', gprefs)
        r('tag_browser_show_counts', gprefs)
        r('tag_browser_item_padding', gprefs)

        r('qv_respects_vls', gprefs)
        r('qv_dclick_changes_column', gprefs)
        r('qv_retkey_changes_column', gprefs)
        r('qv_follows_column', gprefs)

        r('cover_flow_queue_length', config, restart_required=True)
        r('cover_browser_reflections', gprefs)
        r('cover_browser_title_template', db.prefs)
        fm = db.field_metadata
        r('cover_browser_subtitle_field',
          db.prefs,
          choices=[(_('No subtitle'), 'none')] + sorted(
              (fm[k].get('name'), k)
              for k in fm.all_field_keys() if fm[k].get('name')))
        r('emblem_size', gprefs)
        r('emblem_position',
          gprefs,
          choices=[(_('Left'), 'left'), (_('Top'), 'top'),
                   (_('Right'), 'right'), (_('Bottom'), 'bottom')])
        r('book_list_extra_row_spacing', gprefs)
        r('book_details_narrow_comments_layout',
          gprefs,
          choices=[(_('Float'), 'float'), (_('Columns'), 'columns')])
        self.opt_book_details_narrow_comments_layout.setToolTip(
            textwrap.fill(
                _('Choose how the text is laid out when using the "Narrow" user interface layout.'
                  ' A value of "Float" means that the comments text will wrap around'
                  ' the other metadata fields, while a value of "Columns" means that'
                  ' the comments will be in a separate fixed width column.')))
        self.cover_browser_title_template_button.clicked.connect(
            self.edit_cb_title_template)
        self.id_links_button.clicked.connect(self.edit_id_link_rules)

        def get_esc_lang(l):
            if l == 'en':
                return 'English'
            return get_language(l)

        lang = get_lang()
        if lang is None or lang not in available_translations():
            lang = 'en'
        items = [(l, get_esc_lang(l)) for l in available_translations()
                 if l != lang]
        if lang != 'en':
            items.append(('en', get_esc_lang('en')))
        items.sort(cmp=lambda x, y: cmp(x[1].lower(), y[1].lower()))
        choices = [(y, x) for x, y in items]
        # Default language is the autodetected one
        choices = [(get_language(lang), lang)] + choices
        r('language', prefs, choices=choices, restart_required=True)

        r('show_avg_rating', config)
        r('disable_animations', config)
        r('systray_icon', config, restart_required=True)
        r('show_splash_screen', gprefs)
        r('disable_tray_notification', config)
        r('use_roman_numerals_for_series_number', config)
        r('separate_cover_flow', config, restart_required=True)
        r('cb_fullscreen', gprefs)
        r('cb_preserve_aspect_ratio', gprefs)

        choices = [(_('Off'), 'off'), (_('Small'), 'small'),
                   (_('Medium'), 'medium'), (_('Large'), 'large')]
        r('toolbar_icon_size', gprefs, choices=choices)

        choices = [(_('If there is enough room'), 'auto'),
                   (_('Always'), 'always'), (_('Never'), 'never')]
        r('toolbar_text', gprefs, choices=choices)

        choices = [(_('Disabled'), 'disable'),
                   (_('By first letter'), 'first letter'),
                   (_('Partitioned'), 'partition')]
        r('tags_browser_partition_method', gprefs, choices=choices)
        r('tags_browser_collapse_at', gprefs)
        r('tag_browser_dont_collapse', gprefs, setting=CommaSeparatedList)

        choices = set([
            k for k in db.field_metadata.all_field_keys()
            if (db.field_metadata[k]['is_category'] and
                (db.field_metadata[k]['datatype'] in
                 ['text', 'series', 'enumeration'])
                and not db.field_metadata[k]['display'].get('is_names', False))
            or (db.field_metadata[k]['datatype'] in ['composite'] and
                db.field_metadata[k]['display'].get('make_category', False))
        ])
        choices -= set(
            ['authors', 'publisher', 'formats', 'news', 'identifiers'])
        choices |= set(['search'])
        self.opt_categories_using_hierarchy.update_items_cache(choices)
        r('categories_using_hierarchy',
          db.prefs,
          setting=CommaSeparatedList,
          choices=sorted(list(choices), key=sort_key))

        fm = db.field_metadata
        choices = sorted(
            ((fm[k]['name'], k)
             for k in fm.displayable_field_keys() if fm[k]['name']),
            key=lambda x: sort_key(x[0]))
        r('field_under_covers_in_grid', db.prefs, choices=choices)

        self.current_font = self.initial_font = None
        self.change_font_button.clicked.connect(self.change_font)

        self.display_model = DisplayedFields(self.gui.current_db,
                                             self.field_display_order)
        self.display_model.dataChanged.connect(self.changed_signal)
        self.field_display_order.setModel(self.display_model)
        self.df_up_button.clicked.connect(
            partial(move_field_up, self.field_display_order,
                    self.display_model))
        self.df_down_button.clicked.connect(
            partial(move_field_down, self.field_display_order,
                    self.display_model))

        self.qv_display_model = QVDisplayedFields(self.gui.current_db,
                                                  self.qv_display_order)
        self.qv_display_model.dataChanged.connect(self.changed_signal)
        self.qv_display_order.setModel(self.qv_display_model)
        self.qv_up_button.clicked.connect(
            partial(move_field_up, self.qv_display_order,
                    self.qv_display_model))
        self.qv_down_button.clicked.connect(
            partial(move_field_down, self.qv_display_order,
                    self.qv_display_model))

        self.edit_rules = EditRules(self.tabWidget)
        self.edit_rules.changed.connect(self.changed_signal)
        self.tabWidget.addTab(self.edit_rules,
                              QIcon(I('format-fill-color.png')),
                              _('Column &coloring'))

        self.icon_rules = EditRules(self.tabWidget)
        self.icon_rules.changed.connect(self.changed_signal)
        self.tabWidget.addTab(self.icon_rules, QIcon(I('icon_choose.png')),
                              _('Column &icons'))

        self.grid_rules = EditRules(self.emblems_tab)
        self.grid_rules.changed.connect(self.changed_signal)
        self.emblems_tab.setLayout(QVBoxLayout())
        self.emblems_tab.layout().addWidget(self.grid_rules)

        self.tabWidget.setCurrentIndex(0)
        keys = [
            QKeySequence('F11', QKeySequence.PortableText),
            QKeySequence('Ctrl+Shift+F', QKeySequence.PortableText)
        ]
        keys = [unicode(x.toString(QKeySequence.NativeText)) for x in keys]
        self.fs_help_msg.setText(
            unicode(self.fs_help_msg.text()) % (_(' or ').join(keys)))
        self.size_calculated.connect(self.update_cg_cache_size,
                                     type=Qt.QueuedConnection)
        self.tabWidget.currentChanged.connect(self.tab_changed)

        l = self.cg_background_box.layout()
        self.cg_bg_widget = w = Background(self)
        l.addWidget(w, 0, 0, 3, 1)
        self.cover_grid_color_button = b = QPushButton(_('Change &color'),
                                                       self)
        b.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)
        l.addWidget(b, 0, 1)
        b.clicked.connect(self.change_cover_grid_color)
        self.cover_grid_texture_button = b = QPushButton(
            _('Change &background image'), self)
        b.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)
        l.addWidget(b, 1, 1)
        b.clicked.connect(self.change_cover_grid_texture)
        self.cover_grid_default_appearance_button = b = QPushButton(
            _('Restore &default appearance'), self)
        b.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)
        l.addWidget(b, 2, 1)
        b.clicked.connect(self.restore_cover_grid_appearance)
        self.cover_grid_empty_cache.clicked.connect(self.empty_cache)
        self.cover_grid_open_cache.clicked.connect(self.open_cg_cache)
        self.cover_grid_smaller_cover.clicked.connect(
            partial(self.resize_cover, True))
        self.cover_grid_larger_cover.clicked.connect(
            partial(self.resize_cover, False))
        self.cover_grid_reset_size.clicked.connect(self.cg_reset_size)
        self.opt_cover_grid_disk_cache_size.setMinimum(
            self.gui.grid_view.thumbnail_cache.min_disk_cache)
        self.opt_cover_grid_disk_cache_size.setMaximum(
            self.gui.grid_view.thumbnail_cache.min_disk_cache * 100)
        self.opt_cover_grid_width.valueChanged.connect(
            self.update_aspect_ratio)
        self.opt_cover_grid_height.valueChanged.connect(
            self.update_aspect_ratio)
Exemple #32
0
class TagBrowserWidget(QFrame):  # {{{
    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)
        tbb.clear_find.connect(self.reset_find)
        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)

        # self.leak_test_timer = QTimer(self)
        # self.leak_test_timer.timeout.connect(self.test_for_leak)
        # self.leak_test_timer.start(5000)

    def save_state(self):
        gprefs.set('tag browser search box visible',
                   self.toggle_search_button.isChecked())

    def toggle_item(self):
        self.tags_view.toggle_current_index()

    def set_pane_is_visible(self, to_what):
        self.tags_view.set_pane_is_visible(to_what)

    def find_text_changed(self, str):
        self.current_find_position = None

    def set_focus_to_find_box(self):
        self.tb_bar.set_focus_to_find_box()

    def do_find(self, str=None):
        self.current_find_position = None
        self.find()

    @property
    def find_text(self):
        return unicode_type(self.item_search.currentText()).strip()

    def reset_find(self):
        model = self.tags_view.model()
        if model.get_categories_filter():
            model.set_categories_filter(None)
            self.tags_view.recount()
            self.current_find_position = None

    def find(self):
        model = self.tags_view.model()
        model.clear_boxed()

        # When a key is specified don't use the auto-collapsing search.
        # A colon separates the lookup key from the search string.
        # A leading colon says not to use autocollapsing search but search all keys
        txt = self.find_text
        colon = txt.find(':')
        if colon >= 0:
            key = self._parent.library_view.model().db.\
                        field_metadata.search_term_to_field_key(txt[:colon])
            if key in self._parent.library_view.model().db.field_metadata:
                txt = txt[colon + 1:]
            else:
                key = ''
                txt = txt[1:] if colon == 0 else txt
        else:
            key = None

        # key is None indicates that no colon was found.
        # key == '' means either a leading : was found or the key is invalid

        # At this point the txt might have a leading =, in which case do an
        # exact match search

        if (gprefs.get('tag_browser_always_autocollapse', False)
                and key is None and not txt.startswith('*')):
            txt = '*' + txt
        if txt.startswith('*'):
            self.tags_view.collapseAll()
            model.set_categories_filter(txt[1:])
            self.tags_view.recount()
            self.current_find_position = None
            return
        if model.get_categories_filter():
            model.set_categories_filter(None)
            self.tags_view.recount()
            self.current_find_position = None

        if not txt:
            return

        self.item_search.lineEdit().blockSignals(True)
        self.search_button.setFocus(True)
        self.item_search.lineEdit().blockSignals(False)

        if txt.startswith('='):
            equals_match = True
            txt = txt[1:]
        else:
            equals_match = False
        self.current_find_position = \
            model.find_item_node(key, txt, self.current_find_position,
                                 equals_match=equals_match)

        if self.current_find_position:
            self.tags_view.show_item_at_path(self.current_find_position,
                                             box=True)
        elif self.item_search.text():
            self.not_found_label.setVisible(True)
            if self.tags_view.verticalScrollBar().isVisible():
                sbw = self.tags_view.verticalScrollBar().width()
            else:
                sbw = 0
            width = self.width() - 8 - sbw
            height = self.not_found_label.heightForWidth(width) + 20
            self.not_found_label.resize(width, height)
            self.not_found_label.move(4, 10)
            self.not_found_label_timer.start(2000)

    def not_found_label_timer_event(self):
        self.not_found_label.setVisible(False)

    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)
Exemple #33
0
    def __init__(self,
                 ids,
                 get_metadata,
                 field_metadata,
                 parent=None,
                 window_title=None,
                 reject_button_tooltip=None,
                 accept_all_tooltip=None,
                 reject_all_tooltip=None,
                 revert_tooltip=None,
                 intro_msg=None,
                 action_button=None,
                 **kwargs):
        QDialog.__init__(self, parent)
        self.l = l = QVBoxLayout()
        self.setLayout(l)
        self.setWindowIcon(QIcon(I('auto_author_sort.png')))
        self.get_metadata = get_metadata
        self.ids = list(ids)
        self.total = len(self.ids)
        self.accepted = OrderedDict()
        self.rejected_ids = set()
        self.window_title = window_title or _('Compare metadata')

        if intro_msg:
            self.la = la = QLabel(intro_msg)
            la.setWordWrap(True)
            l.addWidget(la)

        self.compare_widget = CompareSingle(field_metadata,
                                            parent=parent,
                                            revert_tooltip=revert_tooltip,
                                            **kwargs)
        self.sa = sa = QScrollArea()
        l.addWidget(sa)
        sa.setWidget(self.compare_widget)
        sa.setWidgetResizable(True)

        self.bb = bb = QDialogButtonBox(QDialogButtonBox.Cancel)
        bb.button(bb.Cancel).setAutoDefault(False)
        bb.rejected.connect(self.reject)
        if self.total > 1:
            self.aarb = b = bb.addButton(_('&Accept all remaining'),
                                         bb.YesRole)
            b.setIcon(QIcon(I('ok.png'))), b.setAutoDefault(False)
            if accept_all_tooltip:
                b.setToolTip(accept_all_tooltip)
            b.clicked.connect(self.accept_all_remaining)
            self.rarb = b = bb.addButton(_('Re&ject all remaining'),
                                         bb.ActionRole)
            b.setIcon(QIcon(I('minus.png'))), b.setAutoDefault(False)
            if reject_all_tooltip:
                b.setToolTip(reject_all_tooltip)
            b.clicked.connect(self.reject_all_remaining)
            self.sb = b = bb.addButton(_('R&eject'), bb.ActionRole)
            b.clicked.connect(partial(self.next_item, False))
            b.setIcon(QIcon(I('minus.png'))), b.setAutoDefault(False)
            if reject_button_tooltip:
                b.setToolTip(reject_button_tooltip)
            self.next_action = ac = QAction(self)
            ac.setShortcut(QKeySequence(Qt.ALT | Qt.Key_Right))
            self.addAction(ac)
        if action_button is not None:
            self.acb = b = bb.addButton(action_button[0], bb.ActionRole)
            b.setIcon(QIcon(action_button[1]))
            self.action_button_action = action_button[2]
            b.clicked.connect(self.action_button_clicked)
        self.nb = b = bb.addButton(
            _('&Next') if self.total > 1 else _('&OK'), bb.ActionRole)
        if self.total > 1:
            b.setToolTip(
                _('Move to next [%s]') %
                self.next_action.shortcut().toString(QKeySequence.NativeText))
            self.next_action.triggered.connect(b.click)
        b.setIcon(QIcon(I('forward.png' if self.total > 1 else 'ok.png')))
        b.clicked.connect(partial(self.next_item, True))
        b.setDefault(True), b.setAutoDefault(True)
        self.bbh = h = QHBoxLayout()
        h.setContentsMargins(0, 0, 0, 0)
        l.addLayout(h)
        self.markq = m = QCheckBox(_('&Mark rejected books'))
        m.setChecked(gprefs['metadata_diff_mark_rejected'])
        m.stateChanged[int].connect(
            lambda: gprefs.set('metadata_diff_mark_rejected', m.isChecked()))
        m.setToolTip(
            _('Mark rejected books in the book list after this dialog is closed'
              ))
        h.addWidget(m), h.addWidget(bb)

        self.next_item(True)

        desktop = QApplication.instance().desktop()
        geom = desktop.availableGeometry(parent or self)
        width = max(700, min(950, geom.width() - 50))
        height = max(650, min(1000, geom.height() - 100))
        self.resize(QSize(width, height))
        geom = gprefs.get('diff_dialog_geom', None)
        if geom is not None:
            self.restoreGeometry(geom)
        b.setFocus(Qt.OtherFocusReason)
Exemple #34
0
    def _setupUi(self):
        settings = Settings()
        settings.beginGroup('Browser-View-Settings')
        windowGeometry = settings.value('WindowGeometry', b'')

        keys = [
            ('LocationBarWidth', int),
            ('WebSearchBarWidth', int),
            ('SideBarWidth', int),
            ('WebViewWidth', int),
            ('SideBar', str),
        ]

        uiState = {}
        for key, typ in keys:
            if settings.contains(key):
                uiState[key] = typ(settings.value(key))

        settings.endGroup()

        widget = QWidget(self)
        widget.setCursor(Qt.ArrowCursor)
        self.setCentralWidget(widget)

        self._mainLayout = QVBoxLayout(widget)
        self._mainLayout.setContentsMargins(0, 0, 0, 0)
        self._mainLayout.setSpacing(0)
        self._mainSplitter = QSplitter(self)
        self._mainSplitter.setObjectName('sidebar-splitter')
        self._tabWidget = TabWidget(self)
        self._superMenu = QMenu(self)
        self._navigationToolbar = NavigationBar(self)
        self._bookmarksToolbar = BookmarksToolbar(self)

        self._tabModel = TabModel(self, self)
        self._tabMruModel = TabMruModel(self, self)
        self._tabMruModel.setSourceModel(self._tabModel)

        self._navigationContainer = NavigationContainer(self)
        self._navigationContainer.addWidget(self._navigationToolbar)
        self._navigationContainer.addWidget(self._bookmarksToolbar)
        self._navigationContainer.setTabBar(self._tabWidget.tabBar())

        self._mainSplitter.addWidget(self._tabWidget)
        self._mainSplitter.setCollapsible(0, False)

        self._mainLayout.addWidget(self._navigationContainer)
        self._mainLayout.addWidget(self._mainSplitter)

        self._statusBar = StatusBar(self)
        self._statusBar.setObjectName('mainwindow-statusbar')
        self._statusBar.setCursor(Qt.ArrowCursor)
        self.setStatusBar(self._statusBar)
        self._progressBar = ProgressBar(self._statusBar)
        self._ipLabel = QLabel(self)
        self._ipLabel.setObjectName('statusbar-ip-label')
        self._ipLabel.setToolTip('IP Address of current page')

        self._statusBar.addPermanentWidget(self._progressBar)
        self._statusBar.addPermanentWidget(self.ipLabel())

        downloadsButton = DownloadsButton(self)
        self._statusBar.addButton(downloadsButton)
        self._navigationToolbar.addToolButton(downloadsButton)

        desktop = gVar.app.desktop()
        windowWidth = desktop.availableGeometry().width() / 1.3
        windowHeight = desktop.availableGeometry().height() / 1.3

        # Let the WM decides where to put new browser window
        if self._windowType not in (const.BW_FirstAppWindow, const.BW_MacFirstWindow) and \
                gVar.app.getWindow():
            if const.OS_WIN:
                # Windows WM places every new window in the middle of screen .. for some reason
                p = gVar.app.getWindow().geometry().topLeft()
                p.setX(p.x() + 30)
                p.setY(p.y() + 30)
                if not desktop.availableGeometry(
                        gVar.app.getWindow()).contains(p):
                    p.setX(
                        desktop.availableGeometry(gVar.app.getWindow()).x() +
                        30)
                    p.setY(
                        desktop.availableGeometry(gVar.app.getWindow()).y() +
                        30)
                self.setGeometry(QRect(p, gVar.app.getWindow().size()))
            else:
                self.resize(gVar.app.getWindow().size())
        elif not self.restoreGeometry(windowGeometry):
            if const.OS_WIN:
                self.setGeometry(
                    QRect(
                        desktop.availableGeometry(gVar.app.getWindow()).x() +
                        30,
                        desktop.availableGeometry(gVar.app.getWindow()).y() +
                        30, windowWidth, windowHeight))
            else:
                self.resize(windowWidth, windowHeight)

        self._restoreUiState(uiState)
        # Set some sane minimum width
        self.setMinimumWidth(300)
Exemple #35
0
    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 b''):
            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())
Exemple #36
0
def ask_about_cc_mismatch(gui, db, newdb, missing_cols, incompatible_cols):  # {{{
    source_metadata = db.field_metadata.custom_field_metadata(include_composites=True)
    dest_library_path = newdb.library_path
    ndbname = os.path.basename(dest_library_path)

    d = QDialog(gui)
    d.setWindowTitle(_('Different custom columns'))
    l = QFormLayout()
    tl = QVBoxLayout()
    d.setLayout(tl)
    d.s = QScrollArea(d)
    tl.addWidget(d.s)
    d.w = QWidget(d)
    d.s.setWidget(d.w)
    d.s.setWidgetResizable(True)
    d.w.setLayout(l)
    d.setMinimumWidth(600)
    d.setMinimumHeight(500)
    d.bb = QDialogButtonBox(QDialogButtonBox.Ok|QDialogButtonBox.Cancel)

    msg = _('The custom columns in the <i>{0}</i> library are different from the '
        'custom columns in the <i>{1}</i> library. As a result, some metadata might not be copied.').format(
        os.path.basename(db.library_path), ndbname)
    d.la = la = QLabel(msg)
    la.setWordWrap(True)
    la.setStyleSheet('QLabel { margin-bottom: 1.5ex }')
    l.addRow(la)
    if incompatible_cols:
        la = d.la2 = QLabel(_('The following columns are incompatible - they have the same name'
                ' but different data types. They will be ignored: ') +
                    ', '.join(sorted(incompatible_cols, key=sort_key)))
        la.setWordWrap(True)
        la.setStyleSheet('QLabel { margin-bottom: 1.5ex }')
        l.addRow(la)

    missing_widgets = []
    if missing_cols:
        la = d.la3 = QLabel(_('The following columns are missing in the <i>{0}</i> library.'
                                ' You can choose to add them automatically below.').format(
                                    ndbname))
        la.setWordWrap(True)
        l.addRow(la)
        for k in missing_cols:
            widgets = (k, QCheckBox(_('Add to the %s library') % ndbname))
            l.addRow(QLabel(k), widgets[1])
            missing_widgets.append(widgets)
    d.la4 = la = QLabel(_('This warning is only shown once per library, per session'))
    la.setWordWrap(True)
    tl.addWidget(la)

    tl.addWidget(d.bb)
    d.bb.accepted.connect(d.accept)
    d.bb.rejected.connect(d.reject)
    d.resize(d.sizeHint())
    if d.exec_() == d.Accepted:
        changes_made = False
        for k, cb in missing_widgets:
            if cb.isChecked():
                col_meta = source_metadata[k]
                newdb.create_custom_column(
                            col_meta['label'], col_meta['name'], col_meta['datatype'],
                            len(col_meta['is_multiple']) > 0,
                            col_meta['is_editable'], col_meta['display'])
                changes_made = True
        if changes_made:
            # Unload the db so that the changes are available
            # when it is next accessed
            from calibre.gui2.ui import get_gui
            library_broker = get_gui().library_broker
            library_broker.unload_library(dest_library_path)
        return True
    return False
Exemple #37
0
    def __init__(self, window, plugin, keystore, device_id):
        title = _("{} Settings").format(plugin.device)
        super(SettingsDialog, self).__init__(window, title)
        self.setMaximumWidth(540)

        devmgr = plugin.device_manager()
        config = devmgr.config
        handler = keystore.handler
        thread = keystore.thread
        hs_rows, hs_cols = (64, 128)

        def invoke_client(method, *args, **kw_args):
            unpair_after = kw_args.pop('unpair_after', False)

            def task():
                client = devmgr.client_by_id(device_id)
                if not client:
                    raise RuntimeError("Device not connected")
                if method:
                    getattr(client, method)(*args, **kw_args)
                if unpair_after:
                    devmgr.unpair_id(device_id)
                return client.features

            thread.add(task, on_success=update)

        def update(features):
            self.features = features
            set_label_enabled()
            if features.bootloader_hash:
                bl_hash = bh2u(features.bootloader_hash)
                bl_hash = "\n".join([bl_hash[:32], bl_hash[32:]])
            else:
                bl_hash = "N/A"
            noyes = [_("No"), _("Yes")]
            endis = [_("Enable Passphrases"), _("Disable Passphrases")]
            disen = [_("Disabled"), _("Enabled")]
            setchange = [_("Set a PIN"), _("Change PIN")]

            version = "%d.%d.%d" % (features.major_version,
                                    features.minor_version,
                                    features.patch_version)
            coins = ", ".join(coin.coin_name for coin in features.coins)

            device_label.setText(features.label)
            pin_set_label.setText(noyes[features.pin_protection])
            passphrases_label.setText(disen[features.passphrase_protection])
            bl_hash_label.setText(bl_hash)
            label_edit.setText(features.label)
            device_id_label.setText(features.device_id)
            initialized_label.setText(noyes[features.initialized])
            version_label.setText(version)
            coins_label.setText(coins)
            clear_pin_button.setVisible(features.pin_protection)
            clear_pin_warning.setVisible(features.pin_protection)
            pin_button.setText(setchange[features.pin_protection])
            pin_msg.setVisible(not features.pin_protection)
            passphrase_button.setText(endis[features.passphrase_protection])
            language_label.setText(features.language)

        def set_label_enabled():
            label_apply.setEnabled(label_edit.text() != self.features.label)

        def rename():
            invoke_client('change_label', label_edit.text())

        def toggle_passphrase():
            title = _("Confirm Toggle Passphrase Protection")
            currently_enabled = self.features.passphrase_protection
            if currently_enabled:
                msg = _("After disabling passphrases, you can only pair this "
                        "Electrum wallet if it had an empty passphrase.  "
                        "If its passphrase was not empty, you will need to "
                        "create a new wallet with the install wizard.  You "
                        "can use this wallet again at any time by re-enabling "
                        "passphrases and entering its passphrase.")
            else:
                msg = _("Your current Electrum wallet can only be used with "
                        "an empty passphrase.  You must create a separate "
                        "wallet with the install wizard for other passphrases "
                        "as each one generates a new set of addresses.")
            msg += "\n\n" + _("Are you sure you want to proceed?")
            if not self.question(msg, title=title):
                return
            invoke_client('toggle_passphrase', unpair_after=currently_enabled)

        def change_homescreen():
            dialog = QFileDialog(self, _("Choose Homescreen"))
            filename, __ = dialog.getOpenFileName()

            if filename.endswith('.toif'):
                img = open(filename, 'rb').read()
                if img[:8] != b'TOIf\x90\x00\x90\x00':
                    raise Exception(
                        'File is not a TOIF file with size of 144x144')
            else:
                from PIL import Image  # FIXME
                im = Image.open(filename)
                if im.size != (128, 64):
                    raise Exception('Image must be 128 x 64 pixels')
                im = im.convert('1')
                pix = im.load()
                img = bytearray(1024)
                for j in range(64):
                    for i in range(128):
                        if pix[i, j]:
                            o = (i + j * 128)
                            img[o // 8] |= (1 << (7 - o % 8))
                img = bytes(img)
                invoke_client('change_homescreen', img)

        def clear_homescreen():
            invoke_client('change_homescreen', b'\x00')

        def set_pin():
            invoke_client('set_pin', remove=False)

        def clear_pin():
            invoke_client('set_pin', remove=True)

        def wipe_device():
            wallet = window.wallet
            if wallet and sum(wallet.get_balance()):
                title = _("Confirm Device Wipe")
                msg = _("Are you SURE you want to wipe the device?\n"
                        "Your wallet still has bitcoins in it!")
                if not self.question(
                        msg, title=title, icon=QMessageBox.Critical):
                    return
            invoke_client('wipe_device', unpair_after=True)

        def slider_moved():
            mins = timeout_slider.sliderPosition()
            timeout_minutes.setText(_("%2d minutes") % mins)

        def slider_released():
            config.set_session_timeout(timeout_slider.sliderPosition() * 60)

        # Information tab
        info_tab = QWidget()
        info_layout = QVBoxLayout(info_tab)
        info_glayout = QGridLayout()
        info_glayout.setColumnStretch(2, 1)
        device_label = QLabel()
        pin_set_label = QLabel()
        passphrases_label = QLabel()
        version_label = QLabel()
        device_id_label = QLabel()
        bl_hash_label = QLabel()
        bl_hash_label.setWordWrap(True)
        coins_label = QLabel()
        coins_label.setWordWrap(True)
        language_label = QLabel()
        initialized_label = QLabel()
        rows = [
            (_("Device Label"), device_label),
            (_("PIN set"), pin_set_label),
            (_("Passphrases"), passphrases_label),
            (_("Firmware Version"), version_label),
            (_("Device ID"), device_id_label),
            (_("Bootloader Hash"), bl_hash_label),
            (_("Supported Coins"), coins_label),
            (_("Language"), language_label),
            (_("Initialized"), initialized_label),
        ]
        for row_num, (label, widget) in enumerate(rows):
            info_glayout.addWidget(QLabel(label), row_num, 0)
            info_glayout.addWidget(widget, row_num, 1)
        info_layout.addLayout(info_glayout)

        # Settings tab
        settings_tab = QWidget()
        settings_layout = QVBoxLayout(settings_tab)
        settings_glayout = QGridLayout()

        # Settings tab - Label
        label_msg = QLabel(
            _("Name this {}.  If you have multiple devices "
              "their labels help distinguish them.").format(plugin.device))
        label_msg.setWordWrap(True)
        label_label = QLabel(_("Device Label"))
        label_edit = QLineEdit()
        label_edit.setMinimumWidth(150)
        label_edit.setMaxLength(plugin.MAX_LABEL_LEN)
        label_apply = QPushButton(_("Apply"))
        label_apply.clicked.connect(rename)
        label_edit.textChanged.connect(set_label_enabled)
        settings_glayout.addWidget(label_label, 0, 0)
        settings_glayout.addWidget(label_edit, 0, 1, 1, 2)
        settings_glayout.addWidget(label_apply, 0, 3)
        settings_glayout.addWidget(label_msg, 1, 1, 1, -1)

        # Settings tab - PIN
        pin_label = QLabel(_("PIN Protection"))
        pin_button = QPushButton()
        pin_button.clicked.connect(set_pin)
        settings_glayout.addWidget(pin_label, 2, 0)
        settings_glayout.addWidget(pin_button, 2, 1)
        pin_msg = QLabel(
            _("PIN protection is strongly recommended.  "
              "A PIN is your only protection against someone "
              "stealing your bitcoins if they obtain physical "
              "access to your {}.").format(plugin.device))
        pin_msg.setWordWrap(True)
        pin_msg.setStyleSheet("color: red")
        settings_glayout.addWidget(pin_msg, 3, 1, 1, -1)

        # Settings tab - Homescreen
        if plugin.device != 'KeepKey':  # Not yet supported by KK firmware
            homescreen_layout = QHBoxLayout()
            homescreen_label = QLabel(_("Homescreen"))
            homescreen_change_button = QPushButton(_("Change..."))
            homescreen_clear_button = QPushButton(_("Reset"))
            homescreen_change_button.clicked.connect(change_homescreen)
            homescreen_clear_button.clicked.connect(clear_homescreen)
            homescreen_msg = QLabel(
                _("You can set the homescreen on your "
                  "device to personalize it.  You must "
                  "choose a {} x {} monochrome black and "
                  "white image.").format(hs_rows, hs_cols))
            homescreen_msg.setWordWrap(True)
            settings_glayout.addWidget(homescreen_label, 4, 0)
            settings_glayout.addWidget(homescreen_change_button, 4, 1)
            settings_glayout.addWidget(homescreen_clear_button, 4, 2)
            settings_glayout.addWidget(homescreen_msg, 5, 1, 1, -1)

        # Settings tab - Session Timeout
        timeout_label = QLabel(_("Session Timeout"))
        timeout_minutes = QLabel()
        timeout_slider = QSlider(Qt.Horizontal)
        timeout_slider.setRange(1, 60)
        timeout_slider.setSingleStep(1)
        timeout_slider.setTickInterval(5)
        timeout_slider.setTickPosition(QSlider.TicksBelow)
        timeout_slider.setTracking(True)
        timeout_msg = QLabel(
            _("Clear the session after the specified period "
              "of inactivity.  Once a session has timed out, "
              "your PIN and passphrase (if enabled) must be "
              "re-entered to use the device."))
        timeout_msg.setWordWrap(True)
        timeout_slider.setSliderPosition(config.get_session_timeout() // 60)
        slider_moved()
        timeout_slider.valueChanged.connect(slider_moved)
        timeout_slider.sliderReleased.connect(slider_released)
        settings_glayout.addWidget(timeout_label, 6, 0)
        settings_glayout.addWidget(timeout_slider, 6, 1, 1, 3)
        settings_glayout.addWidget(timeout_minutes, 6, 4)
        settings_glayout.addWidget(timeout_msg, 7, 1, 1, -1)
        settings_layout.addLayout(settings_glayout)
        settings_layout.addStretch(1)

        # Advanced tab
        advanced_tab = QWidget()
        advanced_layout = QVBoxLayout(advanced_tab)
        advanced_glayout = QGridLayout()

        # Advanced tab - clear PIN
        clear_pin_button = QPushButton(_("Disable PIN"))
        clear_pin_button.clicked.connect(clear_pin)
        clear_pin_warning = QLabel(
            _("If you disable your PIN, anyone with physical access to your "
              "{} device can spend your bitcoins.").format(plugin.device))
        clear_pin_warning.setWordWrap(True)
        clear_pin_warning.setStyleSheet("color: red")
        advanced_glayout.addWidget(clear_pin_button, 0, 2)
        advanced_glayout.addWidget(clear_pin_warning, 1, 0, 1, 5)

        # Advanced tab - toggle passphrase protection
        passphrase_button = QPushButton()
        passphrase_button.clicked.connect(toggle_passphrase)
        passphrase_msg = WWLabel(PASSPHRASE_HELP)
        passphrase_warning = WWLabel(PASSPHRASE_NOT_PIN)
        passphrase_warning.setStyleSheet("color: red")
        advanced_glayout.addWidget(passphrase_button, 3, 2)
        advanced_glayout.addWidget(passphrase_msg, 4, 0, 1, 5)
        advanced_glayout.addWidget(passphrase_warning, 5, 0, 1, 5)

        # Advanced tab - wipe device
        wipe_device_button = QPushButton(_("Wipe Device"))
        wipe_device_button.clicked.connect(wipe_device)
        wipe_device_msg = QLabel(
            _("Wipe the device, removing all data from it.  The firmware "
              "is left unchanged."))
        wipe_device_msg.setWordWrap(True)
        wipe_device_warning = QLabel(
            _("Only wipe a device if you have the recovery seed written down "
              "and the device wallet(s) are empty, otherwise the bitcoins "
              "will be lost forever."))
        wipe_device_warning.setWordWrap(True)
        wipe_device_warning.setStyleSheet("color: red")
        advanced_glayout.addWidget(wipe_device_button, 6, 2)
        advanced_glayout.addWidget(wipe_device_msg, 7, 0, 1, 5)
        advanced_glayout.addWidget(wipe_device_warning, 8, 0, 1, 5)
        advanced_layout.addLayout(advanced_glayout)
        advanced_layout.addStretch(1)

        tabs = QTabWidget(self)
        tabs.addTab(info_tab, _("Information"))
        tabs.addTab(settings_tab, _("Settings"))
        tabs.addTab(advanced_tab, _("Advanced"))
        dialog_vbox = QVBoxLayout(self)
        dialog_vbox.addWidget(tabs)
        dialog_vbox.addLayout(Buttons(CloseButton(self)))

        # Update information
        invoke_client(None)
Exemple #38
0
    def __init__(self, parent, view, row, link_delegate):
        QDialog.__init__(self, parent)
        self.normal_brush = QBrush(Qt.white)
        self.marked_brush = QBrush(Qt.lightGray)
        self.marked = None
        self.gui = parent
        self.splitter = QSplitter(self)
        self._l = l = QVBoxLayout(self)
        self.setLayout(l)
        l.addWidget(self.splitter)

        self.cover = CoverView(self)
        self.cover.resizeEvent = self.cover_view_resized
        self.cover.cover_changed.connect(self.cover_changed)
        self.cover_pixmap = None
        self.cover.sizeHint = self.details_size_hint
        self.splitter.addWidget(self.cover)

        self.details = Details(parent.book_details.book_info, self)
        self.details.page().setLinkDelegationPolicy(
            self.details.page().DelegateAllLinks)
        self.details.linkClicked.connect(self.link_clicked)
        s = self.details.page().settings()
        s.setAttribute(s.JavascriptEnabled, False)
        self.css = css()
        self.link_delegate = link_delegate
        self.details.setAttribute(Qt.WA_OpaquePaintEvent, False)
        palette = self.details.palette()
        self.details.setAcceptDrops(False)
        palette.setBrush(QPalette.Base, Qt.transparent)
        self.details.page().setPalette(palette)

        self.c = QWidget(self)
        self.c.l = l2 = QGridLayout(self.c)
        self.c.setLayout(l2)
        l2.addWidget(self.details, 0, 0, 1, -1)
        self.splitter.addWidget(self.c)

        self.fit_cover = QCheckBox(_('Fit &cover within view'), self)
        self.fit_cover.setChecked(
            gprefs.get('book_info_dialog_fit_cover', True))
        l2.addWidget(self.fit_cover, l2.rowCount(), 0, 1, -1)
        self.previous_button = QPushButton(QIcon(I('previous.png')),
                                           _('&Previous'), self)
        self.previous_button.clicked.connect(self.previous)
        l2.addWidget(self.previous_button, l2.rowCount(), 0)
        self.next_button = QPushButton(QIcon(I('next.png')), _('&Next'), self)
        self.next_button.clicked.connect(self.next)
        l2.addWidget(self.next_button, l2.rowCount() - 1, 1)

        self.view = view
        self.current_row = None
        self.refresh(row)
        self.view.model().new_bookdisplay_data.connect(self.slave)
        self.fit_cover.stateChanged.connect(self.toggle_cover_fit)
        self.ns = QShortcut(QKeySequence('Alt+Right'), self)
        self.ns.activated.connect(self.next)
        self.ps = QShortcut(QKeySequence('Alt+Left'), self)
        self.ps.activated.connect(self.previous)
        self.next_button.setToolTip(
            _('Next [%s]') %
            unicode(self.ns.key().toString(QKeySequence.NativeText)))
        self.previous_button.setToolTip(
            _('Previous [%s]') %
            unicode(self.ps.key().toString(QKeySequence.NativeText)))

        geom = QCoreApplication.instance().desktop().availableGeometry(self)
        screen_height = geom.height() - 100
        screen_width = geom.width() - 100
        self.resize(max(int(screen_width / 2), 700), screen_height)
        saved_layout = gprefs.get('book_info_dialog_layout', None)
        if saved_layout is not None:
            try:
                self.restoreGeometry(saved_layout[0])
                self.splitter.restoreState(saved_layout[1])
            except Exception:
                pass
Exemple #39
0
    def __init__(self,
                 parent=None,
                 one_line_toolbar=False,
                 toolbar_prefs_name=None):
        QWidget.__init__(self, parent)
        self.toolbar_prefs_name = toolbar_prefs_name or self.toolbar_prefs_name
        self.toolbar1 = QToolBar(self)
        self.toolbar2 = QToolBar(self)
        self.toolbar3 = QToolBar(self)
        for i in range(1, 4):
            t = getattr(self, 'toolbar%d' % i)
            t.setIconSize(QSize(18, 18))
        self.editor = EditorWidget(self)
        self.set_html = self.editor.set_html
        self.tabs = QTabWidget(self)
        self.tabs.setTabPosition(self.tabs.South)
        self.wyswyg = QWidget(self.tabs)
        self.code_edit = QPlainTextEdit(self.tabs)
        self.source_dirty = False
        self.wyswyg_dirty = True

        self._layout = QVBoxLayout(self)
        self.wyswyg.layout = l = QVBoxLayout(self.wyswyg)
        self.setLayout(self._layout)
        l.setContentsMargins(0, 0, 0, 0)
        if one_line_toolbar:
            tb = QHBoxLayout()
            l.addLayout(tb)
        else:
            tb = l
        tb.addWidget(self.toolbar1)
        tb.addWidget(self.toolbar2)
        tb.addWidget(self.toolbar3)
        l.addWidget(self.editor)
        self._layout.addWidget(self.tabs)
        self.tabs.addTab(self.wyswyg, _('N&ormal view'))
        self.tabs.addTab(self.code_edit, _('&HTML source'))
        self.tabs.currentChanged[int].connect(self.change_tab)
        self.highlighter = Highlighter(self.code_edit.document())
        self.layout().setContentsMargins(0, 0, 0, 0)
        if self.toolbar_prefs_name is not None:
            hidden = gprefs.get(self.toolbar_prefs_name)
            if hidden:
                self.hide_toolbars()

        # toolbar1 {{{
        self.toolbar1.addAction(self.editor.action_undo)
        self.toolbar1.addAction(self.editor.action_redo)
        self.toolbar1.addAction(self.editor.action_select_all)
        self.toolbar1.addAction(self.editor.action_remove_format)
        self.toolbar1.addAction(self.editor.action_clear)
        self.toolbar1.addSeparator()

        for x in ('copy', 'cut', 'paste'):
            ac = getattr(self.editor, 'action_' + x)
            self.toolbar1.addAction(ac)

        self.toolbar1.addSeparator()
        self.toolbar1.addAction(self.editor.action_background)
        # }}}

        # toolbar2 {{{
        for x in ('', 'un'):
            ac = getattr(self.editor, 'action_%sordered_list' % x)
            self.toolbar2.addAction(ac)
        self.toolbar2.addSeparator()
        for x in ('superscript', 'subscript', 'indent', 'outdent'):
            self.toolbar2.addAction(getattr(self.editor, 'action_' + x))
            if x in ('subscript', 'outdent'):
                self.toolbar2.addSeparator()

        self.toolbar2.addAction(self.editor.action_block_style)
        w = self.toolbar2.widgetForAction(self.editor.action_block_style)
        if hasattr(w, 'setPopupMode'):
            w.setPopupMode(w.InstantPopup)
        self.toolbar2.addAction(self.editor.action_insert_link)
        self.toolbar2.addAction(self.editor.action_insert_hr)
        # }}}

        # toolbar3 {{{
        for x in ('bold', 'italic', 'underline', 'strikethrough'):
            ac = getattr(self.editor, 'action_' + x)
            self.toolbar3.addAction(ac)
        self.toolbar3.addSeparator()

        for x in ('left', 'center', 'right', 'justified'):
            ac = getattr(self.editor, 'action_align_' + x)
            self.toolbar3.addAction(ac)
        self.toolbar3.addSeparator()
        self.toolbar3.addAction(self.editor.action_color)
        # }}}

        self.code_edit.textChanged.connect(self.code_dirtied)
        self.editor.page().contentsChanged.connect(self.wyswyg_dirtied)
Exemple #40
0
class Editor(QWidget):  # {{{

    toolbar_prefs_name = None

    def __init__(self,
                 parent=None,
                 one_line_toolbar=False,
                 toolbar_prefs_name=None):
        QWidget.__init__(self, parent)
        self.toolbar_prefs_name = toolbar_prefs_name or self.toolbar_prefs_name
        self.toolbar1 = QToolBar(self)
        self.toolbar2 = QToolBar(self)
        self.toolbar3 = QToolBar(self)
        for i in range(1, 4):
            t = getattr(self, 'toolbar%d' % i)
            t.setIconSize(QSize(18, 18))
        self.editor = EditorWidget(self)
        self.set_html = self.editor.set_html
        self.tabs = QTabWidget(self)
        self.tabs.setTabPosition(self.tabs.South)
        self.wyswyg = QWidget(self.tabs)
        self.code_edit = QPlainTextEdit(self.tabs)
        self.source_dirty = False
        self.wyswyg_dirty = True

        self._layout = QVBoxLayout(self)
        self.wyswyg.layout = l = QVBoxLayout(self.wyswyg)
        self.setLayout(self._layout)
        l.setContentsMargins(0, 0, 0, 0)
        if one_line_toolbar:
            tb = QHBoxLayout()
            l.addLayout(tb)
        else:
            tb = l
        tb.addWidget(self.toolbar1)
        tb.addWidget(self.toolbar2)
        tb.addWidget(self.toolbar3)
        l.addWidget(self.editor)
        self._layout.addWidget(self.tabs)
        self.tabs.addTab(self.wyswyg, _('N&ormal view'))
        self.tabs.addTab(self.code_edit, _('&HTML source'))
        self.tabs.currentChanged[int].connect(self.change_tab)
        self.highlighter = Highlighter(self.code_edit.document())
        self.layout().setContentsMargins(0, 0, 0, 0)
        if self.toolbar_prefs_name is not None:
            hidden = gprefs.get(self.toolbar_prefs_name)
            if hidden:
                self.hide_toolbars()

        # toolbar1 {{{
        self.toolbar1.addAction(self.editor.action_undo)
        self.toolbar1.addAction(self.editor.action_redo)
        self.toolbar1.addAction(self.editor.action_select_all)
        self.toolbar1.addAction(self.editor.action_remove_format)
        self.toolbar1.addAction(self.editor.action_clear)
        self.toolbar1.addSeparator()

        for x in ('copy', 'cut', 'paste'):
            ac = getattr(self.editor, 'action_' + x)
            self.toolbar1.addAction(ac)

        self.toolbar1.addSeparator()
        self.toolbar1.addAction(self.editor.action_background)
        # }}}

        # toolbar2 {{{
        for x in ('', 'un'):
            ac = getattr(self.editor, 'action_%sordered_list' % x)
            self.toolbar2.addAction(ac)
        self.toolbar2.addSeparator()
        for x in ('superscript', 'subscript', 'indent', 'outdent'):
            self.toolbar2.addAction(getattr(self.editor, 'action_' + x))
            if x in ('subscript', 'outdent'):
                self.toolbar2.addSeparator()

        self.toolbar2.addAction(self.editor.action_block_style)
        w = self.toolbar2.widgetForAction(self.editor.action_block_style)
        if hasattr(w, 'setPopupMode'):
            w.setPopupMode(w.InstantPopup)
        self.toolbar2.addAction(self.editor.action_insert_link)
        self.toolbar2.addAction(self.editor.action_insert_hr)
        # }}}

        # toolbar3 {{{
        for x in ('bold', 'italic', 'underline', 'strikethrough'):
            ac = getattr(self.editor, 'action_' + x)
            self.toolbar3.addAction(ac)
        self.toolbar3.addSeparator()

        for x in ('left', 'center', 'right', 'justified'):
            ac = getattr(self.editor, 'action_align_' + x)
            self.toolbar3.addAction(ac)
        self.toolbar3.addSeparator()
        self.toolbar3.addAction(self.editor.action_color)
        # }}}

        self.code_edit.textChanged.connect(self.code_dirtied)
        self.editor.page().contentsChanged.connect(self.wyswyg_dirtied)

    def set_minimum_height_for_editor(self, val):
        self.editor.setMinimumHeight(val)

    @dynamic_property
    def html(self):
        def fset(self, v):
            self.editor.html = v

        def fget(self):
            self.tabs.setCurrentIndex(0)
            return self.editor.html

        return property(fget=fget, fset=fset)

    def change_tab(self, index):
        # print 'reloading:', (index and self.wyswyg_dirty) or (not index and
        #        self.source_dirty)
        if index == 1:  # changing to code view
            if self.wyswyg_dirty:
                self.code_edit.setPlainText(self.editor.html)
                self.wyswyg_dirty = False
        elif index == 0:  # changing to wyswyg
            if self.source_dirty:
                self.editor.html = unicode(self.code_edit.toPlainText())
                self.source_dirty = False

    @dynamic_property
    def tab(self):
        def fget(self):
            return 'code' if self.tabs.currentWidget(
            ) is self.code_edit else 'wyswyg'

        def fset(self, val):
            self.tabs.setCurrentWidget(self.code_edit if val ==
                                       'code' else self.wyswyg)

        return property(fget=fget, fset=fset)

    def wyswyg_dirtied(self, *args):
        self.wyswyg_dirty = True

    def code_dirtied(self, *args):
        self.source_dirty = True

    def hide_toolbars(self):
        self.toolbar1.setVisible(False)
        self.toolbar2.setVisible(False)
        self.toolbar3.setVisible(False)

    def show_toolbars(self):
        self.toolbar1.setVisible(True)
        self.toolbar2.setVisible(True)
        self.toolbar3.setVisible(True)

    def toggle_toolbars(self):
        visible = self.toolbars_visible
        getattr(self, ('hide' if visible else 'show') + '_toolbars')()
        if self.toolbar_prefs_name is not None:
            gprefs.set(self.toolbar_prefs_name, visible)

    @dynamic_property
    def toolbars_visible(self):
        def fget(self):
            return self.toolbar1.isVisible() or self.toolbar2.isVisible(
            ) or self.toolbar3.isVisible()

        def fset(self, val):
            getattr(self, ('show' if val else 'hide') + '_toolbars')()

        return property(fget=fget, fset=fset)

    def set_readonly(self, what):
        self.editor.set_readonly(what)

    def hide_tabs(self):
        self.tabs.tabBar().setVisible(False)
Exemple #41
0
            return False


# }}}

if __name__ == '__main__':
    from calibre.gui2 import Application
    from calibre.devices.kobo.driver import KOBOTOUCH
    from calibre.devices.scanner import DeviceScanner
    s = DeviceScanner()
    s.scan()
    app = Application([])
    debug_print("KOBOTOUCH:", KOBOTOUCH)
    dev = KOBOTOUCH(None)
    #     dev.startup()
    #     cd = dev.detect_managed_devices(s.devices)
    #     dev.open(cd, 'test')
    cw = dev.config_widget()
    d = QDialog()
    d.l = QVBoxLayout()
    d.setLayout(d.l)
    d.l.addWidget(cw)
    bb = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel)
    d.l.addWidget(bb)
    bb.accepted.connect(d.accept)
    bb.rejected.connect(d.reject)
    if d.exec_() == d.Accepted:
        cw.commit()
    dev.shutdown()
Exemple #42
0
    def request_trezor_init_settings(self, wizard, method, device):
        vbox = QVBoxLayout()
        next_enabled = True
        label = QLabel(_("Enter a label to name your device:"))
        name = QLineEdit()
        hl = QHBoxLayout()
        hl.addWidget(label)
        hl.addWidget(name)
        hl.addStretch(1)
        vbox.addLayout(hl)

        def clean_text(widget):
            text = widget.toPlainText().strip()
            return ' '.join(text.split())

        if method in [TIM_NEW, TIM_RECOVER]:
            gb = QGroupBox()
            hbox1 = QHBoxLayout()
            gb.setLayout(hbox1)
            vbox.addWidget(gb)
            gb.setTitle(_("Select your seed length:"))
            bg = QButtonGroup()
            for i, count in enumerate([12, 18, 24]):
                rb = QRadioButton(gb)
                rb.setText(_("%d words") % count)
                bg.addButton(rb)
                bg.setId(rb, i)
                hbox1.addWidget(rb)
                rb.setChecked(True)
            cb_pin = QCheckBox(_('Enable PIN protection'))
            cb_pin.setChecked(True)
        else:
            text = QTextEdit()
            text.setMaximumHeight(60)
            if method == TIM_MNEMONIC:
                msg = _("Enter your BIP39 mnemonic:")
            else:
                msg = _("Enter the master private key beginning with xprv:")

                def set_enabled():
                    from btn_electrum.keystore import is_xprv
                    wizard.next_button.setEnabled(is_xprv(clean_text(text)))

                text.textChanged.connect(set_enabled)
                next_enabled = False

            vbox.addWidget(QLabel(msg))
            vbox.addWidget(text)
            pin = QLineEdit()
            pin.setValidator(QRegExpValidator(QRegExp('[1-9]{0,9}')))
            pin.setMaximumWidth(100)
            hbox_pin = QHBoxLayout()
            hbox_pin.addWidget(QLabel(_("Enter your PIN (digits 1-9):")))
            hbox_pin.addWidget(pin)
            hbox_pin.addStretch(1)

        if method in [TIM_NEW, TIM_RECOVER]:
            vbox.addWidget(WWLabel(RECOMMEND_PIN))
            vbox.addWidget(cb_pin)
        else:
            vbox.addLayout(hbox_pin)

        passphrase_msg = WWLabel(PASSPHRASE_HELP_SHORT)
        passphrase_warning = WWLabel(PASSPHRASE_NOT_PIN)
        passphrase_warning.setStyleSheet("color: red")
        cb_phrase = QCheckBox(_('Enable passphrases'))
        cb_phrase.setChecked(False)
        vbox.addWidget(passphrase_msg)
        vbox.addWidget(passphrase_warning)
        vbox.addWidget(cb_phrase)

        wizard.exec_layout(vbox, next_enabled=next_enabled)

        if method in [TIM_NEW, TIM_RECOVER]:
            item = bg.checkedId()
            pin = cb_pin.isChecked()
        else:
            item = ' '.join(str(clean_text(text)).split())
            pin = str(pin.text())

        return (item, name.text(), pin, cb_phrase.isChecked())
Exemple #43
0
    def __init__(self, main):
        super(GameCreateWidget, self).__init__()
        self.main_win = main
        self.setObjectName("GameCreateWidget")

        h_layout = QHBoxLayout()

        form_layout = QFormLayout()
        form_layout.setContentsMargins(20, 50, 20, 50)

        self.game_name_value = QLineEdit()
        form_layout.addRow("游戏名称:", self.game_name_value)

        self.game_desc_value = QTextEdit()
        form_layout.addRow("游戏简介:", self.game_desc_value)

        self.game_appid_value = QLineEdit()
        form_layout.addRow("游戏ID:", self.game_appid_value)

        self.game_appkey_value = QLineEdit()
        form_layout.addRow("客户端Key:", self.game_appkey_value)

        h_layout2 = QHBoxLayout()
        self.keystore_path = QLineEdit()
        select_key_btn = QPushButton("浏览")
        select_key_btn.setStyleSheet('QPushButton{border-radius: 0px;}')
        select_key_btn.clicked.connect(self.select_keystore)
        h_layout2.addWidget(self.keystore_path)
        h_layout2.addWidget(select_key_btn)
        form_layout.addRow("KeyStore:", h_layout2)

        self.keystore_pwd_value = QLineEdit()
        form_layout.addRow("KeyPass:"******"Alias:", self.keystore_alias_value)

        self.keystore_aliaspwd_value = QLineEdit()
        form_layout.addRow("AliasPass:"******"添加Icon")
        icon_add_btn.setFixedWidth(100)
        icon_add_btn.clicked.connect(self.add_icon)
        v_layout2.addWidget(icon_add_btn, alignment=Qt.AlignHCenter)
        v_layout2.addStretch(6)
        create_btn = QPushButton("创 建")
        create_btn.setFixedWidth(100)
        create_btn.clicked.connect(self.create)
        v_layout2.addWidget(create_btn,
                            alignment=Qt.AlignRight | Qt.AlignBottom)
        v_layout2.addStretch(1)
        back_btn = QPushButton("返 回")
        back_btn.setFixedWidth(100)
        back_btn.clicked.connect(self.back)
        v_layout2.addWidget(back_btn, alignment=Qt.AlignRight | Qt.AlignBottom)
        h_layout.addLayout(v_layout2, 1)

        self.setLayout(h_layout)
        self.game = {}
        self.icon_path = None
Exemple #44
0
    def do_user_config(self, parent=None):
        '''
        This method shows a configuration dialog for this plugin. It returns
        True if the user clicks OK, False otherwise. The changes are
        automatically applied.
        '''
        from PyQt5.Qt import QDialog, QDialogButtonBox, QVBoxLayout, \
                QLabel, Qt, QLineEdit
        from calibre.gui2 import gprefs

        prefname = 'plugin config dialog:' + self.type + ':' + self.name
        geom = gprefs.get(prefname, None)

        config_dialog = QDialog(parent)
        button_box = QDialogButtonBox(QDialogButtonBox.Ok
                                      | QDialogButtonBox.Cancel)
        v = QVBoxLayout(config_dialog)

        def size_dialog():
            if geom is None:
                config_dialog.resize(config_dialog.sizeHint())
            else:
                config_dialog.restoreGeometry(geom)

        button_box.accepted.connect(config_dialog.accept)
        button_box.rejected.connect(config_dialog.reject)
        config_dialog.setWindowTitle(_('Customize') + ' ' + self.name)
        try:
            config_widget = self.config_widget()
        except NotImplementedError:
            config_widget = None

        if isinstance(config_widget, tuple):
            from calibre.gui2 import warning_dialog
            warning_dialog(parent,
                           _('Cannot configure'),
                           config_widget[0],
                           det_msg=config_widget[1],
                           show=True)
            return False

        if config_widget is not None:
            v.addWidget(config_widget)
            v.addWidget(button_box)
            size_dialog()
            config_dialog.exec_()

            if config_dialog.result() == QDialog.Accepted:
                if hasattr(config_widget, 'validate'):
                    if config_widget.validate():
                        self.save_settings(config_widget)
                else:
                    self.save_settings(config_widget)
        else:
            from calibre.customize.ui import plugin_customization, \
                customize_plugin
            help_text = self.customization_help(gui=True)
            help_text = QLabel(help_text, config_dialog)
            help_text.setWordWrap(True)
            help_text.setTextInteractionFlags(Qt.LinksAccessibleByMouse
                                              | Qt.LinksAccessibleByKeyboard)
            help_text.setOpenExternalLinks(True)
            v.addWidget(help_text)
            sc = plugin_customization(self)
            if not sc:
                sc = ''
            sc = sc.strip()
            sc = QLineEdit(sc, config_dialog)
            v.addWidget(sc)
            v.addWidget(button_box)
            size_dialog()
            config_dialog.exec_()

            if config_dialog.result() == QDialog.Accepted:
                sc = unicode(sc.text()).strip()
                customize_plugin(self, sc)

        geom = bytearray(config_dialog.saveGeometry())
        gprefs[prefname] = geom

        return config_dialog.result()
Exemple #45
0
    def clear(self):
        self.lineEdit().clear()
        EnComboBox.clear(self)

    def eventFilter(self, obj, e):
        try:
            c = self.lineEdit().mcompleter
        except AttributeError:
            return False
        etype = e.type()
        if self.eat_focus_out and self is obj and etype == e.FocusOut:
            if c.isVisible():
                return True
        return EnComboBox.eventFilter(self, obj, e)


if __name__ == '__main__':
    from PyQt5.Qt import QDialog, QVBoxLayout
    app = QApplication([])
    d = QDialog()
    d.setLayout(QVBoxLayout())
    le = EditWithComplete(d)
    d.layout().addWidget(le)
    items = [
        'one', 'otwo', 'othree', 'ooone', 'ootwo', 'oothree', 'a1', 'a2',
        u'Edgas', u'Èdgar', u'Édgaq', u'Edgar', u'Édgar'
    ]
    le.update_items_cache(items)
    le.show_initial_value('')
    d.exec_()
 def setup_ui(self):
     self.l = l = QVBoxLayout(self)
     self._text = QPlainTextEdit(self)
     l.addWidget(self._text)
     l.addWidget(self.bb)
Exemple #47
0
    def __init__(self, parent, db):
        QDialog.__init__(self, parent)
        self.db = db

        self.setWindowTitle(_('Check library -- Problems found'))
        self.setWindowIcon(QIcon(I('debug.png')))

        self._tl = QHBoxLayout()
        self.setLayout(self._tl)
        self.splitter = QSplitter(self)
        self.left = QWidget(self)
        self.splitter.addWidget(self.left)
        self.helpw = QTextEdit(self)
        self.splitter.addWidget(self.helpw)
        self._tl.addWidget(self.splitter)
        self._layout = QVBoxLayout()
        self.left.setLayout(self._layout)
        self.helpw.setReadOnly(True)
        self.helpw.setText(
            _('''\
        <h1>Help</h1>

        <p>calibre stores the list of your books and their metadata in a
        database. The actual book files and covers are stored as normal
        files in the calibre library folder. The database contains a list of the files
        and covers belonging to each book entry. This tool checks that the
        actual files in the library folder on your computer match the
        information in the database.</p>

        <p>The result of each type of check is shown to the left. The various
        checks are:
        </p>
        <ul>
        <li><b>Invalid titles</b>: These are files and folders appearing
        in the library where books titles should, but that do not have the
        correct form to be a book title.</li>
        <li><b>Extra titles</b>: These are extra files in your calibre
        library that appear to be correctly-formed titles, but have no corresponding
        entries in the database</li>
        <li><b>Invalid authors</b>: These are files appearing
        in the library where only author folders should be.</li>
        <li><b>Extra authors</b>: These are folders in the
        calibre library that appear to be authors but that do not have entries
        in the database</li>
        <li><b>Missing book formats</b>: These are book formats that are in
        the database but have no corresponding format file in the book's folder.
        <li><b>Extra book formats</b>: These are book format files found in
        the book's folder but not in the database.
        <li><b>Unknown files in books</b>: These are extra files in the
        folder of each book that do not correspond to a known format or cover
        file.</li>
        <li><b>Missing cover files</b>: These represent books that are marked
        in the database as having covers but the actual cover files are
        missing.</li>
        <li><b>Cover files not in database</b>: These are books that have
        cover files but are marked as not having covers in the database.</li>
        <li><b>Folder raising exception</b>: These represent folders in the
        calibre library that could not be processed/understood by this
        tool.</li>
        </ul>

        <p>There are two kinds of automatic fixes possible: <i>Delete
        marked</i> and <i>Fix marked</i>.</p>
        <p><i>Delete marked</i> is used to remove extra files/folders/covers that
        have no entries in the database. Check the box next to the item you want
        to delete. Use with caution.</p>

        <p><i>Fix marked</i> is applicable only to covers and missing formats
        (the three lines marked 'fixable'). In the case of missing cover files,
        checking the fixable box and pushing this button will tell calibre that
        there is no cover for all of the books listed. Use this option if you
        are not going to restore the covers from a backup. In the case of extra
        cover files, checking the fixable box and pushing this button will tell
        calibre that the cover files it found are correct for all the books
        listed. Use this when you are not going to delete the file(s). In the
        case of missing formats, checking the fixable box and pushing this
        button will tell calibre that the formats are really gone. Use this if
        you are not going to restore the formats from a backup.</p>

        '''))

        self.log = QTreeWidget(self)
        self.log.itemChanged.connect(self.item_changed)
        self.log.itemExpanded.connect(self.item_expanded_or_collapsed)
        self.log.itemCollapsed.connect(self.item_expanded_or_collapsed)
        self._layout.addWidget(self.log)

        self.check_button = QPushButton(_('&Run the check again'))
        self.check_button.setDefault(False)
        self.check_button.clicked.connect(self.run_the_check)
        self.copy_button = QPushButton(_('Copy &to clipboard'))
        self.copy_button.setDefault(False)
        self.copy_button.clicked.connect(self.copy_to_clipboard)
        self.ok_button = QPushButton(_('&Done'))
        self.ok_button.setDefault(True)
        self.ok_button.clicked.connect(self.accept)
        self.mark_delete_button = QPushButton(_('Mark &all for delete'))
        self.mark_delete_button.setToolTip(_('Mark all deletable subitems'))
        self.mark_delete_button.setDefault(False)
        self.mark_delete_button.clicked.connect(self.mark_for_delete)
        self.delete_button = QPushButton(_('Delete &marked'))
        self.delete_button.setToolTip(
            _('Delete marked files (checked subitems)'))
        self.delete_button.setDefault(False)
        self.delete_button.clicked.connect(self.delete_marked)
        self.mark_fix_button = QPushButton(_('Mar&k all for fix'))
        self.mark_fix_button.setToolTip(_('Mark all fixable items'))
        self.mark_fix_button.setDefault(False)
        self.mark_fix_button.clicked.connect(self.mark_for_fix)
        self.fix_button = QPushButton(_('&Fix marked'))
        self.fix_button.setDefault(False)
        self.fix_button.setEnabled(False)
        self.fix_button.setToolTip(
            _('Fix marked sections (checked fixable items)'))
        self.fix_button.clicked.connect(self.fix_items)
        self.bbox = QGridLayout()
        self.bbox.addWidget(self.check_button, 0, 0)
        self.bbox.addWidget(self.copy_button, 0, 1)
        self.bbox.addWidget(self.ok_button, 0, 2)
        self.bbox.addWidget(self.mark_delete_button, 1, 0)
        self.bbox.addWidget(self.delete_button, 1, 1)
        self.bbox.addWidget(self.mark_fix_button, 2, 0)
        self.bbox.addWidget(self.fix_button, 2, 1)

        h = QHBoxLayout()
        ln = QLabel(_('Names to ignore:'))
        h.addWidget(ln)
        self.name_ignores = QLineEdit()
        self.name_ignores.setText(
            db.prefs.get('check_library_ignore_names', ''))
        self.name_ignores.setToolTip(
            _('Enter comma-separated standard file name wildcards, such as synctoy*.dat'
              ))
        ln.setBuddy(self.name_ignores)
        h.addWidget(self.name_ignores)
        le = QLabel(_('Extensions to ignore:'))
        h.addWidget(le)
        self.ext_ignores = QLineEdit()
        self.ext_ignores.setText(
            db.prefs.get('check_library_ignore_extensions', ''))
        self.ext_ignores.setToolTip(
            _('Enter comma-separated extensions without a leading dot. Used only in book folders'
              ))
        le.setBuddy(self.ext_ignores)
        h.addWidget(self.ext_ignores)
        self._layout.addLayout(h)

        self._layout.addLayout(self.bbox)
        self.resize(950, 500)
Exemple #48
0
class CheckLibraryDialog(QDialog):

    is_deletable = 1
    is_fixable = 2

    def __init__(self, parent, db):
        QDialog.__init__(self, parent)
        self.db = db

        self.setWindowTitle(_('Check library -- Problems found'))
        self.setWindowIcon(QIcon(I('debug.png')))

        self._tl = QHBoxLayout()
        self.setLayout(self._tl)
        self.splitter = QSplitter(self)
        self.left = QWidget(self)
        self.splitter.addWidget(self.left)
        self.helpw = QTextEdit(self)
        self.splitter.addWidget(self.helpw)
        self._tl.addWidget(self.splitter)
        self._layout = QVBoxLayout()
        self.left.setLayout(self._layout)
        self.helpw.setReadOnly(True)
        self.helpw.setText(
            _('''\
        <h1>Help</h1>

        <p>calibre stores the list of your books and their metadata in a
        database. The actual book files and covers are stored as normal
        files in the calibre library folder. The database contains a list of the files
        and covers belonging to each book entry. This tool checks that the
        actual files in the library folder on your computer match the
        information in the database.</p>

        <p>The result of each type of check is shown to the left. The various
        checks are:
        </p>
        <ul>
        <li><b>Invalid titles</b>: These are files and folders appearing
        in the library where books titles should, but that do not have the
        correct form to be a book title.</li>
        <li><b>Extra titles</b>: These are extra files in your calibre
        library that appear to be correctly-formed titles, but have no corresponding
        entries in the database</li>
        <li><b>Invalid authors</b>: These are files appearing
        in the library where only author folders should be.</li>
        <li><b>Extra authors</b>: These are folders in the
        calibre library that appear to be authors but that do not have entries
        in the database</li>
        <li><b>Missing book formats</b>: These are book formats that are in
        the database but have no corresponding format file in the book's folder.
        <li><b>Extra book formats</b>: These are book format files found in
        the book's folder but not in the database.
        <li><b>Unknown files in books</b>: These are extra files in the
        folder of each book that do not correspond to a known format or cover
        file.</li>
        <li><b>Missing cover files</b>: These represent books that are marked
        in the database as having covers but the actual cover files are
        missing.</li>
        <li><b>Cover files not in database</b>: These are books that have
        cover files but are marked as not having covers in the database.</li>
        <li><b>Folder raising exception</b>: These represent folders in the
        calibre library that could not be processed/understood by this
        tool.</li>
        </ul>

        <p>There are two kinds of automatic fixes possible: <i>Delete
        marked</i> and <i>Fix marked</i>.</p>
        <p><i>Delete marked</i> is used to remove extra files/folders/covers that
        have no entries in the database. Check the box next to the item you want
        to delete. Use with caution.</p>

        <p><i>Fix marked</i> is applicable only to covers and missing formats
        (the three lines marked 'fixable'). In the case of missing cover files,
        checking the fixable box and pushing this button will tell calibre that
        there is no cover for all of the books listed. Use this option if you
        are not going to restore the covers from a backup. In the case of extra
        cover files, checking the fixable box and pushing this button will tell
        calibre that the cover files it found are correct for all the books
        listed. Use this when you are not going to delete the file(s). In the
        case of missing formats, checking the fixable box and pushing this
        button will tell calibre that the formats are really gone. Use this if
        you are not going to restore the formats from a backup.</p>

        '''))

        self.log = QTreeWidget(self)
        self.log.itemChanged.connect(self.item_changed)
        self.log.itemExpanded.connect(self.item_expanded_or_collapsed)
        self.log.itemCollapsed.connect(self.item_expanded_or_collapsed)
        self._layout.addWidget(self.log)

        self.check_button = QPushButton(_('&Run the check again'))
        self.check_button.setDefault(False)
        self.check_button.clicked.connect(self.run_the_check)
        self.copy_button = QPushButton(_('Copy &to clipboard'))
        self.copy_button.setDefault(False)
        self.copy_button.clicked.connect(self.copy_to_clipboard)
        self.ok_button = QPushButton(_('&Done'))
        self.ok_button.setDefault(True)
        self.ok_button.clicked.connect(self.accept)
        self.mark_delete_button = QPushButton(_('Mark &all for delete'))
        self.mark_delete_button.setToolTip(_('Mark all deletable subitems'))
        self.mark_delete_button.setDefault(False)
        self.mark_delete_button.clicked.connect(self.mark_for_delete)
        self.delete_button = QPushButton(_('Delete &marked'))
        self.delete_button.setToolTip(
            _('Delete marked files (checked subitems)'))
        self.delete_button.setDefault(False)
        self.delete_button.clicked.connect(self.delete_marked)
        self.mark_fix_button = QPushButton(_('Mar&k all for fix'))
        self.mark_fix_button.setToolTip(_('Mark all fixable items'))
        self.mark_fix_button.setDefault(False)
        self.mark_fix_button.clicked.connect(self.mark_for_fix)
        self.fix_button = QPushButton(_('&Fix marked'))
        self.fix_button.setDefault(False)
        self.fix_button.setEnabled(False)
        self.fix_button.setToolTip(
            _('Fix marked sections (checked fixable items)'))
        self.fix_button.clicked.connect(self.fix_items)
        self.bbox = QGridLayout()
        self.bbox.addWidget(self.check_button, 0, 0)
        self.bbox.addWidget(self.copy_button, 0, 1)
        self.bbox.addWidget(self.ok_button, 0, 2)
        self.bbox.addWidget(self.mark_delete_button, 1, 0)
        self.bbox.addWidget(self.delete_button, 1, 1)
        self.bbox.addWidget(self.mark_fix_button, 2, 0)
        self.bbox.addWidget(self.fix_button, 2, 1)

        h = QHBoxLayout()
        ln = QLabel(_('Names to ignore:'))
        h.addWidget(ln)
        self.name_ignores = QLineEdit()
        self.name_ignores.setText(
            db.prefs.get('check_library_ignore_names', ''))
        self.name_ignores.setToolTip(
            _('Enter comma-separated standard file name wildcards, such as synctoy*.dat'
              ))
        ln.setBuddy(self.name_ignores)
        h.addWidget(self.name_ignores)
        le = QLabel(_('Extensions to ignore:'))
        h.addWidget(le)
        self.ext_ignores = QLineEdit()
        self.ext_ignores.setText(
            db.prefs.get('check_library_ignore_extensions', ''))
        self.ext_ignores.setToolTip(
            _('Enter comma-separated extensions without a leading dot. Used only in book folders'
              ))
        le.setBuddy(self.ext_ignores)
        h.addWidget(self.ext_ignores)
        self._layout.addLayout(h)

        self._layout.addLayout(self.bbox)
        self.resize(950, 500)

    def do_exec(self):
        self.run_the_check()

        probs = 0
        for c in self.problem_count:
            probs += self.problem_count[c]
        if probs == 0:
            return False
        self.exec_()
        return True

    def accept(self):
        self.db.new_api.set_pref('check_library_ignore_extensions',
                                 unicode_type(self.ext_ignores.text()))
        self.db.new_api.set_pref('check_library_ignore_names',
                                 unicode_type(self.name_ignores.text()))
        QDialog.accept(self)

    def box_to_list(self, txt):
        return [f.strip() for f in txt.split(',') if f.strip()]

    def run_the_check(self):
        checker = CheckLibrary(self.db.library_path, self.db)
        checker.scan_library(
            self.box_to_list(unicode_type(self.name_ignores.text())),
            self.box_to_list(unicode_type(self.ext_ignores.text())))

        plaintext = []

        def builder(tree, checker, check):
            attr, h, checkable, fixable = check
            list_ = getattr(checker, attr, None)
            if list_ is None:
                self.problem_count[attr] = 0
                return
            else:
                self.problem_count[attr] = len(list_)

            tl = Item()
            tl.setText(0, h)
            if fixable and list:
                tl.setData(1, Qt.UserRole, self.is_fixable)
                tl.setText(1, _('(fixable)'))
                tl.setFlags(Qt.ItemIsEnabled | Qt.ItemIsUserCheckable)
                tl.setCheckState(1, False)
            else:
                tl.setData(1, Qt.UserRole, self.is_deletable)
                tl.setData(2, Qt.UserRole, self.is_deletable)
                tl.setText(1, _('(deletable)'))
                tl.setFlags(Qt.ItemIsEnabled | Qt.ItemIsUserCheckable)
                tl.setCheckState(1, False)
            if attr == 'extra_covers':
                tl.setData(2, Qt.UserRole, self.is_deletable)
                tl.setText(2, _('(deletable)'))
                tl.setFlags(Qt.ItemIsEnabled | Qt.ItemIsUserCheckable)
                tl.setCheckState(2, False)
            self.top_level_items[attr] = tl

            for problem in list_:
                it = Item()
                if checkable:
                    it.setFlags(Qt.ItemIsEnabled | Qt.ItemIsUserCheckable)
                    it.setCheckState(2, False)
                    it.setData(2, Qt.UserRole, self.is_deletable)
                else:
                    it.setFlags(Qt.ItemIsEnabled)
                it.setText(0, problem[0])
                it.setData(0, Qt.UserRole, problem[2])
                it.setText(2, problem[1])
                tl.addChild(it)
                self.all_items.append(it)
                plaintext.append(','.join([h, problem[0], problem[1]]))
            tree.addTopLevelItem(tl)

        t = self.log
        t.clear()
        t.setColumnCount(3)
        t.setHeaderLabels([_('Name'), '', _('Path from library')])
        self.all_items = []
        self.top_level_items = {}
        self.problem_count = {}
        for check in CHECKS:
            builder(t, checker, check)

        t.resizeColumnToContents(0)
        t.resizeColumnToContents(1)
        self.delete_button.setEnabled(False)
        self.fix_button.setEnabled(False)
        self.text_results = '\n'.join(plaintext)

    def item_expanded_or_collapsed(self, item):
        self.log.resizeColumnToContents(0)
        self.log.resizeColumnToContents(1)

    def item_changed(self, item, column):
        def set_delete_boxes(node, col, to_what):
            self.log.blockSignals(True)
            if col:
                node.setCheckState(col, to_what)
            for i in range(0, node.childCount()):
                node.child(i).setCheckState(2, to_what)
            self.log.blockSignals(False)

        def is_child_delete_checked(node):
            checked = False
            all_checked = True
            for i in range(0, node.childCount()):
                c = node.child(i).checkState(2)
                checked = checked or c == Qt.Checked
                all_checked = all_checked and c == Qt.Checked
            return (checked, all_checked)

        def any_child_delete_checked():
            for parent in self.top_level_items.values():
                (c, _) = is_child_delete_checked(parent)
                if c:
                    return True
            return False

        def any_fix_checked():
            for parent in self.top_level_items.values():
                if (parent.data(1, Qt.UserRole) == self.is_fixable
                        and parent.checkState(1) == Qt.Checked):
                    return True
            return False

        if item in self.top_level_items.values():
            if item.childCount() > 0:
                if item.data(1,
                             Qt.UserRole) == self.is_fixable and column == 1:
                    if item.data(2, Qt.UserRole) == self.is_deletable:
                        set_delete_boxes(item, 2, False)
                else:
                    set_delete_boxes(item, column, item.checkState(column))
                    if column == 2:
                        self.log.blockSignals(True)
                        item.setCheckState(1, False)
                        self.log.blockSignals(False)
            else:
                item.setCheckState(column, Qt.Unchecked)
        else:
            for parent in self.top_level_items.values():
                if parent.data(2, Qt.UserRole) == self.is_deletable:
                    (child_chkd, all_chkd) = is_child_delete_checked(parent)
                    if all_chkd and child_chkd:
                        check_state = Qt.Checked
                    elif child_chkd:
                        check_state = Qt.PartiallyChecked
                    else:
                        check_state = Qt.Unchecked
                    self.log.blockSignals(True)
                    if parent.data(1, Qt.UserRole) == self.is_fixable:
                        parent.setCheckState(2, check_state)
                    else:
                        parent.setCheckState(1, check_state)
                    if child_chkd and parent.data(
                            1, Qt.UserRole) == self.is_fixable:
                        parent.setCheckState(1, Qt.Unchecked)
                    self.log.blockSignals(False)
        self.delete_button.setEnabled(any_child_delete_checked())
        self.fix_button.setEnabled(any_fix_checked())

    def mark_for_fix(self):
        for it in self.top_level_items.values():
            if (it.flags() & Qt.ItemIsUserCheckable
                    and it.data(1, Qt.UserRole) == self.is_fixable
                    and it.childCount() > 0):
                it.setCheckState(1, Qt.Checked)

    def mark_for_delete(self):
        for it in self.all_items:
            if (it.flags() & Qt.ItemIsUserCheckable
                    and it.data(2, Qt.UserRole) == self.is_deletable):
                it.setCheckState(2, Qt.Checked)

    def delete_marked(self):
        if not confirm(
                '<p>' + _('The marked files and folders will be '
                          '<b>permanently deleted</b>. Are you sure?') +
                '</p>', 'check_library_editor_delete', self):
            return

        # Sort the paths in reverse length order so that we can be sure that
        # if an item is in another item, the sub-item will be deleted first.
        items = sorted(self.all_items,
                       key=lambda x: len(x.text(1)),
                       reverse=True)
        for it in items:
            if it.checkState(2) == Qt.Checked:
                try:
                    p = os.path.join(self.db.library_path,
                                     unicode_type(it.text(2)))
                    if os.path.isdir(p):
                        delete_tree(p)
                    else:
                        delete_file(p)
                except:
                    prints(
                        'failed to delete',
                        os.path.join(self.db.library_path,
                                     unicode_type(it.text(2))))
        self.run_the_check()

    def fix_missing_formats(self):
        tl = self.top_level_items['missing_formats']
        child_count = tl.childCount()
        for i in range(0, child_count):
            item = tl.child(i)
            id = int(item.data(0, Qt.UserRole))
            all = self.db.formats(id, index_is_id=True, verify_formats=False)
            all = {f.strip() for f in all.split(',')} if all else set()
            valid = self.db.formats(id, index_is_id=True, verify_formats=True)
            valid = {f.strip() for f in valid.split(',')} if valid else set()
            for fmt in all - valid:
                self.db.remove_format(id, fmt, index_is_id=True, db_only=True)

    def fix_missing_covers(self):
        tl = self.top_level_items['missing_covers']
        child_count = tl.childCount()
        for i in range(0, child_count):
            item = tl.child(i)
            id = int(item.data(0, Qt.UserRole))
            self.db.set_has_cover(id, False)

    def fix_extra_covers(self):
        tl = self.top_level_items['extra_covers']
        child_count = tl.childCount()
        for i in range(0, child_count):
            item = tl.child(i)
            id = int(item.data(0, Qt.UserRole))
            self.db.set_has_cover(id, True)

    def fix_items(self):
        for check in CHECKS:
            attr = check[0]
            fixable = check[3]
            tl = self.top_level_items[attr]
            if fixable and tl.checkState(1):
                func = getattr(self, 'fix_' + attr, None)
                if func is not None and callable(func):
                    func()
        self.run_the_check()

    def copy_to_clipboard(self):
        QApplication.clipboard().setText(self.text_results)
Exemple #49
0
class BrowserWindow(QMainWindow):
    class SavedWindow(object):
        def __init__(self, window=None):
            '''
            @param: window BrowserWindow
            '''
            self.windowState = QByteArray()
            self.windowGeometry = QByteArray()
            self.windowUiState = {}  # QString -> QVariant
            self.virtualDesktop = -1
            self.currentTab = -1
            self.tabs = []  # WebTab.SavedTab
            if window:
                self.init(window)

        def init(self, window):
            if window.isFullScreen():
                self.windowState = QByteArray()
            else:
                self.windowState = window.saveState()
            self.windowGeometry = window.saveGeometry()
            self.windowUiState = window._saveUiState()

            tabsCount = window.tabCount()
            for idx in range(tabsCount):
                # TabbedWebView
                webView = window.weView(idx)
                if not webView:
                    continue
                webTab = webView.webTab()
                if not webTab:
                    continue
                tab = WebTab.SavedTab(webTab)
                if not tab.isValid():
                    continue
                if webTab.isCurrentTab():
                    self.currentTab = len(self.tabs)
                self.tabs.append(tab)

        def isValid(self):
            for tab in self.tabs:
                if not tab.isValid():
                    return False
            return self.currentTab > -1

        def clear(self):
            self.windowState.clear()
            self.windowGeometry.clear()
            self.virtualDesktop = -1
            self.currentTab = -1
            self.tabs.clear()

    def __init__(self, type_, startUrl=QUrl()):
        super().__init__(None)
        self._startUrl = startUrl
        self._homepage = QUrl()
        self._windowType = type_
        self._startTab = None  # WebTab
        self._startPage = None  # WebPage
        self._mainLayout = None  # QVBoxLayout
        self._mainSplitter = None  # QSplitter
        self._tabWidget = None  # TabWidget
        self._sideBar = None  # QPointer<SideBar>
        self._sideBarManager = SideBarManager(self)
        self._statusBar = None

        self._navigationContainer = None  # NavigationContainer
        self._navigationToolbar = None  # NavigationBar
        self._bookmarksToolbar = None  # BookmarksToolbar

        self._progressBar = None  # ProgressBar
        self._ipLabel = None  # QLabel
        self._superMenu = None  # QMenu
        self._mainMenu = None  # MainMenu

        self._tabModel = None  # TabModel
        self._tabMruModel = None  # TabMruModel

        self._sideBarWidth = 0
        self._webViewWidth = 0

        # Shortcuts
        self._useTabNumberShortcuts = False
        self._useSpeedDialNumberShortcuts = False
        self._useSingleKeyShortcuts = False

        # Remember visibility of menubar and statusbar after entering Fullscreen
        self._menuBarVisible = False
        self._statusBarVisible = False
        self._htmlFullScreenView = None  # TabbedWebView
        self._hideNavigationTimer = None  # QTimer

        self._deleteOnCloseWidgets = []  # QList<QPointer<QWidget>>

        self.setAttribute(Qt.WA_DeleteOnClose)
        self.setAttribute(Qt.WA_DontCreateNativeAncestors)

        self.setObjectName('mainwindow')
        self.setWindowTitle(const.APPNAME)
        self.setProperty('private', gVar.app.isPrivate())

        self._setupUi()
        self._setupMenu()

        self._hideNavigationTimer = QTimer(self)
        self._hideNavigationTimer.setInterval(1000)
        self._hideNavigationTimer.setSingleShot(True)
        self._hideNavigationTimer.timeout.connect(self._hideNavigationSlot)

        gVar.app.settingsReloaded.connect(self._loadSettings)

        QTimer.singleShot(0, self._postLaunch)

        if gVar.app.isPrivate():
            gVar.appTools.setWmClass(
                '%s Browser (Private Window)' % const.APPNAME, self)
        else:
            gVar.appTools.setWmClass('%s Browser' % const.APPNAME, self)

    def __del__(self):
        gVar.app.plugins().emitMainWindowDeleted(self)
        for widget in self._deleteOnCloseWidgets:
            widget.deleteLater()

    def setStartTab(self, tab):
        '''
        @param: tab WebTab
        '''
        self._startTab = tab

    def setStartPage(self, page):
        '''
        @param: page WebPage
        '''
        self._startPage = page

    def restoreWindow(self, window):
        '''
        @param: window SavedWindow
        '''
        self.restoreState(window.windowState)
        self.restoreGeometry(window.windowGeometry)
        self._restoreUiState(window.windowUiState)
        if not gVar.app.isTestModeEnabled():
            self.show(
            )  # Window has to be visible before adding QWebEngineView's
        self._tabWidget.restoreState(window.tabs, window.currentTab)
        self._updateStartupFocus()

    def fullScreenNavigationVisible(self):
        return self._navigationContainer.isVisible()

    def showNavigationWithFullScreen(self):
        if self._htmlFullScreenView:
            return
        if self._hideNavigationTimer.isActive():
            self._hideNavigationTimer.stop()
        self._navigationContainer.show()

    def hideNavigationWithFullScreen(self):
        if self._tabWidget.isCurrentTabFresh():
            return
        if not self._hideNavigationTimer.isActive():
            self._hideNavigationTimer.start()

    def currentTabChanged(self):
        view = self.weView()
        self._navigationToolbar.setCurrentView(view)
        if not view:
            return

        title = view.webTab().title(True)  # allowEmpty
        if not title:
            self.setWindowTitle(const.APPNAME)
        else:
            self.setWindowTitle('%s - %s' % (title, const.APPNAME))
        self._ipLabel.setText(view.getIp())
        view.setFocus()

        self.updateLoadingActions()

        # Settings correct tab order (LocationBar -> WebSearchBar -> WebView)
        self.setTabOrder(self.locationBar(),
                         self._navigationToolbar.webSearchBar())
        self.setTabOrder(self._navigationToolbar.webSearchBar(), view)

    def updateLoadingActions(self):
        view = self.weView()
        if not view:
            return

        isLoading = view.isLoading()
        self._ipLabel.setVisible(not isLoading)
        self._progressBar.setVisible(isLoading)
        self.action('View/Stop').setEnabled(isLoading)
        self.action('View/Reload').setEnabled(not isLoading)

        if isLoading:
            self._progressBar.setValue(view.loadingProgress())
            self._navigationToolbar.showStopButton()
        else:
            self._navigationToolbar.showReloadButton()

    def addBookmark(self, url, title):
        BookmarksTools.addBookmarkDilaog(self, url, title)

    def addDeleteOnCloseWidget(self, widget):
        '''
        @param: widget QWidget
        '''
        if widget not in self._deleteOnCloseWidgets:
            self._deleteOnCloseWidgets.append(widget)

    def createToolbarsMenu(self, menu):
        self.removeActions(menu.actions())
        menu.clear()

        action = menu.addAction('&Menu Bar', self.toggleShowMenubar)
        action.setCheckable(True)
        action.setChecked(self.menuBar().isVisible())

        action = menu.addAction('&Navigation Toolbar',
                                self.toggleShowNavigationToolbar)
        action.setCheckable(True)
        action.setChecked(self._navigationToolbar.isVisible())

        action = menu.addAction('&Bookmarks Toolbar',
                                self.toggleShowBookmarksToolbar)
        action.setCheckable(True)
        action.setChecked(Settings().value(
            'Browser-View-Settings/showBookmarksToolbar', True))

        menu.addSeparator()

        action = menu.addAction('&Tabs on Top', self.toggleTabsOnTop)
        action.setCheckable(True)
        action.setChecked(gVar.appSettings.tabsOnTop)

        self.addActions(menu.actions())

    def createSidebarsMenu(self, menu):
        self._sideBarManager.createMenu(menu)

    def createEncodingMenu(self, menu):
        isoCodecs = []
        utfCodecs = []
        windowsCodecs = []
        isciiCodecs = []
        ibmCodecs = []
        otherCodecs = []
        allCodecs = []

        for mib in QTextCodec.availableMibs():
            codecName = QTextCodec.codecForMib(mib).name()
            codecName = codecName.data().decode('utf8')
            if codecName in allCodecs:
                continue
            allCodecs.append(codecName)
            if codecName.startswith('ISO'):
                isoCodecs.append(codecName)
            elif codecName.startswith('UTF'):
                utfCodecs.append(codecName)
            elif codecName.startswith('windows'):
                windowsCodecs.append(codecName)
            elif codecName.startswith('Iscii'):
                isciiCodecs.append(codecName)
            elif codecName.startswith('IBM'):
                ibmCodecs.append(codecName)
            else:
                otherCodecs.append(codecName)

        if not menu.isEmpty():
            menu.addSeperator()

        self._createEncodingSubMenu('ISO', isoCodecs, menu)
        self._createEncodingSubMenu('UTF', utfCodecs, menu)
        self._createEncodingSubMenu('Windows', windowsCodecs, menu)
        self._createEncodingSubMenu('Iscii', isciiCodecs, menu)
        self._createEncodingSubMenu('IBM', ibmCodecs, menu)
        self._createEncodingSubMenu('Other', otherCodecs, menu)

    def removeActions(self, actions):
        '''
        @param: actions QList<QAction*>
        '''
        for action in actions:
            self.removeAction(action)

    def addSideBar(self):
        '''
        @return SideBar*
        '''
        if self._sideBar:
            return self._sideBar
        self._sideBar = SideBar(self._sideBarManager, self)
        self._mainSplitter.insertWidget(0, self._sideBar)
        self._mainSplitter.setCollapsible(0, False)
        self._mainSplitter.setSizes([self._sideBarWidth, self._webViewWidth])
        return self._sideBar

    def setSideBarNone(self):
        '''
        @note: when sideBar is notified destroyed, we should clean python ref in
        window
        '''
        self._sideBar = None

    def saveSideBarSettings(self):
        if self._sideBar:
            # That +1 is important here, without it, the sidebar width would
            # decrease by 1 pixel every close
            self._sideBarWidth = self._mainSplitter.sizes()[0] + 1
            self._webViewWidth = self.width() - self._sideBarWidth
        Settings().setValue('Browser-View-Settings/SideBar',
                            self._sideBarManager.activeSideBar())

    def tabCount(self):
        return self._tabWidget.count()

    def weView(self, index=None):
        '''
        @return TabbedWebView
        '''

        if index is None:
            index = self._tabWidget.currentIndex()
        webTab = self._tabWidget.widget(index)
        if not webTab:
            return None
        return webTab.webView()

    def windowType(self):
        '''
        @return const.BrowserWindowType
        '''
        return self._windowType

    def locationBar(self):
        '''
        @return LocationBar
        '''
        return self._tabWidget.locationBars().currentWidget()

    def tabWidget(self):
        return self._tabWidget

    def bookmarksToolbar(self):
        '''
        @return BookmarksToolbar
        '''
        return self._bookmarksToolbar

    def statusBar(self):
        '''
        @return StatusBar
        '''
        return self._statusBar

    def navigationBar(self):
        '''
        @return NavigationBar
        '''
        return self._navigationToolbar

    def sideBarManager(self):
        '''
        @return SideBarManager
        '''
        return self._sideBarManager

    def ipLabel(self):
        '''
        @return QLabel
        '''
        return self._ipLabel

    def superMenu(self):
        '''
        @return QMenu
        '''
        return self._superMenu

    def homepageUrl(self):
        return self._homepage

    def action(self, name):
        '''
        @return QAction
        '''
        return self._mainMenu.action(name)

    def tabModel(self):
        '''
        @return TabModel
        '''
        return self._tabModel

    def tabMruModel(self):
        '''
        @return TabMruModel
        '''
        return self._tabMruModel

    # public Q_SIGNALS:
    startingCompleted = pyqtSignal()
    aboutToClose = pyqtSignal()

    # public Q_SLOTS:
    def addTab(self):
        self._tabWidget.addViewByUrl(QUrl(), const.NT_SelectedNewEmptyTab,
                                     True)
        self._tabWidget.setCurrentTabFresh(True)

        if self.isFullScreen():
            self.showNavigationWithFullScreen()

    def goHome(self):
        self.loadAddress(self._homepage)

    def goHomeInNewTab(self):
        self._tabWidget.addViewByUrl(self._homepage, const.NT_SelectedTab)

    def goBack(self):
        self.weView().back()

    def goForward(self):
        self.weView().forward()

    def reload(self):
        self.weView().reload()

    def reloadBypassCache(self):
        self.weView().reloadBypassCache()

    def setWindowTitle(self, title):
        if gVar.app.isPrivate():
            title = '%s (Private Browsing)' % title
        super().setWindowTitle(title)

    def showWebInspector(self):
        webView = self.weView()
        if webView and webView.webTab():
            webView.webTab().showWebInspector()

    def toggleWebInspector(self):
        webView = self.weView()
        if webView and webView.webTab():
            webView.webTab().toggleWebInspector()

    def showHistoryManager(self):
        gVar.app.browsingLibrary().showHistory(self)

    def toggleShowMenubar(self):
        self.setUpdatesEnabled(False)
        menuBar = self.menuBar()
        menuBar.setVisible(not menuBar.isVisible())
        self._navigationToolbar.setSuperMenuVisible(not menuBar.isVisible())
        self.setUpdatesEnabled(True)

        Settings().setValue('Browser-View-Settings/showMenuBar',
                            menuBar.isVisible())

        # Make sure we show Navigation Toolbar when Menu Bar is hidden
        if not self._navigationToolbar.isVisible() and not menuBar.isVisible():
            self.toggleShowNavigationToolbar()

    def toggleShowStatusBar(self):
        self.setUpdatesEnabled(False)
        self._statusBar.setVisible(not self._statusBar.isVisible())
        self.setUpdatesEnabled(True)
        Settings().setValue('Browser-View-Settings/showStatusBar',
                            self._statusBar.isVisible())

    def toggleShowBookmarksToolbar(self):
        self.setUpdatesEnabled(False)
        self._bookmarksToolbar.setVisible(
            not self._bookmarksToolbar.isVisible())
        self.setUpdatesEnabled(True)
        Settings().setValue('Browser-View-Settings/showBookmarksToolbar',
                            self._bookmarksToolbar.isVisible())
        Settings().setValue('Browser-View-Settings/instantBookmarksToolbar',
                            False)

    def toggleShowNavigationToolbar(self):
        self.setUpdatesEnabled(False)
        self._navigationToolbar.setVisible(
            not self._navigationToolbar.isVisible())
        self.setUpdatesEnabled(True)
        Settings().setValue('Browser-View-Settings/showNavigationToolbar',
                            self._navigationToolbar.isVisible())

        # Make sure we show Navigation Toolbar when Menu Bar is hidden
        if not self._navigationToolbar.isVisible() and not self.menuBar(
        ).isVisible():
            self.toggleShowMenubar()

    def toggleTabsOnTop(self, enable):
        gVar.appSettings.tabsOnTop = enable
        self._navigationContainer.toggleTabsOnTop(enable)

    def toggleFullScreen(self):
        if self._htmlFullScreenView:
            self.weView().triggerPageAction(QWebEnginePage.ExitFullScreen)
            return
        if self.isFullScreen():
            self.setWindowState(self.windowState() & ~Qt.WindowFullScreen)
        else:
            self.setWindowState(self.windowState() | Qt.WindowFullScreen)

    def requestHtmlFullScreen(self, view, enable):
        '''
        @param: view TabbedWebView
        @param: enable bool
        '''
        if enable:
            self.setWindowState(self.windowState() | Qt.WindowFullScreen)
        else:
            self.setWindowState(self.windowState() & ~Qt.WindowFullScreen)
        if self._sideBar:
            self._sideBar.setHidden(enable)
        self._htmlFullScreenView = enable and view or None

    def loadActionUrl(self, obj=None):
        if not obj:
            obj = self.sender()
        action = obj
        if isinstance(action, QAction):
            self.loadAddress(action.data().toUrl())

    def loadActionUrlInNewTab(self, obj=None):
        if not obj:
            obj = self.sender()
        action = obj
        if isinstance(action, QAction):
            self.loadAddress(action.data().toUrl(),
                             const.NT_SelectedTabAtTheEnd)

    def bookmarkPage(self):
        view = self.weView()
        BookmarksTools.addBookmarkDialog(self, view.url(), view.title())

    def bookmarkAllTabs(self):
        BookmarksTools.bookmarkAllTabsDialog(self, self._tabWidget)

    def loadAddress(self, url):
        webView = self.weView()
        if webView.webTab().isPinned():
            index = self._tabWidget.addViewByUrl(
                url, gVar.appSettings.newTabPosition)
            self.weView(index).setFocus()
        else:
            webView.setFocus()
            webView.loadByReq(LoadRequest(url))

    def showSource(self, view=None):
        if not view:
            view = self.weView()
        if not view:
            return
        view.showSource()

    # private Q_SLOTS:
    def _openLocation(self):
        if self.isFullScreen():
            self.showNavigationWithFullScreen()
        self.locationBar().setFocus()
        self.locationBar().selectAll()

    def _openFile(self):
        fileTypes = ("%s(*.html *.htm *.shtml *.shtm *.xhtml);;"
                     "%s(*.png *.jpg *.jpeg *.bmp *.gif *.svg *.tiff);;"
                     "%s(*.txt);;"
                     "%s(*.*)")
        fileTypes %= ("HTML files", "Image files", "Text files", "All files")
        filePath = gVar.appTools.getOpenFileName("MainWindow-openFile",
                                                 self, "Open file...",
                                                 QDir.homePath(), fileTypes)

        if filePath:
            self.loadAddress(QUrl.fromLocalFile(filePath))

    def _closeWindow(self):
        if const.OS_MAC:
            self.close()
            return
        if gVar.app.windowCount() > 1:
            self.close()

    def _closeTab(self):
        # Don't close pinned tabs with keyboard shortcuts (Ctrl+w, Ctrl+F4)
        webView = self.weView()
        if webView and not webView.webTab().isPinned():
            self._tabWidget.requestCloseTab()

    def _loadSettings(self):
        settings = Settings()
        # Url settings
        settings.beginGroup('Web-URL-Settings')
        self._homepage = settings.value('homepage', 'app:start', type=QUrl)
        settings.endGroup()
        # Browser Window settings
        settings.beginGroup('Browser-View-Settings')
        showStatusBar = settings.value('showStatusBar', False)
        showBookmarksToolbar = settings.value('showBookmarksToolbar', False)
        showNavigationToolbar = settings.value('showNavigationToolbar', True)
        showMenuBar = settings.value('showMenuBar', False)
        # Make sure both menubar and navigationbar are not hidden
        if not showNavigationToolbar:
            showMenuBar = True
            settings.setValue('showMenubar', True)
        settings.endGroup()

        settings.beginGroup('Shortcuts')
        self._useTabNumberShortcuts = settings.value('useTabNumberShortcuts',
                                                     True)
        self._useSpeedDialNumberShortcuts = settings.value(
            'useSpeedDialNumberShortcuts', True)
        self._useSingleKeyShortcuts = settings.value('useSingleKeyShortcuts',
                                                     False)
        settings.endGroup()

        settings.beginGroup('Web-Browser-Settings')
        quitAction = self._mainMenu.action('Standard/Quit')
        if settings.value('closeAppWithCtrlQ', True):
            quitAction.setShortcut(
                gVar.appTools.actionShortcut(QKeySequence.Quit,
                                             QKeySequence('Ctrl+Q')))
        else:
            quitAction.setShortcut(QKeySequence())
        settings.endGroup()

        self._statusBarVisible = showStatusBar
        self.statusBar().setVisible(not self.isFullScreen() and showStatusBar)
        self._bookmarksToolbar.setVisible(showBookmarksToolbar)
        self._navigationToolbar.setVisible(showNavigationToolbar)
        if not const.OS_MACOS:
            self._menuBarVisible = showMenuBar
            self.menuBar().setVisible(not self.isFullScreen() and showMenuBar)
        showSuperMenu = self.isFullScreen() or not showMenuBar
        # TODO: debug code
        showSuperMenu = True
        self._navigationToolbar.setSuperMenuVisible(showSuperMenu)

    def _postLaunch(self):  # noqa C901
        self._loadSettings()
        addTab = True
        startUrl = QUrl()

        from .MainApplication import MainApplication
        afterLaunch = gVar.app.afterLaunch()
        if afterLaunch == MainApplication.OpenBlankPage:
            startUrl = QUrl()
        elif afterLaunch == MainApplication.OpenSpeedDial:
            startUrl = QUrl('app:speeddial')
        elif afterLaunch in (MainApplication.OpenHomePage,
                             MainApplication.RestoreSession,
                             MainApplication.SelectSession):
            startUrl = QUrl(self._homepage)

        if not gVar.app.isTestModeEnabled():
            self.show()

        if self._windowType == const.BW_FirstAppWindow:
            if gVar.app.isStartingAfterCrash():
                addTab = False
                startUrl.clear()
                self._tabWidget.addViewByUrl(QUrl('app:restore'),
                                             const.NT_CleanSelectedTabAtTheEnd)
            elif afterLaunch in (MainApplication.SelectSession,
                                 MainApplication.RestoreSession):
                addTab = self._tabWidget.count() <= 0
        elif self._windowType in (const.BW_NewWindow, const.BW_MacFirstWindow):
            addTab = True
        elif self._windowType == const.BW_OtherRestoredWindow:
            addTab = False

        if not self._startUrl.isEmpty():
            startUrl = QUrl(self._startUrl)
            addTab = True
        if self._startTab:
            addTab = False
            self._tabWidget.addViewByTab(self._startTab, const.NT_SelectedTab)
        if self._startPage:
            addTab = False
            self._tabWidget.addViewByUrl(QUrl())
            self.weView().setPage(self._startPage)
        if addTab:
            self._tabWidget.addViewByUrl(startUrl,
                                         const.NT_CleanSelectedTabAtTheEnd)
            if not startUrl or startUrl == 'app:speeddial':
                self.locationBar().setFocus()
        # Someting went really wrong .. add one tab
        if self._tabWidget.count() <= 0:
            self._tabWidget.addViewByUrl(self._homepage,
                                         const.NT_SelectedTabAtTheEnd)

        gVar.app.plugins().emitMainWindowCreated(self)
        self.startingCompleted.emit()

        self.raise_()
        self.activateWindow()
        self._updateStartupFocus()

    def _webSearch(self):
        self._navigationToolbar.webSearchBar().setFocus()
        self._navigationToolbar.webSearchBar().selectAll()

    def _searchOnPage(self):
        webView = self.weView()
        if webView and webView.webTab():
            searchText = webView.page().selectedText()
            if '\n' not in searchText:
                webView.webTab().showSearchToolBar(searchText)
            else:
                webView.webTab().showSearchToolBar()

    def _changeEncoding(self):
        action = self.sender()
        if action:
            encoding = action.data()
            gVar.app.webSettings().setDefaultTextEncoding(encoding)
            Settings().setValue('Web-Browser-Settings/DefaultEncoding',
                                encoding)
            self.weView().reload()

    def _printPage(self):
        self.weView().printPage()

    def _saveSettings(self):
        if gVar.app.isPrivate():
            return
        settings = Settings()
        settings.beginGroup('Browser-View-Settings')
        settings.setValue('WindowGeometry', self.saveGeometry())

        state = self._saveUiState()
        for key, val in state.items():
            settings.setValue(key, val)

        settings.endGroup()

    def _hideNavigationSlot(self):
        view = self.weView()
        mouseInView = view and view.underMouse()
        if self.isFullScreen() and mouseInView:
            self._navigationContainer.hide()

    # private
    # override
    def event(self, event):
        '''
        @param: event QEvent
        '''
        if event.type() == QEvent.WindowStateChange:
            e = event
            assert (isinstance(e, QWindowStateChangeEvent))
            if not (e.oldState() & Qt.WindowFullScreen) and (
                    self.windowState() & Qt.WindowFullScreen):
                # Enter fullscreen
                self._statusBarVisible = self._statusBar.isVisible()
                if not const.OS_MACOS:
                    self._menuBarVisible = self.menuBar().isVisible()
                    self.menuBar().hide()
                self._statusBar.hide()

                self._navigationContainer.hide()
                self._navigationToolbar.enterFullScreen()

                # Show main menu button since menubar is hidden
                self._navigationToolbar.setSuperMenuVisible(True)
            elif (e.oldState() & Qt.WindowFullScreen
                  ) and not (self.windowState() & Qt.WindowFullScreen):
                # Leave fullscreen
                self._statusBar.setVisible(self._statusBarVisible)
                if not const.OS_MACOS:
                    self.menuBar().setVisible(self._menuBarVisible)

                self._navigationContainer.show()
                self._navigationToolbar.setSuperMenuVisible(
                    not self._menuBarVisible)
                self._navigationToolbar.leaveFullScreen()
                self._htmlFullScreenView = None

            if self._hideNavigationTimer:
                self._hideNavigationTimer.stop()

        return super().event(event)

    # override
    def resizeEvent(self, event):
        '''
        @param: event QResizeEvent
        '''
        self._bookmarksToolbar.setMaximumWidth(self.width())
        super().resizeEvent(event)

    # override
    def keyPressEvent(self, event):  # noqa C901
        '''
        @param: event QKeyEvent
        '''
        if gVar.app.plugins().processKeyPress(const.ON_BrowserWindow, self,
                                              event):
            return

        number = -1
        # TabbedWebView
        view = self.weView()
        evtKey = event.key()

        if evtKey == Qt.Key_Back:
            if view:
                view.back()
                event.accept()

        elif evtKey == Qt.Key_Forward:
            if view:
                view.forward()
                event.accept()

        elif evtKey == Qt.Key_Stop:
            if view:
                view.stop()
                event.accept()

        elif evtKey in (Qt.Key_Reload, Qt.Key_Refresh):
            if view:
                view.reload()
                event.accept()

        elif evtKey == Qt.Key_HomePage:
            self.goHome()
            event.accept()

        elif evtKey == Qt.Key_Favorites:
            gVar.app.browsingLibrary().showBookmarks(self)
            event.accept()

        elif evtKey == Qt.Key_Search:
            self.searchOnPage()
            event.accept()

        elif evtKey in (Qt.Key_F6, Qt.Key_OpenUrl):
            self.openLocation()
            event.accept()

        elif evtKey == Qt.Key_History:
            self.showHistoryManager()
            event.accept()

        elif evtKey == Qt.Key_AddFavorite:
            self.bookmarkPage()
            event.accept()

        elif evtKey == Qt.Key_News:
            self.action("Tools/RssReader").trigger()
            event.accept()

        elif evtKey == Qt.Key_Tools:
            self.action("Standard/Preferences").trigger()
            event.accept()

        elif evtKey == Qt.Key_Tab:
            if event.modifiers() == Qt.ControlModifier:
                self._tabWidget.event(event)

        elif evtKey == Qt.Key_Backtab:
            if event.modifiers() == Qt.ControlModifier + Qt.ShiftModifier:
                self._tabWidget.event(event)

        elif evtKey == Qt.Key_PageDown:
            if event.modifiers() == Qt.ControlModifier:
                self._tabWidget.nextTab()
                event.accept()

        elif evtKey == Qt.Key_PageUp:
            if event.modifiers() == Qt.ControlModifier:
                self._tabWidget.previousTab()
                event.accept()

        elif evtKey == Qt.Key_Equal:
            if view and event.modifiers() == Qt.ControlModifier:
                view.zoomIn()
                event.accept()

        elif evtKey == Qt.Key_I:
            if event.modifiers() == Qt.ControlModifier:
                self.action("Tools/SiteInfo").trigger()
                event.accept()

        elif evtKey == Qt.Key_U:
            if event.modifiers() == Qt.ControlModifier:
                self.action("View/PageSource").trigger()
                event.accept()

        elif evtKey == Qt.Key_F:
            if event.modifiers() == Qt.ControlModifier:
                self.action("Edit/Find").trigger()
                event.accept()

        elif evtKey == Qt.Key_Slash:
            if self._useSingleKeyShortcuts:
                self.action("Edit/Find").trigger()
                event.accept()

        elif evtKey == Qt.Key_1:
            number = 1
        elif evtKey == Qt.Key_2:
            number = 2
        elif evtKey == Qt.Key_3:
            number = 3
        elif evtKey == Qt.Key_4:
            number = 4
        elif evtKey == Qt.Key_5:
            number = 5
        elif evtKey == Qt.Key_6:
            number = 6
        elif evtKey == Qt.Key_7:
            number = 7
        elif evtKey == Qt.Key_8:
            number = 8
        elif evtKey == Qt.Key_9:
            number = 9

        if number != -1:
            modifiers = event.modifiers()
            if modifiers & Qt.AltModifier and self._useTabNumberShortcuts:
                if number == 9:
                    number = self._tabWidget.count()
                self._tabWidget.setCurrentIndex(number - 1)
                event.accept()
                return
            if modifiers & Qt.ControlModifier and self._useSpeedDialNumberShortcuts:
                # QUrl
                url = gVar.app.plugins().speedDial().urlForShortcut(number - 1)
                if url.isValid():
                    self.loadAddress(url)
                    event.accept()
                    return
            if modifiers == Qt.NoModifier and self._useSingleKeyShortcuts:
                if number == 1:
                    self._tabWidget.previousTab()
                if number == 2:
                    self._tabWidget.nextTab()

        super().keyPressEvent(event)

    # override
    def keyReleaseEvent(self, event):
        '''
        @param: event QKeyEvent
        '''
        if gVar.app.plugins().processKeyRelease(const.ON_BrowserWindow, self,
                                                event):
            return

        evtKey = event.key()
        if evtKey == Qt.Key_F:
            if event.modifiers() == Qt.ControlModifier:
                self.action('Edit/Find').trigger()
                event.accept()

        super().keyReleaseEvent(event)

    # override
    def closeEvent(self, event):
        '''
        @param: event QCloseEvent
        '''
        if gVar.app.isClosing():
            self._saveSettings()
            return
        settings = Settings()
        askOnClose = settings.value('Browser-Tabs-Settings/AskOnClosing', True)

        from .MainApplication import MainApplication
        if gVar.app.afterLaunch() in (MainApplication.SelectSession,
                                      MainApplication.RestoreSession
                                      ) and gVar.app.windowCount() == 1:
            askOnClose = False

        if askOnClose and self._tabWidget.normalTabsCount() > 1:
            dialog = CheckBoxDialog(QMessageBox.Yes | QMessageBox.No, self)
            dialog.setDefaultButton(QMessageBox.No)
            dialog.setText(
                "There are still %s open tabs and your session won't be stored.\n"
                % self._tabWidget.count() +
                "Are you sure you want to close this window?")
            dialog.setCheckBoxText("Don't ask again")
            dialog.setWindowTitle('There are still open tabs')
            dialog.setIcon(QMessageBox.Warning)
            if dialog.exec_() != QMessageBox.Yes:
                event.ignore()
                return
            if dialog.isChecked():
                settings.setValue('Browser-Tabs-Settings/AskOnClosing', False)

        self.aboutToClose.emit()

        self._saveSettings()
        gVar.app.closedWindowsManager().saveWindow(self)
        if gVar.app.windowCount() == 1:
            gVar.app.quitApplication()

        event.accept()

    # == private ==
    def _setupUi(self):
        settings = Settings()
        settings.beginGroup('Browser-View-Settings')
        windowGeometry = settings.value('WindowGeometry', b'')

        keys = [
            ('LocationBarWidth', int),
            ('WebSearchBarWidth', int),
            ('SideBarWidth', int),
            ('WebViewWidth', int),
            ('SideBar', str),
        ]

        uiState = {}
        for key, typ in keys:
            if settings.contains(key):
                uiState[key] = typ(settings.value(key))

        settings.endGroup()

        widget = QWidget(self)
        widget.setCursor(Qt.ArrowCursor)
        self.setCentralWidget(widget)

        self._mainLayout = QVBoxLayout(widget)
        self._mainLayout.setContentsMargins(0, 0, 0, 0)
        self._mainLayout.setSpacing(0)
        self._mainSplitter = QSplitter(self)
        self._mainSplitter.setObjectName('sidebar-splitter')
        self._tabWidget = TabWidget(self)
        self._superMenu = QMenu(self)
        self._navigationToolbar = NavigationBar(self)
        self._bookmarksToolbar = BookmarksToolbar(self)

        self._tabModel = TabModel(self, self)
        self._tabMruModel = TabMruModel(self, self)
        self._tabMruModel.setSourceModel(self._tabModel)

        self._navigationContainer = NavigationContainer(self)
        self._navigationContainer.addWidget(self._navigationToolbar)
        self._navigationContainer.addWidget(self._bookmarksToolbar)
        self._navigationContainer.setTabBar(self._tabWidget.tabBar())

        self._mainSplitter.addWidget(self._tabWidget)
        self._mainSplitter.setCollapsible(0, False)

        self._mainLayout.addWidget(self._navigationContainer)
        self._mainLayout.addWidget(self._mainSplitter)

        self._statusBar = StatusBar(self)
        self._statusBar.setObjectName('mainwindow-statusbar')
        self._statusBar.setCursor(Qt.ArrowCursor)
        self.setStatusBar(self._statusBar)
        self._progressBar = ProgressBar(self._statusBar)
        self._ipLabel = QLabel(self)
        self._ipLabel.setObjectName('statusbar-ip-label')
        self._ipLabel.setToolTip('IP Address of current page')

        self._statusBar.addPermanentWidget(self._progressBar)
        self._statusBar.addPermanentWidget(self.ipLabel())

        downloadsButton = DownloadsButton(self)
        self._statusBar.addButton(downloadsButton)
        self._navigationToolbar.addToolButton(downloadsButton)

        desktop = gVar.app.desktop()
        windowWidth = desktop.availableGeometry().width() / 1.3
        windowHeight = desktop.availableGeometry().height() / 1.3

        # Let the WM decides where to put new browser window
        if self._windowType not in (const.BW_FirstAppWindow, const.BW_MacFirstWindow) and \
                gVar.app.getWindow():
            if const.OS_WIN:
                # Windows WM places every new window in the middle of screen .. for some reason
                p = gVar.app.getWindow().geometry().topLeft()
                p.setX(p.x() + 30)
                p.setY(p.y() + 30)
                if not desktop.availableGeometry(
                        gVar.app.getWindow()).contains(p):
                    p.setX(
                        desktop.availableGeometry(gVar.app.getWindow()).x() +
                        30)
                    p.setY(
                        desktop.availableGeometry(gVar.app.getWindow()).y() +
                        30)
                self.setGeometry(QRect(p, gVar.app.getWindow().size()))
            else:
                self.resize(gVar.app.getWindow().size())
        elif not self.restoreGeometry(windowGeometry):
            if const.OS_WIN:
                self.setGeometry(
                    QRect(
                        desktop.availableGeometry(gVar.app.getWindow()).x() +
                        30,
                        desktop.availableGeometry(gVar.app.getWindow()).y() +
                        30, windowWidth, windowHeight))
            else:
                self.resize(windowWidth, windowHeight)

        self._restoreUiState(uiState)
        # Set some sane minimum width
        self.setMinimumWidth(300)

    def _setupMenu(self):
        if const.OS_MACOS:
            macMainMenu = None
            if not macMainMenu:
                macMainMenu = MainMenu(self, 0)
                macMainMenu.initMenuBar(QMenuBar(0))
                gVar.app.activeWindowChanged.connect(macMainMenu.setWindow)
            else:
                macMainMenu.setWindow(self)
        else:
            self.setMenuBar(MenuBar(self))
            self._mainMenu = MainMenu(self, self)
            self._mainMenu.initMenuBar(self.menuBar())

        self._mainMenu.initSuperMenu(self._superMenu)

        # Setup other shortcuts
        reloadBypassCacheAction = QShortcut(QKeySequence('Ctrl+F5'), self)
        reloadBypassCacheAction2 = QShortcut(QKeySequence('Ctrl+Shift+R'),
                                             self)
        reloadBypassCacheAction.activated.connect(self.reloadBypassCache)
        reloadBypassCacheAction2.activated.connect(self.reloadBypassCache)

        closeTabAction = QShortcut(QKeySequence('Ctrl+W'), self)
        closeTabAction2 = QShortcut(QKeySequence('Ctrl+F4'), self)

        closeTabAction.activated.connect(self._closeTab)
        closeTabAction2.activated.connect(self._closeTab)

        reloadAction = QShortcut(QKeySequence('Ctrl+R'), self)
        reloadAction.activated.connect(self.reload)

        openLocationAction = QShortcut(QKeySequence('Alt+D'), self)
        openLocationAction.activated.connect(self._openLocation)

        inspectorAction = QShortcut(QKeySequence('F12'), self)
        inspectorAction.activated.connect(self.toggleWebInspector)

        restoreClosedWindow = QShortcut(QKeySequence('Ctrl+Shift+N'), self)
        restoreClosedWindow.activated.connect(
            gVar.app.closedWindowsManager().restoreClosedWindow)

    def _updateStartupFocus(self):
        def _updateStartupFocusCb():
            # Scroll to current tab
            self.tabWidget().tabBar().ensureVisible()
            # Update focus
            page = self.weView().page()
            url = page.requestedUrl()
            if not self._startPage and not LocationBar.convertUrlToText(url):
                self.locationBar().setFocus()
            else:
                self.weView().setFocus()

        QTimer.singleShot(500, _updateStartupFocusCb)

    def _createEncodingAction(self, codecName, activeCodecName, menu):
        '''
        @param: codecName QString
        @param: activeCodecName QString
        @param: menu QMenu
        '''
        action = QAction(codecName, menu)
        action.setData(codecName)
        action.setCheckable(True)
        action.triggered.connect(self._changeEncoding)
        if activeCodecName.lower() == codecName.lower():
            action.setChecked(True)
        return action

    def _createEncodingSubMenu(self, name, codecNames, menu):
        '''
        @param: name QString
        @param: codecName QStringList
        @param: menu QMenu
        '''
        if not codecNames:
            return

        codecNames.sort()
        subMenu = QMenu(name, menu)
        activeCodecName = gVar.app.webSettings().defaultTextEncoding()

        group = QActionGroup(subMenu)

        for codecName in codecNames:
            act = self._createEncodingAction(codecName, activeCodecName,
                                             subMenu)
            group.addAction(act)
            subMenu.addAction(act)

        menu.addMenu(subMenu)

    def _saveUiState(self):
        '''
        @return: QHash<QStirng, QVariant>
        '''
        self.saveSideBarSettings()
        state = {}
        state['LocationBarWidth'] = self._navigationToolbar.splitter().sizes(
        )[0]
        state['WebSearchBarWidth'] = self._navigationToolbar.splitter().sizes(
        )[1]
        state['SideBarWidth'] = self._sideBarWidth
        state['WebViewWidth'] = self._webViewWidth
        state['SideBar'] = self._sideBarManager.activeSideBar()
        return state

    def _restoreUiState(self, state):
        '''
        @param: state QHash<QString, QVariant>
        '''
        locationBarWidth = state.get('LocationBarWidth', 480)
        webSearchBarWidth = state.get('WebSearchBarWidth', 140)
        self._navigationToolbar.setSplitterSizes(locationBarWidth,
                                                 webSearchBarWidth)

        self._sideBarWidth = state.get('SideBarWidth', 250)
        self._webViewWidth = state.get('WebViewWidth', 2000)
        if self._sideBar:
            self._mainSplitter.setSizes(
                [self._sideBarWidth, self._webViewWidth])
        activeSideBar = state.get('SideBar')
        if not activeSideBar and self._sideBar:
            self._sideBar.close()
        else:
            self._sideBarManager.showSideBar(activeSideBar, False)
Exemple #50
0
    def setupUi(self, x):
        self.l = l = QVBoxLayout(self)
        self.la1 = la = QLabel(
            _("Values for the tweaks are shown below. Edit them to change the behavior of calibre."
              " Your changes will only take effect <b>after a restart</b> of calibre."
              ))
        l.addWidget(la), la.setWordWrap(True)
        self.splitter = s = QSplitter(self)
        s.setChildrenCollapsible(False)
        l.addWidget(s, 10)

        self.lv = lv = QWidget(self)
        lv.l = l2 = QVBoxLayout(lv)
        l2.setContentsMargins(0, 0, 0, 0)
        self.tweaks_view = tv = TweaksView(self)
        l2.addWidget(tv)
        self.plugin_tweaks_button = b = QPushButton(self)
        b.setToolTip(
            _("Edit tweaks for any custom plugins you have installed"))
        b.setText(_("&Plugin tweaks"))
        l2.addWidget(b)
        s.addWidget(lv)

        self.lv1 = lv = QWidget(self)
        s.addWidget(lv)
        lv.g = g = QGridLayout(lv)
        g.setContentsMargins(0, 0, 0, 0)

        self.search = sb = SearchBox2(self)
        sb.sizePolicy().setHorizontalStretch(10)
        sb.setSizeAdjustPolicy(sb.AdjustToMinimumContentsLength)
        sb.setMinimumContentsLength(10)
        g.addWidget(self.search, 0, 0, 1, 1)
        self.next_button = b = QPushButton(self)
        b.setIcon(QIcon(I("arrow-down.png")))
        b.setText(_("&Next"))
        g.addWidget(self.next_button, 0, 1, 1, 1)
        self.previous_button = b = QPushButton(self)
        b.setIcon(QIcon(I("arrow-up.png")))
        b.setText(_("&Previous"))
        g.addWidget(self.previous_button, 0, 2, 1, 1)

        self.hb = hb = QGroupBox(self)
        hb.setTitle(_("Help"))
        hb.l = l2 = QVBoxLayout(hb)
        self.help = h = QPlainTextEdit(self)
        l2.addWidget(h)
        h.setLineWrapMode(QPlainTextEdit.NoWrap)
        h.setReadOnly(True)
        g.addWidget(hb, 1, 0, 1, 3)

        self.eb = eb = QGroupBox(self)
        g.addWidget(eb, 2, 0, 1, 3)
        eb.setTitle(_("Edit tweak"))
        eb.g = ebg = QGridLayout(eb)
        self.edit_tweak = et = QPlainTextEdit(self)
        et.setMinimumWidth(400)
        et.setLineWrapMode(QPlainTextEdit.NoWrap)
        ebg.addWidget(et, 0, 0, 1, 2)
        self.restore_default_button = b = QPushButton(self)
        b.setToolTip(_("Restore this tweak to its default value"))
        b.setText(_("&Reset this tweak"))
        ebg.addWidget(b, 1, 0, 1, 1)
        self.apply_button = ab = QPushButton(self)
        ab.setToolTip(_("Apply any changes you made to this tweak"))
        ab.setText(_("&Apply changes to this tweak"))
        ebg.addWidget(ab, 1, 1, 1, 1)
Exemple #51
0
class UserDefinedDevice(QDialog):
    def __init__(self, parent=None):
        QDialog.__init__(self, parent)
        self._layout = QVBoxLayout(self)
        self.setLayout(self._layout)
        self.log = QPlainTextEdit(self)
        self._layout.addWidget(self.log)
        self.log.setPlainText(_('Getting device information') + '...')
        self.copy = QPushButton(_('Copy to &clipboard'))
        self.copy.setDefault(True)
        self.setWindowTitle(_('User-defined device information'))
        self.setWindowIcon(QIcon(I('debug.png')))
        self.copy.clicked.connect(self.copy_to_clipboard)
        self.ok = QPushButton('&OK')
        self.ok.setAutoDefault(False)
        self.ok.clicked.connect(self.accept)
        self.bbox = QDialogButtonBox(self)
        self.bbox.addButton(self.copy, QDialogButtonBox.ActionRole)
        self.bbox.addButton(self.ok, QDialogButtonBox.AcceptRole)
        self._layout.addWidget(self.bbox)
        self.resize(750, 500)
        self.bbox.setEnabled(False)
        QTimer.singleShot(1000, self.device_info)

    def device_info(self):
        try:
            from calibre.devices import device_info
            r = step_dialog(
                self.parent(), _('Device Detection'),
                _('Ensure your device is disconnected, then press OK'))
            if r:
                self.close()
                return
            before = device_info()
            r = step_dialog(
                self.parent(), _('Device Detection'),
                _('Ensure your device is connected, then press OK'))
            if r:
                self.close()
                return
            after = device_info()
            new_devices = after['device_set'] - before['device_set']
            res = ''
            if len(new_devices) == 1:

                def fmtid(x):
                    if isinstance(x, (int, long)):
                        x = hex(x)
                    if not x.startswith('0x'):
                        x = '0x' + x
                    return x

                for d in new_devices:
                    res =  _('USB Vendor ID (in hex)') + ': ' + \
                            fmtid(after['device_details'][d][0]) + '\n'
                    res += _('USB Product ID (in hex)') + ': ' + \
                            fmtid(after['device_details'][d][1]) + '\n'
                    res += _('USB Revision ID (in hex)') + ': ' + \
                            fmtid(after['device_details'][d][2]) + '\n'
            trailer = _(
                'Copy these values to the clipboard, paste them into an '
                'editor, then enter them into the USER_DEVICE by '
                'customizing the device plugin in Preferences->Advanced->Plugins. '
                'Remember to also enter the folders where you want the books to '
                'be put. You must restart calibre for your changes '
                'to take effect.\n')
            self.log.setPlainText(res + '\n\n' + trailer)
        finally:
            self.bbox.setEnabled(True)

    def copy_to_clipboard(self):
        QApplication.clipboard().setText(self.log.toPlainText())
Exemple #52
0
    def __init__(self, parent):
        QWidget.__init__(self, parent)
        self.parent = parent
        self._layout = QVBoxLayout()
        self.setLayout(self._layout)
        self._layout.setContentsMargins(0, 0, 0, 0)

        # Set up the find box & button
        search_layout = QHBoxLayout()
        self._layout.addLayout(search_layout)
        self.item_search = HistoryLineEdit(parent)
        self.item_search.setMinimumContentsLength(5)
        self.item_search.setSizeAdjustPolicy(
            self.item_search.AdjustToMinimumContentsLengthWithIcon)
        try:
            self.item_search.lineEdit().setPlaceholderText(
                _('Find item in Tag browser'))
        except:
            pass  # Using Qt < 4.7
        self.item_search.setToolTip(
            _('Search for items. This is a "contains" search; items containing the\n'
              'text anywhere in the name will be found. You can limit the search\n'
              'to particular categories using syntax similar to search. For example,\n'
              'tags:foo will find foo in any tag, but not in authors etc. Entering\n'
              '*foo will filter all categories at once, showing only those items\n'
              'containing the text "foo"'))
        search_layout.addWidget(self.item_search)
        ac = QAction(parent)
        parent.addAction(ac)
        parent.keyboard.register_shortcut('tag browser find box',
                                          _('Find item'),
                                          default_keys=(),
                                          action=ac,
                                          group=_('Tag browser'))
        ac.triggered.connect(self.set_focus_to_find_box)

        self.search_button = QToolButton()
        self.search_button.setText(_('Find'))
        self.search_button.setToolTip(_('Find the first/next matching item'))
        search_layout.addWidget(self.search_button)
        ac = QAction(parent)
        parent.addAction(ac)
        parent.keyboard.register_shortcut('tag browser find button',
                                          _('Find button'),
                                          default_keys=(),
                                          action=ac,
                                          group=_('Tag browser'))
        ac.triggered.connect(self.search_button.click)

        self.expand_button = QToolButton()
        self.expand_button.setText('-')
        self.expand_button.setToolTip(_('Collapse all categories'))
        search_layout.addWidget(self.expand_button)
        search_layout.setStretch(0, 10)
        search_layout.setStretch(1, 1)
        search_layout.setStretch(2, 1)
        ac = QAction(parent)
        parent.addAction(ac)
        parent.keyboard.register_shortcut('tag browser collapse all',
                                          _('Collapse all'),
                                          default_keys=(),
                                          action=ac,
                                          group=_('Tag browser'))
        ac.triggered.connect(self.expand_button.clicked)

        self.current_find_position = None
        self.search_button.clicked.connect(self.find)
        self.item_search.initialize('tag_browser_search')
        self.item_search.lineEdit().returnPressed.connect(self.do_find)
        self.item_search.lineEdit().textEdited.connect(self.find_text_changed)
        self.item_search.activated[str].connect(self.do_find)
        self.item_search.completer().setCaseSensitivity(Qt.CaseSensitive)

        parent.tags_view = TagsView(parent)
        self.tags_view = parent.tags_view
        self.expand_button.clicked.connect(self.tags_view.collapseAll)
        self._layout.addWidget(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)

        parent.alter_tb = l = QPushButton(parent)
        l.setText(_('Alter Tag browser'))
        l.setIcon(QIcon(I('tags.png')))
        l.m = QMenu()
        l.setMenu(l.m)
        self._layout.addWidget(l)
        ac = QAction(parent)
        parent.addAction(ac)
        parent.keyboard.register_shortcut('tag browser alter',
                                          _('Alter 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)
Exemple #53
0
    def __init__(self, parent, prefs):
        QFrame.__init__(self, parent)
        self.prefs = prefs
        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'))
        connect_lambda(b.clicked, self, lambda self: 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'))
        connect_lambda(b.clicked, self, lambda self: 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'))
        connect_lambda(b.clicked, self, lambda self: 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)
Exemple #54
0
 def __init__(self, parent):
     QWidget.__init__(self, parent)
     l = QVBoxLayout(parent)
     l.addWidget(self)
     l.setContentsMargins(0, 0, 0, 0)
     l = QFormLayout(self)
     l.setContentsMargins(0, 0, 0, 0)
     l.setFieldGrowthPolicy(l.AllNonFixedFieldsGrow)
     self.choices = c = QComboBox()
     c.setMinimumContentsLength(30)
     for text, data in [
         (_('Search for the author on Goodreads'), 'search-goodreads'),
         (_('Search for the author on Amazon'), 'search-amzn'),
         (_('Search for the author in your calibre library'),
          'search-calibre'),
         (_('Search for the author on Wikipedia'), 'search-wikipedia'),
         (_('Search for the author on Google Books'), 'search-google'),
         (_('Search for the book on Goodreads'), 'search-goodreads-book'),
         (_('Search for the book on Amazon'), 'search-amzn-book'),
         (_('Search for the book on Google Books'), 'search-google-book'),
         (_('Use a custom search URL'), 'url'),
     ]:
         c.addItem(text, data)
     l.addRow(_('Clicking on &author names should:'), c)
     self.custom_url = u = QLineEdit(self)
     u.textChanged.connect(self.changed_signal)
     u.setPlaceholderText(_('Enter the URL'))
     c.currentIndexChanged.connect(self.current_changed)
     l.addRow(u)
     self.current_changed()
     c.currentIndexChanged.connect(self.changed_signal)
Exemple #55
0
    def setup_ui(self):
        self.vl = vl = QVBoxLayout(self)
        self.stack = l = QStackedLayout()
        self.pi = pi = ProgressIndicator(self, 256)
        vl.addLayout(l), vl.addWidget(self.bb)
        self.restore_defs_button = b = self.bb.addButton(
            _('Restore &default icons'), self.bb.ActionRole)
        b.clicked.connect(self.restore_defaults)
        b.setIcon(QIcon(I('view-refresh.png')))
        self.c = c = QWidget(self)
        self.c.v = v = QVBoxLayout(self.c)
        v.addStretch(), v.addWidget(pi, 0, Qt.AlignCenter)
        self.wait_msg = m = QLabel(self)
        v.addWidget(m, 0, Qt.AlignCenter), v.addStretch()
        f = m.font()
        f.setBold(True), f.setPointSize(28), m.setFont(f)
        self.start_spinner()

        l.addWidget(c)
        self.w = w = QWidget(self)
        l.addWidget(w)
        w.l = l = QGridLayout(w)

        def add_row(x, y=None):
            if isinstance(x, type('')):
                x = QLabel(x)
            row = l.rowCount()
            if y is None:
                if isinstance(x, QLabel):
                    x.setWordWrap(True)
                l.addWidget(x, row, 0, 1, 2)
            else:
                if isinstance(x, QLabel):
                    x.setBuddy(y)
                l.addWidget(x, row, 0), l.addWidget(y, row, 1)

        add_row(
            _('Choose an icon theme below. You will need to restart'
              ' calibre to see the new icons.'))
        add_row(
            _('Current icon theme:') + '\xa0<b>' +
            (self.current_theme or 'None'))
        self.sort_by = sb = QComboBox(self)
        add_row(_('&Sort by:'), sb)
        sb.addItems([
            _('Number of icons'),
            _('Popularity'),
            _('Name'),
        ])
        sb.setEditable(False), sb.setCurrentIndex(
            gprefs.get('choose_icon_theme_sort_by', 1))
        sb.currentIndexChanged[int].connect(self.re_sort)
        sb.currentIndexChanged[int].connect(
            lambda: gprefs.set('choose_icon_theme_sort_by', sb.currentIndex()))
        self.theme_list = tl = QListWidget(self)
        tl.setVerticalScrollMode(tl.ScrollPerPixel)
        self.delegate = Delegate(tl)
        tl.setItemDelegate(self.delegate)
        tl.itemDoubleClicked.connect(self.accept)
        add_row(tl)

        t = Thread(name='GetIconThemes', target=self.get_themes)
        t.daemon = True
        t.start()
Exemple #56
0
    def __initUI(self):

        # Onglet "Visualisation images"
        vbox = QVBoxLayout()

        # Ligne 1 : extraction trajec
        self.picked_color.setFrameStyle(QFrame.StyledPanel | QFrame.Plain);
        
        line1 = QHBoxLayout()
        line1.addStretch(1)
        line1.addWidget(self.btn_algo)
        line1.addWidget(self.btn_traj)
        line1.addWidget(self.target_color_label)
        line1.addWidget(self.picked_color)
        line1.addWidget(self.btn_clear)
        line1.addWidget(self.btn_exportCSV)
        line1.addStretch(1)

        # Ligne 2 : infos video + visu image
        line2 = QHBoxLayout()

        # boîte d'infos sur la vidéo
        infoVBox = QVBoxLayout()
        for _ in ImageDisplay.video_infos:
            label = QLabel(self)
            label.setFrameStyle(QFrame.StyledPanel | QFrame.Plain);
            infoVBox.addWidget(label)
            self.videoLabels.append(label)
        infoVBox.addStretch()

        widget = QLabel("Conversion pixels -> mm", self)
        self.dicoScale['Pixels-mm'] = widget
        infoVBox.addWidget(widget)

        grid = QGridLayout()
        infoVBox.addLayout(grid)

        widget = QLabel("pixels  ",self)
        self.dicoScale['pixels'] = widget
        grid.addWidget(widget,1,1)

        self.scale_pixel = QLineEdit(self)
        self.dicoScale['pixelsForMM'] = self.scale_pixel
        grid.addWidget(self.scale_pixel,1,2)

        widget = QLabel("millimètres ",self)
        self.dicoScale['millimeters'] = widget
        grid.addWidget(widget,2,1)

        self.scale_mm = QLineEdit(self)
        self.dicoScale['mmForPixels'] = self.scale_mm
        grid.addWidget(self.scale_mm,2,2)

        self.lbl_epsilon = QLabel("Epsilon ",self)
        grid.addWidget(self.lbl_epsilon,5,1)

        self.epsi_spin = QSpinBox(self)
        self.epsi_spin.setRange(1,50)
        self.epsi_spin.setSingleStep(1)
        self.epsi_spin.setValue(10)
        grid.addWidget(self.epsi_spin,5,2)
        
        infoVBox.addStretch()

        line2.addLayout(infoVBox)
        line2.addStretch(1)
        line2.addWidget(self.img_lbl) # le QLabel por afficher l'image
        line2.addStretch(1)

        # line 3 : navigation boutons
        self.image_index.setFrameStyle(QFrame.Panel | QFrame.Sunken)
        self.image_index.setText("       ")
        line3 = QHBoxLayout()
        line3.addStretch(1)
        line3.addWidget(self.btn_first)
        line3.addWidget(self.btn_prev)
        line3.addWidget(self.image_index)
        line3.addWidget(self.btn_next)
        line3.addWidget(self.btn_last)
        line3.addStretch(1)

        # line 4 : first , step, last image selection
        line4 = QHBoxLayout()
        line4.addStretch(1)
        line4.addWidget(self.images_firstRank)
        line4.addWidget(self.images_step)
        line4.addWidget(self.images_lastRank)
        line4.addStretch(1)

        vbox.addLayout(line1)
        vbox.addStretch(1)
        vbox.addLayout(line2)
        vbox.addStretch(1)
        vbox.addLayout(line3)
        vbox.addLayout(line4)

        self.setLayout(vbox)

        self.buttonsState()
        self.__buttonsConnect()
        self.__setVideoLabelVisible(False)
Exemple #57
0
class DownloadDialog(QDialog):  # {{{

    def __init__(self, url, fname, parent):
        QDialog.__init__(self, parent)
        self.setWindowTitle(_('Download %s')%fname)
        self.l = QVBoxLayout(self)
        self.purl = urlparse(url)
        self.msg = QLabel(_('Downloading <b>%(fname)s</b> from %(url)s')%dict(
            fname=fname, url=self.purl.netloc))
        self.msg.setWordWrap(True)
        self.l.addWidget(self.msg)
        self.pb = QProgressBar(self)
        self.pb.setMinimum(0)
        self.pb.setMaximum(0)
        self.l.addWidget(self.pb)
        self.bb = QDialogButtonBox(QDialogButtonBox.Cancel, Qt.Horizontal, self)
        self.l.addWidget(self.bb)
        self.bb.rejected.connect(self.reject)
        sz = self.sizeHint()
        self.resize(max(sz.width(), 400), sz.height())

        fpath = PersistentTemporaryFile(os.path.splitext(fname)[1])
        fpath.close()
        self.fpath = fpath.name

        self.worker = Worker(url, self.fpath, Queue())
        self.rejected = False

    def reject(self):
        self.rejected = True
        QDialog.reject(self)

    def start_download(self):
        self.worker.start()
        QTimer.singleShot(50, self.update)
        self.exec_()
        if self.worker.err is not None:
            error_dialog(self.parent(), _('Download failed'),
                _('Failed to download from %(url)r with error: %(err)s')%dict(
                    url=self.worker.url, err=self.worker.err),
                det_msg=self.worker.tb, show=True)

    def update(self):
        if self.rejected:
            return

        try:
            progress = self.worker.rq.get_nowait()
        except Empty:
            pass
        else:
            self.update_pb(progress)

        if not self.worker.is_alive():
            return self.accept()
        QTimer.singleShot(50, self.update)

    def update_pb(self, progress):
        transferred, block_size, total = progress
        if total == -1:
            self.pb.setMaximum(0)
            self.pb.setMinimum(0)
            self.pb.setValue(0)
        else:
            so_far = transferred * block_size
            self.pb.setMaximum(max(total, so_far))
            self.pb.setValue(so_far)

    @property
    def err(self):
        return self.worker.err
Exemple #58
0
class TagBrowserWidget(QWidget):  # {{{
    def __init__(self, parent):
        QWidget.__init__(self, parent)
        self.parent = parent
        self._layout = QVBoxLayout()
        self.setLayout(self._layout)
        self._layout.setContentsMargins(0, 0, 0, 0)

        # Set up the find box & button
        search_layout = QHBoxLayout()
        self._layout.addLayout(search_layout)
        self.item_search = HistoryLineEdit(parent)
        self.item_search.setMinimumContentsLength(5)
        self.item_search.setSizeAdjustPolicy(
            self.item_search.AdjustToMinimumContentsLengthWithIcon)
        try:
            self.item_search.lineEdit().setPlaceholderText(
                _('Find item in Tag browser'))
        except:
            pass  # Using Qt < 4.7
        self.item_search.setToolTip(
            _('Search for items. This is a "contains" search; items containing the\n'
              'text anywhere in the name will be found. You can limit the search\n'
              'to particular categories using syntax similar to search. For example,\n'
              'tags:foo will find foo in any tag, but not in authors etc. Entering\n'
              '*foo will filter all categories at once, showing only those items\n'
              'containing the text "foo"'))
        search_layout.addWidget(self.item_search)
        ac = QAction(parent)
        parent.addAction(ac)
        parent.keyboard.register_shortcut('tag browser find box',
                                          _('Find item'),
                                          default_keys=(),
                                          action=ac,
                                          group=_('Tag browser'))
        ac.triggered.connect(self.set_focus_to_find_box)

        self.search_button = QToolButton()
        self.search_button.setText(_('Find'))
        self.search_button.setToolTip(_('Find the first/next matching item'))
        search_layout.addWidget(self.search_button)
        ac = QAction(parent)
        parent.addAction(ac)
        parent.keyboard.register_shortcut('tag browser find button',
                                          _('Find button'),
                                          default_keys=(),
                                          action=ac,
                                          group=_('Tag browser'))
        ac.triggered.connect(self.search_button.click)

        self.expand_button = QToolButton()
        self.expand_button.setText('-')
        self.expand_button.setToolTip(_('Collapse all categories'))
        search_layout.addWidget(self.expand_button)
        search_layout.setStretch(0, 10)
        search_layout.setStretch(1, 1)
        search_layout.setStretch(2, 1)
        ac = QAction(parent)
        parent.addAction(ac)
        parent.keyboard.register_shortcut('tag browser collapse all',
                                          _('Collapse all'),
                                          default_keys=(),
                                          action=ac,
                                          group=_('Tag browser'))
        ac.triggered.connect(self.expand_button.clicked)

        self.current_find_position = None
        self.search_button.clicked.connect(self.find)
        self.item_search.initialize('tag_browser_search')
        self.item_search.lineEdit().returnPressed.connect(self.do_find)
        self.item_search.lineEdit().textEdited.connect(self.find_text_changed)
        self.item_search.activated[str].connect(self.do_find)
        self.item_search.completer().setCaseSensitivity(Qt.CaseSensitive)

        parent.tags_view = TagsView(parent)
        self.tags_view = parent.tags_view
        self.expand_button.clicked.connect(self.tags_view.collapseAll)
        self._layout.addWidget(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)

        parent.alter_tb = l = QPushButton(parent)
        l.setText(_('Alter Tag browser'))
        l.setIcon(QIcon(I('tags.png')))
        l.m = QMenu()
        l.setMenu(l.m)
        self._layout.addWidget(l)
        ac = QAction(parent)
        parent.addAction(ac)
        parent.keyboard.register_shortcut('tag browser alter',
                                          _('Alter 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)

        # self.leak_test_timer = QTimer(self)
        # self.leak_test_timer.timeout.connect(self.test_for_leak)
        # self.leak_test_timer.start(5000)

    def toggle_item(self):
        self.tags_view.toggle_current_index()

    def set_pane_is_visible(self, to_what):
        self.tags_view.set_pane_is_visible(to_what)

    def find_text_changed(self, str):
        self.current_find_position = None

    def set_focus_to_find_box(self):
        self.item_search.setFocus()
        self.item_search.lineEdit().selectAll()

    def do_find(self, str=None):
        self.current_find_position = None
        self.find()

    def find(self):
        model = self.tags_view.model()
        model.clear_boxed()
        txt = unicode(self.item_search.currentText()).strip()

        if txt.startswith('*'):
            model.set_categories_filter(txt[1:])
            self.tags_view.recount()
            self.current_find_position = None
            return
        if model.get_categories_filter():
            model.set_categories_filter(None)
            self.tags_view.recount()
            self.current_find_position = None

        if not txt:
            return

        self.item_search.lineEdit().blockSignals(True)
        self.search_button.setFocus(True)
        self.item_search.lineEdit().blockSignals(False)

        key = None
        colon = txt.rfind(':') if len(txt) > 2 else 0
        if colon > 0:
            key = self.parent.library_view.model().db.\
                        field_metadata.search_term_to_field_key(txt[:colon])
            txt = txt[colon + 1:]

        self.current_find_position = \
            model.find_item_node(key, txt, self.current_find_position)

        if self.current_find_position:
            self.tags_view.show_item_at_path(self.current_find_position,
                                             box=True)
        elif self.item_search.text():
            self.not_found_label.setVisible(True)
            if self.tags_view.verticalScrollBar().isVisible():
                sbw = self.tags_view.verticalScrollBar().width()
            else:
                sbw = 0
            width = self.width() - 8 - sbw
            height = self.not_found_label.heightForWidth(width) + 20
            self.not_found_label.resize(width, height)
            self.not_found_label.move(4, 10)
            self.not_found_label_timer.start(2000)

    def not_found_label_timer_event(self):
        self.not_found_label.setVisible(False)
Exemple #59
0
    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)
        tbb.clear_find.connect(self.reset_find)
        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)
Exemple #60
0
 def __init__(self, parent):
     QWidget.__init__(self, parent)
     l = QVBoxLayout()
     self.setLayout(l)
     l.addStretch(10)
     self.pi = ProgressIndicator(self, 128)
     l.addWidget(self.pi, alignment=Qt.AlignHCenter)
     self.dummy = QLabel('<h2>\xa0')
     l.addSpacing(10)
     l.addWidget(self.dummy, alignment=Qt.AlignHCenter)
     l.addStretch(10)
     self.text = _('Calculating differences, please wait...')