Example #1
0
 def plugin_to_index(self, plugin):
     for i, category in enumerate(self.categories):
         parent = self.index(i, 0, QModelIndex())
         for j, p in enumerate(self._data[category]):
             if plugin == p:
                 return self.index(j, 0, parent)
     return QModelIndex()
Example #2
0
    def find_next(self, idx, query, backwards=False):
        query = query.strip()
        if not query:
            return idx
        matches = self.parse(query)
        if not matches:
            return idx
        if idx.parent().isValid():
            loc = (idx.parent().row(), idx.row())
        else:
            loc = (idx.row(), -1)
        if loc not in matches:
            return self.find(query)
        if len(matches) == 1:
            return QModelIndex()
        matches = list(sorted(matches))
        i = matches.index(loc)
        if backwards:
            ans = i - 1 if i - 1 >= 0 else len(matches) - 1
        else:
            ans = i + 1 if i + 1 < len(matches) else 0

        ans = matches[ans]

        return self.index(ans[0], 0, QModelIndex()) if ans[1] < 0 else \
                self.index(ans[1], 0, self.index(ans[0], 0, QModelIndex()))
Example #3
0
    def index(self, row, column, parent=QModelIndex()):
        if not self.hasIndex(row, column, parent):
            return QModelIndex()

        if parent.isValid():
            return self.createIndex(row, column, 1 + parent.row())
        else:
            return self.createIndex(row, column, 0)
Example #4
0
 def plugin_to_index_by_properties(self, plugin):
     for i, category in enumerate(self.categories):
         parent = self.index(i, 0, QModelIndex())
         for j, p in enumerate(self._data[category]):
             if plugin.name == p.name and plugin.type == p.type and \
                     plugin.author == p.author and plugin.version == p.version:
                 return self.index(j, 0, parent)
     return QModelIndex()
Example #5
0
    def parent(self, index):
        if not index.isValid():
            return QModelIndex()

        child_item = index.internalPointer()
        parent_item = child_item.parent

        if parent_item is self.root or parent_item is None:
            return QModelIndex()

        ans = self.createIndex(parent_item.row(), 0, parent_item)
        return ans
Example #6
0
 def find(self, query):
     query = query.strip()
     if not query:
         return QModelIndex()
     matches = self.parse(query)
     if not matches:
         return QModelIndex()
     matches = list(sorted(matches))
     c, p = matches[0]
     cat_idx = self.index(c, 0, QModelIndex())
     if p == -1:
         return cat_idx
     return self.index(p, 0, cat_idx)
Example #7
0
    def index(self, row, column, parent):
        if not self.hasIndex(row, column, parent):
            return QModelIndex()

        if not parent.isValid():
            parent_item = self.root
        else:
            parent_item = parent.internalPointer()

        try:
            child_item = parent_item.children[row]
        except IndexError:
            return QModelIndex()

        ans = self.createIndex(row, column, child_item)
        return ans
Example #8
0
    def refresh(self, row, mi=None):
        if isinstance(row, QModelIndex):
            row = row.row()
        if row == self.current_row and mi is None:
            return
        mi = self.view.model().get_book_display_info(row) if mi is None else mi
        if mi is None:
            # Indicates books was deleted from library, or row numbers have
            # changed
            return

        self.previous_button.setEnabled(False if row == 0 else True)
        self.next_button.setEnabled(False if row ==
                                    self.view.model().rowCount(QModelIndex()) -
                                    1 else True)
        self.current_row = row
        self.setWindowTitle(mi.title)
        self.cover_pixmap = QPixmap.fromImage(mi.cover_data[1])
        self.path_to_book = getattr(mi, 'path', None)
        try:
            dpr = self.devicePixelRatioF()
        except AttributeError:
            dpr = self.devicePixelRatio()
        self.cover_pixmap.setDevicePixelRatio(dpr)
        self.marked = mi.marked
        self.resize_cover()
        html = render_html(mi,
                           True,
                           self,
                           pref_name='popup_book_display_fields')
        set_html(mi, html, self.details)
        self.update_cover_tooltip()
Example #9
0
 def update_result(self, plugin_name, width, height, data):
     if plugin_name.endswith('}'):
         # multi cover plugin
         plugin_name = plugin_name.partition('{')[0]
         plugin = [plugin for plugin in self.plugin_map if plugin.name == plugin_name]
         if not plugin:
             return
         plugin = plugin[0]
         last_row = max(self.plugin_map[plugin])
         pmap = self.load_pixmap(data)
         if pmap.isNull():
             return
         self.beginInsertRows(QModelIndex(), last_row, last_row)
         for rows in itervalues(self.plugin_map):
             for i in range(len(rows)):
                 if rows[i] >= last_row:
                     rows[i] += 1
         self.plugin_map[plugin].insert(-1, last_row)
         self.covers.insert(last_row, self.get_item(plugin_name, pmap, waiting=False))
         self.endInsertRows()
     else:
         # single cover plugin
         idx = None
         for plugin, rows in iteritems(self.plugin_map):
             if plugin.name == plugin_name:
                 idx = rows[0]
                 break
         if idx is None:
             return
         pmap = self.load_pixmap(data)
         if pmap.isNull():
             return
         self.covers[idx] = self.get_item(plugin_name, pmap, waiting=False)
         self.dataChanged.emit(self.index(idx), self.index(idx))
Example #10
0
    def edit_metadata_for(self, rows, book_ids, bulk=None):
        previous = self.gui.library_view.currentIndex()
        if bulk or (bulk is None and len(rows) > 1):
            return self.do_edit_bulk_metadata(rows, book_ids)

        current_row = 0
        row_list = rows
        editing_multiple = len(row_list) > 1

        if not editing_multiple:
            cr = row_list[0]
            row_list = \
                list(range(self.gui.library_view.model().rowCount(QModelIndex())))
            current_row = row_list.index(cr)

        view = self.gui.library_view.alternate_views.current_view
        try:
            hpos = view.horizontalScrollBar().value()
        except Exception:
            hpos = 0

        changed, rows_to_refresh = self.do_edit_metadata(row_list, current_row, editing_multiple)

        m = self.gui.library_view.model()

        if rows_to_refresh:
            m.refresh_rows(rows_to_refresh)

        if changed:
            self.refresh_books_after_metadata_edit(changed, previous)
        if self.gui.library_view.alternate_views.current_view is view:
            if hasattr(view, 'restore_hpos'):
                view.restore_hpos(hpos)
            else:
                view.horizontalScrollBar().setValue(hpos)
Example #11
0
 def get_ids_from_selected_rows():
     rows = self.gui.library_view.selectionModel().selectedRows()
     if not rows or len(rows) < 2:
         rows = range(self.gui.library_view.model().rowCount(
             QModelIndex()))
     ids = list(map(self.gui.library_view.model().id, rows))
     return ids
Example #12
0
    def generate_catalog(self):
        rows = self.gui.library_view.selectionModel().selectedRows()
        if not rows or len(rows) < 2:
            rows = range(self.gui.library_view.model().rowCount(QModelIndex()))
        ids = list(map(self.gui.library_view.model().id, rows))

        if not ids:
            return error_dialog(self.gui,
                                _('No books selected'),
                                _('No books selected for catalog generation'),
                                show=True)

        db = self.gui.library_view.model().db
        dbspec = {}
        for id in ids:
            dbspec[id] = {'ondevice': db.ondevice(id, index_is_id=True)}

        # Calling gui2.tools:generate_catalog()
        ret = generate_catalog(self.gui, dbspec, ids, self.gui.device_manager,
                               db)
        if ret is None:
            return

        func, args, desc, out, sync, title = ret

        fmt = os.path.splitext(out)[1][1:].upper()
        job = self.gui.job_manager.run_job(self.Dispatcher(
            self.catalog_generated),
                                           func,
                                           args=args,
                                           description=desc)
        job.catalog_file_path = out
        job.fmt = fmt
        job.catalog_sync, job.catalog_title = sync, title
        self.gui.status_bar.show_message(_('Generating %s catalog...') % fmt)
Example #13
0
 def text_edited(self, *args):
     if self.no_popup:
         return
     self.update_completions()
     select_first = len(self.mcompleter.model().current_prefix) > 0
     if not select_first:
         self.mcompleter.setCurrentIndex(QModelIndex())
     self.complete(select_first=select_first)
Example #14
0
 def selectAll(self):
     # We re-implement this to ensure that only indexes from column 0 are
     # selected. The base class implementation selects all columns. This
     # causes problems with selection syncing, see
     # https://bugs.launchpad.net/bugs/1236348
     m = self.model()
     sm = self.selectionModel()
     sel = QItemSelection(m.index(0, 0), m.index(m.rowCount(QModelIndex())-1, 0))
     sm.select(sel, QItemSelectionModel.SelectionFlag.ClearAndSelect)
Example #15
0
 def moveCursor(self, action, modifiers):
     index = QListView.moveCursor(self, action, modifiers)
     if action in (QAbstractItemView.CursorAction.MoveLeft, QAbstractItemView.CursorAction.MoveRight) and index.isValid():
         ci = self.currentIndex()
         if ci.isValid() and index.row() == ci.row():
             nr = index.row() + (1 if action == QAbstractItemView.CursorAction.MoveRight else -1)
             if 0 <= nr < self.model().rowCount(QModelIndex()):
                 index = self.model().index(nr, 0)
     return index
Example #16
0
 def refresh_after_polish(self):
     self.refresh_debounce_timer.stop()
     book_ids = tuple(self.to_be_refreshed)
     self.to_be_refreshed = set()
     if self.gui.current_view() is self.gui.library_view:
         self.gui.library_view.model().refresh_ids(book_ids)
         current = self.gui.library_view.currentIndex()
         if current.isValid():
             self.gui.library_view.model().current_changed(current, QModelIndex())
     self.gui.tags_view.recount()
def dump_tags_model(m):
    from qt.core import QModelIndex, Qt
    ans, indent = [], '  '

    def dump_node(index, level=-1):
        if level > -1:
            ans.append(indent*level + index.data(Qt.ItemDataRole.UserRole).dump_data())
        for i in range(m.rowCount(index)):
            dump_node(m.index(i, 0, index), level + 1)
        if level == 0:
            ans.append('')
    dump_node(QModelIndex())
    return '\n'.join(ans)
Example #18
0
 def search(self, query):
     cq = self.current_query
     if cq['items'] and -1 < cq['index'] < len(cq['items']):
         cq['items'][cq['index']].set_current_search_result(False)
     if cq['text'] != query:
         items = tuple(self.find_items(query))
         cq.update({'text': query, 'items': items, 'index': -1})
     if len(cq['items']) > 0:
         cq['index'] = (cq['index'] + 1) % len(cq['items'])
         item = cq['items'][cq['index']]
         item.set_current_search_result(True)
         index = self.indexFromItem(item)
         return index
     return QModelIndex()
Example #19
0
 def library_ids_deleted(self, ids_deleted, current_row=None):
     view = self.gui.library_view
     for v in (self.gui.memory_view, self.gui.card_a_view, self.gui.card_b_view):
         if v is None:
             continue
         v.model().clear_ondevice(ids_deleted)
     if current_row is not None:
         ci = view.model().index(current_row, 0)
         if not ci.isValid():
             # Current row is after the last row, set it to the last row
             current_row = view.row_count() - 1
         view.set_current_row(current_row)
     if view.model().rowCount(QModelIndex()) < 1:
         self.gui.book_details.reset_info()
Example #20
0
    def book_converted(self, job):
        temp_files, fmt, book_id = self.conversion_jobs.pop(job)[:3]
        try:
            if job.failed:
                self.gui.job_exception(job)
                return
            db = self.gui.current_db
            if not db.new_api.has_id(book_id):
                return error_dialog(
                    self.gui,
                    _('Book deleted'),
                    _('The book you were trying to convert has been deleted from the calibre library.'
                      ),
                    show=True)
            same_fmt = getattr(job, 'conversion_of_same_fmt', False)
            manually_fine_tune_toc = getattr(job, 'manually_fine_tune_toc',
                                             False)
            fmtf = temp_files[-1].name
            if os.stat(fmtf).st_size < 1:
                raise Exception(
                    _('Empty output file, '
                      'probably the conversion process crashed'))

            if same_fmt and tweaks['save_original_format']:
                db.save_original_format(book_id, fmt, notify=False)

            with open(temp_files[-1].name, 'rb') as data:
                db.add_format(book_id, fmt, data, index_is_id=True)
            self.gui.book_converted.emit(book_id, fmt)
            self.gui.status_bar.show_message(
                job.description + ' ' + _('completed'), 2000)
        finally:
            for f in temp_files:
                try:
                    if os.path.exists(f.name):
                        os.remove(f.name)
                except:
                    pass
        self.gui.tags_view.recount()
        if self.gui.current_view() is self.gui.library_view:
            lv = self.gui.library_view
            lv.model().refresh_ids((book_id, ))
            current = lv.currentIndex()
            if current.isValid():
                lv.model().current_changed(current, QModelIndex())
        if manually_fine_tune_toc:
            self.gui.iactions['Edit ToC'].do_one(book_id, fmt.upper())
Example #21
0
 def paint(self, painter, option, index):
     icon = index.data(Qt.ItemDataRole.DecorationRole)
     if icon and not icon.isNull():
         QStyledItemDelegate.paint(self, painter, option, QModelIndex())
         pw, ph = option.rect.width(), option.rect.height()
         scaled, w, h = fit_image(option.decorationSize.width(),
                                  option.decorationSize.height(), pw, ph)
         r = option.rect
         if pw > w:
             x = (pw - w) // 2
             r = r.adjusted(x, 0, -x, 0)
         if ph > h:
             y = (ph - h) // 2
             r = r.adjusted(0, y, 0, -y)
         painter.drawPixmap(r, icon.pixmap(w, h))
     else:
         QStyledItemDelegate.paint(self, painter, option, index)
Example #22
0
 def parent(self, index):
     if not index.isValid() or index.internalId() == 0:
         return QModelIndex()
     return self.createIndex(0, 0)
Example #23
0
 def index(self, row, column, parent=QModelIndex()):
     return self.createIndex(row, column)
Example #24
0
 def plugin_to_index(self, display_plugin):
     for i, p in enumerate(self.display_plugins):
         if display_plugin == p:
             return self.index(i, 0, QModelIndex())
     return QModelIndex()
Example #25
0
 def hide_all(self, *args):
     self.model.hide_jobs(list(range(0,
         self.model.rowCount(QModelIndex()))))
     self.proxy_model.beginResetModel(), self.proxy_model.endResetModel()
Example #26
0
 def columnCount(self, parent=QModelIndex()):
     return 5
Example #27
0
 def rowCount(self, parent=QModelIndex()):
     return len(self.jobs)
Example #28
0
 def hide(self):
     self.setCurrentIndex(QModelIndex())
     QListView.hide(self)
Example #29
0
#!/usr/bin/env python
# vim:fileencoding=utf-8

__license__ = 'GPL v3'
__copyright__ = '2013, Kovid Goyal <kovid at kovidgoyal.net>'

import shutil

from qt.core import (QAbstractListModel, Qt, QModelIndex, QApplication,
                     QWidget, QGridLayout, QListView, QStyledItemDelegate,
                     pyqtSignal, QPushButton, QIcon, QItemSelectionModel)

from calibre.gui2 import error_dialog

ROOT = QModelIndex()

MAX_SAVEPOINTS = 100


def cleanup(containers):
    for container in containers:
        try:
            shutil.rmtree(container.root, ignore_errors=True)
        except:
            pass


class State(object):
    def __init__(self, container):
        self.container = container
        self.message = None