示例#1
1
    def __init__(self, gui, interface_action, books):
        '''
        :param gui: Parent gui
        :param interface_action: InterfaceActionObject (InterfacePluginAction class from action.py)
        :param books: list of Kobo book
        '''
        
        self.books = books
        self.gui = gui
        self.interface_action = interface_action
        self.books = books

        SizePersistedDialog.__init__(self, gui, PLUGIN_NAME + 'plugin:selections dialog')
        self.setWindowTitle(_(PLUGIN_NAME + ' v' + PLUGIN_VERSION))
        self.setMinimumWidth(300)
        self.setMinimumHeight(300)
        layout = QVBoxLayout(self)
        self.setLayout(layout)
        title_layout = ImageTitleLayout(self, 'images/obok.png', _('Obok DeDRM'))
        layout.addLayout(title_layout)

        help_label = QLabel(_('<a href="http://www.foo.com/">Help</a>'), self)
        help_label.setTextInteractionFlags(Qt.LinksAccessibleByMouse | Qt.LinksAccessibleByKeyboard)
        help_label.setAlignment(Qt.AlignRight)
        help_label.linkActivated.connect(self._help_link_activated)
        title_layout.addWidget(help_label)
        title_layout.setAlignment(Qt.AlignTop)

        layout.addSpacing(5)
        main_layout = QHBoxLayout()
        layout.addLayout(main_layout)
#        self.listy = QListWidget()
#        self.listy.setSelectionMode(QAbstractItemView.ExtendedSelection)
#        main_layout.addWidget(self.listy)
#        self.listy.addItems(books)
        self.books_table = BookListTableWidget(self)
        main_layout.addWidget(self.books_table)

        layout.addSpacing(10)
        button_box = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel)
        button_box.accepted.connect(self._ok_clicked)
        button_box.rejected.connect(self.reject)
        self.select_all_button = button_box.addButton(_("Select All"), QDialogButtonBox.ResetRole)
        self.select_all_button.setToolTip(_("Select all books to add them to the calibre library."))
        self.select_all_button.clicked.connect(self._select_all_clicked)
        self.select_drm_button = button_box.addButton(_("All with DRM"), QDialogButtonBox.ResetRole)
        self.select_drm_button.setToolTip(_("Select all books with DRM."))
        self.select_drm_button.clicked.connect(self._select_drm_clicked)
        self.select_free_button = button_box.addButton(_("All DRM free"), QDialogButtonBox.ResetRole)
        self.select_free_button.setToolTip(_("Select all books without DRM."))
        self.select_free_button.clicked.connect(self._select_free_clicked)
        layout.addWidget(button_box)

        # Cause our dialog size to be restored from prefs or created on first usage
        self.resize_dialog()
        self.books_table.populate_table(self.books)
    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)
示例#3
0
 def init_UI(self):
     """create both buttons, arrange them and connect them
     """
     if self.direction == Qt.Horizontal:
         layout = QHBoxLayout()
         spacer_width = self.stretch
         spacer_height = 1
     else:
         layout = QVBoxLayout()
         spacer_width = 1
         spacer_height = self.stretch
     self.setLayout(layout)
     
     self.confirm_btn = ConfirmResetButton("Confirm all changes", "confirm", self.widgets, self.log, self)
     self.confirm_btn.clicked.connect(self.on_data_changed)
     layout.addWidget(self.confirm_btn)
     
     if self.stretch:
         layout.addSpacerItem(QSpacerItem(spacer_width, spacer_height, QSizePolicy.Expanding, QSizePolicy.Expanding))
     
     self.reset_btn = ConfirmResetButton("Reset all changes", "reset", self.widgets, self.log, self)
     self.reset_btn.clicked.connect(self.on_data_changed)
     layout.addWidget(self.reset_btn)
     
     for widget in self.widgets:
         widget.model.dataChanged.connect(self.on_data_changed)
     self.confirm_btn.clicked.connect(self.reset_btn.normalize)
     self.reset_btn.clicked.connect(self.confirm_btn.normalize)
    def initialize(self, item):
        """
        Initialize Actions QWidget, with ack and downtime buttons

        """

        self.item = item

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

        self.acknowledge_btn.setIcon(QIcon(settings.get_image('acknowledge')))
        self.acknowledge_btn.setFixedSize(80, 20)
        self.acknowledge_btn.clicked.connect(self.add_acknowledge)
        self.acknowledge_btn.setToolTip(_('Acknowledge the current item'))
        layout.addWidget(self.acknowledge_btn)

        self.downtime_btn.setIcon(QIcon(settings.get_image('downtime')))
        self.downtime_btn.setFixedSize(80, 20)
        self.downtime_btn.clicked.connect(self.add_downtime)
        self.downtime_btn.setToolTip(_('Schedule a Downtime on current item'))
        layout.addWidget(self.downtime_btn)

        layout.setAlignment(Qt.AlignCenter)
示例#5
0
    def setup_ui(self):
        from calibre.gui2.preferences.look_feel import DisplayedFields, move_field_up, move_field_down
        self.l = QVBoxLayout(self)
        self.field_display_order = fdo = QListView(self)
        self.model = DisplayedFields(self.db, fdo, pref_name='popup_book_display_fields')
        self.model.initialize()
        fdo.setModel(self.model)
        fdo.setAlternatingRowColors(True)
        del self.db
        self.l.addWidget(QLabel('Select displayed metadata'))
        h = QHBoxLayout()
        h.addWidget(fdo)
        v = QVBoxLayout()
        self.mub = b = QToolButton(self)
        b.clicked.connect(partial(move_field_up, fdo, self.model))
        b.setIcon(QIcon(I('arrow-up.png')))
        b.setToolTip(_('Move the selected field up'))
        v.addWidget(b), v.addStretch(10)
        self.mud = b = QToolButton(self)
        b.setIcon(QIcon(I('arrow-down.png')))
        b.setToolTip(_('Move the selected field down'))
        b.clicked.connect(partial(move_field_down, fdo, self.model))
        v.addWidget(b)
        h.addLayout(v)

        self.l.addLayout(h)
        self.l.addWidget(QLabel('<p>' + _(
            'Note that <b>comments</b> will always be displayed at the end, regardless of the order you assign here')))

        b = self.bb.addButton(_('Restore &defaults'), self.bb.ActionRole)
        b.clicked.connect(self.restore_defaults)
        self.l.addWidget(self.bb)
        self.setMinimumHeight(500)
示例#6
0
class BarTitle(QWidget):  # {{{

    def __init__(self, parent=None):
        QWidget.__init__(self, parent)
        self._layout = QHBoxLayout()
        self.setLayout(self._layout)
        self._layout.addStretch(10)
        self.icon = QLabel('')
        self._layout.addWidget(self.icon)
        self.title = QLabel('')
        self.title.setStyleSheet('QLabel { font-weight: bold }')
        self.title.setAlignment(Qt.AlignLeft | Qt.AlignCenter)
        self._layout.addWidget(self.title)
        self._layout.addStretch(10)

    def show_plugin(self, plugin):
        self.pmap = QPixmap(plugin.icon).scaled(ICON_SIZE, ICON_SIZE,
                Qt.KeepAspectRatio, Qt.SmoothTransformation)
        self.icon.setPixmap(self.pmap)
        self.title.setText(plugin.gui_name)
        tt = plugin.description
        self.setStatusTip(tt)
        tt = textwrap.fill(tt)
        self.setToolTip(tt)
        self.setWhatsThis(tt)
    def setup_ui(self, parent):
        cm = self.col_metadata
        self.make_widgets(parent, DateTimeEdit)
        self.widgets.append(QLabel(""))
        w = QWidget(parent)
        self.widgets.append(w)
        l = QHBoxLayout()
        l.setContentsMargins(0, 0, 0, 0)
        w.setLayout(l)
        l.addStretch(1)
        self.today_button = QPushButton(_("Set '%s' to today") % cm["name"], parent)
        l.addWidget(self.today_button)
        self.clear_button = QPushButton(_("Clear '%s'") % cm["name"], parent)
        l.addWidget(self.clear_button)
        l.addStretch(2)

        w = self.main_widget
        format = cm["display"].get("date_format", "")
        if not format:
            format = "dd MMM yyyy"
        w.setDisplayFormat(format)
        w.setCalendarPopup(True)
        w.setMinimumDateTime(UNDEFINED_QDATETIME)
        w.setSpecialValueText(_("Undefined"))
        self.today_button.clicked.connect(w.set_to_today)
        self.clear_button.clicked.connect(w.set_to_clear)
示例#8
0
    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)

        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())
示例#9
0
    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)

        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())
示例#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())
    def get_search_widget(self):
        """
        Create and return the search QWidget

        :return: search QWidget
        :rtype: QWidget
        """

        widget = QWidget()
        layout = QHBoxLayout()
        layout.setSpacing(0)
        widget.setLayout(layout)

        # Search label
        search_lbl = QLabel(_('Search Host'))
        search_lbl.setObjectName('bordertitle')
        search_lbl.setFixedHeight(25)
        search_lbl.setToolTip(_('Search Host'))
        layout.addWidget(search_lbl)

        # QLineEdit
        self.line_search.setFixedHeight(search_lbl.height())
        layout.addWidget(self.line_search)
        self.create_line_search([])

        return widget
示例#12
0
class CursorPositionWidget(QWidget):  # {{{

    def __init__(self, parent):
        QWidget.__init__(self, parent)
        self.l = QHBoxLayout(self)
        self.setLayout(self.l)
        self.la = QLabel('')
        self.l.addWidget(self.la)
        self.l.setContentsMargins(0, 0, 0, 0)
        f = self.la.font()
        f.setBold(False)
        self.la.setFont(f)

    def update_position(self, line=None, col=None, character=None):
        if line is None:
            self.la.setText('')
        else:
            try:
                name = character_name(character) if character and tprefs['editor_show_char_under_cursor'] else None
            except Exception:
                name = None
            text = _('Line: {0} : {1}').format(line, col)
            if not name:
                name = {'\t':'TAB'}.get(character, None)
            if name and tprefs['editor_show_char_under_cursor']:
                text = name + ' : ' + text
            self.la.setText(text)
示例#13
0
    def make_widgets(self, parent, main_widget_class, extra_label_text=''):
        w = QWidget(parent)
        self.widgets = [QLabel('&'+self.col_metadata['name']+':', w), w]
        l = QHBoxLayout()
        l.setContentsMargins(0, 0, 0, 0)
        w.setLayout(l)
        self.main_widget = main_widget_class(w)
        l.addWidget(self.main_widget)
        l.setStretchFactor(self.main_widget, 10)
        self.a_c_checkbox = QCheckBox(_('Apply changes'), w)
        l.addWidget(self.a_c_checkbox)
        self.ignore_change_signals = True

        # connect to the various changed signals so we can auto-update the
        # apply changes checkbox
        if hasattr(self.main_widget, 'editTextChanged'):
            # editable combobox widgets
            self.main_widget.editTextChanged.connect(self.a_c_checkbox_changed)
        if hasattr(self.main_widget, 'textChanged'):
            # lineEdit widgets
            self.main_widget.textChanged.connect(self.a_c_checkbox_changed)
        if hasattr(self.main_widget, 'currentIndexChanged'):
            # combobox widgets
            self.main_widget.currentIndexChanged[int].connect(self.a_c_checkbox_changed)
        if hasattr(self.main_widget, 'valueChanged'):
            # spinbox widgets
            self.main_widget.valueChanged.connect(self.a_c_checkbox_changed)
        if hasattr(self.main_widget, 'dateTimeChanged'):
            # dateEdit widgets
            self.main_widget.dateTimeChanged.connect(self.a_c_checkbox_changed)
示例#14
0
    def setup_ui(self, parent):
        cm = self.col_metadata
        self.make_widgets(parent, DateTimeEdit)
        self.widgets.append(QLabel(''))
        w = QWidget(parent)
        self.widgets.append(w)
        l = QHBoxLayout()
        l.setContentsMargins(0, 0, 0, 0)
        w.setLayout(l)
        l.addStretch(1)
        self.today_button = QPushButton(_('Set \'%s\' to today')%cm['name'], parent)
        l.addWidget(self.today_button)
        self.clear_button = QPushButton(_('Clear \'%s\'')%cm['name'], parent)
        l.addWidget(self.clear_button)
        l.addStretch(2)

        w = self.main_widget
        format = cm['display'].get('date_format','')
        if not format:
            format = 'dd MMM yyyy'
        w.setDisplayFormat(format)
        w.setCalendarPopup(True)
        w.setMinimumDateTime(UNDEFINED_QDATETIME)
        w.setSpecialValueText(_('Undefined'))
        self.today_button.clicked.connect(w.set_to_today)
        self.clear_button.clicked.connect(w.set_to_clear)
    def __init__(self):
        QWidget.__init__(self)
        self.l = QVBoxLayout()
        self.setLayout(self.l)

        self.cbox1 = QCheckBox("Reformatting")
        self.cbox1.setChecked(prefs["reformat"])
        self.l.addWidget(self.cbox1)

        self.cbox5 = QCheckBox("Paragraph by Ending mark")
        self.cbox5.setChecked(prefs["para_by_mark"])
        self.l.addWidget(self.cbox5)

        self.cbox2 = QCheckBox("Pretty Quote char")
        self.cbox2.setChecked(prefs["pretty_quote"])
        self.l.addWidget(self.cbox2)

        self.cbox3 = QCheckBox("Guess Chapter")
        self.cbox3.setChecked(prefs["guess_chapter"])
        self.l.addWidget(self.cbox3)

        self.cbox4 = QCheckBox("Allow Empty Paragraph")
        self.cbox4.setChecked(prefs["insert_empty_paragraph"])
        self.l.addWidget(self.cbox4)

        cl = QHBoxLayout()
        cl.addWidget(QLabel("Broken Word over lines"))
        self.combo1 = QComboBox()
        wbrk_list = ["None", "Pattern", "Naver"]
        self.combo1.addItems(wbrk_list)
        self.combo1.setCurrentIndex(wbrk_list.index(prefs["correct_word_break"]))
        cl.addWidget(self.combo1)
        self.l.addLayout(cl)
示例#16
0
 def create_color_button(key, text):
     b = ColorButton(data, key, text, self)
     b.changed.connect(self.changed), l.addWidget(b)
     bc = QToolButton(self)
     bc.setIcon(QIcon(I('clear_left.png')))
     bc.setToolTip(_('Remove color'))
     bc.clicked.connect(b.clear)
     h = QHBoxLayout()
     h.addWidget(b), h.addWidget(bc)
     return h
示例#17
0
 def setup_ui(self, parent):
     self.make_widgets(parent, EditWithComplete)
     values = self.all_values = list(self.db.all_custom(num=self.col_id))
     values.sort(key=sort_key)
     self.main_widget.setSizeAdjustPolicy(self.main_widget.AdjustToMinimumContentsLengthWithIcon)
     self.main_widget.setMinimumContentsLength(25)
     self.widgets.append(QLabel('', parent))
     w = QWidget(parent)
     layout = QHBoxLayout(w)
     layout.setContentsMargins(0, 0, 0, 0)
     self.remove_series = QCheckBox(parent)
     self.remove_series.setText(_('Clear series'))
     layout.addWidget(self.remove_series)
     self.idx_widget = QCheckBox(parent)
     self.idx_widget.setText(_('Automatically number books'))
     self.idx_widget.setToolTip('<p>' + _(
         'If not checked, the series number for the books will be set to 1. '
         'If checked, selected books will be automatically numbered, '
         'in the order you selected them. So if you selected '
         'Book A and then Book B, Book A will have series number 1 '
         'and Book B series number 2.') + '</p>')
     layout.addWidget(self.idx_widget)
     self.force_number = QCheckBox(parent)
     self.force_number.setText(_('Force numbers to start with '))
     self.force_number.setToolTip('<p>' + _(
         'Series will normally be renumbered from the highest '
         'number in the database for that series. Checking this '
         'box will tell calibre to start numbering from the value '
         'in the box') + '</p>')
     layout.addWidget(self.force_number)
     self.series_start_number = QDoubleSpinBox(parent)
     self.series_start_number.setMinimum(0.0)
     self.series_start_number.setMaximum(9999999.0)
     self.series_start_number.setProperty("value", 1.0)
     layout.addWidget(self.series_start_number)
     self.series_increment = QDoubleSpinBox(parent)
     self.series_increment.setMinimum(0.00)
     self.series_increment.setMaximum(99999.0)
     self.series_increment.setProperty("value", 1.0)
     self.series_increment.setToolTip('<p>' + _(
         'The amount by which to increment the series number '
         'for successive books. Only applicable when using '
         'force series numbers.') + '</p>')
     self.series_increment.setPrefix('+')
     layout.addWidget(self.series_increment)
     layout.addItem(QSpacerItem(20, 10, QSizePolicy.Expanding, QSizePolicy.Minimum))
     self.widgets.append(w)
     self.idx_widget.stateChanged.connect(self.a_c_checkbox_changed)
     self.force_number.stateChanged.connect(self.a_c_checkbox_changed)
     self.series_start_number.valueChanged.connect(self.a_c_checkbox_changed)
     self.series_increment.valueChanged.connect(self.a_c_checkbox_changed)
     self.remove_series.stateChanged.connect(self.a_c_checkbox_changed)
     self.main_widget
     self.ignore_change_signals = False
示例#18
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())
示例#19
0
    def __init__(self, gui, header, prefs, icon, books,
                 save_size_name='epubmerge:update list dialog'):
        SizePersistedDialog.__init__(self, gui, save_size_name)
        self.gui = gui

        self.setWindowTitle(header)
        self.setWindowIcon(icon)

        layout = QVBoxLayout(self)
        self.setLayout(layout)
        title_layout = ImageTitleLayout(self, 'images/icon.png',
                                        header)
        layout.addLayout(title_layout)
        books_layout = QHBoxLayout()
        layout.addLayout(books_layout)

        self.books_table = StoryListTableWidget(self)
        books_layout.addWidget(self.books_table)

        button_layout = QVBoxLayout()
        books_layout.addLayout(button_layout)
        spacerItem = QtGui.QSpacerItem(20, 40, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding)
        button_layout.addItem(spacerItem)
        self.move_up_button = QtGui.QToolButton(self)
        self.move_up_button.setToolTip(_('Move selected books up the list'))
        self.move_up_button.setIcon(QIcon(I('arrow-up.png')))
        self.move_up_button.clicked.connect(self.books_table.move_rows_up)
        button_layout.addWidget(self.move_up_button)
        self.remove_button = QtGui.QToolButton(self)
        self.remove_button.setToolTip(_('Remove selected books from the list'))
        self.remove_button.setIcon(get_icon('list_remove.png'))
        self.remove_button.clicked.connect(self.remove_from_list)
        button_layout.addWidget(self.remove_button)
        self.move_down_button = QtGui.QToolButton(self)
        self.move_down_button.setToolTip(_('Move selected books down the list'))
        self.move_down_button.setIcon(QIcon(I('arrow-down.png')))
        self.move_down_button.clicked.connect(self.books_table.move_rows_down)
        button_layout.addWidget(self.move_down_button)
        spacerItem1 = QtGui.QSpacerItem(20, 40, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding)
        button_layout.addItem(spacerItem1)

        options_layout = QHBoxLayout()

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

        layout.addLayout(options_layout)

        # Cause our dialog size to be restored from prefs or created on first usage
        self.resize_dialog()
        self.books_table.populate_table(books)
示例#20
0
class DaysOfWeek(Base):

    HELP = _('''\
                Download this periodical every week on the specified days after
                the specified time. For example, if you choose: Monday after
                9:00 AM, then the periodical will be download every Monday as
                soon after 9:00 AM as possible.
            ''')

    def __init__(self, parent=None):
        Base.__init__(self, parent)
        self.days = [
            QCheckBox(force_unicode(calendar.day_abbr[d]), self)
            for d in xrange(7)
        ]
        for i, cb in enumerate(self.days):
            row = i % 2
            col = i // 2
            self.l.addWidget(cb, row, col, 1, 1)

        self.time = QTimeEdit(self)
        self.time.setDisplayFormat('hh:mm AP')
        if canonicalize_lang(get_lang()) in {'deu', 'nds'}:
            self.time.setDisplayFormat('HH:mm')
        self.hl = QHBoxLayout()
        self.l1 = QLabel(_('&Download after:'))
        self.l1.setBuddy(self.time)
        self.hl.addWidget(self.l1)
        self.hl.addWidget(self.time)
        self.l.addLayout(self.hl, 1, 3, 1, 1)
        self.initialize()

    def initialize(self, typ=None, val=None):
        if typ is None:
            typ = 'day/time'
            val = (-1, 6, 0)
        if typ == 'day/time':
            val = convert_day_time_schedule(val)

        days_of_week, hour, minute = val
        for i, d in enumerate(self.days):
            d.setChecked(i in days_of_week)

        self.time.setTime(QTime(hour, minute))

    @property
    def schedule(self):
        days_of_week = tuple(
            [i for i, d in enumerate(self.days) if d.isChecked()])
        t = self.time.time()
        hour, minute = t.hour(), t.minute()
        return 'days_of_week', (days_of_week, int(hour), int(minute))
示例#21
0
    def __init__(self, parent, key_type_name, plugin_keys, create_key, keyfile_ext = u""):
        QDialog.__init__(self,parent)
        self.parent = parent
        self.key_type_name = key_type_name
        self.plugin_keys = plugin_keys
        self.create_key = create_key
        self.keyfile_ext = keyfile_ext
        self.json_file = (keyfile_ext == u"k4i")

        self.setWindowTitle("{0} {1}: Manage {2}s".format(PLUGIN_NAME, PLUGIN_VERSION, self.key_type_name))

        # Start Qt Gui dialog layout
        layout = QVBoxLayout(self)
        self.setLayout(layout)

        keys_group_box = QGroupBox(_(u"{0}s".format(self.key_type_name)), self)
        layout.addWidget(keys_group_box)
        keys_group_box_layout = QHBoxLayout()
        keys_group_box.setLayout(keys_group_box_layout)

        self.listy = QListWidget(self)
        self.listy.setToolTip(u"{0}s that will be used to decrypt ebooks".format(self.key_type_name))
        self.listy.setSelectionMode(QAbstractItemView.SingleSelection)
        self.populate_list()
        keys_group_box_layout.addWidget(self.listy)

        button_layout = QVBoxLayout()
        keys_group_box_layout.addLayout(button_layout)
        self._add_key_button = QtGui.QToolButton(self)
        self._add_key_button.setIcon(QIcon(I('plus.png')))
        self._add_key_button.setToolTip(u"Create new {0}".format(self.key_type_name))
        self._add_key_button.clicked.connect(self.add_key)
        button_layout.addWidget(self._add_key_button)

        self._delete_key_button = QtGui.QToolButton(self)
        self._delete_key_button.setToolTip(_(u"Delete highlighted key"))
        self._delete_key_button.setIcon(QIcon(I('list_remove.png')))
        self._delete_key_button.clicked.connect(self.delete_key)
        button_layout.addWidget(self._delete_key_button)

        spacerItem = QtGui.QSpacerItem(20, 40, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding)
        button_layout.addItem(spacerItem)

        layout.addSpacing(5)
        migrate_layout = QHBoxLayout()
        layout.addLayout(migrate_layout)
        migrate_layout.addStretch()
        self.button_box = QDialogButtonBox(QDialogButtonBox.Close)
        self.button_box.rejected.connect(self.close)
        migrate_layout.addWidget(self.button_box)

        self.resize(self.sizeHint())
示例#22
0
    def __init__(self, parent):
        QWidget.__init__(self, parent)
        layout = QHBoxLayout()
        layout.setSpacing(5)
        layout.setContentsMargins(0, 0, 0, 0)

        self.tags_box = EditWithComplete(parent)
        layout.addWidget(self.tags_box, stretch=1000)
        self.editor_button = QToolButton(self)
        self.editor_button.setToolTip(_('Open Item Editor'))
        self.editor_button.setIcon(QIcon(I('chapters.png')))
        layout.addWidget(self.editor_button)
        self.setLayout(layout)
示例#23
0
    def __init__(self, parent, values):
        QWidget.__init__(self, parent)
        layout = QHBoxLayout()
        layout.setSpacing(5)
        layout.setContentsMargins(0, 0, 0, 0)

        self.tags_box = EditWithComplete(parent)
        self.tags_box.update_items_cache(values)
        layout.addWidget(self.tags_box, stretch=3)
        self.checkbox = QCheckBox(_('Remove all tags'), parent)
        layout.addWidget(self.checkbox)
        layout.addStretch(1)
        self.setLayout(layout)
        self.checkbox.stateChanged[int].connect(self.box_touched)
    def initialize(self):
        """
        Initialize QWidget

        """

        layout = QHBoxLayout()
        self.setLayout(layout)

        self.services_title.setObjectName('itemtitle')
        layout.addWidget(self.services_title)
        layout.setAlignment(self.services_title, Qt.AlignLeft)

        icons_widget = QWidget()
        icons_layout = QHBoxLayout()
        icons_widget.setLayout(icons_layout)

        for icon in Service.get_available_icons():
            state = icon.replace('services_', '').upper()
            icon_pixmap = QIcon(settings.get_image(icon))
            self.states_btns[state].setIcon(icon_pixmap)
            self.states_btns[state].setFixedSize(20, 20)
            self.states_btns[state].setToolTip(state)
            self.states_btns[state].setCheckable(True)
            self.states_btns[state].setObjectName('services')
            icons_layout.addWidget(self.states_btns[state])
            self.nb_labels[state].setObjectName(get_icon_name_from_state('service', state))
            icons_layout.addWidget(self.nb_labels[state])

        layout.addWidget(icons_widget)
        layout.setAlignment(icons_widget, Qt.AlignRight)
示例#25
0
 def setup_ui(self, parent):
     self.make_widgets(parent, EditWithComplete)
     values = self.all_values = list(self.db.all_custom(num=self.col_id))
     values.sort(key=sort_key)
     self.main_widget.setSizeAdjustPolicy(self.main_widget.AdjustToMinimumContentsLengthWithIcon)
     self.main_widget.setMinimumContentsLength(25)
     self.widgets.append(QLabel('', parent))
     w = QWidget(parent)
     layout = QHBoxLayout(w)
     layout.setContentsMargins(0, 0, 0, 0)
     self.remove_series = QCheckBox(parent)
     self.remove_series.setText(_('Remove series'))
     layout.addWidget(self.remove_series)
     self.idx_widget = QCheckBox(parent)
     self.idx_widget.setText(_('Automatically number books'))
     layout.addWidget(self.idx_widget)
     self.force_number = QCheckBox(parent)
     self.force_number.setText(_('Force numbers to start with '))
     layout.addWidget(self.force_number)
     self.series_start_number = QSpinBox(parent)
     self.series_start_number.setMinimum(1)
     self.series_start_number.setMaximum(9999999)
     self.series_start_number.setProperty("value", 1)
     layout.addWidget(self.series_start_number)
     layout.addItem(QSpacerItem(20, 10, QSizePolicy.Expanding, QSizePolicy.Minimum))
     self.widgets.append(w)
     self.idx_widget.stateChanged.connect(self.check_changed_checkbox)
     self.force_number.stateChanged.connect(self.check_changed_checkbox)
     self.series_start_number.valueChanged.connect(self.check_changed_checkbox)
     self.remove_series.stateChanged.connect(self.check_changed_checkbox)
     self.ignore_change_signals = False
示例#26
0
 def create_row2(row, widget, button=None, front_button=None):
     row += 1
     ql = BuddyLabel(widget)
     if front_button:
         ltl = QHBoxLayout()
         ltl.addWidget(front_button)
         ltl.addWidget(ql)
         l.addLayout(ltl, row, 0, 1, 1)
     else:
         l.addWidget(ql, row, 0, 1, 1)
     l.addWidget(widget, row, 1, 1, 2 if button is None else 1)
     if button is not None:
         l.addWidget(button, row, 2, 1, 1)
     if button is not None:
         sto(widget, button)
示例#27
0
class ConfigWidget(QWidget):

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

        self.label = QLabel('Hello world &message:')
        self.l.addWidget(self.label)

        self.msg = QLineEdit(self)
        self.msg.setText(prefs['hello_world_msg'])
        self.l.addWidget(self.msg)
        self.label.setBuddy(self.msg)

    def save_settings(self):
        prefs['hello_world_msg'] = self.msg.text()
    def initialize(self):
        """
        Initialize QWidget

        """

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

        self.toggle_btn.setText(_('ON'))
        self.toggle_btn.setFixedSize(80, 20)
        self.toggle_btn.setCheckable(True)
        self.toggle_btn.setChecked(True)
        self.toggle_btn.setObjectName('True')
        self.toggle_btn.clicked.connect(self.update_btn_state)
        layout.addWidget(self.toggle_btn)
示例#29
0
class ConfigWidget(QWidget):

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

        self.label = QLabel('Enter the keyword')
        self.l.addWidget(self.label)

        self.msg = QLineEdit(self)
        self.msg.setText("")
        self.l.addWidget(self.msg)
        self.label.setBuddy(self.msg)

    def save_settings(self):
        prefs['hello_world_msg'] = unicode(self.msg.text())
示例#30
0
    def __init__(self, title = None, zoom = False, parent = None):
        super(CurveWidget, self).__init__(parent)
        self.setObjectName('CurveWidget')
        self.setFixedSize(300, 300)
        self.setStyleSheet('QWidget#CurveWidget{background-color:rgba(100,100,100,200);}')
        self._enableDBClick = False
        self._showNormal = True
        self._curves = []

        #
        self.initialize(zoom)

        # TODO
        horiLayoutMain = QHBoxLayout(self)

        tableWidget = QTableWidget(self);
        horiLayoutMain.addWidget(tableWidget)
示例#31
0
class TDockWidget(QDockWidget):

    def __init__(self, title="", parent=None, flags=Qt.WindowFlags(), bind_widget=None, close_slot=None, toggle_slot=None):
        QDockWidget.__init__(self, title, parent, flags)
        self.installEventFilter(self)
        self.main_win = parent
        # default stlyesheets for title bars
        self.title_stylesheet = "QWidget {background: rgb(68,68,68);}"
        self.button_style = "QPushButton:hover:!pressed {background: grey;}"
        from TigGUI.Images.ControlDialog import ImageControlDialog
        from TigGUI.Plot.SkyModelPlot import ToolDialog
        from TigGUI.Plot.SkyModelPlot import LiveImageZoom
        if bind_widget is not None:
            self.bind_widget = bind_widget
        if bind_widget is not None:
            if isinstance(bind_widget, ToolDialog):
                self.tdock_style = "ToolDialog {border: 1.5px solid rgb(68,68,68);}"
            elif isinstance(bind_widget, ImageControlDialog):
                self.tdock_style = "ImageControlDialog {border: 1.5px solid rgb(68,68,68);}"
        # set default sizes for QDockWidgets
        self.btn_w = 28
        self.btn_h = 28
        self.icon_size = QSize(20, 20)
        self.font_size = 8
        # setup custom title bar for profiles dockable
        self.dock_title_bar = QWidget()
        self.dock_title_bar.setContentsMargins(0, 0, 0, 0)
        self.dock_title_bar.setStyleSheet(self.title_stylesheet)
        self.dock_title_bar.setBaseSize(0, 0)
        self.dock_title_layout = QHBoxLayout()
        self.dock_title_layout.setContentsMargins(0, 0, 0, 0)
        self.dock_title_layout.setSpacing(0)
        self.dock_title_bar.setLayout(self.dock_title_layout)
        # custom close button
        self.close_button = QPushButton()
        self.close_button.setStyleSheet(self.button_style)
        self.close_button.setMaximumWidth(self.btn_w)
        self.close_button.setMaximumHeight(self.btn_h)
        self.close_button.setContentsMargins(0, 0, 0, 0)
        self.close_button.setBaseSize(0, 0)
        self.close_icon = self.dock_title_bar.style().standardIcon(QStyle.SP_TitleBarCloseButton)
        self.close_button.setIcon(self.close_icon)
        self.close_button.setToolTip("Close")
        # custom toggle button
        self.toggle_button = QPushButton()
        self.toggle_button.setStyleSheet(self.button_style)
        self.toggle_button.setMaximumWidth(self.btn_w)
        self.toggle_button.setMaximumHeight(self.btn_h)
        self.toggle_button.setContentsMargins(0, 0, 0, 0)
        self.toggle_button.setBaseSize(0, 0)
        self.toggle_icon = self.dock_title_bar.style().standardIcon(QStyle.SP_TitleBarShadeButton)
        self.toggle_button.setIcon(self.toggle_icon)
        self.toggle_button.setToolTip("Dock/float widget")
        # tigger logo
        self.image0 = pixmaps.tigger_logo.pm()
        self.title_icon = QLabel()
        self.title_icon.setContentsMargins(0, 0, 0, 0)
        self.title_icon.setBaseSize(0, 0)
        self.title_icon.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)
        self.title_icon.setScaledContents(True)
        self.title_icon.setPixmap(self.image0)
        self.title_icon.setAlignment(Qt.AlignCenter)
        self.title_icon.setMaximumSize(self.icon_size)
        # set dock widget title
        self.title_font = QFont()
        self.title_font.setBold(True)
        self.title_font.setPointSize(self.font_size)
        if bind_widget is not None:
            if isinstance(bind_widget, ImageControlDialog):
                self.dock_title = QLabel(f"{title}: Control Dialog")
            else:
                self.dock_title = QLabel(title)
        self.dock_title.setFont(self.title_font)
        self.dock_title.setAlignment(Qt.AlignCenter)
        self.dock_title.setContentsMargins(0, 0, 0, 0)
        self.dock_title.setBaseSize(0, 0)
        self.dock_title.setSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.Minimum)
        # add dock widget title items to layout
        self.dock_title_layout.addWidget(self.title_icon)
        self.dock_title_layout.addWidget(self.dock_title)
        self.dock_title_layout.addWidget(self.toggle_button)
        self.dock_title_layout.addWidget(self.close_button)
        # set up profiles as dockable
        self.setStyleSheet(self.tdock_style)
        self.setWidget(bind_widget)
        self.setFeatures(QDockWidget.AllDockWidgetFeatures)
        if bind_widget is not None:
            if isinstance(bind_widget, ToolDialog):
                self.setAllowedAreas(Qt.AllDockWidgetAreas)
            elif isinstance(bind_widget, ImageControlDialog):
                self.setAllowedAreas(Qt.RightDockWidgetArea | Qt.LeftDockWidgetArea)
        self.setTitleBarWidget(self.dock_title_bar)
        self.setFloating(False)
        # get current sizeHints()
        if bind_widget is not None:
            self.setBaseSize(bind_widget.sizeHint())
            if isinstance(bind_widget, LiveImageZoom):
                bind_widget.livezoom_resize_signal.connect(self._resizeDockWidget)
        if close_slot is not None:
            self.close_button.clicked.connect(close_slot)
        if toggle_slot is not None:
            self.toggle_button.clicked.connect(toggle_slot)

    def _resizeDockWidget(self, qsize):
        # live zoom signal slot to resize dockwidget and dock areas
        self.setMinimumSize(qsize)
        self.main_win.resizeDocks([self], [qsize.width()], Qt.Horizontal)
        self.main_win.resizeDocks([self], [qsize.height()], Qt.Vertical)

    # hack to stop QDockWidget responding to drag events for undocking - work around for Qt bug
    def eventFilter(self, source, event):
        # event seq 2, 5, 3 - mouse press, mouse move, mouse release
        if event.type() == QEvent.MouseButtonPress:
            label = self.childAt(event.pos())
            if not label:
                return super(TDockWidget, self).eventFilter(source, event)
            if isinstance(label, QLabel):
                if not self.isFloating():
                    fake_mouse_event = QMouseEvent(QEvent.MouseButtonRelease, event.pos(), event.button(), event.buttons(), event.modifiers())
                    super(TDockWidget, self).event(fake_mouse_event)
                    return True
        return super(TDockWidget, self).eventFilter(source, event)
示例#32
0
    def setup_ui(self):
        self.l = l = QGridLayout(self)
        self.setLayout(l)

        self.la1 = la = QLabel(_('&Existing images in the book'))
        la.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed)
        l.addWidget(la, 0, 0, 1, 2)
        if self.for_browsing:
            la.setVisible(False)

        self.view = v = QListView(self)
        v.setViewMode(v.IconMode)
        v.setFlow(v.LeftToRight)
        v.setSpacing(4)
        v.setResizeMode(v.Adjust)
        v.setUniformItemSizes(True)
        pi = plugins['progress_indicator'][0]
        if hasattr(pi, 'set_no_activate_on_click'):
            pi.set_no_activate_on_click(v)
        v.activated.connect(self.activated)
        v.doubleClicked.connect(self.activated)
        self.d = ImageDelegate(v)
        v.setItemDelegate(self.d)
        self.model = Images(self.view)
        self.fm = fm = QSortFilterProxyModel(self.view)
        self.fm.setDynamicSortFilter(self.for_browsing)
        fm.setSourceModel(self.model)
        fm.setFilterCaseSensitivity(False)
        v.setModel(fm)
        l.addWidget(v, 1, 0, 1, 2)
        v.pressed.connect(self.pressed)
        la.setBuddy(v)

        self.filter = f = QLineEdit(self)
        f.setPlaceholderText(_('Search for image by file name'))
        l.addWidget(f, 2, 0)
        self.cb = b = QToolButton(self)
        b.setIcon(QIcon(I('clear_left.png')))
        b.clicked.connect(f.clear)
        l.addWidget(b, 2, 1)
        f.textChanged.connect(self.filter_changed)

        if self.for_browsing:
            self.bb.clear()
            self.bb.addButton(self.bb.Close)
            b = self.refresh_button = self.bb.addButton(
                _('&Refresh'), self.bb.ActionRole)
            b.clicked.connect(self.refresh)
            b.setIcon(QIcon(I('view-refresh.png')))
            b.setToolTip(_('Refresh the displayed images'))
            self.setAttribute(Qt.WA_DeleteOnClose, False)
        else:
            b = self.import_button = self.bb.addButton(_('&Import image'),
                                                       self.bb.ActionRole)
            b.clicked.connect(self.import_image)
            b.setIcon(QIcon(I('view-image.png')))
            b.setToolTip(_('Import an image from elsewhere in your computer'))
            b = self.paste_button = self.bb.addButton(_('&Paste image'),
                                                      self.bb.ActionRole)
            b.clicked.connect(self.paste_image)
            b.setIcon(QIcon(I('edit-paste.png')))
            b.setToolTip(_('Paste an image from the clipboard'))
            self.fullpage = f = QCheckBox(_('Full page image'), self)
            f.setToolTip(
                _('Insert the image so that it takes up an entire page when viewed in a reader'
                  ))
            f.setChecked(tprefs['insert_full_screen_image'])
            self.preserve_aspect_ratio = a = QCheckBox(
                _('Preserve aspect ratio'))
            a.setToolTip(
                _('Preserve the aspect ratio of the inserted image when rendering it full paged'
                  ))
            a.setChecked(tprefs['preserve_aspect_ratio_when_inserting_image'])
            f.toggled.connect(
                lambda: (tprefs.set('insert_full_screen_image', f.isChecked()),
                         a.setVisible(f.isChecked())))
            a.toggled.connect(lambda: tprefs.set(
                'preserve_aspect_ratio_when_inserting_image', a.isChecked()))
            a.setVisible(f.isChecked())
            h = QHBoxLayout()
            l.addLayout(h, 3, 0, 1, -1)
            h.addWidget(f), h.addStretch(10), h.addWidget(a)
        l.addWidget(self.bb, 4, 0, 1, 2)
示例#33
0
class ComicalibreDialog(QDialog):
    """ The main dialog for users to enter options before starting. """
    def __init__(self, gui, icon, do_user_config):
        """ Initialize the gui dialog. """
        QDialog.__init__(self, gui)
        self.gui = gui
        self.icon = icon
        self.do_user_config = do_user_config
        self.db = gui.current_db
        self.create_gui()

    def start_process(self, process_type):
        """ Starts the processing worker and progress bar. """
        prefs["comic_vine_api_key"] = self.api_msg.text()
        prefs["tags_to_add"] = self.tags_msg.text()
        self.worker = ComicalibreWork(self.gui)
        self.result_text.setText("Processing...")
        self.title_start.setEnabled(False)
        self.series_start.setEnabled(False)
        self.ids_start.setEnabled(False)
        keep_tags = self.keep_tags_cb.isChecked()
        errors = self.worker.process(self.progress_bar, process_type,
                                     keep_tags)
        self.title_start.setEnabled(True)
        self.series_start.setEnabled(True)
        self.ids_start.setEnabled(True)
        results = "Finished!" + os.linesep
        for error in errors:
            results = results + error + os.linesep
        self.result_text.setText(results)

    def title_process(self):
        self.start_process(0)

    def series_process(self):
        self.start_process(1)

    def ids_process(self):
        self.start_process(2)

    def create_gui(self):
        """ Layout arrangement for the dialog and its input widgets. """
        self.layout = QVBoxLayout()
        self.layout.setSpacing(20)
        self.setLayout(self.layout)

        # Create an editable box for user to input Comic Vine API Key.
        self.api_layout = QHBoxLayout()
        self.api_msg = QLineEdit(self)
        self.api_msg.setFixedWidth(350)
        self.api_msg.setText(prefs["comic_vine_api_key"])

        self.api_label = QLabel("Comic Vine API Key")
        self.api_label.setBuddy(self.api_msg)

        self.api_layout.addWidget(self.api_label)
        self.api_layout.addWidget(self.api_msg)

        # Create an editable box for user to input Tags to add to all books.
        self.tags_layout = QHBoxLayout()
        self.tags_msg = QLineEdit(self)
        self.tags_msg.setText(prefs["tags_to_add"])

        self.tags_label = QLabel("Tags To Add")
        self.tags_label.setBuddy(self.tags_msg)

        self.tags_layout.addWidget(self.tags_label)
        self.tags_layout.addWidget(self.tags_msg)

        # Add the fields to the main layout.
        self.layout.addLayout(self.api_layout)
        self.layout.addLayout(self.tags_layout)

        # Option to keep current tags.
        self.keep_tags_cb = QCheckBox("Keep existing tags while adding new.",
                                      self)
        self.layout.addWidget(self.keep_tags_cb)

        # Separate the buttons from the input.
        self.btn_sep = QFrame()
        self.btn_sep.setFrameShape(QFrame.HLine)
        self.btn_sep.setFrameShadow(QFrame.Sunken)
        self.layout.addWidget(self.btn_sep)

        # Create a start button to kick off the processing with title.
        self.title_start = QPushButton("Using Title - Hover For Details", self)
        self.title_start.setToolTip(
            "This expects the title of a book to have a "
            "specific formatted string containing volume "
            "ID and issue#. e.g." + os.linesep + "Desired "
            "Title --- v1234 n0124" + os.linesep + "Where "
            "--- is required and the number after v "
            "matches Comic Vine's volume ID. The number "
            "after n is the issue number.")
        self.title_start.clicked.connect(self.title_process)
        self.layout.addWidget(self.title_start)

        # Create a start button to kick off the processing with series.
        self.series_start = QPushButton("Using Series - Hover For Details",
                                        self)
        self.series_start.setToolTip(
            "This expects the series name to match the "
            "Comic Vine volume ID and the series number "
            "equals issue number.")
        self.series_start.clicked.connect(self.series_process)
        self.layout.addWidget(self.series_start)

        # Create a start button to kick off the processing with CV IDs.
        self.ids_start = QPushButton("Using IDs - Hover For Details", self)
        self.ids_start.setToolTip(
            "This expects two custom columns with lookup "
            "comicvineissueid and comicvinevolumeid. "
            "These must match Comic Vine's IDs for the "
            "issue and the volume.")
        self.ids_start.clicked.connect(self.ids_process)
        self.layout.addWidget(self.ids_start)

        # Separate the progress and results.
        self.result_sep = QFrame()
        self.result_sep.setFrameShape(QFrame.HLine)
        self.result_sep.setFrameShadow(QFrame.Sunken)
        self.layout.addWidget(self.result_sep)

        # Create progress bar.
        self.progress_bar = QProgressBar()
        self.progress_bar.setRange(0, 100)
        self.progress_bar.setMinimumWidth(485)
        self.layout.addWidget(self.progress_bar)

        # Create results text area.
        self.result_box = QGroupBox()
        self.result_box.setTitle("Results")
        self.result_text = QLabel("Run Comicalibre to see results.")
        self.result_scroll = QScrollArea()
        self.result_scroll.setWidget(self.result_text)
        self.result_scroll.setWidgetResizable(True)
        self.result_layout = QVBoxLayout()
        self.result_layout.addWidget(self.result_scroll)
        self.result_box.setLayout(self.result_layout)
        self.layout.addWidget(self.result_box)

        self.setWindowTitle("Comicalibre")
        self.setWindowIcon(self.icon)
        self.resize(self.sizeHint())
示例#34
0
    def __initUI(self):
        self.__figure, self.__axe1   = plt.subplots()
        self.__axe2 = self.__axe1.twinx()
        self.__figure.subplots_adjust(left=0.1,right=0.9,bottom=0.14,top=0.92)
        self.__canvas  = FigureCanvas(self.__figure)
        self.__toolbar = NavigationToolbar(self.__canvas, self)

        self.__btnPlot1.clicked.connect(self.PlotZ1)
        self.__btnPlot2.clicked.connect(self.PlotZ2)
        self.__btnClear1.clicked.connect(self.ClearAxe1)
        self.__btnClear2.clicked.connect(self.ClearAxe2)
        self.__btnClear.clicked.connect(self.ClearAxes)
        self.__btnCSV.clicked.connect(self.ExportCSV)
        self.__btnCSV.setEnabled(False)

        mess = '''Type in a Python expression like: Y-Y.mean()
                  In this expression you can use use:
                  - the position vector X or Y,
                  - the vecolity vector VX or VX,
                  - the time vector T'''
        self.__lineZ1Edit.setToolTip(mess)
        self.__lineZ2Edit.setToolTip(mess)

        self.__lineZ1Edit.setFixedWidth(200)
        self.__lineZ2Edit.setFixedWidth(200)
        
        vbox = QVBoxLayout()
        self.setLayout(vbox)

        # Ligne 1 : tracé de l'image
        self.setLayout(vbox)

        hbox = QHBoxLayout()
        hbox.addWidget(self.__labelZ1Edit)
        hbox.addWidget(self.__lineZ1Edit)
        hbox.addWidget(self.__labelZ1label)
        hbox.addWidget(self.__lineZ1label)
        hbox.addStretch()
        hbox.addWidget(self.__btnClear1)
        hbox.addWidget(self.__btnPlot1)
        
        vbox.addLayout(hbox)

        hbox = QHBoxLayout()
        hbox.addWidget(self.__labelZ2Edit)
        hbox.addWidget(self.__lineZ2Edit)
        hbox.addWidget(self.__labelZ2label)
        hbox.addWidget(self.__lineZ2label)
        hbox.addStretch()
        hbox.addWidget(self.__btnClear2)
        hbox.addWidget(self.__btnPlot2)

        vbox.addLayout(hbox)
        
        vbox.addWidget(self.__canvas)

        hbox = QHBoxLayout()
        
        hbox.addWidget(self.__toolbar)
        hbox.addStretch()
        hbox.addWidget(self.__btnClear)
        hbox.addWidget(self.__btnCSV)

        vbox.addLayout(hbox)
示例#35
0
    def setup_ui(self, ):
        layout = QVBoxLayout(self)
        self.setLayout(layout)

        help_layout = QHBoxLayout()
        layout.addLayout(help_layout)
        # Add hyperlink to a help file at the right. We will replace the correct name when it is clicked.
        help_label = QLabel('<a href="http://www.foo.com/">Plugin Help</a>',
                            self)
        help_label.setTextInteractionFlags(Qt.LinksAccessibleByMouse
                                           | Qt.LinksAccessibleByKeyboard)
        help_label.setAlignment(Qt.AlignRight)
        help_label.linkActivated.connect(self.help_link_activated)
        help_layout.addWidget(help_label)

        self.edu_quotes = QCheckBox(_('Smarten Quotation marks'), self)
        layout.addWidget(self.edu_quotes)
        self.edu_quotes.setChecked(self.prefs['edu_quotes'])
        self.edu_quotes.stateChanged.connect(self.quotes_gui_changes)

        exceptions_group_box = QGroupBox('', self)
        layout.addWidget(exceptions_group_box)
        exceptions_group_box_layout = QVBoxLayout()
        exceptions_group_box.setLayout(exceptions_group_box_layout)
        self.use_file = QCheckBox(_('Use custom apostrophe exceptions file'),
                                  self)
        exceptions_group_box_layout.addWidget(self.use_file)
        if not self.edu_quotes.isChecked():
            self.use_file.setDisabled(True)
        else:
            self.use_file.setChecked(self.prefs['use_file'])
        self.use_file.stateChanged.connect(self.use_file_gui_changes)

        path_layout = QHBoxLayout()
        exceptions_group_box_layout.addLayout(path_layout)
        self.file_path = QLineEdit('', self)
        if not self.edu_quotes.isChecked() and not self.use_file.isChecked():
            self.file_path.setReadOnly(True)
        else:
            self.file_path.setText(self.prefs['file_path'])
            self.file_path.setReadOnly(True)
        path_layout.addWidget(self.file_path)
        self.file_button = QPushButton('...', self)
        self.file_button.clicked.connect(self.getFile)
        path_layout.addWidget(self.file_button)
        if not self.edu_quotes.isChecked() and not self.use_file.isChecked():
            self.file_button.setDisabled(True)

        combo_layout = QVBoxLayout()
        layout.addLayout(combo_layout)
        label = QLabel(_('(em|en)-dash settings'), self)
        combo_layout.addWidget(label)
        self.dashes_combo = QComboBox()
        combo_layout.addWidget(self.dashes_combo)
        values = [
            _('Do not educate dashes'),
            _('-- = emdash (no endash support)'),
            _('-- = emdash | --- = endash'),
            _('--- = emdash | -- = endash')
        ]
        self.dashes_combo.addItems(values)
        self.dashes_combo.setCurrentIndex(self.prefs['dashes'])
        # self.dashes_combo.currentIndexChanged.connect(self.update_gui)

        self.ellipses = QCheckBox(_('Smarten ellipses'), self)
        layout.addWidget(self.ellipses)
        self.ellipses.setChecked(self.prefs['ellipses'])

        self.unicode = QCheckBox(
            _('Educate with unicode characters (instead of entities)'), self)
        layout.addWidget(self.unicode)
        self.unicode.setChecked(self.prefs['unicode'])

        layout.addSpacing(10)
        button_box = QDialogButtonBox(QDialogButtonBox.Ok
                                      | QDialogButtonBox.Cancel)
        button_box.accepted.connect(self._ok_clicked)
        button_box.rejected.connect(self.reject)
        layout.addWidget(button_box)
示例#36
0
    def setup_ui(self):  # {{{
        self.setWindowModality(Qt.ApplicationModal)
        self.setWindowIcon(QIcon(I('column.png')))
        self.vl = l = QVBoxLayout(self)
        self.heading_label = la = QLabel('')
        l.addWidget(la)
        self.shortcuts = s = QLabel('')
        s.setWordWrap(True)
        s.linkActivated.connect(self.shortcut_activated)
        text = '<p>'+_('Quick create:')
        for col, name in [('isbn', _('ISBN')), ('formats', _('Formats')),
                ('yesno', _('Yes/No')),
                ('tags', _('Tags')), ('series', ngettext('Series', 'Series', 1)), ('rating',
                    _('Rating')), ('people', _("Names")), ('text', _('Short text'))]:
            text += ' <a href="col:%s">%s</a>,'%(col, name)
        text = text[:-1]
        s.setText(text)
        l.addWidget(s)
        self.g = g = QGridLayout()
        l.addLayout(g)
        l.addStretch(10)
        self.button_box = bb = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel, self)
        bb.accepted.connect(self.accept), bb.rejected.connect(self.reject)
        l.addWidget(bb)

        def add_row(text, widget):
            if text is None:
                f = g.addWidget if isinstance(widget, QWidget) else g.addLayout
                f(widget, g.rowCount(), 0, 1, -1)
                return

            row = g.rowCount()
            la = QLabel(text)
            g.addWidget(la, row, 0, 1, 1)
            if isinstance(widget, QWidget):
                la.setBuddy(widget)
                g.addWidget(widget, row, 1, 1, 1)
            else:
                widget.setContentsMargins(0, 0, 0, 0)
                g.addLayout(widget, row, 1, 1, 1)
                for i in range(widget.count()):
                    w = widget.itemAt(i).widget()
                    if isinstance(w, QWidget):
                        la.setBuddy(w)
                        break
            return la

        # Lookup name
        self.column_name_box = cnb = QLineEdit(self)
        cnb.setToolTip(_("Used for searching the column. Must contain only digits and lower case letters."))
        add_row(_("&Lookup name"), cnb)

        # Heading
        self.column_heading_box = chb = QLineEdit(self)
        chb.setToolTip(_("Column heading in the library view and category name in the Tag browser"))
        add_row(_("Column &heading"), chb)

        # Column Type
        h = QHBoxLayout()
        self.column_type_box = ctb = QComboBox(self)
        ctb.setMinimumWidth(70)
        ctb.setToolTip(_("What kind of information will be kept in the column."))
        h.addWidget(ctb)
        self.use_decorations = ud = QCheckBox(_("Show &checkmarks"), self)
        ud.setToolTip(_("Show check marks in the GUI. Values of 'yes', 'checked', and 'true'\n"
            "will show a green check. Values of 'no', 'unchecked', and 'false' will show a red X.\n"
            "Everything else will show nothing."))
        h.addWidget(ud)
        self.is_names = ins = QCheckBox(_("Contains names"), self)
        ins.setToolTip(_("Check this box if this column contains names, like the authors column."))
        h.addWidget(ins)
        add_row(_("&Column type"), h)

        # Description
        self.description_box = d = QLineEdit(self)
        d.setToolTip(_("Optional text describing what this column is for"))
        add_row(_("D&escription"), d)

        # Date/number formatting
        h = QHBoxLayout()
        self.format_box = fb = QLineEdit(self)
        h.addWidget(fb)
        self.format_default_label = la = QLabel('')
        la.setOpenExternalLinks(True), la.setWordWrap(True)
        h.addWidget(la)
        self.format_label = add_row('', h)

        # Template
        self.composite_box = cb = TemplateLineEditor(self)
        self.composite_default_label = cdl = QLabel(_("Default: (nothing)"))
        cb.setToolTip(_("Field template. Uses the same syntax as save templates."))
        cdl.setToolTip(_("Similar to save templates. For example, %s") % "{title} {isbn}")
        h = QHBoxLayout()
        h.addWidget(cb), h.addWidget(cdl)
        self.composite_label = add_row(_("&Template"), h)

        # Comments properties
        self.comments_heading_position = ct = QComboBox(self)
        for k, text in (
                ('hide', _('No heading')),
                ('above', _('Show heading above the text')),
                ('side', _('Show heading to the side of the text'))
        ):
            ct.addItem(text, k)
        ct.setToolTip(_('Choose whether or not the column heading is shown in the Book\n'
                        'details panel and, if shown, where'))
        self.comments_heading_position_label = add_row(_('Column heading'), ct)

        self.comments_type = ct = QComboBox(self)
        for k, text in (
                ('html', 'HTML'),
                ('short-text', _('Short text, like a title')),
                ('long-text', _('Plain text')),
                ('markdown', _('Plain text formatted using markdown'))
        ):
            ct.addItem(text, k)
        ct.setToolTip(_('Choose how the data in this column is interpreted.\n'
                        'This controls how the data is displayed in the Book details panel\n'
                        'and how it is edited.'))
        self.comments_type_label = add_row(_('Interpret this column as:') + ' ', ct)

        # Values for enum type
        l = QGridLayout()
        self.enum_box = eb = QLineEdit(self)
        eb.setToolTip(_(
            "A comma-separated list of permitted values. The empty value is always\n"
            "included, and is the default. For example, the list 'one,two,three' has\n"
            "four values, the first of them being the empty value."))
        self.enum_default_label = la = QLabel(_("Values"))
        la.setBuddy(eb)
        l.addWidget(eb), l.addWidget(la, 0, 1)
        self.enum_colors = ec = QLineEdit(self)
        ec.setToolTip(_("A list of color names to use when displaying an item. The\n"
            "list must be empty or contain a color for each value."))
        self.enum_colors_label = la = QLabel(_('Colors'))
        la.setBuddy(ec)
        l.addWidget(ec), l.addWidget(la, 1, 1)
        self.enum_label = add_row(_('&Values'), l)

        # Rating allow half stars
        self.allow_half_stars = ahs = QCheckBox(_('Allow half stars'))
        ahs.setToolTip(_('Allow half star ratings, for example: ') + '★★★⯨')
        add_row(None, ahs)

        # Composite display properties
        l = QHBoxLayout()
        self.composite_sort_by_label = la = QLabel(_("&Sort/search column by"))
        self.composite_sort_by = csb = QComboBox(self)
        la.setBuddy(csb), csb.setToolTip(_("How this column should handled in the GUI when sorting and searching"))
        l.addWidget(la), l.addWidget(csb)
        self.composite_make_category = cmc = QCheckBox(_("Show in Tag browser"))
        cmc.setToolTip(_("If checked, this column will appear in the Tag browser as a category"))
        l.addWidget(cmc)
        self.composite_contains_html = cch = QCheckBox(_("Show as HTML in Book details"))
        cch.setToolTip('<p>' + _(
            'If checked, this column will be displayed as HTML in '
            'Book details and the Content server. This can be used to '
            'construct links with the template language. For example, '
            'the template '
            '<pre>&lt;big&gt;&lt;b&gt;{title}&lt;/b&gt;&lt;/big&gt;'
            '{series:| [|}{series_index:| [|]]}</pre>'
            'will create a field displaying the title in bold large '
            'characters, along with the series, for example <br>"<big><b>'
            'An Oblique Approach</b></big> [Belisarius [1]]". The template '
            '<pre>&lt;a href="https://www.beam-ebooks.de/ebook/{identifiers'
            ':select(beam)}"&gt;Beam book&lt;/a&gt;</pre> '
            'will generate a link to the book on the Beam e-books site.') + '</p>')
        l.addWidget(cch)
        add_row(None, l)

        # Default value
        self.default_value = dv = QLineEdit(self)
        dv.setToolTip('<p>' + _('Default value when a new book is added to the '
            'library. For Date columns enter the word "Now", or the date as '
            'yyyy-mm-dd. For Yes/No columns enter "Yes" or "No". For Text with '
            'a fixed set of values enter one of the permitted values. For '
            'Rating columns enter a number between 0 and 5.') + '</p>')
        self.default_value_label = add_row(_('Default value'), dv)

        self.resize(self.sizeHint())
示例#37
0
    def do_layout(self):
        self.central_widget.clear()
        self.labels = []
        sto = QWidget.setTabOrder

        self.central_widget.tabBar().setVisible(False)
        tab0 = QWidget(self)
        self.central_widget.addTab(tab0, _("&Metadata"))
        l = QGridLayout()
        tab0.setLayout(l)

        # Basic metadata in col 0
        tl = QGridLayout()
        gb = QGroupBox(_('Basic metadata'), tab0)
        l.addWidget(gb, 0, 0, 1, 1)
        gb.setLayout(tl)

        self.button_box_layout.insertWidget(1, self.fetch_metadata_button)
        self.button_box_layout.insertWidget(2, self.config_metadata_button)
        sto(self.button_box, self.fetch_metadata_button)
        sto(self.fetch_metadata_button, self.config_metadata_button)
        sto(self.config_metadata_button, self.title)

        def create_row(row, widget, tab_to, button=None, icon=None, span=1):
            ql = BuddyLabel(widget)
            tl.addWidget(ql, row, 1, 1, 1)
            tl.addWidget(widget, row, 2, 1, 1)
            if button is not None:
                tl.addWidget(button, row, 3, span, 1)
                if icon is not None:
                    button.setIcon(QIcon(I(icon)))
            if tab_to is not None:
                if button is not None:
                    sto(widget, button)
                    sto(button, tab_to)
                else:
                    sto(widget, tab_to)

        tl.addWidget(self.swap_title_author_button, 0, 0, 2, 1)
        tl.addWidget(self.manage_authors_button, 2, 0, 2, 1)
        tl.addWidget(self.paste_isbn_button, 12, 0, 1, 1)
        tl.addWidget(self.tags_editor_button, 6, 0, 1, 1)

        create_row(0,
                   self.title,
                   self.title_sort,
                   button=self.deduce_title_sort_button,
                   span=2,
                   icon='auto_author_sort.png')
        create_row(1, self.title_sort, self.authors)
        create_row(2,
                   self.authors,
                   self.author_sort,
                   button=self.deduce_author_sort_button,
                   span=2,
                   icon='auto_author_sort.png')
        create_row(3, self.author_sort, self.series)
        create_row(4,
                   self.series,
                   self.series_index,
                   button=self.clear_series_button,
                   icon='trash.png')
        create_row(5, self.series_index, self.tags)
        create_row(6, self.tags, self.rating, button=self.clear_tags_button)
        create_row(7,
                   self.rating,
                   self.pubdate,
                   button=self.clear_ratings_button)
        create_row(8,
                   self.pubdate,
                   self.publisher,
                   button=self.pubdate.clear_button,
                   icon='trash.png')
        create_row(9, self.publisher, self.languages)
        create_row(10, self.languages, self.timestamp)
        create_row(11,
                   self.timestamp,
                   self.identifiers,
                   button=self.timestamp.clear_button,
                   icon='trash.png')
        create_row(12,
                   self.identifiers,
                   self.comments,
                   button=self.clear_identifiers_button,
                   icon='trash.png')
        sto(self.clear_identifiers_button, self.swap_title_author_button)
        sto(self.swap_title_author_button, self.manage_authors_button)
        sto(self.manage_authors_button, self.tags_editor_button)
        sto(self.tags_editor_button, self.paste_isbn_button)
        tl.addItem(QSpacerItem(1, 1, QSizePolicy.Fixed, QSizePolicy.Expanding),
                   13, 1, 1, 1)

        # Custom metadata in col 1
        w = getattr(self, 'custom_metadata_widgets_parent', None)
        if w is not None:
            gb = QGroupBox(_('Custom metadata'), tab0)
            gbl = QVBoxLayout()
            gb.setLayout(gbl)
            sr = QScrollArea(gb)
            sr.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
            sr.setWidgetResizable(True)
            sr.setFrameStyle(QFrame.NoFrame)
            sr.setWidget(w)
            gbl.addWidget(sr)
            l.addWidget(gb, 0, 1, 1, 1)
            sp = QSizePolicy()
            sp.setVerticalStretch(10)
            sp.setHorizontalPolicy(QSizePolicy.Minimum)
            sp.setVerticalPolicy(QSizePolicy.Expanding)
            gb.setSizePolicy(sp)
            self.set_custom_metadata_tab_order()

        # comments span col 0 & 1
        w = QGroupBox(_('Comments'), tab0)
        sp = QSizePolicy()
        sp.setVerticalStretch(10)
        sp.setHorizontalPolicy(QSizePolicy.Expanding)
        sp.setVerticalPolicy(QSizePolicy.Expanding)
        w.setSizePolicy(sp)
        lb = QHBoxLayout()
        w.setLayout(lb)
        lb.addWidget(self.comments)
        l.addWidget(w, 1, 0, 1, 2)

        # Cover & formats in col 3
        gb = QGroupBox(_('Cover'), tab0)
        lb = QGridLayout()
        gb.setLayout(lb)
        lb.addWidget(self.cover, 0, 0, 1, 3, alignment=Qt.AlignCenter)
        sto(self.manage_authors_button, self.cover.buttons[0])
        for i, b in enumerate(self.cover.buttons[:3]):
            lb.addWidget(b, 1, i, 1, 1)
            sto(b, self.cover.buttons[i + 1])
        hl = QHBoxLayout()
        for b in self.cover.buttons[3:]:
            hl.addWidget(b)
        sto(self.cover.buttons[-2], self.cover.buttons[-1])
        lb.addLayout(hl, 2, 0, 1, 3)
        l.addWidget(gb, 0, 2, 1, 1)
        l.addWidget(self.formats_manager, 1, 2, 1, 1)
        sto(self.cover.buttons[-1], self.formats_manager)

        self.formats_manager.formats.setMaximumWidth(10000)
        self.formats_manager.formats.setIconSize(QSize(32, 32))
示例#38
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.editor.data_changed.connect(self.data_changed)
        self.set_base_url = self.editor.set_base_url
        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, _('&Normal 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.data_changed.connect(self.wyswyg_dirtied)
示例#39
0
文件: server.py 项目: tletnes/calibre
class SearchTheInternet(QWidget):

    changed_signal = pyqtSignal()

    def __init__(self, parent):
        QWidget.__init__(self, parent)
        self.sa = QScrollArea(self)
        self.lw = QWidget(self)
        self.l = QVBoxLayout(self.lw)
        self.sa.setWidget(self.lw), self.sa.setWidgetResizable(True)
        self.gl = gl = QVBoxLayout(self)
        self.la = QLabel(_(
            'Add new locations to search for books or authors using the "Search the internet" feature'
            ' of the Content server. The URLs should contain {author} which will be'
            ' replaced by the author name and, for book URLs, {title} which will'
            ' be replaced by the book title.'))
        self.la.setWordWrap(True)
        gl.addWidget(self.la)

        self.h = QHBoxLayout()
        gl.addLayout(self.h)
        self.add_url_button = b = QPushButton(QIcon(I('plus.png')), _('&Add URL'))
        b.clicked.connect(self.add_url)
        self.h.addWidget(b)
        self.export_button = b = QPushButton(_('Export URLs'))
        b.clicked.connect(self.export_urls)
        self.h.addWidget(b)
        self.import_button = b = QPushButton(_('Import URLs'))
        b.clicked.connect(self.import_urls)
        self.h.addWidget(b)
        self.clear_button = b = QPushButton(_('Clear'))
        b.clicked.connect(self.clear)
        self.h.addWidget(b)

        self.h.addStretch(10)
        gl.addWidget(self.sa, stretch=10)
        self.items = []

    def genesis(self):
        self.current_urls = search_the_net_urls() or []

    @property
    def current_urls(self):
        return [item.as_dict for item in self.items if not item.is_empty]

    def append_item(self, item_as_dict):
        self.items.append(URLItem(item_as_dict, self))
        self.l.addWidget(self.items[-1])

    def clear(self):
        [(self.l.removeWidget(w), w.setParent(None), w.deleteLater()) for w in self.items]
        self.items = []
        self.changed_signal.emit()

    @current_urls.setter
    def current_urls(self, val):
        self.clear()
        for entry in val:
            self.append_item(entry)

    def add_url(self):
        self.items.append(URLItem(None, self))
        self.l.addWidget(self.items[-1])
        QTimer.singleShot(100, self.scroll_to_bottom)

    def scroll_to_bottom(self):
        sb = self.sa.verticalScrollBar()
        if sb:
            sb.setValue(sb.maximum())
        self.items[-1].name_widget.setFocus(Qt.OtherFocusReason)

    @property
    def serialized_urls(self):
        return json.dumps(self.current_urls, indent=2)

    def commit(self):
        for item in self.items:
            if not item.validate():
                return False
        cu = self.current_urls
        if cu:
            with lopen(search_the_net_urls.path, 'wb') as f:
                f.write(self.serialized_urls)
        else:
            try:
                os.remove(search_the_net_urls.path)
            except EnvironmentError as err:
                if err.errno != errno.ENOENT:
                    raise
        return True

    def export_urls(self):
        path = choose_save_file(
            self, 'search-net-urls', _('Choose URLs file'),
            filters=[(_('URL files'), ['json'])], initial_filename='search-urls.json')
        if path:
            with lopen(path, 'wb') as f:
                f.write(self.serialized_urls)

    def import_urls(self):
        paths = choose_files(self, 'search-net-urls', _('Choose URLs file'),
            filters=[(_('URL files'), ['json'])], all_files=False, select_only_single_file=True)
        if paths:
            with lopen(paths[0], 'rb') as f:
                items = json.loads(f.read())
                [self.append_item(x) for x in items]
                self.changed_signal.emit()
示例#40
0
    def __init__(self,
                 parent,
                 key_type_name,
                 plugin_keys,
                 create_key,
                 keyfile_ext=u""):
        QDialog.__init__(self, parent)
        self.parent = parent
        self.key_type_name = key_type_name
        self.plugin_keys = plugin_keys
        self.create_key = create_key
        self.keyfile_ext = keyfile_ext
        self.json_file = (keyfile_ext == u"k4i")

        self.setWindowTitle("{0} {1}: Manage {2}s".format(
            PLUGIN_NAME, PLUGIN_VERSION, self.key_type_name))

        # Start Qt Gui dialog layout
        layout = QVBoxLayout(self)
        self.setLayout(layout)

        keys_group_box = QGroupBox(_(u"{0}s".format(self.key_type_name)), self)
        layout.addWidget(keys_group_box)
        keys_group_box_layout = QHBoxLayout()
        keys_group_box.setLayout(keys_group_box_layout)

        self.listy = QListWidget(self)
        self.listy.setToolTip(
            u"{0}s that will be used to decrypt ebooks".format(
                self.key_type_name))
        self.listy.setSelectionMode(QAbstractItemView.SingleSelection)
        self.populate_list()
        keys_group_box_layout.addWidget(self.listy)

        button_layout = QVBoxLayout()
        keys_group_box_layout.addLayout(button_layout)
        self._add_key_button = QtGui.QToolButton(self)
        self._add_key_button.setIcon(QIcon(I('plus.png')))
        self._add_key_button.setToolTip(u"Create new {0}".format(
            self.key_type_name))
        self._add_key_button.clicked.connect(self.add_key)
        button_layout.addWidget(self._add_key_button)

        self._delete_key_button = QtGui.QToolButton(self)
        self._delete_key_button.setToolTip(_(u"Delete highlighted key"))
        self._delete_key_button.setIcon(QIcon(I('list_remove.png')))
        self._delete_key_button.clicked.connect(self.delete_key)
        button_layout.addWidget(self._delete_key_button)

        spacerItem = QtGui.QSpacerItem(20, 40, QtGui.QSizePolicy.Minimum,
                                       QtGui.QSizePolicy.Expanding)
        button_layout.addItem(spacerItem)

        layout.addSpacing(5)
        migrate_layout = QHBoxLayout()
        layout.addLayout(migrate_layout)
        migrate_layout.addStretch()
        self.button_box = QDialogButtonBox(QDialogButtonBox.Close)
        self.button_box.rejected.connect(self.close)
        migrate_layout.addWidget(self.button_box)

        self.resize(self.sizeHint())
示例#41
0
    def setup_ui(self):
        DELETE_STR = _('Delete')
        MODIFY_STR = _('Modify')
        NO_ATTRIB_STR = _('No attributes ("naked" tag)')
        self.NO_CHANGE_STR = _('No change')

        layout = QVBoxLayout(self)
        self.setLayout(layout)

        help_layout = QHBoxLayout()
        layout.addLayout(help_layout)
        # Add hyperlink to a help file at the right. We will replace the correct name when it is clicked.
        help_label = QLabel('<a href="http://www.foo.com/">Plugin Help</a>',
                            self)
        help_label.setTextInteractionFlags(Qt.LinksAccessibleByMouse
                                           | Qt.LinksAccessibleByKeyboard)
        help_label.setAlignment(Qt.AlignRight)
        help_label.linkActivated.connect(self.help_link_activated)
        help_layout.addWidget(help_label)

        action_layout = QHBoxLayout()
        layout.addLayout(action_layout)
        label = QLabel(_('Action type:'), self)
        action_layout.addWidget(label)
        self.action_combo = QComboBox()
        action_layout.addWidget(self.action_combo)
        self.action_combo.addItems([DELETE_STR, MODIFY_STR])
        self.action_combo.currentIndexChanged.connect(self.update_gui)

        tag_layout = QHBoxLayout()
        layout.addLayout(tag_layout)
        label = QLabel(_('Tag name:'), self)
        tag_layout.addWidget(label)
        self.tag_combo = QComboBox()
        tag_layout.addWidget(self.tag_combo)
        self.tag_combo.addItems(self.taglist)
        self.tag_combo.currentIndexChanged.connect(self.update_gui)

        attr_layout = QHBoxLayout()
        layout.addLayout(attr_layout)
        label = QLabel(_('Having the attribute:'), self)
        attr_layout.addWidget(label)
        self.attr_combo = QComboBox()
        attr_layout.addWidget(self.attr_combo)
        self.attr_combo.addItems(self.prefs['attrs'])
        self.attr_combo.addItem(NO_ATTRIB_STR)
        self.attr_combo.currentIndexChanged.connect(self.update_gui)

        srch_layout = QHBoxLayout()
        layout.addLayout(srch_layout)
        label = QLabel(_("Whose value is (no quotes):"), self)
        srch_layout.addWidget(label)
        self.srch_txt = QLineEdit('', self)
        srch_layout.addWidget(self.srch_txt)
        self.srch_method = QCheckBox(_('Regex'), self)
        srch_layout.addWidget(self.srch_method)

        newtag_layout = QHBoxLayout()
        layout.addLayout(newtag_layout)
        label = QLabel(_('Change tag to:'), self)
        newtag_layout.addWidget(label)
        self.newtag_combo = QComboBox()
        newtag_layout.addWidget(self.newtag_combo)

        self.newtag_combo.addItem(self.NO_CHANGE_STR)
        self.newtag_combo.addItems(self.prefs['{}_changes'.format(
            unicode(self.tag_combo.currentText()))])

        if self.action_combo.currentIndex() == 0:
            self.newtag_combo.setDisabled(True)

        newattr_layout = QVBoxLayout()
        layout.addLayout(newattr_layout)
        label = QLabel(_('New attribute string to insert (entire):'), self)
        newattr_layout.addWidget(label)
        self.newattr_txt = QLineEdit('', self)
        newattr_layout.addWidget(self.newattr_txt)
        self.copy_attr = QCheckBox(_('Copy existing attribute string'), self)
        self.copy_attr.stateChanged.connect(self.update_txt_box)
        newattr_layout.addWidget(self.copy_attr)
        if self.action_combo.currentIndex() == 0:
            self.copy_attr.setDisabled(True)
            self.newattr_txt.setDisabled(True)

        layout.addSpacing(10)
        button_box = QDialogButtonBox(QDialogButtonBox.Ok
                                      | QDialogButtonBox.Cancel)
        button_box.accepted.connect(self._ok_clicked)
        button_box.rejected.connect(self.reject)
        layout.addWidget(button_box)
示例#42
0
class CheckLibraryDialog(QDialog):

    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(self.ext_ignores.text()))
        self.db.new_api.set_pref('check_library_ignore_names', unicode(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(self.name_ignores.text())),
                             self.box_to_list(unicode(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.setText(1, _('(fixable)'))
                tl.setFlags(Qt.ItemIsEnabled | Qt.ItemIsUserCheckable)
                tl.setCheckState(1, False)
            else:
                tl.setFlags(Qt.ItemIsEnabled)
            self.top_level_items[attr] = tl

            for problem in list:
                it = Item()
                if checkable:
                    it.setFlags(Qt.ItemIsEnabled | Qt.ItemIsUserCheckable)
                    it.setCheckState(1, False)
                else:
                    it.setFlags(Qt.ItemIsEnabled)
                it.setText(0, problem[0])
                it.setData(0, Qt.UserRole, problem[2])
                it.setText(1, 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(2)
        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):
        self.fix_button.setEnabled(False)
        for it in self.top_level_items.values():
            if it.checkState(1):
                self.fix_button.setEnabled(True)

        self.delete_button.setEnabled(False)
        for it in self.all_items:
            if it.checkState(1):
                self.delete_button.setEnabled(True)
                return

    def mark_for_fix(self):
        for it in self.top_level_items.values():
            if it.flags() & Qt.ItemIsUserCheckable:
                it.setCheckState(1, Qt.Checked)

    def mark_for_delete(self):
        for it in self.all_items:
            if it.flags() & Qt.ItemIsUserCheckable:
                it.setCheckState(1, 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(1):
                try:
                    p = os.path.join(self.db.library_path ,unicode(it.text(1)))
                    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(it.text(1))))
        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 = set([f.strip() for f in all.split(',')]) if all else set()
            valid = self.db.formats(id, index_is_id=True, verify_formats=True)
            valid = set([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)
class HashcrackerTab(QWidget):

    def __init__(self, console):
        super().__init__()

        self.layout = QVBoxLayout(self)

        self.titleText = QLabel("<H1>Hashcracker</H1>\nHash hier einfügen")
        self.layout.addWidget(self.titleText)

        self.hashField = QLineEdit()
        self.layout.addWidget(self.hashField)

        self.hashSelectionLabel = QLabel("Wähle Hashfunktion aus")
        self.layout.addWidget(self.hashSelectionLabel)

        self.selectHash = QComboBox(self)
        self.selectHash.addItems(["SHA1", "SHA224", "SHA256", "SHA384", "SHA512", "MD5"])
        self.selectHash.setCurrentText("SHA-512")
        self.layout.addWidget(self.selectHash)

        self.hboxText = QHBoxLayout()
        self.bruteforceLabel = QLabel("<H2>Bruteforce</H2>")
        self.listLabel = QLabel("<H2>Passwort Liste</H2>")
        self.rtLabel = QLabel("<H2>Ranbowtable Crack</H2>")
        self.hboxText.addWidget(self.bruteforceLabel)
        self.hboxText.addWidget(self.listLabel)
        self.hboxText.addWidget(self.rtLabel)
        self.layout.addLayout(self.hboxText)

        self.hboxAction = QHBoxLayout()
        self.bruteforceCharset = QLineEdit("Charset")
        self.hboxAction.addWidget(self.bruteforceCharset)
        self.listSelect = QPushButton("Wähle Datei aus")
        self.hboxAction.addWidget(self.listSelect)
        self.rtSelect = QPushButton("Wähle Ranbowtable aus")
        self.hboxAction.addWidget(self.rtSelect)
        self.layout.addLayout(self.hboxAction)

        self.hboxCrackButton = QHBoxLayout()
        self.bruteforceCrack = QPushButton("Crack Bruteforce")
        self.hboxCrackButton.addWidget(self.bruteforceCrack)
        self.listCrack = QPushButton("Crack List")
        self.hboxCrackButton.addWidget(self.listCrack)
        self.rainbowCrack = QPushButton("Crack Rainbowtable")
        self.hboxCrackButton.addWidget(self.rainbowCrack)
        self.layout.addLayout(self.hboxCrackButton)

        self.layout.addStretch(1)
示例#44
0
    def __init__(self, parent=None):
        BasicSettings.__init__(self, parent)
        self.dictionaries_changed = self.snippets_changed = False
        self.l = l = QFormLayout(self)
        self.setLayout(l)

        fc = FontFamilyChooser(self)
        self('editor_font_family',
             widget=fc,
             getter=attrgetter('font_family'),
             setter=lambda x, val: setattr(x, 'font_family', val))
        fc.family_changed.connect(self.emit_changed)
        l.addRow(_('Editor font family:'), fc)

        fs = self('editor_font_size')
        fs.setMinimum(8), fs.setSuffix(' pt'), fs.setMaximum(50)
        l.addRow(_('Editor font &size:'), fs)

        choices = self.theme_choices()
        theme = self.choices_widget('editor_theme', choices, 'auto', 'auto')
        self.custom_theme_button = b = QPushButton(
            _('Create/edit &custom color schemes'))
        b.clicked.connect(self.custom_theme)
        h = QHBoxLayout()
        h.addWidget(theme), h.addWidget(b)
        l.addRow(_('&Color scheme:'), h)
        l.labelForField(h).setBuddy(theme)

        tw = self('editor_tab_stop_width')
        tw.setMinimum(2), tw.setSuffix(_(' characters')), tw.setMaximum(20)
        l.addRow(_('W&idth of tabs:'), tw)

        self.tb = b = QPushButton(_('Change &templates'))
        l.addRow(_('Templates for new files:'), b)
        connect_lambda(b.clicked, self,
                       lambda self: TemplatesDialog(self).exec_())

        lw = self('editor_line_wrap')
        lw.setText(_('&Wrap long lines in the editor'))
        l.addRow(lw)

        lw = self('replace_entities_as_typed')
        lw.setText(_('&Replace HTML entities as they are typed'))
        lw.setToolTip('<p>' + _(
            'With this option, every time you type in a complete html entity, such as &amp;hellip;'
            ' it is automatically replaced by its corresponding character. The replacement'
            ' happens only when the trailing semi-colon is typed.'))
        l.addRow(lw)

        lw = self('auto_close_tags')
        lw.setText(_('Auto close t&ags when typing </'))
        lw.setToolTip('<p>' + prepare_string_for_xml(
            _('With this option, every time you type </ the current HTML closing tag is auto-completed'
              )))
        l.addRow(lw)

        lw = self('editor_show_char_under_cursor')
        lw.setText(
            _('Show the &name of the current character before the cursor along with the line and column number'
              ))
        l.addRow(lw)

        lw = self('pretty_print_on_open')
        lw.setText(
            _('Beautify individual &files automatically when they are opened'))
        lw.setToolTip('<p>' + _(
            'This will cause the beautify current file action to be performed automatically every'
            ' time you open a HTML/CSS/etc. file for editing.'))
        l.addRow(lw)

        lw = self('inline_spell_check')
        lw.setText(_('Show &misspelled words underlined in the code view'))
        lw.setToolTip('<p>' + _(
            'This will cause spelling errors to be highlighted in the code view'
            ' for easy correction as you type.'))
        l.addRow(lw)

        lw = self('editor_accepts_drops')
        lw.setText(_('Allow drag and drop &editing of text'))
        lw.setToolTip('<p>' + _(
            'Allow using drag and drop to move text around in the editor.'
            ' It can be useful to turn this off if you have a misbehaving touchpad.'
        ))
        l.addRow(lw)

        self.dictionaries = d = QPushButton(_('Manage &spelling dictionaries'),
                                            self)
        d.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)
        d.clicked.connect(self.manage_dictionaries)
        l.addRow(d)

        self.snippets = s = QPushButton(_('Manage sni&ppets'), self)
        s.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)
        s.clicked.connect(self.manage_snippets)
        l.addRow(s)
示例#45
0
    def do_layout(self):
        self.central_widget.clear()
        self.tabs = []
        self.labels = []
        sto = QWidget.setTabOrder

        self.on_drag_enter.connect(self.handle_drag_enter)
        self.tabs.append(DragTrackingWidget(self, self.on_drag_enter))
        self.central_widget.addTab(self.tabs[0], _("&Metadata"))
        self.tabs[0].l = QGridLayout()
        self.tabs[0].setLayout(self.tabs[0].l)

        self.tabs.append(QWidget(self))
        self.central_widget.addTab(self.tabs[1], _("&Cover and formats"))
        self.tabs[1].l = QGridLayout()
        self.tabs[1].setLayout(self.tabs[1].l)

        # accept drop events so we can automatically switch to the second tab to
        # drop covers and formats
        self.tabs[0].setAcceptDrops(True)

        # Tab 0
        tab0 = self.tabs[0]

        tl = QGridLayout()
        gb = QGroupBox(_('&Basic metadata'), self.tabs[0])
        self.tabs[0].l.addWidget(gb, 0, 0, 1, 1)
        gb.setLayout(tl)

        self.button_box_layout.insertWidget(1, self.fetch_metadata_button)
        self.button_box_layout.insertWidget(2, self.config_metadata_button)
        sto(self.button_box, self.fetch_metadata_button)
        sto(self.fetch_metadata_button, self.config_metadata_button)
        sto(self.config_metadata_button, self.title)

        def create_row(row, widget, tab_to, button=None, icon=None, span=1):
            ql = BuddyLabel(widget)
            tl.addWidget(ql, row, 1, 1, 1)
            tl.addWidget(widget, row, 2, 1, 1)
            if button is not None:
                tl.addWidget(button, row, 3, span, 1)
                if icon is not None:
                    button.setIcon(QIcon(I(icon)))
            if tab_to is not None:
                if button is not None:
                    sto(widget, button)
                    sto(button, tab_to)
                else:
                    sto(widget, tab_to)

        tl.addWidget(self.swap_title_author_button, 0, 0, 2, 1)
        tl.addWidget(self.manage_authors_button, 2, 0, 1, 1)
        tl.addWidget(self.paste_isbn_button, 12, 0, 1, 1)
        tl.addWidget(self.tags_editor_button, 6, 0, 1, 1)

        create_row(0,
                   self.title,
                   self.title_sort,
                   button=self.deduce_title_sort_button,
                   span=2,
                   icon='auto_author_sort.png')
        create_row(1, self.title_sort, self.authors)
        create_row(2,
                   self.authors,
                   self.author_sort,
                   button=self.deduce_author_sort_button,
                   span=2,
                   icon='auto_author_sort.png')
        create_row(3, self.author_sort, self.series)
        create_row(4,
                   self.series,
                   self.series_index,
                   button=self.clear_series_button,
                   icon='trash.png')
        create_row(5, self.series_index, self.tags)
        create_row(6, self.tags, self.rating, button=self.clear_tags_button)
        create_row(7,
                   self.rating,
                   self.pubdate,
                   button=self.clear_ratings_button)
        create_row(8,
                   self.pubdate,
                   self.publisher,
                   button=self.pubdate.clear_button,
                   icon='trash.png')
        create_row(9, self.publisher, self.languages)
        create_row(10, self.languages, self.timestamp)
        create_row(11,
                   self.timestamp,
                   self.identifiers,
                   button=self.timestamp.clear_button,
                   icon='trash.png')
        create_row(12,
                   self.identifiers,
                   self.comments,
                   button=self.clear_identifiers_button,
                   icon='trash.png')
        sto(self.clear_identifiers_button, self.swap_title_author_button)
        sto(self.swap_title_author_button, self.manage_authors_button)
        sto(self.manage_authors_button, self.tags_editor_button)
        sto(self.tags_editor_button, self.paste_isbn_button)
        tl.addItem(QSpacerItem(1, 1, QSizePolicy.Fixed, QSizePolicy.Expanding),
                   13, 1, 1, 1)

        w = getattr(self, 'custom_metadata_widgets_parent', None)
        if w is not None:
            gb = QGroupBox(_('C&ustom metadata'), tab0)
            gbl = QVBoxLayout()
            gb.setLayout(gbl)
            sr = QScrollArea(tab0)
            sr.setWidgetResizable(True)
            sr.setFrameStyle(QFrame.NoFrame)
            sr.setWidget(w)
            gbl.addWidget(sr)
            self.tabs[0].l.addWidget(gb, 0, 1, 1, 1)
            sto(self.identifiers, gb)

        w = QGroupBox(_('&Comments'), tab0)
        sp = QSizePolicy()
        sp.setVerticalStretch(10)
        sp.setHorizontalPolicy(QSizePolicy.Expanding)
        sp.setVerticalPolicy(QSizePolicy.Expanding)
        w.setSizePolicy(sp)
        l = QHBoxLayout()
        w.setLayout(l)
        l.addWidget(self.comments)
        tab0.l.addWidget(w, 1, 0, 1, 2)

        # Tab 1
        tab1 = self.tabs[1]

        wsp = QWidget(tab1)
        wgl = QVBoxLayout()
        wsp.setLayout(wgl)

        # right-hand side of splitter
        gb = QGroupBox(_('Change cover'), tab1)
        l = QGridLayout()
        gb.setLayout(l)
        for i, b in enumerate(self.cover.buttons[:3]):
            l.addWidget(b, 0, i, 1, 1)
            sto(b, self.cover.buttons[i + 1])
        hl = QHBoxLayout()
        for b in self.cover.buttons[3:]:
            hl.addWidget(b)
        sto(self.cover.buttons[-2], self.cover.buttons[-1])
        l.addLayout(hl, 1, 0, 1, 3)
        wgl.addWidget(gb)
        wgl.addItem(
            QSpacerItem(10, 10, QSizePolicy.Expanding, QSizePolicy.Expanding))
        wgl.addItem(
            QSpacerItem(10, 10, QSizePolicy.Expanding, QSizePolicy.Expanding))
        wgl.addWidget(self.formats_manager)

        self.splitter = QSplitter(Qt.Horizontal, tab1)
        tab1.l.addWidget(self.splitter)
        self.splitter.addWidget(self.cover)
        self.splitter.addWidget(wsp)

        self.formats_manager.formats.setMaximumWidth(10000)
        self.formats_manager.formats.setIconSize(QSize(64, 64))
示例#46
0
    def _initialize_controls(self):
        self.setWindowTitle(_('User plugins'))
        self.setWindowIcon(QIcon(I('plugins/plugin_updater.png')))
        layout = QVBoxLayout(self)
        self.setLayout(layout)
        title_layout = ImageTitleLayout(self, 'plugins/plugin_updater.png',
                _('User Plugins'))
        layout.addLayout(title_layout)

        header_layout = QHBoxLayout()
        layout.addLayout(header_layout)
        self.filter_combo = PluginFilterComboBox(self)
        self.filter_combo.setMinimumContentsLength(20)
        self.filter_combo.currentIndexChanged[int].connect(self._filter_combo_changed)
        header_layout.addWidget(QLabel(_('Filter list of plugins')+':', self))
        header_layout.addWidget(self.filter_combo)
        header_layout.addStretch(10)

        # filter plugins by name
        header_layout.addWidget(QLabel(_('Filter by name')+':', self))
        self.filter_by_name_lineedit = QLineEdit(self)
        self.filter_by_name_lineedit.setText("")
        self.filter_by_name_lineedit.textChanged.connect(self._filter_name_lineedit_changed)

        header_layout.addWidget(self.filter_by_name_lineedit)

        self.plugin_view = QTableView(self)
        self.plugin_view.horizontalHeader().setStretchLastSection(True)
        self.plugin_view.setSelectionBehavior(QAbstractItemView.SelectRows)
        self.plugin_view.setSelectionMode(QAbstractItemView.SingleSelection)
        self.plugin_view.setAlternatingRowColors(True)
        self.plugin_view.setSortingEnabled(True)
        self.plugin_view.setIconSize(QSize(28, 28))
        layout.addWidget(self.plugin_view)

        details_layout = QHBoxLayout()
        layout.addLayout(details_layout)
        forum_label = self.forum_label = QLabel('')
        forum_label.setTextInteractionFlags(Qt.LinksAccessibleByMouse | Qt.LinksAccessibleByKeyboard)
        forum_label.linkActivated.connect(self._forum_label_activated)
        details_layout.addWidget(QLabel(_('Description')+':', self), 0, Qt.AlignLeft)
        details_layout.addWidget(forum_label, 1, Qt.AlignRight)

        self.description = QLabel(self)
        self.description.setFrameStyle(QFrame.Panel | QFrame.Sunken)
        self.description.setAlignment(Qt.AlignTop | Qt.AlignLeft)
        self.description.setMinimumHeight(40)
        self.description.setWordWrap(True)
        layout.addWidget(self.description)

        self.button_box = QDialogButtonBox(QDialogButtonBox.Close)
        self.button_box.rejected.connect(self.reject)
        self.finished.connect(self._finished)
        self.install_button = self.button_box.addButton(_('&Install'), QDialogButtonBox.AcceptRole)
        self.install_button.setToolTip(_('Install the selected plugin'))
        self.install_button.clicked.connect(self._install_clicked)
        self.install_button.setEnabled(False)
        self.configure_button = self.button_box.addButton(' '+_('&Customize plugin ')+' ', QDialogButtonBox.ResetRole)
        self.configure_button.setToolTip(_('Customize the options for this plugin'))
        self.configure_button.clicked.connect(self._configure_clicked)
        self.configure_button.setEnabled(False)
        layout.addWidget(self.button_box)
示例#47
0
class AnnotationsAppearance(SizePersistedDialog):
    '''
    Dialog for managing CSS rules, including Preview window
    '''
    if isosx:
        FONT = QFont('Monaco', 12)
    elif iswindows:
        FONT = QFont('Lucida Console', 9)
    elif islinux:
        FONT = QFont('Monospace', 9)
        FONT.setStyleHint(QFont.TypeWriter)

    def __init__(self, parent, icon, prefs):

        self.parent = parent
        self.prefs = prefs
        self.icon = icon
        super(AnnotationsAppearance, self).__init__(parent,
                                                    'appearance_dialog')
        self.setWindowTitle(_('Modify appearance'))
        self.setWindowIcon(icon)
        self.l = QVBoxLayout(self)
        self.setLayout(self.l)

        # Add a label for description
        #self.description_label = QLabel(_("Descriptive text here"))
        #self.l.addWidget(self.description_label)

        # Add a group box, vertical layout for preview window
        self.preview_gb = QGroupBox(self)
        self.preview_gb.setTitle(_("Preview"))
        self.preview_vl = QVBoxLayout(self.preview_gb)
        self.l.addWidget(self.preview_gb)

        self.wv = QWebView()
        self.wv.setHtml('<p></p>')
        self.wv.setMinimumHeight(100)
        self.wv.setMaximumHeight(16777215)
        self.wv.setGeometry(0, 0, 200, 100)
        self.wv.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
        self.preview_vl.addWidget(self.wv)

        # Create a group box, horizontal layout for the table
        self.css_table_gb = QGroupBox(self)
        self.css_table_gb.setTitle(_("Annotation elements"))
        self.elements_hl = QHBoxLayout(self.css_table_gb)
        self.l.addWidget(self.css_table_gb)

        # Add the group box to the main layout
        self.elements_table = AnnotationElementsTable(
            self, 'annotation_elements_tw')
        self.elements_hl.addWidget(self.elements_table)
        self.elements_table.initialize()

        # Options
        self.options_gb = QGroupBox(self)
        self.options_gb.setTitle(_("Options"))
        self.options_gl = QGridLayout(self.options_gb)
        self.l.addWidget(self.options_gb)
        current_row = 0

        # <hr/> separator
        # addWidget(widget, row, col, rowspan, colspan)
        self.hr_checkbox = QCheckBox(
            _('Add horizontal rule between annotations'))
        self.hr_checkbox.stateChanged.connect(self.hr_checkbox_changed)
        self.hr_checkbox.setCheckState(
            JSONConfig('plugins/annotations').get('appearance_hr_checkbox',
                                                  False))
        self.options_gl.addWidget(self.hr_checkbox, current_row, 0, 1, 4)
        current_row += 1

        # Timestamp
        self.timestamp_fmt_label = QLabel(_("Timestamp format:"))
        self.options_gl.addWidget(self.timestamp_fmt_label, current_row, 0)

        self.timestamp_fmt_le = QLineEdit(
            JSONConfig('plugins/annotations').get(
                'appearance_timestamp_format', default_timestamp),
            parent=self)
        self.timestamp_fmt_le.textEdited.connect(self.timestamp_fmt_changed)
        self.timestamp_fmt_le.setFont(self.FONT)
        self.timestamp_fmt_le.setObjectName('timestamp_fmt_le')
        self.timestamp_fmt_le.setToolTip(_('Format string for timestamp'))
        self.timestamp_fmt_le.setMaximumWidth(16777215)
        self.timestamp_fmt_le.setSizePolicy(QSizePolicy.Expanding,
                                            QSizePolicy.Minimum)
        self.options_gl.addWidget(self.timestamp_fmt_le, current_row, 1)

        self.timestamp_fmt_reset_tb = QToolButton(self)
        self.timestamp_fmt_reset_tb.setToolTip(_("Reset to default"))
        self.timestamp_fmt_reset_tb.setIcon(QIcon(I('trash.png')))
        self.timestamp_fmt_reset_tb.clicked.connect(
            self.reset_timestamp_to_default)
        self.options_gl.addWidget(self.timestamp_fmt_reset_tb, current_row, 2)

        self.timestamp_fmt_help_tb = QToolButton(self)
        self.timestamp_fmt_help_tb.setToolTip(_("Format string reference"))
        self.timestamp_fmt_help_tb.setIcon(QIcon(I('help.png')))
        self.timestamp_fmt_help_tb.clicked.connect(self.show_help)
        self.options_gl.addWidget(self.timestamp_fmt_help_tb, current_row, 3)

        # Button box
        bb = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel)
        bb.accepted.connect(self.accept)
        bb.rejected.connect(self.reject)
        self.l.addWidget(bb)

        # Spacer
        self.spacerItem = QtGui.QSpacerItem(20, 40, QtGui.QSizePolicy.Minimum,
                                            QtGui.QSizePolicy.Expanding)
        self.l.addItem(self.spacerItem)

        # Sizing
        sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Preferred,
                                       QtGui.QSizePolicy.Preferred)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(self.sizePolicy().hasHeightForWidth())
        self.setSizePolicy(sizePolicy)
        self.resize_dialog()

    def hr_checkbox_changed(self, state):
        self.prefs.set('appearance_hr_checkbox', state)
        self.elements_table.preview_css()

    def reset_timestamp_to_default(self):
        from calibre_plugins.annotations.appearance import default_timestamp
        self.timestamp_fmt_le.setText(default_timestamp)
        self.timestamp_fmt_changed()

    def show_help(self):
        '''
        Display strftime help file
        '''
        help_html = get_resources('help/timestamp_formats.html')
        print("1 - %s" % help_html)
        help_html = help_html.decode('utf-8')
        print("2 - %s" % help_html)

        hv = HelpView(self,
                      self.icon,
                      self.prefs,
                      html=help_html,
                      title=_("Timestamp formats"))
        hv.show()

    def sizeHint(self):
        return QtCore.QSize(600, 200)

    def timestamp_fmt_changed(self):
        self.prefs.set('appearance_timestamp_format',
                       str(self.timestamp_fmt_le.text()))
        self.elements_table.preview_css()
示例#48
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)
        # Not sure if the shortcut should be translatable ...
        sc = QShortcut(QKeySequence(_('ALT+f')), parent)
        sc.activated.connect(self.set_focus_to_find_box)

        self.search_button = QToolButton()
        self.search_button.setText(_('F&ind'))
        self.search_button.setToolTip(_('Find the first/next matching item'))
        search_layout.addWidget(self.search_button)

        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)

        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)

        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((_('Sort by name'), _('Sort by number of books'),
                               _('Sort by 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)
示例#49
0
class ConfigWidget(QWidget):
    def __init__(self):
        QWidget.__init__(self)
        self.l = QVBoxLayout()
        self.l.setContentsMargins(0, 0, 0, 0)
        self.setLayout(self.l)

        self.help_msg = QLabel('''
            <h2 style="text-align: center">Get Started</h2>
            <p>
                To start syncing your library you will need to create an account to retrieve<br>
                your API key.
            </p>
        ''')
        self.l.addWidget(self.help_msg)

        self.form = QFormLayout()
        self.form.setFieldGrowthPolicy(QFormLayout.ExpandingFieldsGrow)
        self.l.addLayout(self.form)

        self.link = QLabel('<a href="{0}">{0}</a>'.format(prefs['api_base'] + '/api-key'))
        self.link.setOpenExternalLinks(True)
        self.form.addRow('Visit:', self.link)

        self.api_key = QLineEdit(self)
        self.api_key.setText(prefs['api_key'])
        self.form.addRow('API Key:', self.api_key)

        self.debug = QCheckBox(self)
        self.debug.setChecked(prefs['debug'])
        self.form.addRow('Debug Logging:', self.debug)

        self.update_metadata_layout = QHBoxLayout()
        self.update_metadata_layout.setContentsMargins(0, 0, 0, 0)

        self.update_metadata = QCheckBox(self)
        self.update_metadata.setChecked(prefs['update_metadata'])
        self.update_metadata_layout.addWidget(self.update_metadata)

        self.update_metadata_hint = QLabel('(sync all metadata changes made)')
        self.update_metadata_layout.addWidget(self.update_metadata_hint)

        self.form.addRow('Update Metadata:', self.update_metadata_layout)

        self.threads = QComboBox(self)
        for n in range(3):
            self.threads.addItem(str(pow(2, n)))
        self.threads.setCurrentText(str(prefs['threads']))
        self.form.addRow('Sync Threads:', self.threads)

        self.bookshelves_custom_column = QComboBox(self)
        self.bookshelves_custom_column.addItem('')
        for key, meta in get_current_db().new_api.field_metadata.custom_iteritems():
            if meta['datatype'] == 'text':
                self.bookshelves_custom_column.addItem(key)
        self.bookshelves_custom_column.setCurrentText(prefs['bookshelves_custom_column'])
        self.form.addRow('Bookshelves Column:', self.bookshelves_custom_column)

    def save_settings(self):
        prefs['api_key'] = unicode(self.api_key.text())
        prefs['debug'] = self.debug.isChecked()
        prefs['update_metadata'] = self.update_metadata.isChecked()
        prefs['threads'] = int(self.threads.currentText())
        prefs['bookshelves_custom_column'] = unicode(self.bookshelves_custom_column.currentText())
示例#50
0
    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(_('These settings control the basic features of the plugin.'))
        label.setWordWrap(True)
        self.l.addWidget(label)
        self.l.addSpacing(5)
        
        self.titlenavpoints = QCheckBox(_('Insert Table of Contents entry for each title?'),self)
        self.titlenavpoints.setToolTip(_('''If set, a new TOC entry will be made for each title and
it's existing TOC nested underneath it.'''))
        self.titlenavpoints.setChecked(prefs['titlenavpoints'])
        self.l.addWidget(self.titlenavpoints)

        self.flattentoc = QCheckBox(_('Flatten Table of Contents?'),self)
        self.flattentoc.setToolTip(_('Remove nesting and make TOC all on one level.'))
        self.flattentoc.setChecked(prefs['flattentoc'])
        self.l.addWidget(self.flattentoc)
        
        self.includecomments = QCheckBox(_("Include Books' Comments?"),self)
        self.includecomments.setToolTip(_('''Include all the merged books' comments in the new book's comments.
Default is a list of included titles only.'''))
        self.includecomments.setChecked(prefs['includecomments'])
        self.l.addWidget(self.includecomments)
        
        self.keepmeta = QCheckBox(_('Keep UnMerge Metadata?'),self)
        self.keepmeta.setToolTip(_('''If set, a copy of the original metadata for each merged book will
be included, allowing for UnMerge.  This includes your calibre custom
columns.  Leave off if you plan to distribute the epub to others.'''))
        self.keepmeta.setChecked(prefs['keepmeta'])
        self.l.addWidget(self.keepmeta)

#         self.showunmerge = QCheckBox(_('Show UnMerge Option?'),self)
#         self.showunmerge.setToolTip(_('''If set, the UnMerge Epub option will be shown on the EpubMerge menu.
# Only Epubs merged with 'Keep UnMerge Metadata' can be UnMerged.'''))
#         self.showunmerge.setChecked(prefs['showunmerge'])
#         self.l.addWidget(self.showunmerge)

        horz = QHBoxLayout()
        horz.addWidget(QLabel(_("Add tags to merged books:")))
        
        self.mergetags = QLineEdit(self)
        self.mergetags.setText(prefs['mergetags'])
        self.mergetags.setToolTip(_('Tags you enter here will be added to all new merged books'))
        horz.addWidget(self.mergetags)
        self.l.addLayout(horz)

        horz = QHBoxLayout()
        horz.addWidget(QLabel(_("Merged Book Word:")))
        
        self.mergeword = QLineEdit(self)
        self.mergeword.setText(prefs['mergeword'])
        self.mergeword.setToolTip(_('''Word use to describe merged books in default title and summary.
For people who don't like the word Anthology.'''))
## Defaults back to Anthology if cleared.

        horz.addWidget(self.mergeword)
        self.l.addLayout(horz)

        self.l.addSpacing(15)        

        label = QLabel(_("These controls aren't plugin settings as such, but convenience buttons for setting Keyboard shortcuts and getting all the EpubMerge confirmation dialogs back again."))
        label.setWordWrap(True)
        self.l.addWidget(label)
        self.l.addSpacing(5)
        
        keyboard_shortcuts_button = QPushButton(_('Keyboard shortcuts...'), self)
        keyboard_shortcuts_button.setToolTip(_('Edit the keyboard shortcuts associated with this plugin'))
        keyboard_shortcuts_button.clicked.connect(parent_dialog.edit_shortcuts)
        self.l.addWidget(keyboard_shortcuts_button)

        reset_confirmation_button = QPushButton(_('Reset disabled &confirmation dialogs'), self)
        reset_confirmation_button.setToolTip(_('Reset all show me again dialogs for the EpubMerge plugin'))
        reset_confirmation_button.clicked.connect(self.reset_dialogs)
        self.l.addWidget(reset_confirmation_button)
        
        view_prefs_button = QPushButton(_('View library preferences...'), self)
        view_prefs_button.setToolTip(_('View data stored in the library database for this plugin'))
        view_prefs_button.clicked.connect(self.view_prefs)
        self.l.addWidget(view_prefs_button)
        
        self.l.insertStretch(-1)
示例#51
0
    def __init__(self,
                 gui,
                 header,
                 prefs,
                 icon,
                 books,
                 save_size_name='epubmerge:update list dialog'):
        SizePersistedDialog.__init__(self, gui, save_size_name)
        self.gui = gui

        self.setWindowTitle(header)
        self.setWindowIcon(icon)

        layout = QVBoxLayout(self)
        self.setLayout(layout)
        title_layout = ImageTitleLayout(self, 'images/icon.png', header)
        layout.addLayout(title_layout)
        books_layout = QHBoxLayout()
        layout.addLayout(books_layout)

        self.books_table = StoryListTableWidget(self)
        books_layout.addWidget(self.books_table)

        button_layout = QVBoxLayout()
        books_layout.addLayout(button_layout)
        spacerItem = QtGui.QSpacerItem(20, 40, QtGui.QSizePolicy.Minimum,
                                       QtGui.QSizePolicy.Expanding)
        button_layout.addItem(spacerItem)
        self.move_up_button = QtGui.QToolButton(self)
        self.move_up_button.setToolTip(_('Move selected books up the list'))
        self.move_up_button.setIcon(QIcon(I('arrow-up.png')))
        self.move_up_button.clicked.connect(self.books_table.move_rows_up)
        button_layout.addWidget(self.move_up_button)
        self.remove_button = QtGui.QToolButton(self)
        self.remove_button.setToolTip(_('Remove selected books from the list'))
        self.remove_button.setIcon(get_icon('list_remove.png'))
        self.remove_button.clicked.connect(self.remove_from_list)
        button_layout.addWidget(self.remove_button)
        self.move_down_button = QtGui.QToolButton(self)
        self.move_down_button.setToolTip(
            _('Move selected books down the list'))
        self.move_down_button.setIcon(QIcon(I('arrow-down.png')))
        self.move_down_button.clicked.connect(self.books_table.move_rows_down)
        button_layout.addWidget(self.move_down_button)
        spacerItem1 = QtGui.QSpacerItem(20, 40, QtGui.QSizePolicy.Minimum,
                                        QtGui.QSizePolicy.Expanding)
        button_layout.addItem(spacerItem1)

        options_layout = QHBoxLayout()

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

        layout.addLayout(options_layout)

        # Cause our dialog size to be restored from prefs or created on first usage
        self.resize_dialog()
        self.books_table.populate_table(books)
示例#52
0
class Diff(Dialog):

    revert_requested = pyqtSignal()
    line_activated = pyqtSignal(object, object, object)

    def __init__(self,
                 revert_button_msg=None,
                 parent=None,
                 show_open_in_editor=False,
                 show_as_window=False):
        self.context = 3
        self.beautify = False
        self.apply_diff_calls = []
        self.show_open_in_editor = show_open_in_editor
        self.revert_button_msg = revert_button_msg
        Dialog.__init__(self,
                        _('Differences between books'),
                        'diff-dialog',
                        parent=parent)
        if show_as_window:
            self.setWindowFlags(Qt.Window)
        self.view.line_activated.connect(self.line_activated)

    def sizeHint(self):
        geom = QApplication.instance().desktop().availableGeometry(self)
        return QSize(int(0.9 * geom.width()), int(0.8 * geom.height()))

    def setup_ui(self):
        self.setWindowIcon(QIcon(I('diff.png')))
        self.stacks = st = QStackedLayout(self)
        self.busy = BusyWidget(self)
        self.w = QWidget(self)
        st.addWidget(self.busy), st.addWidget(self.w)

        self.setLayout(st)
        self.l = l = QGridLayout()
        self.w.setLayout(l)

        self.view = v = DiffView(self,
                                 show_open_in_editor=self.show_open_in_editor)
        l.addWidget(v, l.rowCount(), 0, 1, -1)

        r = l.rowCount()
        self.bp = b = QToolButton(self)
        b.setIcon(QIcon(I('back.png')))
        b.clicked.connect(partial(self.view.next_change, -1))
        b.setToolTip(_('Go to previous change') + ' [p]')
        b.setText(_('&Previous change')), b.setToolButtonStyle(
            Qt.ToolButtonTextBesideIcon)
        l.addWidget(b, r, 0)

        self.bn = b = QToolButton(self)
        b.setIcon(QIcon(I('forward.png')))
        b.clicked.connect(partial(self.view.next_change, 1))
        b.setToolTip(_('Go to next change') + ' [n]')
        b.setText(_('&Next change')), b.setToolButtonStyle(
            Qt.ToolButtonTextBesideIcon)
        l.addWidget(b, r, 1)

        self.search = s = HistoryLineEdit2(self)
        s.initialize('diff_search_history')
        l.addWidget(s, r, 2)
        s.setPlaceholderText(_('Search for text'))
        s.returnPressed.connect(partial(self.do_search, False))
        self.sbn = b = QToolButton(self)
        b.setIcon(QIcon(I('arrow-down.png')))
        b.clicked.connect(partial(self.do_search, False))
        b.setToolTip(_('Find next match'))
        b.setText(_('Next &match')), b.setToolButtonStyle(
            Qt.ToolButtonTextBesideIcon)
        l.addWidget(b, r, 3)
        self.sbp = b = QToolButton(self)
        b.setIcon(QIcon(I('arrow-up.png')))
        b.clicked.connect(partial(self.do_search, True))
        b.setToolTip(_('Find previous match'))
        b.setText(_('P&revious match')), b.setToolButtonStyle(
            Qt.ToolButtonTextBesideIcon)
        l.addWidget(b, r, 4)
        self.lb = b = QRadioButton(_('Left panel'), self)
        b.setToolTip(_('Perform search in the left panel'))
        l.addWidget(b, r, 5)
        self.rb = b = QRadioButton(_('Right panel'), self)
        b.setToolTip(_('Perform search in the right panel'))
        l.addWidget(b, r, 6)
        b.setChecked(True)
        self.pb = b = QToolButton(self)
        b.setIcon(QIcon(I('config.png')))
        b.setText(_('&Options')), b.setToolButtonStyle(
            Qt.ToolButtonTextBesideIcon)
        b.setToolTip(_('Change how the differences are displayed'))
        b.setPopupMode(b.InstantPopup)
        m = QMenu(b)
        b.setMenu(m)
        cm = self.cm = QMenu(_('Lines of context around each change'))
        for i in (3, 5, 10, 50):
            cm.addAction(
                _('Show %d lines of context') % i,
                partial(self.change_context, i))
        cm.addAction(_('Show all text'), partial(self.change_context, None))
        self.beautify_action = m.addAction('', self.toggle_beautify)
        self.set_beautify_action_text()
        m.addMenu(cm)
        l.addWidget(b, r, 7)

        self.hl = QHBoxLayout()
        l.addLayout(self.hl, l.rowCount(), 0, 1, -1)
        self.names = QLabel('')
        self.hl.addWidget(self.names, r)

        self.bb.setStandardButtons(self.bb.Close)
        if self.revert_button_msg is not None:
            self.rvb = b = self.bb.addButton(self.revert_button_msg,
                                             self.bb.ActionRole)
            b.setIcon(QIcon(I('edit-undo.png'))), b.setAutoDefault(False)
            b.clicked.connect(self.revert_requested)
            b.clicked.connect(self.reject)
        self.bb.button(self.bb.Close).setDefault(True)
        self.hl.addWidget(self.bb, r)

        self.view.setFocus(Qt.OtherFocusReason)

    def break_cycles(self):
        self.view = None
        for x in ('revert_requested', 'line_activated'):
            try:
                getattr(self, x).disconnect()
            except:
                pass

    def do_search(self, reverse):
        text = unicode(self.search.text())
        if not text.strip():
            return
        v = self.view.view.left if self.lb.isChecked(
        ) else self.view.view.right
        v.search(text, reverse=reverse)

    def change_context(self, context):
        if context == self.context:
            return
        self.context = context
        self.refresh()

    def refresh(self):
        with self:
            self.view.clear()
            for args, kwargs in self.apply_diff_calls:
                kwargs['context'] = self.context
                kwargs['beautify'] = self.beautify
                self.view.add_diff(*args, **kwargs)
            self.view.finalize()

    def toggle_beautify(self):
        self.beautify = not self.beautify
        self.set_beautify_action_text()
        self.refresh()

    def set_beautify_action_text(self):
        self.beautify_action.setText(
            _('Beautify files before comparing them') if not self.beautify else
            _('Do not beautify files before comparing'))

    def __enter__(self):
        self.stacks.setCurrentIndex(0)
        self.busy.pi.startAnimation()
        QApplication.setOverrideCursor(QCursor(Qt.WaitCursor))
        QApplication.processEvents(QEventLoop.ExcludeUserInputEvents
                                   | QEventLoop.ExcludeSocketNotifiers)

    def __exit__(self, *args):
        self.busy.pi.stopAnimation()
        self.stacks.setCurrentIndex(1)
        QApplication.restoreOverrideCursor()

    def set_names(self, names):
        if isinstance(names, tuple):
            self.names.setText('%s <--> %s' % names)
        else:
            self.names.setText('')

    def ebook_diff(self, path1, path2, names=None):
        self.set_names(names)
        with self:
            identical = self.apply_diff(_('The books are identical'),
                                        *ebook_diff(path1, path2))
            self.view.finalize()
        if identical:
            self.reject()

    def container_diff(self, left, right, identical_msg=None, names=None):
        self.set_names(names)
        with self:
            identical = self.apply_diff(identical_msg or _('No changes found'),
                                        *container_diff(left, right))
            self.view.finalize()
        if identical:
            self.reject()

    def file_diff(self, left, right, identical_msg=None):
        with self:
            identical = self.apply_diff(
                identical_msg or _('The files are identical'),
                *file_diff(left, right))
            self.view.finalize()
        if identical:
            self.reject()

    def dir_diff(self, left, right, identical_msg=None):
        with self:
            identical = self.apply_diff(
                identical_msg or _('The directories are identical'),
                *dir_diff(left, right))
            self.view.finalize()
        if identical:
            self.reject()

    def apply_diff(self, identical_msg, cache, syntax_map, changed_names,
                   renamed_names, removed_names, added_names):
        self.view.clear()
        self.apply_diff_calls = calls = []

        def add(args, kwargs):
            self.view.add_diff(*args, **kwargs)
            calls.append((args, kwargs))

        if len(changed_names) + len(renamed_names) + len(removed_names) + len(
                added_names) < 1:
            info_dialog(self, _('No changes found'), identical_msg, show=True)
            return True

        kwargs = lambda name: {
            'context': self.context,
            'beautify': self.beautify,
            'syntax': syntax_map.get(name, None)
        }

        if isinstance(changed_names, dict):
            for name, other_name in sorted(
                    changed_names.iteritems(),
                    key=lambda x: numeric_sort_key(x[0])):
                args = (name, other_name, cache.left(name),
                        cache.right(other_name))
                add(args, kwargs(name))
        else:
            for name in sorted(changed_names, key=numeric_sort_key):
                args = (name, name, cache.left(name), cache.right(name))
                add(args, kwargs(name))

        for name in sorted(added_names, key=numeric_sort_key):
            args = (_('[%s was added]') % name, name, None, cache.right(name))
            add(args, kwargs(name))

        for name in sorted(removed_names, key=numeric_sort_key):
            args = (name, _('[%s was removed]') % name, cache.left(name), None)
            add(args, kwargs(name))

        for name, new_name in sorted(renamed_names.iteritems(),
                                     key=lambda x: numeric_sort_key(x[0])):
            args = (name, new_name, None, None)
            add(args, kwargs(name))

    def keyPressEvent(self, ev):
        if not self.view.handle_key(ev):
            if ev.key() in (Qt.Key_Enter, Qt.Key_Return):
                return  # The enter key is used by the search box, so prevent it closing the dialog
            if ev.key() == Qt.Key_Slash:
                return self.search.setFocus(Qt.OtherFocusReason)
            if ev.matches(QKeySequence.Copy):
                text = self.view.view.left.selected_text + self.view.view.right.selected_text
                if text:
                    QApplication.clipboard().setText(text)
                return
            if ev.matches(QKeySequence.FindNext):
                self.sbn.click()
                return
            if ev.matches(QKeySequence.FindPrevious):
                self.sbp.click()
                return
            return Dialog.keyPressEvent(self, ev)
示例#53
0
    def __init__(self, parent):
        QWidget.__init__(self, parent)
        self.l = l = QGridLayout(self)
        l.setContentsMargins(0, 0, 0, 0)
        self.setLayout(l)

        self.bookmarks_list = bl = BookmarksList(self)
        bl.itemChanged.connect(self.item_changed)
        l.addWidget(bl, 0, 0, 1, -1)
        bl.itemClicked.connect(self.item_activated)
        bl.bookmark_activated.connect(self.item_activated)
        bl.changed.connect(lambda: self.edited.emit(self.get_bookmarks()))
        bl.ac_edit.triggered.connect(self.edit_bookmark)
        bl.ac_delete.triggered.connect(self.delete_bookmark)

        self.la = la = QLabel(_('Double click to edit the bookmarks'))
        la.setWordWrap(True)
        l.addWidget(la, l.rowCount(), 0, 1, -1)

        self.button_new = b = QPushButton(QIcon(I('bookmarks.png')), _('&New'),
                                          self)
        b.clicked.connect(self.create_requested)
        b.setToolTip(_('Create a new bookmark at the current location'))
        l.addWidget(b)

        self.button_delete = b = QPushButton(QIcon(I('trash.png')),
                                             _('&Remove'), self)
        b.setToolTip(_('Remove the currently selected bookmark'))
        b.clicked.connect(self.delete_bookmark)
        l.addWidget(b, l.rowCount() - 1, 1)

        self.button_prev = b = QPushButton(QIcon(I('back.png')),
                                           _('P&revious'), self)
        b.clicked.connect(self.bookmarks_list.previous_bookmark)
        l.addWidget(b)

        self.button_next = b = QPushButton(QIcon(I('forward.png')), _('Nex&t'),
                                           self)
        b.clicked.connect(self.bookmarks_list.next_bookmark)
        l.addWidget(b, l.rowCount() - 1, 1)

        la = QLabel(_('&Sort by:'))
        self.sort_by = sb = QComboBox(self)
        la.setBuddy(sb)
        sb.addItem(_('Title'), 'title')
        sb.addItem(_('Position in book'), 'pos')
        sb.addItem(_('Date'), 'timestamp')
        sb.setToolTip(_('Change how the bookmarks are sorted'))
        i = sb.findData(vprefs['bookmarks_sort'])
        if i > -1:
            sb.setCurrentIndex(i)
        h = QHBoxLayout()
        h.addWidget(la), h.addWidget(sb, 10)
        l.addLayout(h, l.rowCount(), 0, 1, 2)
        sb.currentIndexChanged.connect(self.sort_by_changed)

        self.button_export = b = QPushButton(_('E&xport'), self)
        b.clicked.connect(self.export_bookmarks)
        l.addWidget(b, l.rowCount(), 0)

        self.button_import = b = QPushButton(_('&Import'), self)
        b.clicked.connect(self.import_bookmarks)
        l.addWidget(b, l.rowCount() - 1, 1)
示例#54
0
class ConfigWidget(QWidget):

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

        self.ll = QHBoxLayout()
        self.l.addLayout(self.ll)

        self.label_exe = QLabel(_('&Prince executable:'))
        self.ll.addWidget(self.label_exe)

        self.exe = QLineEdit(self)
        self.exe.setText(prefs['prince_exe'])
        self.exe.setToolTip(
            _('<qt>Executable for the Prince program (command-line interface)</qt>'
              ))
        self.ll.addWidget(self.exe)
        self.label_exe.setBuddy(self.exe)

        self.browse = QPushButton(_('&Browse') + '...', self)
        self.browse.setToolTip(
            _('<qt>Search the Prince executable in your computer</qt>'))
        self.browse.clicked.connect(self.select_exe)
        self.ll.addWidget(self.browse)

        self.lll = QHBoxLayout()
        self.l.addLayout(self.lll)

        self.label_fmts = QLabel(_('Preferred &formats:'))
        self.lll.addWidget(self.label_fmts)

        self.fmts = QLineEdit(self)
        self.fmts.setText(','.join(prefs['formats']))
        self.fmts.setToolTip(
            _('<qt>Comma-separated list of preferred formats to use as source, the first that matches will be used</qt>'
              ))
        self.lll.addWidget(self.fmts)
        self.label_fmts.setBuddy(self.fmts)

        self.add_book = QCheckBox(_('&Add PDF to the book record'))
        self.add_book.setToolTip(
            _('<qt>Add the converted PDF to the selected book record</qt>'))
        self.add_book.setChecked(prefs['add_book'])
        self.l.addWidget(self.add_book)

        self.show_css = QCheckBox(_('&Show CSS in the Convert dialog'))
        self.show_css.setToolTip(
            _('<qt>Show by default the styles in the Convert dialog</qt>'))
        self.show_css.setChecked(prefs['show_CSS'])
        self.l.addWidget(self.show_css)

        self.css_layout = QVBoxLayout()

        self.llll = QHBoxLayout()
        self.css_layout.addLayout(self.llll)

        self.css_list = QComboBox()
        self.css_list.setToolTip(
            _('<qt>List of custom styles defined. Select one to edit</qt>'))
        self.css_list.setSizeAdjustPolicy(QComboBox.AdjustToContents)
        self.CSS_list = prefs['custom_CSS_list'].copy()
        self.default_CSS = prefs['default_CSS']
        if 'custom_CSS' in prefs:
            self.CSS_list[_('old')] = prefs['custom_CSS']
            self.default_CSS = _('old')
        if self.default_CSS not in self.CSS_list:
            self.default_CSS = sorted(self.CSS_list,
                                      key=lambda x: x.lower())[0]
        for key in sorted(self.CSS_list, key=lambda x: x.lower()):
            self.css_list.addItem(key, key)
        self.css_list.setCurrentIndex(self.css_list.findText(self.default_CSS))
        self.css_list.currentIndexChanged.connect(self.set_css)
        self.llll.addWidget(self.css_list)

        self.css_rename = QPushButton(_('Re&name'))
        self.css_rename.setToolTip(
            _('<qt>Rename the current style to the name on the right</qt>'))
        self.css_rename.clicked.connect(self.rename_css)
        self.css_rename.setEnabled(False)
        self.llll.addWidget(self.css_rename)

        self.css_name = QLineEdit(self)
        self.css_name.setToolTip(
            _('<qt>Name for the new or renamed style</qt>'))
        self.css_name.setText(self.css_list.currentText())
        self.css_name.textChanged.connect(self.check_names)
        self.llll.addWidget(self.css_name)

        self.css_add = QPushButton(_('A&dd'))
        self.css_add.setToolTip(
            _('<qt>Add a new empty style with the name on the left</qt>'))
        self.css_add.clicked.connect(self.add_css)
        self.css_add.setEnabled(False)
        self.llll.addWidget(self.css_add)

        self.css_remove = QPushButton(_('Re&move'))
        self.css_remove.setToolTip(_('<qt>Remove the current style</qt>'))
        self.css_remove.clicked.connect(self.remove_css)
        self.llll.addWidget(self.css_remove)

        self.llll_ = QHBoxLayout()
        self.css_layout.addLayout(self.llll_)

        self.label_args = QLabel(_('Addi&tional command-line arguments:'))
        self.llll_.addWidget(self.label_args)

        self.args = QLineEdit(self)
        # Make sure custom_CSS_list and custom_args_list have the same keys
        if 'custom_args_list' in prefs:
            self.args_list = prefs['custom_args_list'].copy()
        else:
            self.args_list = {}
        for key in self.CSS_list:
            if not key in self.args_list:
                self.args_list[key] = ''
        for key in self.args_list:
            if not key in self.CSS_list:
                del self.args_list[key]
        self.args.setText(self.args_list[unicode(self.css_list.currentText())])
        self.args.setToolTip(
            _('<qt>Additional command-line arguments used in conversions with this style</qt>'
              ))
        self.llll_.addWidget(self.args)
        self.label_args.setBuddy(self.args)

        self.css = TextEditWithTooltip(self, expected_geometry=(80, 20))
        self.css.setLineWrapMode(TextEditWithTooltip.NoWrap)
        self.css.load_text(self.CSS_list[unicode(self.css_list.currentText())],
                           'css')
        self.css.setToolTip(
            _('<qt>Custom stylesheet that will be applied, if selected, to all Prince PDF conversions</qt>'
              ))
        self.css_layout.addWidget(self.css)

        self.css_templates = QLabel(_('Book metadata can be used in the stylesheet. Anything between %(s1)s and %(s2)s will be processed as a calibre template. For instance, %(s3)s in the stylesheet will be replaced with the book title in the conversion.') % \
          {'s1':'<span style="font-family:monospace ; font-weight:bold">@{@</span>', \
           's2':'<span style="font-family:monospace ; font-weight:bold">@}@</span>', \
           's3':'<span style="font-family:monospace ; font-weight:bold">@{@{title}@}@</span>'})
        self.css_templates.setWordWrap(True)
        self.css_layout.addWidget(self.css_templates)

        self.css_box = QGroupBox(_('&Custom styles:'))
        self.css_box.setLayout(self.css_layout)
        self.l.addWidget(self.css_box)

        self.lllll = QHBoxLayout()
        self.lllll.setAlignment(Qt.AlignLeft)
        self.l.addLayout(self.lllll)

        self.defaults = QPushButton(_('&Restore defaults'))
        self.defaults.setToolTip(_('<qt>Restore the default settings</qt>'))
        self.defaults.clicked.connect(self.restore_defaults)
        self.lllll.addWidget(self.defaults, alignment=Qt.AlignLeft)

        self.warning = QLabel(_('<b>Warning</b>: Deletes modified styles'))
        self.lllll.addWidget(self.warning)

        self.adjustSize()

    def select_exe(self):
        '''
        Create a dialog to select the Prince executable
        '''
        dialog = QFileDialog()
        dialog.setFileMode(QFileDialog.ExistingFile)
        filename = dialog.getOpenFileName(self, _('Select Prince executable'),
                                          '', '')
        if filename:
            try:
                self.exe.setText(filename)
            except (TypeError):
                self.exe.setText(filename[0])

    def restore_defaults(self):
        '''
        Restore the default settings
        '''
        self.exe.setText(prefs.defaults['prince_exe'])
        self.fmts.setText(','.join(prefs.defaults['formats']).lower())
        self.show_css.setChecked(prefs.defaults['show_CSS'])
        self.add_book.setChecked(prefs.defaults['add_book'])
        self.css_list.currentIndexChanged.disconnect()
        self.css_list.clear()
        self.CSS_list = prefs.defaults['custom_CSS_list'].copy()
        self.args_list = prefs.defaults['custom_args_list'].copy()
        self.default_CSS = prefs.defaults['default_CSS']
        for key in sorted(self.CSS_list, key=lambda x: x.lower()):
            self.css_list.addItem(key, key)
        self.css_list.setCurrentIndex(self.css_list.findText(self.default_CSS))
        self.css_name.setText(self.default_CSS)
        self.css.load_text(self.CSS_list[unicode(self.css_list.currentText())],
                           'css')
        self.args.setText(self.args_list[unicode(self.css_list.currentText())])
        self.css_list.currentIndexChanged.connect(self.set_css)

    def save_settings(self):
        '''
        Save the current settings
        '''
        prefs['prince_exe'] = unicode(self.exe.text())
        prefs['formats'] = unicode(self.fmts.text().lower()).split(',')
        prefs['show_CSS'] = self.show_css.isChecked()
        prefs['add_book'] = self.add_book.isChecked()
        self.set_css()
        prefs['default_CSS'] = self.default_CSS
        prefs['custom_CSS_list'] = self.CSS_list.copy()
        prefs['custom_args_list'] = self.args_list.copy()
        if 'custom_CSS' in prefs:
            del prefs['custom_CSS']

    def set_css(self):
        '''
        Fill the CSS text box with the selected stylesheet, and similarly for command-line arguments
        '''
        self.CSS_list[self.default_CSS] = unicode(self.css.toPlainText())
        self.args_list[self.default_CSS] = unicode(self.args.text())
        self.default_CSS = unicode(self.css_list.currentText())
        self.css.load_text(self.CSS_list[self.default_CSS], 'css')
        self.args.setText(self.args_list[self.default_CSS])
        self.css_name.setText(self.css_list.currentText())

    def add_css(self):
        '''
        Add a new style
        '''
        from calibre.gui2 import error_dialog

        name = unicode(self.css_name.text())
        if name in self.CSS_list:
            error_dialog(
                self,
                _('Cannot add style'),
                _('A style with the name "%s" is already defined, use a different name.'
                  ) % name,
                show=True)
        else:
            self.CSS_list[name] = ''
            self.args_list[name] = ''
            self.css_list.addItem(name, name)
            self.css_list.setCurrentIndex(self.css_list.findText(name))
            self.css_add.setEnabled(False)
            self.css_rename.setEnabled(False)

    def remove_css(self):
        '''
        Remove an existing style
        '''
        from calibre.gui2 import error_dialog

        if (self.css_list.count() > 1):
            self.css_list.currentIndexChanged.disconnect()
            self.css_list.removeItem(self.css_list.currentIndex())
            del self.CSS_list[self.default_CSS]
            del self.args_list[self.default_CSS]
            self.default_CSS = unicode(self.css_list.currentText())
            self.css.load_text(self.CSS_list[self.default_CSS], 'css')
            self.args.setText(self.args_list[self.default_CSS])
            self.css_list.currentIndexChanged.connect(self.set_css)
            self.css_name.setText(self.css_list.currentText())
        else:
            error_dialog(
                self,
                _('Cannot delete the last style'),
                _('The last style cannot be removed. You can rename it and/or remove its contents.'
                  ),
                show=True)

    def rename_css(self):
        '''
        Rename a style
        '''
        from calibre.gui2 import error_dialog

        name = unicode(self.css_name.text())
        if name in self.CSS_list:
            error_dialog(
                self,
                _('Cannot rename style'),
                _('A style with the name "%s" is already defined, use a different name.'
                  ) % name,
                show=True)
        else:
            self.CSS_list[name] = self.CSS_list.pop(self.default_CSS)
            self.args_list[name] = self.args_list.pop(self.default_CSS)
            self.css_list.setItemText(self.css_list.currentIndex(), name)
            self.default_CSS = name

    def check_names(self, text):
        name = unicode(text)
        if name in self.CSS_list:
            self.css_add.setEnabled(False)
            self.css_rename.setEnabled(False)
        else:
            self.css_add.setEnabled(True)
            self.css_rename.setEnabled(True)
    def __init__(self, parent, books, list_name):
        SizePersistedDialog.__init__(self, parent,
                                     'reading list plugin:edit list dialog')
        self.setWindowTitle('Edit List')
        layout = QVBoxLayout(self)
        self.setLayout(layout)
        title_layout = ImageTitleLayout(self, 'images/reading_list.png',
                                        '\'%s\' list books' % list_name)
        layout.addLayout(title_layout)
        books_layout = QHBoxLayout()
        layout.addLayout(books_layout)

        self.books_table = EditListTableWidget(self)
        books_layout.addWidget(self.books_table)

        button_layout = QVBoxLayout()
        books_layout.addLayout(button_layout)

        # move to top button
        self.move_top_button = QtGui.QToolButton(self)
        self.move_top_button.setToolTip(
            'Move selected books to the top of the list')
        self.move_top_button.setIcon(
            get_icon('images/arrow_up_double_bar.png'))
        self.move_top_button.clicked.connect(self.books_table.move_to_top)
        button_layout.addWidget(self.move_top_button)
        # move up 10 rows button
        self.move_10_up_button = QtGui.QToolButton(self)
        self.move_10_up_button.setToolTip(
            'Move selected books 10 rows up the list')
        self.move_10_up_button.setIcon(get_icon('images/arrow_up_double.png'))
        self.move_10_up_button.clicked.connect(
            self.books_table.move_10_rows_up)
        button_layout.addWidget(self.move_10_up_button)
        # move up one row button
        self.move_up_button = QtGui.QToolButton(self)
        self.move_up_button.setToolTip('Move selected books up the list')
        self.move_up_button.setIcon(get_icon('images/arrow_up_single.png'))
        self.move_up_button.clicked.connect(self.books_table.move_rows_up)
        button_layout.addWidget(self.move_up_button)

        spacerItem = QtGui.QSpacerItem(20, 40, QtGui.QSizePolicy.Minimum,
                                       QtGui.QSizePolicy.Expanding)
        button_layout.addItem(spacerItem)

        # remove from list button
        self.remove_button = QtGui.QToolButton(self)
        self.remove_button.setToolTip('Remove selected books from the list')
        self.remove_button.setIcon(get_icon('list_remove.png'))
        self.remove_button.clicked.connect(self.remove_from_list)
        button_layout.addWidget(self.remove_button)
        spacerItem1 = QtGui.QSpacerItem(20, 40, QtGui.QSizePolicy.Minimum,
                                        QtGui.QSizePolicy.Expanding)

        # move down one row button
        button_layout.addItem(spacerItem1)
        self.move_down_button = QtGui.QToolButton(self)
        self.move_down_button.setToolTip('Move selected books down the list')
        self.move_down_button.setIcon(get_icon('images/arrow_down_single.png'))
        self.move_down_button.clicked.connect(self.books_table.move_rows_down)
        button_layout.addWidget(self.move_down_button)
        # move down 10 rows button
        self.move_10_down_button = QtGui.QToolButton(self)
        self.move_10_down_button.setToolTip(
            'Move selected books 10 rows down the list')
        #self.move_10_down_button.setIcon(QIcon(I('arrow-down.png')))
        self.move_10_down_button.setIcon(
            get_icon('images/arrow_down_double.png'))
        self.move_10_down_button.clicked.connect(
            self.books_table.move_10_rows_down)
        button_layout.addWidget(self.move_10_down_button)
        # move to bottom button
        self.move_bottom_button = QtGui.QToolButton(self)
        self.move_bottom_button.setToolTip(
            'Move selected books to the bottom of the list')
        #self.move_bottom_button.setIcon(QIcon(I('arrow-down.png')))
        self.move_bottom_button.setIcon(
            get_icon('images/arrow_down_double_bar.png'))
        self.move_bottom_button.clicked.connect(
            self.books_table.move_to_bottom)
        button_layout.addWidget(self.move_bottom_button)

        button_box = QDialogButtonBox(QDialogButtonBox.Ok
                                      | QDialogButtonBox.Cancel)
        button_box.accepted.connect(self.accept)
        button_box.rejected.connect(self.reject)
        layout.addWidget(button_box)
        # Cause our dialog size to be restored from prefs or created on first usage
        self.resize_dialog()
        self.books_table.populate_table(books)
示例#56
0
class Config(QDialog):
    '''
    Configuration dialog for single book conversion. If accepted, has the
    following important attributes

    output_format - Output format (without a leading .)
    input_format  - Input format (without a leading .)
    opf_path - Path to OPF file with user specified metadata
    cover_path - Path to user specified cover (can be None)
    recommendations - A pickled list of 3 tuples in the same format as the
    recommendations member of the Input/Output plugins.
    '''
    def __init__(self,
                 parent,
                 db,
                 book_id,
                 preferred_input_format=None,
                 preferred_output_format=None):
        QDialog.__init__(self, parent)
        self.widgets = []
        self.setupUi()
        self.opt_individual_saved_settings.setVisible(False)
        self.db, self.book_id = db, book_id

        self.setup_input_output_formats(self.db, self.book_id,
                                        preferred_input_format,
                                        preferred_output_format)
        self.setup_pipeline()

        self.input_formats.currentIndexChanged[native_string_type].connect(
            self.setup_pipeline)
        self.output_formats.currentIndexChanged[native_string_type].connect(
            self.setup_pipeline)
        self.groups.setSpacing(5)
        self.groups.activated[(QModelIndex)].connect(self.show_pane)
        self.groups.clicked[(QModelIndex)].connect(self.show_pane)
        self.groups.entered[(QModelIndex)].connect(self.show_group_help)
        rb = self.buttonBox.button(self.buttonBox.RestoreDefaults)
        rb.setText(_('Restore &defaults'))
        rb.clicked.connect(self.restore_defaults)
        self.groups.setMouseTracking(True)
        geom = gprefs.get('convert_single_dialog_geom', None)
        if geom:
            QApplication.instance().safe_restore_geometry(self, geom)
        else:
            self.resize(self.sizeHint())

    def setupUi(self):
        self.setObjectName("Dialog")
        self.resize(1024, 700)
        self.setWindowIcon(QIcon(I('convert.png')))
        self.gridLayout = QGridLayout(self)
        self.gridLayout.setObjectName("gridLayout")
        self.horizontalLayout = QHBoxLayout()
        self.horizontalLayout.setObjectName("horizontalLayout")
        self.input_label = QLabel(self)
        self.input_label.setObjectName("input_label")
        self.horizontalLayout.addWidget(self.input_label)
        self.input_formats = QComboBox(self)
        self.input_formats.setSizeAdjustPolicy(
            QComboBox.AdjustToMinimumContentsLengthWithIcon)
        self.input_formats.setMinimumContentsLength(5)
        self.input_formats.setObjectName("input_formats")
        self.horizontalLayout.addWidget(self.input_formats)
        self.opt_individual_saved_settings = QCheckBox(self)
        self.opt_individual_saved_settings.setObjectName(
            "opt_individual_saved_settings")
        self.horizontalLayout.addWidget(self.opt_individual_saved_settings)
        spacerItem = QSpacerItem(40, 20, QSizePolicy.Expanding,
                                 QSizePolicy.Minimum)
        self.horizontalLayout.addItem(spacerItem)
        self.label_2 = QLabel(self)
        self.label_2.setObjectName("label_2")
        self.horizontalLayout.addWidget(self.label_2)
        self.output_formats = QComboBox(self)
        self.output_formats.setSizeAdjustPolicy(
            QComboBox.AdjustToMinimumContentsLengthWithIcon)
        self.output_formats.setMinimumContentsLength(5)
        self.output_formats.setObjectName("output_formats")
        self.horizontalLayout.addWidget(self.output_formats)
        self.gridLayout.addLayout(self.horizontalLayout, 0, 0, 1, 2)
        self.groups = QListView(self)
        sizePolicy = QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
        sizePolicy.setHorizontalStretch(1)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(
            self.groups.sizePolicy().hasHeightForWidth())
        self.groups.setSizePolicy(sizePolicy)
        self.groups.setTabKeyNavigation(True)
        self.groups.setIconSize(QSize(48, 48))
        self.groups.setWordWrap(True)
        self.groups.setObjectName("groups")
        self.gridLayout.addWidget(self.groups, 1, 0, 3, 1)
        self.scrollArea = QScrollArea(self)
        sizePolicy = QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
        sizePolicy.setHorizontalStretch(4)
        sizePolicy.setVerticalStretch(10)
        sizePolicy.setHeightForWidth(
            self.scrollArea.sizePolicy().hasHeightForWidth())
        self.scrollArea.setSizePolicy(sizePolicy)
        self.scrollArea.setFrameShape(QFrame.NoFrame)
        self.scrollArea.setLineWidth(0)
        self.scrollArea.setWidgetResizable(True)
        self.scrollArea.setObjectName("scrollArea")
        self.page = QWidget()
        self.page.setObjectName("page")
        self.gridLayout.addWidget(self.scrollArea, 1, 1, 1, 1)
        self.buttonBox = QDialogButtonBox(self)
        self.buttonBox.setOrientation(Qt.Horizontal)
        self.buttonBox.setStandardButtons(QDialogButtonBox.Cancel
                                          | QDialogButtonBox.Ok
                                          | QDialogButtonBox.RestoreDefaults)
        self.buttonBox.setObjectName("buttonBox")
        self.gridLayout.addWidget(self.buttonBox, 3, 1, 1, 1)
        self.help = QTextEdit(self)
        sizePolicy = QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(
            self.help.sizePolicy().hasHeightForWidth())
        self.help.setSizePolicy(sizePolicy)
        self.help.setMaximumHeight(80)
        self.help.setObjectName("help")
        self.gridLayout.addWidget(self.help, 2, 1, 1, 1)
        self.input_label.setBuddy(self.input_formats)
        self.label_2.setBuddy(self.output_formats)
        self.input_label.setText(_("&Input format:"))
        self.opt_individual_saved_settings.setText(
            _("Use &saved conversion settings for individual books"))
        self.label_2.setText(_("&Output format:"))

        self.buttonBox.accepted.connect(self.accept)
        self.buttonBox.rejected.connect(self.reject)

    def sizeHint(self):
        desktop = QCoreApplication.instance().desktop()
        geom = desktop.availableGeometry(self)
        nh, nw = max(300, geom.height() - 100), max(400, geom.width() - 70)
        return QSize(nw, nh)

    def restore_defaults(self):
        delete_specifics(self.db, self.book_id)
        self.setup_pipeline()

    @property
    def input_format(self):
        return unicode_type(self.input_formats.currentText()).lower()

    @property
    def output_format(self):
        return unicode_type(self.output_formats.currentText()).lower()

    @property
    def manually_fine_tune_toc(self):
        for w in self.widgets:
            if hasattr(w, 'manually_fine_tune_toc'):
                return w.manually_fine_tune_toc.isChecked()

    def setup_pipeline(self, *args):
        oidx = self.groups.currentIndex().row()
        input_format = self.input_format
        output_format = self.output_format
        self.plumber = create_dummy_plumber(input_format, output_format)

        def widget_factory(cls):
            return cls(self, self.plumber.get_option_by_name,
                       self.plumber.get_option_help, self.db, self.book_id)

        self.mw = widget_factory(MetadataWidget)
        self.setWindowTitle(
            _('Convert') + ' ' + unicode_type(self.mw.title.text()))
        lf = widget_factory(LookAndFeelWidget)
        hw = widget_factory(HeuristicsWidget)
        sr = widget_factory(SearchAndReplaceWidget)
        ps = widget_factory(PageSetupWidget)
        sd = widget_factory(StructureDetectionWidget)
        toc = widget_factory(TOCWidget)
        from calibre.gui2.actions.toc_edit import SUPPORTED
        toc.manually_fine_tune_toc.setVisible(
            output_format.upper() in SUPPORTED)
        debug = widget_factory(DebugWidget)

        output_widget = self.plumber.output_plugin.gui_configuration_widget(
            self, self.plumber.get_option_by_name,
            self.plumber.get_option_help, self.db, self.book_id)
        input_widget = self.plumber.input_plugin.gui_configuration_widget(
            self, self.plumber.get_option_by_name,
            self.plumber.get_option_help, self.db, self.book_id)

        self.break_cycles()
        self.widgets = widgets = [self.mw, lf, hw, ps, sd, toc, sr]
        if input_widget is not None:
            widgets.append(input_widget)
        if output_widget is not None:
            widgets.append(output_widget)
        widgets.append(debug)
        for w in widgets:
            w.set_help_signal.connect(self.help.setPlainText)
            w.setVisible(False)

        self._groups_model = GroupModel(widgets)
        self.groups.setModel(self._groups_model)

        idx = oidx if -1 < oidx < self._groups_model.rowCount() else 0
        self.groups.setCurrentIndex(self._groups_model.index(idx))
        self.show_pane(idx)
        try:
            shutil.rmtree(self.plumber.archive_input_tdir, ignore_errors=True)
        except Exception:
            pass

    def setup_input_output_formats(self, db, book_id, preferred_input_format,
                                   preferred_output_format):
        if preferred_output_format:
            preferred_output_format = preferred_output_format.upper()
        output_formats = get_output_formats(preferred_output_format)
        input_format, input_formats = get_input_format_for_book(
            db, book_id, preferred_input_format)
        preferred_output_format = preferred_output_format if \
            preferred_output_format in output_formats else \
            sort_formats_by_preference(output_formats,
                    [prefs['output_format']])[0]
        self.input_formats.addItems(
            (unicode_type(x.upper()) for x in input_formats))
        self.output_formats.addItems(
            (unicode_type(x.upper()) for x in output_formats))
        self.input_formats.setCurrentIndex(input_formats.index(input_format))
        self.output_formats.setCurrentIndex(
            output_formats.index(preferred_output_format))

    def show_pane(self, index):
        if hasattr(index, 'row'):
            index = index.row()
        ow = self.scrollArea.takeWidget()
        if ow:
            ow.setParent(self)
        for i, w in enumerate(self.widgets):
            if i == index:
                self.scrollArea.setWidget(w)
                w.show()
            else:
                w.setVisible(False)

    def accept(self):
        recs = GuiRecommendations()
        for w in self._groups_model.widgets:
            if not w.pre_commit_check():
                return
            x = w.commit(save_defaults=False)
            recs.update(x)
        self.opf_file, self.cover_file = self.mw.opf_file, self.mw.cover_file
        self._recommendations = recs
        if self.db is not None:
            recs['gui_preferred_input_format'] = self.input_format
            save_specifics(self.db, self.book_id, recs)
        self.break_cycles()
        QDialog.accept(self)

    def reject(self):
        self.break_cycles()
        QDialog.reject(self)

    def done(self, r):
        if self.isVisible():
            gprefs['convert_single_dialog_geom'] = \
                bytearray(self.saveGeometry())
        return QDialog.done(self, r)

    def break_cycles(self):
        for w in self.widgets:
            w.break_cycles()

    @property
    def recommendations(self):
        recs = [(k, v, OptionRecommendation.HIGH)
                for k, v in self._recommendations.items()]
        return recs

    def show_group_help(self, index):
        widget = self._groups_model.widgets[index.row()]
        self.help.setPlainText(widget.HELP)
示例#57
0
    def __init__(self, plugin):
        DefaultConfigWidget.__init__(self, plugin)
        c = plugin_prefs[STORE_NAME]
        all_tags = get_current_db().all_tags()

        self.gb.setMaximumHeight(80)
        genre_group_box = QGroupBox(_('Naverbook genre to calibre tag mappings'), self)
        self.l.addWidget(genre_group_box, self.l.rowCount(), 0, 1, 2)
        genre_group_box_layout = QVBoxLayout()
        genre_group_box.setLayout(genre_group_box_layout)

        tags_layout = QHBoxLayout()
        genre_group_box_layout.addLayout(tags_layout)

        self.edit_table = GenreTagMappingsTableWidget(self, all_tags)
        tags_layout.addWidget(self.edit_table)
        button_layout = QVBoxLayout()
        tags_layout.addLayout(button_layout)
        add_mapping_button = QtGui.QToolButton(self)
        add_mapping_button.setToolTip(_('Add genre mapping'))
        add_mapping_button.setIcon(QIcon(I('plus.png')))
        add_mapping_button.clicked.connect(self.add_mapping)
        button_layout.addWidget(add_mapping_button)
        spacerItem1 = QtGui.QSpacerItem(20, 40, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding)
        button_layout.addItem(spacerItem1)
        remove_mapping_button = QtGui.QToolButton(self)
        remove_mapping_button.setToolTip(_('Delete genre mapping'))
        remove_mapping_button.setIcon(QIcon(I('minus.png')))
        remove_mapping_button.clicked.connect(self.delete_mapping)
        button_layout.addWidget(remove_mapping_button)
        spacerItem3 = QtGui.QSpacerItem(20, 40, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding)
        button_layout.addItem(spacerItem3)
        rename_genre_button = QtGui.QToolButton(self)
        rename_genre_button.setToolTip(_('Rename Goodreads genre'))
        rename_genre_button.setIcon(QIcon(I('edit-undo.png')))
        rename_genre_button.clicked.connect(self.rename_genre)
        button_layout.addWidget(rename_genre_button)
        spacerItem2 = QtGui.QSpacerItem(20, 40, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding)
        button_layout.addItem(spacerItem2)
        reset_defaults_button = QtGui.QToolButton(self)
        reset_defaults_button.setToolTip(_('Reset to plugin default mappings'))
        reset_defaults_button.setIcon(QIcon(I('clear_left.png')))
        reset_defaults_button.clicked.connect(self.reset_to_defaults)
        button_layout.addWidget(reset_defaults_button)
        self.l.setRowStretch(self.l.rowCount()-1, 2)

        other_group_box = QGroupBox(_('Other options'), self)
        self.l.addWidget(other_group_box, self.l.rowCount(), 0, 1, 2)
        other_group_box_layout = QVBoxLayout()
        other_group_box.setLayout(other_group_box_layout)

        self.get_editions_checkbox = QCheckBox('Scan multiple editions for title/author searches (slower)', self)
        self.get_editions_checkbox.setToolTip('When checked will perform an additional search to scan the top ranked\n'
                                              'Goodreads editions (if available) to exclude audiobook editions.\n'
                                              'Without this enabled you will get a faster search, using the "best".\n'
                                              'edition ranked by Goodreads which can in some cases be an audiobook.')
        self.get_editions_checkbox.setChecked(c[KEY_GET_EDITIONS])
        other_group_box_layout.addWidget(self.get_editions_checkbox)
        self.all_authors_checkbox = QCheckBox('Get all contributing authors (e.g. illustrators, series editors etc)', self)
        self.all_authors_checkbox.setToolTip('Goodreads for some books will list all of the contributing authors and\n'
                                              'the type of contribution like (Editor), (Illustrator) etc.\n\n'
                                              'When this option is checked, all contributing authors are retrieved.\n\n'
                                              'When unchecked (default) only the primary author(s) are returned which\n'
                                              'are those that either have no contribution type specified, or have the\n'
                                              'value of (Goodreads Author).\n\n'
                                              'If there is no primary author then only those with the same contribution\n'
                                              'type as the first author are returned.\n'
                                              'e.g. "A, B (Illustrator)" will return author A\n'
                                              'e.g. "A (Goodreads Author)" will return author A\n'
                                              'e.g. "A (Editor), B (Editor), C (Illustrator)" will return authors A & B\n'
                                              'e.g. "A (Editor), B (Series Editor)" will return author A\n')
        self.all_authors_checkbox.setChecked(c[KEY_GET_ALL_AUTHORS])
        other_group_box_layout.addWidget(self.all_authors_checkbox)

        self.edit_table.populate_table(c[KEY_GENRE_MAPPINGS])
示例#58
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)
示例#59
0
    def __init__(self, parent=None, panel_name='search'):
        QWidget.__init__(self, parent)
        self.ignore_search_type_changes = False
        self.l = l = QVBoxLayout(self)
        l.setContentsMargins(0, 0, 0, 0)
        h = QHBoxLayout()
        h.setContentsMargins(0, 0, 0, 0)
        l.addLayout(h)

        self.search_box = sb = SearchBox(self)
        self.panel_name = panel_name
        sb.initialize('viewer-{}-panel-expression'.format(panel_name))
        sb.item_selected.connect(self.saved_search_selected)
        sb.history_saved.connect(self.history_saved)
        sb.cleared.connect(self.cleared)
        sb.lineEdit().returnPressed.connect(self.find_next)
        h.addWidget(sb)

        self.next_button = nb = QToolButton(self)
        h.addWidget(nb)
        nb.setFocusPolicy(Qt.NoFocus)
        nb.setIcon(QIcon(I('arrow-down.png')))
        nb.clicked.connect(self.find_next)
        nb.setToolTip(_('Find next match'))

        self.prev_button = nb = QToolButton(self)
        h.addWidget(nb)
        nb.setFocusPolicy(Qt.NoFocus)
        nb.setIcon(QIcon(I('arrow-up.png')))
        nb.clicked.connect(self.find_previous)
        nb.setToolTip(_('Find previous match'))

        h = QHBoxLayout()
        h.setContentsMargins(0, 0, 0, 0)
        l.addLayout(h)
        self.query_type = qt = QComboBox(self)
        qt.setFocusPolicy(Qt.NoFocus)
        qt.addItem(_('Contains'), 'normal')
        qt.addItem(_('Whole words'), 'word')
        qt.addItem(_('Regex'), 'regex')
        qt.setToolTip(('<p>' + _(
            'Choose the type of search: <ul>'
            '<li><b>Contains</b> will search for the entered text anywhere.'
            '<li><b>Whole words</b> will search for whole words that equal the entered text.'
            '<li><b>Regex</b> will interpret the text as a regular expression.'
        )))
        qt.setCurrentIndex(
            qt.findData(
                vprefs.get('viewer-{}-mode'.format(self.panel_name), 'normal')
                or 'normal'))
        qt.currentIndexChanged.connect(self.save_search_type)
        h.addWidget(qt)

        self.case_sensitive = cs = QCheckBox(_('&Case sensitive'), self)
        cs.setFocusPolicy(Qt.NoFocus)
        cs.setChecked(
            bool(
                vprefs.get('viewer-{}-case-sensitive'.format(self.panel_name),
                           False)))
        cs.stateChanged.connect(self.save_search_type)
        h.addWidget(cs)

        self.return_button = rb = QToolButton(self)
        rb.setIcon(QIcon(I('back.png')))
        rb.setToolTip(_('Go back to where you were before searching'))
        rb.clicked.connect(self.go_back)
        h.addWidget(rb)
示例#60
0
    def __init__(self):
        super().__init__()

        self.setWindowTitle(WINDOW_TITLE)

        from pathlib import Path
        file_name = str(Path(__file__).resolve().parent / 'favicon.ico')
        icon = QIcon(file_name)

        self.setWindowIcon(icon)

        self.tray = QSystemTrayIcon(icon)
        self.tray.setToolTip(self.windowTitle())
        self.tray.activated.connect(self._on_tray_activated)
        self.tray.show()

        self.logged_dict = dict()

        self.pb_refresh = QPushButton('REFRESH')
        self.pb_refresh.clicked.connect(self.refresh)

        self.cb_show_log = QCheckBox()
        self.cb_show_log.setChecked(True)

        self.log = QPlainTextEdit()
        self.log.setReadOnly(True)
        self.log.setWordWrapMode(QTextOption.NoWrap)
        log_font = self.log.font()
        log_font.setFamily('Courier New')
        self.log.setFont(log_font)

        self.cb_show_log.clicked.connect(self.log.setVisible)
        self.log.setVisible(self.cb_show_log.isChecked())

        header_labels = ['DATE', 'TOTAL LOGGED TIME']
        self.table_logged = QTableWidget()
        self.table_logged.setEditTriggers(QTableWidget.NoEditTriggers)
        self.table_logged.setSelectionBehavior(QTableWidget.SelectRows)
        self.table_logged.setSelectionMode(QTableWidget.SingleSelection)
        self.table_logged.setColumnCount(len(header_labels))
        self.table_logged.setHorizontalHeaderLabels(header_labels)
        self.table_logged.horizontalHeader().setStretchLastSection(True)
        self.table_logged.itemClicked.connect(
            self._on_table_logged_item_clicked)

        header_labels = ['TIME', 'LOGGED', 'JIRA']
        self.table_logged_info = QTableWidget()
        self.table_logged_info.setEditTriggers(QTableWidget.NoEditTriggers)
        self.table_logged_info.setSelectionBehavior(QTableWidget.SelectRows)
        self.table_logged_info.setSelectionMode(QTableWidget.SingleSelection)
        self.table_logged_info.setColumnCount(len(header_labels))
        self.table_logged_info.setHorizontalHeaderLabels(header_labels)
        self.table_logged_info.horizontalHeader().setSectionResizeMode(
            1, QHeaderView.ResizeToContents)
        self.table_logged_info.horizontalHeader().setStretchLastSection(True)
        self.table_logged_info.itemDoubleClicked.connect(
            self._on_table_logged_info_item_double_clicked)

        main_layout = QVBoxLayout()

        central_widget = QWidget()
        central_widget.setLayout(main_layout)

        self.setCentralWidget(central_widget)

        self.pb_refresh.setSizePolicy(
            QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Preferred))

        h_layout = QHBoxLayout()
        h_layout.addWidget(self.pb_refresh)
        h_layout.addWidget(self.cb_show_log)

        layout_table_widget = QVBoxLayout()
        layout_table_widget.setContentsMargins(0, 0, 0, 0)
        layout_table_widget.addWidget(self.table_logged)
        layout_table_widget.addWidget(self.table_logged_info)

        table_widget = QWidget()
        table_widget.setLayout(layout_table_widget)

        splitter = QSplitter(Qt.Horizontal)
        splitter.addWidget(table_widget)
        splitter.addWidget(self.log)

        main_layout.addLayout(h_layout)
        main_layout.addWidget(splitter)