Example #1
0
class ChooseFormatDialog(QDialog):
    def __init__(self, window, msg, formats, show_open_with=False):
        QDialog.__init__(self, window)
        self.resize(507, 377)
        self.setWindowIcon(QIcon(I("mimetypes/unknown.png")))
        self.setWindowTitle(_('Choose format'))
        self.l = l = QVBoxLayout(self)
        self.msg = QLabel(msg)
        l.addWidget(self.msg)
        self.formats = QListWidget(self)
        self.formats.setIconSize(QSize(64, 64))
        self.formats.activated[QModelIndex].connect(self.activated_slot)
        l.addWidget(self.formats)
        self.h = h = QHBoxLayout()
        h.setContentsMargins(0, 0, 0, 0)
        l.addLayout(h)
        if show_open_with:
            self.owb = QPushButton(_('&Open with...'), self)
            self.formats.currentRowChanged.connect(
                self.update_open_with_button)
            h.addWidget(self.owb)
            self.own = QMenu(self.owb.text())
            self.owb.setMenu(self.own)
            self.own.aboutToShow.connect(self.populate_open_with)
        self.buttonBox = bb = QDialogButtonBox(self)
        bb.setStandardButtons(QDialogButtonBox.StandardButton.Ok
                              | QDialogButtonBox.StandardButton.Cancel)
        bb.accepted.connect(self.accept), bb.rejected.connect(self.reject)
        h.addStretch(10), h.addWidget(self.buttonBox)

        formats = list(formats)
        for format in formats:
            self.formats.addItem(
                QListWidgetItem(
                    file_icon_provider().icon_from_ext(format.lower()),
                    format.upper()))
        self._formats = formats
        self.formats.setCurrentRow(0)
        self._format = self.open_with_format = None
        if show_open_with:
            self.populate_open_with()
            self.update_open_with_button()

    def populate_open_with(self):
        from calibre.gui2.open_with import populate_menu, edit_programs
        menu = self.own
        menu.clear()
        fmt = self._formats[self.formats.currentRow()]

        def connect_action(ac, entry):
            connect_lambda(ac.triggered, self,
                           lambda self: self.open_with(entry))

        populate_menu(menu, connect_action, fmt)
        if len(menu.actions()) == 0:
            menu.addAction(
                _('Open %s with...') % fmt.upper(), self.choose_open_with)
        else:
            menu.addSeparator()
            menu.addAction(
                _('Add other application for %s files...') % fmt.upper(),
                self.choose_open_with)
            menu.addAction(_('Edit "Open with" applications...'),
                           partial(edit_programs, fmt, self))

    def update_open_with_button(self):
        fmt = self._formats[self.formats.currentRow()]
        self.owb.setText(_('Open %s with...') % fmt)

    def open_with(self, entry):
        self.open_with_format = (self._formats[self.formats.currentRow()],
                                 entry)
        self.accept()

    def choose_open_with(self):
        from calibre.gui2.open_with import choose_program
        fmt = self._formats[self.formats.currentRow()]
        entry = choose_program(fmt, self)
        if entry is not None:
            self.open_with(entry)

    def book_converted(self, book_id, fmt):
        fmt = fmt.upper()
        if fmt not in self._formats:
            self._formats.append(fmt)
            self.formats.addItem(
                QListWidgetItem(
                    file_icon_provider().icon_from_ext(fmt.lower()),
                    fmt.upper()))

    def activated_slot(self, *args):
        self.accept()

    def format(self):
        return self._format

    def accept(self):
        self._format = self._formats[self.formats.currentRow()]
        return QDialog.accept(self)
Example #2
0
class SavedSearchEditor(Dialog):
    def __init__(self, parent, initial_search=None):
        self.initial_search = initial_search
        Dialog.__init__(self, _('Manage Saved searches'),
                        'manage-saved-searches', parent)

    def setup_ui(self):
        from calibre.gui2.ui import get_gui
        db = get_gui().current_db
        self.l = l = QVBoxLayout(self)
        b = self.bb.addButton(_('&Add search'),
                              QDialogButtonBox.ButtonRole.ActionRole)
        b.setIcon(QIcon(I('plus.png')))
        b.clicked.connect(self.add_search)

        b = self.bb.addButton(_('&Remove search'),
                              QDialogButtonBox.ButtonRole.ActionRole)
        b.setIcon(QIcon(I('minus.png')))
        b.clicked.connect(self.del_search)

        b = self.bb.addButton(_('&Edit search'),
                              QDialogButtonBox.ButtonRole.ActionRole)
        b.setIcon(QIcon(I('modified.png')))
        b.clicked.connect(self.edit_search)

        self.slist = QListWidget(self)
        self.slist.setStyleSheet('QListView::item { padding: 3px }')
        self.slist.activated.connect(self.edit_search)
        self.slist.setAlternatingRowColors(True)
        self.searches = {
            name: db.saved_search_lookup(name)
            for name in db.saved_search_names()
        }
        self.populate_search_list()
        if self.initial_search is not None and self.initial_search in self.searches:
            self.select_search(self.initial_search)
        elif self.searches:
            self.slist.setCurrentRow(0)
        self.slist.currentItemChanged.connect(self.current_index_changed)
        l.addWidget(self.slist)

        self.desc = la = QLabel('\xa0')
        la.setWordWrap(True)
        l.addWidget(la)

        l.addWidget(self.bb)
        self.current_index_changed(self.slist.currentItem())
        self.setMinimumHeight(500)
        self.setMinimumWidth(600)

    @property
    def current_search_name(self):
        i = self.slist.currentItem()
        if i is not None:
            ans = i.text()
            if ans in self.searches:
                return ans

    def keyPressEvent(self, ev):
        if ev.key() == Qt.Key.Key_Delete:
            self.del_search()
            return
        return Dialog.keyPressEvent(self, ev)

    def populate_search_list(self):
        self.slist.clear()
        for name in sorted(self.searches.keys(), key=sort_key):
            self.slist.addItem(name)

    def add_search(self):
        d = AddSavedSearch(parent=self,
                           commit_changes=False,
                           validate=self.validate_add)
        if d.exec_() != QDialog.DialogCode.Accepted:
            return
        name, expression = d.accepted_data
        self.searches[name] = expression
        self.populate_search_list()
        self.select_search(name)

    def del_search(self):
        n = self.current_search_name
        if n is not None:
            if not confirm(
                    '<p>' + _('The current saved search will be '
                              '<b>permanently deleted</b>. Are you sure?') +
                    '</p>', 'saved_search_editor_delete', self):
                return
            self.slist.takeItem(self.slist.currentRow())
            del self.searches[n]

    def edit_search(self):
        n = self.current_search_name
        if not n:
            return
        d = AddSavedSearch(parent=self,
                           commit_changes=False,
                           label=_('Edit the name and/or expression below.'),
                           validate=self.validate_edit)
        d.setWindowTitle(_('Edit saved search'))
        d.sname.setText(n)
        d.search.setPlainText(self.searches[n])
        if d.exec_() != QDialog.DialogCode.Accepted:
            return
        name, expression = d.accepted_data
        self.slist.currentItem().setText(name)
        del self.searches[n]
        self.searches[name] = expression
        self.current_index_changed(self.slist.currentItem())

    def duplicate_msg(self, name):
        return _(
            'A saved search with the name {} already exists. Choose another name'
        ).format(name)

    def validate_edit(self, name, expression):
        q = self.current_search_name
        if icu_lower(name) in {icu_lower(n) for n in self.searches if n != q}:
            return self.duplicate_msg(name)

    def validate_add(self, name, expression):
        if icu_lower(name) in {icu_lower(n) for n in self.searches}:
            return self.duplicate_msg(name)

    def select_search(self, name):
        items = self.slist.findItems(
            name,
            Qt.MatchFlag.MatchFixedString | Qt.MatchFlag.MatchCaseSensitive)
        if items:
            self.slist.setCurrentItem(items[0])

    def current_index_changed(self, item):
        n = self.current_search_name
        if n:
            t = self.searches[n]
        else:
            t = ''
        self.desc.setText('<p><b>{}</b>: '.format(_('Search expression')) +
                          prepare_string_for_xml(t))

    def accept(self):
        commit_searches(self.searches)
        Dialog.accept(self)