Beispiel #1
2
    def __call__(self, item, where):
        self.current_item, self.current_where = item, where
        self.current_name = None
        self.current_frag = None
        self.name.setText(_('(Untitled)'))
        dest_index, frag = 0, None
        if item is not None:
            if where is None:
                self.name.setText(item.data(0, Qt.DisplayRole) or '')
                self.name.setCursorPosition(0)
            toc = item.data(0, Qt.UserRole)
            if toc.dest:
                for i in xrange(self.dest_list.count()):
                    litem = self.dest_list.item(i)
                    if unicode(litem.data(Qt.DisplayRole) or '') == toc.dest:
                        dest_index = i
                        frag = toc.frag
                        break

        self.dest_list.blockSignals(True)
        self.dest_list.setCurrentRow(dest_index)
        self.dest_list.blockSignals(False)
        item = self.dest_list.item(dest_index)
        self.current_changed(item)
        if frag:
            self.current_frag = frag
            QTimer.singleShot(1, self.show_frag)
Beispiel #2
1
    def do_one_isbn_add(self):
        try:
            db = self.gui.library_view.model().db

            try:
                x = self.isbn_books.pop(0)
            except IndexError:
                self.gui.library_view.model().books_added(self.isbn_add_dialog.value)
                self.isbn_add_dialog.accept()
                self.gui.iactions['Edit Metadata'].download_metadata(
                    ids=self.add_by_isbn_ids, ensure_fields=frozenset(['title',
                        'authors']))
                return

            mi = MetaInformation(None)
            mi.isbn = x['isbn']
            if self.isbn_add_tags:
                mi.tags = list(self.isbn_add_tags)
            fmts = [] if x['path'] is None else [x['path']]
            self.add_by_isbn_ids.add(db.import_book(mi, fmts))
            self.isbn_add_dialog.value += 1
            QTimer.singleShot(10, self.do_one_isbn_add)
        except:
            self.isbn_add_dialog.accept()
            raise
Beispiel #3
0
    def execute(self):
        if not self.timer.isActive() or self.is_date_changed:
            QTimer.singleShot(500, self.setTime)
            self.timer.stop()

        index = self.ui.countryList.currentIndex()
        ctx.installData.timezone = self.ui.countryList.itemData(index)
        ctx.logger.debug("Time zone selected as %s " % ctx.installData.timezone)

        if ctx.flags.install_type == ctx.STEP_BASE:
            #FIXME:Refactor hacky code
            ctx.installData.rootPassword = ctx.consts.default_password
            ctx.installData.hostName = yali.util.product_release()
            if ctx.storageInitialized:
                disks = filter(lambda d: not d.format.hidden, ctx.storage.disks)
                if len(disks) == 1:
                    ctx.storage.clearPartDisks = [disks[0].name]
                    ctx.mainScreen.step_increment = 2
                else:
                    ctx.mainScreen.step_increment = 1
                return True
            else:
                self.pds_messagebox.setMessage(_("Storage Devices initialising..."))
                self.pds_messagebox.animate(start=MIDCENTER, stop=MIDCENTER)
                ctx.mainScreen.step_increment = 0
                self.pthread.start()
                QTimer.singleShot(2, self.startStorageInitialize)
                return False

        return True
Beispiel #4
0
 def do_one_block(self):
     try:
         start_cursor, end_cursor = self.requests[0]
     except IndexError:
         return
     self.ignore_requests = True
     try:
         block = start_cursor.block()
         if not block.isValid():
             self.requests.popleft()
             return
         formats, force_next_highlight = self.parse_single_block(block)
         self.apply_format_changes(block, formats)
         try:
             self.doc.markContentsDirty(block.position(), block.length())
         except AttributeError:
             self.requests.clear()
             return
         ok = start_cursor.movePosition(start_cursor.NextBlock)
         if not ok:
             self.requests.popleft()
             return
         next_block = start_cursor.block()
         if next_block.position() > end_cursor.position():
             if force_next_highlight:
                 end_cursor.setPosition(next_block.position() + 1)
             else:
                 self.requests.popleft()
             return
     finally:
         self.ignore_requests = False
         QTimer.singleShot(0, self.do_one_block)
Beispiel #5
0
    def finalize_layout(self):
        self.status_bar.initialize(self.system_tray_icon)
        self.book_details.show_book_info.connect(self.iactions['Show Book Details'].show_book_info)
        self.book_details.files_dropped.connect(self.iactions['Add Books'].files_dropped_on_book)
        self.book_details.cover_changed.connect(self.bd_cover_changed,
                type=Qt.QueuedConnection)
        self.book_details.cover_removed.connect(self.bd_cover_removed,
                type=Qt.QueuedConnection)
        self.book_details.remote_file_dropped.connect(
                self.iactions['Add Books'].remote_file_dropped_on_book,
                type=Qt.QueuedConnection)
        self.book_details.open_containing_folder.connect(self.iactions['View'].view_folder_for_id)
        self.book_details.view_specific_format.connect(self.iactions['View'].view_format_by_id)
        self.book_details.search_requested.connect(self.search.set_search_string)
        self.book_details.remove_specific_format.connect(
                self.iactions['Remove Books'].remove_format_by_id)
        self.book_details.save_specific_format.connect(
                self.iactions['Save To Disk'].save_library_format_by_ids)
        self.book_details.restore_specific_format.connect(
            self.iactions['Remove Books'].restore_format)
        self.book_details.copy_link.connect(self.bd_copy_link,
                type=Qt.QueuedConnection)
        self.book_details.view_device_book.connect(
                self.iactions['View'].view_device_book)
        self.book_details.manage_author.connect(lambda author:self.do_author_sort_edit(self, author, select_sort=False, select_link=False))
        self.book_details.compare_specific_format.connect(self.compare_format)

        m = self.library_view.model()
        if m.rowCount(None) > 0:
            QTimer.singleShot(0, self.library_view.set_current_row)
            m.current_changed(self.library_view.currentIndex(),
                    self.library_view.currentIndex())
        self.library_view.setFocus(Qt.OtherFocusReason)
Beispiel #6
0
    def __init__(self, log, parent=None):
        QDialog.__init__(self, parent)
        self.log = log
        self.l = l = QVBoxLayout()
        self.setLayout(l)

        self.tb = QTextBrowser(self)
        l.addWidget(self.tb)

        self.bb = QDialogButtonBox(QDialogButtonBox.Close)
        l.addWidget(self.bb)
        self.copy_button = self.bb.addButton(_('Copy to clipboard'),
                self.bb.ActionRole)
        self.copy_button.clicked.connect(self.copy_to_clipboard)
        self.copy_button.setIcon(QIcon(I('edit-copy.png')))
        self.bb.rejected.connect(self.reject)
        self.bb.accepted.connect(self.accept)

        self.setWindowTitle(_('Download log'))
        self.setWindowIcon(QIcon(I('debug.png')))
        self.resize(QSize(800, 400))

        self.keep_updating = True
        self.last_html = None
        self.finished.connect(self.stop)
        QTimer.singleShot(100, self.update_log)

        self.show()
Beispiel #7
0
    def __init__(self, parent, library_path, wait_time=2):
        QDialog.__init__(self, parent)
        self.l = QVBoxLayout()
        self.setLayout(self.l)
        self.l1 = QLabel('<b>'+_('Restoring database from backups, do not'
            ' interrupt, this will happen in three stages')+'...')
        self.setWindowTitle(_('Restoring database'))
        self.l.addWidget(self.l1)
        self.pb = QProgressBar(self)
        self.l.addWidget(self.pb)
        self.pb.setMaximum(0)
        self.pb.setMinimum(0)
        self.msg = QLabel('')
        self.l.addWidget(self.msg)
        self.msg.setWordWrap(True)
        self.bb = QDialogButtonBox(QDialogButtonBox.Cancel)
        self.l.addWidget(self.bb)
        self.bb.rejected.connect(self.reject)
        self.resize(self.sizeHint() + QSize(100, 50))
        self.error = None
        self.rejected = False
        self.library_path = library_path
        self.update_signal.connect(self.do_update, type=Qt.QueuedConnection)

        from calibre.db.restore import Restore
        self.restorer = Restore(library_path, self)
        self.restorer.daemon = True

        # Give the metadata backup thread time to stop
        QTimer.singleShot(wait_time * 1000, self.start)
Beispiel #8
0
    def __init__(self, parent, db):
        QObject.__init__(self, parent)
        self.internet_connection_failed = False
        self._parent = parent
        self.no_internet_msg = _('Cannot download news as no internet connection '
                'is active')
        self.no_internet_dialog = d = error_dialog(self._parent,
                self.no_internet_msg, _('No internet connection'),
                show_copy_button=False)
        d.setModal(False)

        self.recipe_model = RecipeModel()
        self.db = db
        self.lock = QMutex(QMutex.Recursive)
        self.download_queue = set([])

        self.news_menu = QMenu()
        self.news_icon = QIcon(I('news.png'))
        self.scheduler_action = QAction(QIcon(I('scheduler.png')), _('Schedule news download'), self)
        self.news_menu.addAction(self.scheduler_action)
        self.scheduler_action.triggered[bool].connect(self.show_dialog)
        self.cac = QAction(QIcon(I('user_profile.png')), _('Add a custom news source'), self)
        self.cac.triggered[bool].connect(self.customize_feeds)
        self.news_menu.addAction(self.cac)
        self.news_menu.addSeparator()
        self.all_action = self.news_menu.addAction(
                _('Download all scheduled news sources'),
                self.download_all_scheduled)

        self.timer = QTimer(self)
        self.timer.start(int(self.INTERVAL * 60 * 1000))
        self.timer.timeout.connect(self.check)
        self.oldest = gconf['oldest_news']
        QTimer.singleShot(5 * 1000, self.oldest_check)
Beispiel #9
0
    def perform_action(self, ac, loc):
        if ac in ('new', 'existing'):
            self.callback(loc, copy_structure=self.copy_structure.isChecked())
        else:
            # move library
            self.db.prefs.disable_setting = True
            abort_move = Event()
            pd = ProgressDialog(_('Moving library, please wait...'), _('Scanning...'), max=0, min=0, icon='lt.png', parent=self)
            pd.canceled_signal.connect(abort_move.set)
            self.parent().library_view.model().stop_metadata_backup()
            move_error = []

            def do_move():
                try:
                    self.db.new_api.move_library_to(loc, abort=abort_move, progress=pd.show_new_progress)
                except Exception:
                    import traceback
                    move_error.append(traceback.format_exc())
                finally:
                    pd.finished_moving.emit()

            t = Thread(name='MoveLibrary', target=do_move)
            QTimer.singleShot(0, t.start)
            pd.exec_()
            if abort_move.is_set():
                self.callback(self.db.library_path)
                return
            if move_error:
                error_dialog(self.parent(), _('Failed to move library'), _(
                    'There was an error while moving the library. The operation has been aborted. Click'
                    ' "Show details" for details.'), det_msg=move_error[0], show=True)
                self.callback(self.db.library_path)
                return
            self.callback(loc, library_renamed=True)
Beispiel #10
0
 def confirm_delete(self, spine_items, other_names):
     spine_names = {name for name, remove in spine_items if remove}
     if not question_dialog(self, _('Are you sure?'), _(
             'Are you sure you want to delete the selected files?'), det_msg='\n'.join(spine_names | other_names)):
         return
     self.delete_requested.emit(spine_items, other_names)
     QTimer.singleShot(10, self.refresh)
Beispiel #11
0
    def dump(self, items, out_stream, pdf_metadata):
        self.metadata = pdf_metadata
        self._delete_tmpdir()
        self.outline = Outline(self.toc, items)

        self.render_queue = items
        self.combine_queue = []
        self.out_stream = out_stream
        self.insert_cover()

        self.render_succeeded = False
        self.current_page_num = self.doc.page_count()
        self.combine_queue.append(os.path.join(self.tmp_path,
            'qprinter_out.pdf'))
        self.first_page = True
        self.setup_printer(self.combine_queue[-1])
        QTimer.singleShot(0, self._render_book)
        self.loop.exec_()
        if self.painter is not None:
            self.painter.end()
        if self.printer is not None:
            self.printer.abort()

        if not self.render_succeeded:
            raise Exception('Rendering HTML to PDF failed')
Beispiel #12
0
 def link_clicked(self, url):
     path = os.path.abspath(unicode(url.toLocalFile()))
     frag = None
     if path in self.iterator.spine:
         self.update_page_number()  # Ensure page number is accurate as it is used for history
         self.history.add(self.pos.value())
         path = self.iterator.spine[self.iterator.spine.index(path)]
         if url.hasFragment():
             frag = unicode(url.fragment())
         if path != self.current_page:
             self.pending_anchor = frag
             self.load_path(path)
         else:
             oldpos = self.view.document.ypos
             if frag:
                 self.view.scroll_to(frag)
             else:
                 # Scroll to top
                 self.view.scroll_to(0)
             if self.view.document.ypos == oldpos:
                 # If we are coming from goto_next_section() call this will
                 # cause another goto next section call with the next toc
                 # entry, since this one did not cause any scrolling at all.
                 QTimer.singleShot(10, self.update_indexing_state)
     else:
         open_url(url)
Beispiel #13
0
    def do_book_action(self):
        if self.wasCanceled():
            return self.do_close()
        if self.i >= self.total_count:
            return self.do_close()
        epub_format = self.entries[self.i]
        self.i += 1

        # assign the elements of the 3-tuple details to legible variables
        book_id, mi, path = epub_format[0], epub_format[1], epub_format[2]
        
        # Get the title and build the caption and label text from the string parameters provided
        dtitle = mi.title
        self.setWindowTitle('{0} {1} {2}  ({3} {4} failures)...'.format(self.action_type[0], self.total_count,
                                                                self.status_msg_type, len(self.failures), self.action_type[1]))
        self.setLabelText('{0}: {1}'.format(self.action_type[0], dtitle))
        # Send the necessary elements to the process_epub_formats callback function (action.py)
        # and record the results
        if self.callback_fn(book_id, mi, path):
            self.successes.append((book_id, mi, path))
        else:
            self.failures.append((book_id, mi, path))
        self.setValue(self.i)

        # Lather, rinse, repeat
        QTimer.singleShot(0, self.do_book_action)
Beispiel #14
0
    def __init__(self, container, do_embed=False):
        self.container = container
        self.log = self.logger = container.log
        self.do_embed = do_embed
        must_use_qt()
        self.parser = CSSParser(loglevel=logging.CRITICAL, log=logging.getLogger('calibre.css'))
        self.first_letter_pat = regex.compile(r'^[\p{Ps}\p{Ps}\p{Pe}\p{Pi}\p{Pf}\p{Po}]+', regex.VERSION1 | regex.UNICODE)

        self.loop = QEventLoop()
        self.view = QWebView()
        self.page = Page(self.log)
        self.view.setPage(self.page)
        self.page.setViewportSize(QSize(1200, 1600))

        self.view.loadFinished.connect(self.collect,
                type=Qt.QueuedConnection)

        self.render_queue = list(container.spine_items)
        self.font_stats = {}
        self.font_usage_map = {}
        self.font_spec_map = {}
        self.font_rule_map = {}
        self.all_font_rules = {}

        QTimer.singleShot(0, self.render_book)

        if self.loop.exec_() == 1:
            raise Exception('Failed to gather statistics from book, see log for details')
Beispiel #15
0
 def load_finished(self, ok):
     self.close_progress_indicator()
     path = self.view.path()
     try:
         index = self.iterator.spine.index(path)
     except (ValueError, AttributeError):
         return -1
     self.current_page = self.iterator.spine[index]
     self.current_index = index
     self.set_page_number(self.view.scroll_fraction)
     QTimer.singleShot(100, self.update_indexing_state)
     if self.pending_search is not None:
         self.do_search(self.pending_search,
                 self.pending_search_dir=='backwards')
         self.pending_search = None
         self.pending_search_dir = None
     if self.pending_anchor is not None:
         self.view.scroll_to(self.pending_anchor)
         self.pending_anchor = None
     if self.pending_reference is not None:
         self.view.goto(self.pending_reference)
         self.pending_reference = None
     if self.pending_bookmark is not None:
         self.goto_bookmark(self.pending_bookmark)
         self.pending_bookmark = None
     if self.pending_restore:
         self.view.document.page_position.restore()
     return self.current_index
Beispiel #16
0
 def check(self):
     if self.rejected:
         return
     if self.thread.is_alive():
         QTimer.singleShot(100, self.check)
     else:
         self.accept()
Beispiel #17
0
 def close_tab(self, tab=None):
     tab = tab or self.current_tab
     if tab is not None:
         self.delete_removed_tabs(self.tab_tree.remove_tab(tab))
     if not self.tabs:
         self.open_url(WELCOME_URL, switch_to_tab=True)
         QTimer.singleShot(0, self.current_tab_changed)
Beispiel #18
0
 def drop_event(self, event, mime_data):
     mime = 'application/calibre+from_library'
     if mime_data.hasFormat(mime):
         self.dropped_ids = tuple(map(int, str(mime_data.data(mime)).split()))
         QTimer.singleShot(1, self.do_drop)
         return True
     return False
Beispiel #19
0
def main():
    from calibre.gui2 import Application
    from PyQt5.Qt import QMainWindow, QStatusBar, QTimer

    app = Application([])
    w = QMainWindow()
    s = QStatusBar(w)
    w.setStatusBar(s)
    s.showMessage("Testing ProceedQuestion")
    w.show()
    p = ProceedQuestion(w)

    def doit():
        p.dummy_question()
        p.dummy_question(action_label="A very long button for testing relayout (indeed)")
        p(
            lambda p: None,
            None,
            "ass2",
            "ass2",
            "testing2",
            "testing2",
            det_msg="details shown first, with a long line to test wrapping of text and width layout",
            show_det=True,
            show_ok=True,
        )

    QTimer.singleShot(10, doit)
    app.exec_()
Beispiel #20
0
    def do_book_action(self):
        if self.wasCanceled():
            return self.do_close()
        if self.i >= self.total_count:
            return self.do_close()
        book = self.indices[self.i]
        self.i += 1

        # Get the title and build the caption and label text from the string parameters provided
        if self.db_type == 'calibre':
            dtitle = book[0].title
        elif self.db_type == 'kobo':
            dtitle = book.title
        self.setWindowTitle('{0} {1} {2}  ({3} {4} failures)...'.format(self.action_type[0], self.total_count,
                                                                self.status_msg_type, len(self.failures), self.action_type[1]))
        self.setLabelText('{0}: {1}'.format(self.action_type[0], dtitle))
        # If a calibre db, feed the calibre bookmap to action.py's add_new_books method
        if self.db_type == 'calibre':
            if self.callback_fn([book]):
                self.successes.append(book)
            else:
                self.failures.append(book)
        # If a kobo db, feed the index to the kobo book to action.py's get_decrypted_kobo_books method
        elif self.db_type == 'kobo':
            if self.callback_fn(book):
                debug_print("DecryptAddProgressDialog::do_book_action - decrypted book: '%s'" % dtitle)
                self.successes.append(book)
            else:
                debug_print("DecryptAddProgressDialog::do_book_action - book decryption failed: '%s'" % dtitle)
                self.failures.append(book)
        self.setValue(self.i)

        # Lather, rinse, repeat.
        QTimer.singleShot(0, self.do_book_action)
    def add_event(self, event_type, msg, timer=False, host=None):
        """
        Add event to events list

        :param event_type: the type of event: OK, DOWN, ACK, ...
        :type event_type: str
        :param msg: message of event
        :type msg: str
        :param timer: timer to hide event at end of time
        :type timer: bool
        :param host: data of a host to set ``Qt.UserRole``
        :type host: None | str
        """

        if not self.event_exist(msg):
            logger.debug(
                'Add Event: msg: %s, timer: %s, host: %s', msg, timer, host
            )
            event = EventItem()
            event.initialize(event_type, msg, timer=timer, host=host)

            self.events_list.insertItem(0, event)
            if timer:
                event_duration = int(
                    settings.get_config('Alignak-app', 'notification_duration')
                ) * 1000
                QTimer.singleShot(
                    event_duration,
                    lambda: self.remove_timer_event(event)
                )
        else:
            logger.debug(
                'Event with msg: %s already exist.', msg
            )
Beispiel #22
0
 def stop_server(self):
     self.gui.content_server.threaded_exit()
     self.stopping_msg = info_dialog(self, _('Stopping'),
             _('Stopping server, this could take upto a minute, please wait...'),
             show_copy_button=False)
     QTimer.singleShot(500, self.check_exited)
     self.stopping_msg.exec_()
Beispiel #23
0
    def check_exited(self):
        if getattr(self.server, 'is_running', False):
            QTimer.singleShot(20, self.check_exited)
            return

        self.gui.content_server = None
        self.main_tab.update_button_state()
        self.stopping_msg.accept()
Beispiel #24
0
 def __init__(self, parent, request):
     QNetworkReply.__init__(self, parent)
     self.setOpenMode(QNetworkReply.ReadOnly | QNetworkReply.Unbuffered)
     self.setHeader(QNetworkRequest.ContentTypeHeader, 'application/octet-stream')
     self.setHeader(QNetworkRequest.ContentLengthHeader, 0)
     self.setRequest(request)
     self.setUrl(request.url())
     QTimer.singleShot(0, self.finalize_reply)
Beispiel #25
0
 def check_exited(self):
     if self.gui.content_server.is_running:
         QTimer.singleShot(20, self.check_exited)
         if not self.stopping_msg.isVisible():
             self.stopping_msg.exec_()
         return
     self.gui.content_server = None
     self.stopping_msg.accept()
Beispiel #26
0
 def update_log(self):
     if not self.keep_updating:
         return
     html = self.log.html
     if html != self.last_html:
         self.last_html = html
         self.tb.setHtml('<pre style="font-family:monospace">%s</pre>'%html)
     QTimer.singleShot(1000, self.update_log)
Beispiel #27
0
    def __init__(self, parent=None, initial=None):
        QDialog.__init__(self, parent)
        self.setWindowTitle(_('Choose a texture'))

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

        self.tdir = texture_dir()

        self.images = il = QListWidget(self)
        il.itemDoubleClicked.connect(self.accept, type=Qt.QueuedConnection)
        il.setIconSize(QSize(256, 256))
        il.setViewMode(il.IconMode)
        il.setFlow(il.LeftToRight)
        il.setSpacing(20)
        il.setSelectionMode(il.SingleSelection)
        il.itemSelectionChanged.connect(self.update_remove_state)
        l.addWidget(il)

        self.ad = ad = QLabel(_('The builtin textures come from <a href="https://subtlepatterns.com">subtlepatterns.com</a>.'))
        ad.setOpenExternalLinks(True)
        ad.setWordWrap(True)
        l.addWidget(ad)
        self.bb = bb = QDialogButtonBox(QDialogButtonBox.Ok|QDialogButtonBox.Cancel)
        bb.accepted.connect(self.accept)
        bb.rejected.connect(self.reject)
        b = self.add_button = bb.addButton(_('Add texture'), bb.ActionRole)
        b.setIcon(QIcon(I('plus.png')))
        b.clicked.connect(self.add_texture)
        b = self.remove_button = bb.addButton(_('Remove texture'), bb.ActionRole)
        b.setIcon(QIcon(I('minus.png')))
        b.clicked.connect(self.remove_texture)
        l.addWidget(bb)

        images = [{
            'fname': ':'+os.path.basename(x),
            'path': x,
            'name': ' '.join(map(lambda s: s.capitalize(), os.path.splitext(os.path.basename(x))[0].split('_')))
        } for x in glob.glob(I('textures/*.png'))] + [{
            'fname': os.path.basename(x),
            'path': x,
            'name': os.path.splitext(os.path.basename(x))[0],
        } for x in glob.glob(os.path.join(self.tdir, '*')) if x.rpartition('.')[-1].lower() in {'jpeg', 'png', 'jpg'}]

        images.sort(key=lambda x:sort_key(x['name']))

        for i in images:
            self.create_item(i)
        self.update_remove_state()

        if initial:
            existing = {unicode_type(i.data(Qt.UserRole) or ''):i for i in (self.images.item(c) for c in range(self.images.count()))}
            item = existing.get(initial, None)
            if item is not None:
                item.setSelected(True)
                QTimer.singleShot(100, partial(il.scrollToItem, item))

        self.resize(QSize(950, 650))
Beispiel #28
0
 def start_download(self):
     self.worker.start()
     QTimer.singleShot(50, self.update)
     self.exec_()
     if self.worker.err is not None:
         error_dialog(self.parent(), _('Download failed'),
             _('Failed to download from %(url)r with error: %(err)s')%dict(
                 url=self.worker.url, err=self.worker.err),
             det_msg=self.worker.tb, show=True)
Beispiel #29
0
 def cover_browser_shown(self):
     self.cover_flow.setFocus(Qt.OtherFocusReason)
     if CoverFlow is not None:
         self.cover_flow.setCurrentSlide(self.library_view.currentIndex().row())
         self.cover_flow_syncing_enabled = True
         QTimer.singleShot(500, self.cover_flow_do_sync)
     self.library_view.setCurrentIndex(
             self.library_view.currentIndex())
     self.library_view.scroll_to_row(self.library_view.currentIndex().row())
Beispiel #30
0
 def add_isbns(self, books, add_tags=[]):
     self.isbn_books = list(books)
     self.add_by_isbn_ids = set()
     self.isbn_add_tags = add_tags
     QTimer.singleShot(10, self.do_one_isbn_add)
     self.isbn_add_dialog = ProgressDialog(_('Adding'),
             _('Creating book records from ISBNs'), max=len(books),
             cancelable=False, parent=self.gui)
     self.isbn_add_dialog.exec_()
Beispiel #31
0
    def initialize(self, library_path, db, listener, actions, show_gui=True):
        opts = self.opts
        self.preferences_action, self.quit_action = actions
        self.library_path = library_path
        self.content_server = None
        self._spare_pool = None
        self.must_restart_before_config = False
        self.listener = Listener(listener)
        self.check_messages_timer = QTimer()
        self.check_messages_timer.timeout.connect(
            self.another_instance_wants_to_talk)
        self.check_messages_timer.start(1000)

        for ac in self.iactions.values():
            try:
                ac.do_genesis()
            except Exception:
                # Ignore errors in third party plugins
                import traceback
                traceback.print_exc()
                if getattr(ac, 'plugin_path', None) is None:
                    raise
        self.donate_action = QAction(QIcon(I('donate.png')),
                                     _('&Donate to support calibre'), self)
        for st in self.istores.values():
            st.do_genesis()
        MainWindowMixin.init_main_window_mixin(self, db)

        # Jobs Button {{{
        self.job_manager = JobManager()
        self.jobs_dialog = JobsDialog(self, self.job_manager)
        self.jobs_button = JobsButton(horizontal=True, parent=self)
        self.jobs_button.initialize(self.jobs_dialog, self.job_manager)
        # }}}

        LayoutMixin.init_layout_mixin(self)
        DeviceMixin.init_device_mixin(self)

        self.progress_indicator = ProgressIndicator(self)
        self.progress_indicator.pos = (0, 20)
        self.verbose = opts.verbose
        self.get_metadata = GetMetadata()
        self.upload_memory = {}
        self.metadata_dialogs = []
        self.default_thumbnail = None
        self.tb_wrapper = textwrap.TextWrapper(width=40)
        self.viewers = collections.deque()
        self.system_tray_icon = None
        if config['systray_icon']:
            self.system_tray_icon = factory(
                app_id='com.calibre-ebook.gui').create_system_tray_icon(
                    parent=self, title='calibre')
        if self.system_tray_icon is not None:
            self.system_tray_icon.setIcon(QIcon(I('lt.png')))
            if not (iswindows or isosx):
                self.system_tray_icon.setIcon(
                    QIcon.fromTheme('calibre-gui', QIcon(I('lt.png'))))
            self.system_tray_icon.setToolTip(self.jobs_button.tray_tooltip())
            self.system_tray_icon.setVisible(True)
            self.jobs_button.tray_tooltip_updated.connect(
                self.system_tray_icon.setToolTip)
        elif config['systray_icon']:
            prints(
                'Failed to create system tray icon, your desktop environment probably does not support the StatusNotifier spec'
            )
        self.system_tray_menu = QMenu(self)
        self.toggle_to_tray_action = self.system_tray_menu.addAction(
            QIcon(I('page.png')), '')
        self.toggle_to_tray_action.triggered.connect(
            self.system_tray_icon_activated)
        self.system_tray_menu.addAction(self.donate_action)
        self.donate_button.clicked.connect(self.donate_action.trigger)
        self.donate_button.setToolTip(self.donate_action.text().replace(
            '&', ''))
        self.donate_button.setIcon(self.donate_action.icon())
        self.donate_button.setStatusTip(self.donate_button.toolTip())
        self.eject_action = self.system_tray_menu.addAction(
            QIcon(I('eject.png')), _('&Eject connected device'))
        self.eject_action.setEnabled(False)
        self.addAction(self.quit_action)
        self.system_tray_menu.addAction(self.quit_action)
        self.keyboard.register_shortcut('quit calibre',
                                        _('Quit calibre'),
                                        default_keys=('Ctrl+Q', ),
                                        action=self.quit_action)
        if self.system_tray_icon is not None:
            self.system_tray_icon.setContextMenu(self.system_tray_menu)
            self.system_tray_icon.activated.connect(
                self.system_tray_icon_activated)
        self.quit_action.triggered[bool].connect(self.quit)
        self.donate_action.triggered[bool].connect(self.donate)

        self.esc_action = QAction(self)
        self.addAction(self.esc_action)
        self.keyboard.register_shortcut('clear current search',
                                        _('Clear the current search'),
                                        default_keys=('Esc', ),
                                        action=self.esc_action)
        self.esc_action.triggered.connect(self.esc)

        self.shift_esc_action = QAction(self)
        self.addAction(self.shift_esc_action)
        self.keyboard.register_shortcut('focus book list',
                                        _('Focus the book list'),
                                        default_keys=('Shift+Esc', ),
                                        action=self.shift_esc_action)
        self.shift_esc_action.triggered.connect(self.shift_esc)

        self.ctrl_esc_action = QAction(self)
        self.addAction(self.ctrl_esc_action)
        self.keyboard.register_shortcut('clear virtual library',
                                        _('Clear the virtual library'),
                                        default_keys=('Ctrl+Esc', ),
                                        action=self.ctrl_esc_action)
        self.ctrl_esc_action.triggered.connect(self.ctrl_esc)

        self.alt_esc_action = QAction(self)
        self.addAction(self.alt_esc_action)
        self.keyboard.register_shortcut('clear additional restriction',
                                        _('Clear the additional restriction'),
                                        default_keys=('Alt+Esc', ),
                                        action=self.alt_esc_action)
        self.alt_esc_action.triggered.connect(
            self.clear_additional_restriction)

        # ###################### Start spare job server ########################
        QTimer.singleShot(1000, self.create_spare_pool)

        # ###################### Location Manager ########################
        self.location_manager.location_selected.connect(self.location_selected)
        self.location_manager.unmount_device.connect(
            self.device_manager.umount_device)
        self.location_manager.configure_device.connect(
            self.configure_connected_device)
        self.location_manager.update_device_metadata.connect(
            self.update_metadata_on_device)
        self.eject_action.triggered.connect(self.device_manager.umount_device)

        # ################### Update notification ###################
        UpdateMixin.init_update_mixin(self, opts)

        # ###################### Search boxes ########################
        SearchRestrictionMixin.init_search_restirction_mixin(self)
        SavedSearchBoxMixin.init_saved_seach_box_mixin(self)

        # ###################### Library view ########################
        LibraryViewMixin.init_library_view_mixin(self, db)
        SearchBoxMixin.init_search_box_mixin(self)  # Requires current_db

        if show_gui:
            self.show()

        if self.system_tray_icon is not None and self.system_tray_icon.isVisible(
        ) and opts.start_in_tray:
            self.hide_windows()
        self.library_view.model().count_changed_signal.connect(
            self.iactions['Choose Library'].count_changed)
        if not gprefs.get('quick_start_guide_added', False):
            try:
                add_quick_start_guide(self.library_view)
            except:
                import traceback
                traceback.print_exc()
        for view in ('library', 'memory', 'card_a', 'card_b'):
            v = getattr(self, '%s_view' % view)
            v.selectionModel().selectionChanged.connect(self.update_status_bar)
            v.model().count_changed_signal.connect(self.update_status_bar)

        self.library_view.model().count_changed()
        self.bars_manager.database_changed(self.library_view.model().db)
        self.library_view.model().database_changed.connect(
            self.bars_manager.database_changed, type=Qt.QueuedConnection)

        # ########################## Tags Browser ##############################
        TagBrowserMixin.init_tag_browser_mixin(self, db)

        # ######################## Search Restriction ##########################
        if db.prefs['virtual_lib_on_startup']:
            self.apply_virtual_library(db.prefs['virtual_lib_on_startup'])
        self.rebuild_vl_tabs()

        # ########################## Cover Flow ################################

        CoverFlowMixin.init_cover_flow_mixin(self)

        self._calculated_available_height = min(max_available_height() - 15,
                                                self.height())
        self.resize(self.width(), self._calculated_available_height)

        self.build_context_menus()

        for ac in self.iactions.values():
            try:
                ac.gui_layout_complete()
            except:
                import traceback
                traceback.print_exc()
                if ac.plugin_path is None:
                    raise

        if config['autolaunch_server']:
            self.start_content_server()

        self.keyboard_interrupt.connect(self.quit, type=Qt.QueuedConnection)

        self.read_settings()
        self.finalize_layout()
        if self.bars_manager.showing_donate:
            self.donate_button.start_animation()
        self.set_window_title()

        for ac in self.iactions.values():
            try:
                ac.initialization_complete()
            except:
                import traceback
                traceback.print_exc()
                if ac.plugin_path is None:
                    raise
        self.set_current_library_information(current_library_name(),
                                             db.library_id, db.field_metadata)

        register_keyboard_shortcuts()
        self.keyboard.finalize()
        self.auto_adder = AutoAdder(gprefs['auto_add_path'], self)

        self.save_layout_state()

        # Collect cycles now
        gc.collect()

        if show_gui and self.gui_debug is not None:
            QTimer.singleShot(10, self.show_gui_debug_msg)

        self.iactions['Connect Share'].check_smartdevice_menus()
        QTimer.singleShot(1, self.start_smartdevice)
        QTimer.singleShot(100, self.update_toggle_to_tray_action)
Beispiel #32
0
    def __init__(self,
                 pathtoebook=None,
                 debug_javascript=False,
                 open_at=None,
                 start_in_fullscreen=False,
                 continue_reading=False):
        MainWindow.__init__(self, debug_javascript)
        self.view.magnification_changed.connect(self.magnification_changed)
        self.closed = False
        self.show_toc_on_open = False
        self.current_book_has_toc = False
        self.iterator = None
        self.current_page = None
        self.pending_search = None
        self.pending_search_dir = None
        self.pending_anchor = None
        self.pending_reference = None
        self.pending_bookmark = None
        self.pending_restore = False
        self.pending_goto_page = None
        self.cursor_hidden = False
        self.existing_bookmarks = []
        self.selected_text = None
        self.was_maximized = False
        self.page_position_on_footnote_toggle = []
        self.read_settings()
        self.autosave_timer = t = QTimer(self)
        t.setInterval(self.AUTOSAVE_INTERVAL * 1000), t.setSingleShot(True)
        t.timeout.connect(self.autosave)
        self.pos.value_changed.connect(self.update_pos_label)
        self.pos.value_changed.connect(self.autosave_timer.start)
        self.pos.setMinimumWidth(150)
        self.setFocusPolicy(Qt.StrongFocus)
        self.view.set_manager(self)
        self.pi = ProgressIndicator(self)
        self.action_quit = QAction(_('&Quit'), self)
        self.addAction(self.action_quit)
        self.view_resized_timer = QTimer(self)
        self.view_resized_timer.timeout.connect(self.viewport_resize_finished)
        self.view_resized_timer.setSingleShot(True)
        self.resize_in_progress = False
        self.action_reload = QAction(_('&Reload book'), self)
        self.action_reload.triggered.connect(self.reload_book)
        self.action_quit.triggered.connect(self.quit)
        self.action_reference_mode.triggered[bool].connect(
            self.view.reference_mode)
        self.action_metadata.triggered[bool].connect(self.metadata.setVisible)
        self.action_table_of_contents.toggled[bool].connect(
            self.set_toc_visible)
        self.action_copy.triggered[bool].connect(self.copy)
        self.action_font_size_larger.triggered.connect(self.font_size_larger)
        self.action_font_size_smaller.triggered.connect(self.font_size_smaller)
        self.action_open_ebook.triggered[bool].connect(self.open_ebook)
        self.action_next_page.triggered.connect(self.view.next_page)
        self.action_previous_page.triggered.connect(self.view.previous_page)
        self.action_find_next.triggered.connect(self.find_next)
        self.action_find_previous.triggered.connect(self.find_previous)
        self.action_full_screen.triggered[bool].connect(self.toggle_fullscreen)
        self.action_back.triggered[bool].connect(self.back)
        self.action_forward.triggered[bool].connect(self.forward)
        self.action_preferences.triggered.connect(self.do_config)
        self.pos.editingFinished.connect(self.goto_page_num)
        self.vertical_scrollbar.valueChanged[int].connect(
            lambda x: self.goto_page(x / 100.))
        self.search.search.connect(self.find)
        self.search.focus_to_library.connect(
            lambda: self.view.setFocus(Qt.OtherFocusReason))
        self.toc.pressed[QModelIndex].connect(self.toc_clicked)
        self.toc.searched.connect(partial(self.toc_clicked, force=True))

        def toggle_toc(ev):
            try:
                key = self.view.shortcuts.get_match(ev)
            except AttributeError:
                pass
            if key == 'Table of Contents':
                ev.accept()
                self.action_table_of_contents.trigger()
                return True
            return False

        self.toc.handle_shortcuts = toggle_toc
        self.reference.goto.connect(self.goto)
        self.bookmarks.edited.connect(self.bookmarks_edited)
        self.bookmarks.activated.connect(self.goto_bookmark)
        self.bookmarks.create_requested.connect(self.bookmark)

        self.set_bookmarks([])
        self.load_theme_menu()

        if pathtoebook is not None:
            f = functools.partial(self.load_ebook,
                                  pathtoebook,
                                  open_at=open_at)
            QTimer.singleShot(50, f)
        elif continue_reading:
            QTimer.singleShot(50, self.continue_reading)
        self.window_mode_changed = None
        self.toggle_toolbar_action = QAction(_('Show/hide controls'), self)
        self.toggle_toolbar_action.setCheckable(True)
        self.toggle_toolbar_action.triggered.connect(self.toggle_toolbars)
        self.toolbar_hidden = None
        self.addAction(self.toggle_toolbar_action)
        self.full_screen_label_anim = QPropertyAnimation(
            self.full_screen_label, b'size')
        self.clock_timer = QTimer(self)
        self.clock_timer.timeout.connect(self.update_clock)

        self.action_print.triggered.connect(self.print_book)
        self.clear_recent_history_action = QAction(
            _('Clear list of recently opened books'), self)
        self.clear_recent_history_action.triggered.connect(
            self.clear_recent_history)
        self.build_recent_menu()
        self.open_history_menu.triggered.connect(self.open_recent)

        for x in ('tool_bar', 'tool_bar2'):
            x = getattr(self, x)
            for action in x.actions():
                # So that the keyboard shortcuts for these actions will
                # continue to function even when the toolbars are hidden
                self.addAction(action)

        for plugin in self.view.document.all_viewer_plugins:
            plugin.customize_ui(self)
        self.view.document.settings_changed.connect(self.settings_changed)

        self.restore_state()
        self.settings_changed()
        self.action_toggle_paged_mode.toggled[bool].connect(
            self.toggle_paged_mode)
        if (start_in_fullscreen or self.view.document.start_in_fullscreen):
            self.action_full_screen.trigger()
        self.hide_cursor_timer = t = QTimer(self)
        t.setSingleShot(True), t.setInterval(3000)
        t.timeout.connect(self.hide_cursor)
        t.start()
Beispiel #33
0
    def do_multiple_book_action(self):
        if self.wasCanceled():
            return self.do_close()
        if self.i >= self.total_count:
            return self.do_close()
        book_info = self.books[self.i]
        self.i += 1

        book_id, dtitle, format_dict = book_info[0], book_info[1], book_info[2]

        all_formats = self.db.formats(book_id,
                                      index_is_id=True,
                                      verify_formats=True)
        if all_formats is not None:
            all_formats = all_formats.split(',')
        else:
            all_formats = []

        self.setWindowTitle(
            _('{0} {1} {2} ({3} issues)...').format(self.action_type,
                                                    self.total_count,
                                                    self.status_msg_type,
                                                    len(self.failures)))
        self.setLabelText(_('{0}: {1}').format(self.action_type, dtitle))

        if self.target_format in format_dict.keys():
            format = format_dict[self.target_format].get_format_details()
            kindle_obj = format['kindle_obj']

            if not kindle_obj.isEncrypted:
                if getattr(kindle_obj, self.attr):
                    if format['goal_format'] not in all_formats:
                        target_format = self.target_format
                        if format['goal_format'] == 'ZIP':
                            target_format = 'ZIP'
                        success, error = self.callback_fn(
                            kindle_obj, book_id, target_format, True)
                        if success:
                            self.successes.append((book_id, dtitle))
                        elif error is None:
                            self.failures.append((
                                5, dtitle,
                                _('{0} already has a {1} format. Won\'t overwrite.'
                                  ).format(dtitle, format['goal_format'])))
                        else:
                            self.failures.append(
                                (4, dtitle,
                                 _('Unknown error processing {0}\'s {1} format'
                                   ).format(dtitle, self.target_format)))
                    else:
                        self.failures.append((
                            5, dtitle,
                            _('{0} already has a {1} format. Won\'t overwrite.'
                              ).format(dtitle, format['goal_format'])))
                else:
                    self.failures.append(
                        (3, dtitle,
                         _('{0}\'s {1} format is not a {2} book.').format(
                             dtitle, self.target_format, self.kindle_type)))
            else:
                self.failures.append(
                    (2, dtitle, _('{0} is encrypted.').format(dtitle)))
        else:
            self.failures.append(
                (1, dtitle, _('{0} has no {1} format to work with.').format(
                    dtitle, self.target_format)))

        self.setValue(self.i)

        QTimer.singleShot(0, self.do_multiple_book_action)
Beispiel #34
0
 def setEditorData(self, editor, index):
     name = unicode(index.data(NAME_ROLE) or '')
     # We do this because Qt calls selectAll() unconditionally on the
     # editor, and we want only a part of the file name to be selected
     QTimer.singleShot(0, partial(self.set_editor_data, name, editor))
Beispiel #35
0
 def title_changed(self, title):
     if self.wait_for_title and title == self.wait_for_title and self.load_complete:
         QTimer.singleShot(self.settle_time, self.print_to_pdf)
Beispiel #36
0
 def display(self):
     if not self.isVisible():
         self.show()
     self.raise_()
     QTimer.singleShot(0, self.model.build)
Beispiel #37
0
 def add_url(self):
     self.items.append(URLItem(None, self))
     self.l.addWidget(self.items[-1])
     QTimer.singleShot(100, self.scroll_to_bottom)
Beispiel #38
0
 def spare_pool(self):
     ans, self._spare_pool = self._spare_pool, None
     QTimer.singleShot(1000, self.create_spare_pool)
     return ans
Beispiel #39
0
    def eventFilter(self, obj, event):  # noqa C901
        '''
        @param: obj QObject
        @param: event QEvent
        '''
        evtype = event.type()
        # Keyboard events are sent to parent widget
        if obj == self and evtype == QEvent.ParentChange and self.parentWidget():
            self.parentWidget().installEventFilter(self)

        # Hack to find widget that receives input events
        if obj == self and evtype == QEvent.ChildAdded:
            if const.QTWEBENGINEWIDGETS_VERSION >= const.QT_VERSION_CHECK(5, 12, 0):
                # NOTE: qobject_cast<QWidget*>(static_cast<QChildEvent*>(event)->child());
                assert(isinstance(event, QChildEvent))
                child = event.child()
                #assert(isinstance(child, QWidget))

                def xxx():
                    if not sip.isdeleted(child) and \
                            child.inherits('QtWebEngineCore::RenderWidgetHostViewQtDelegateWidget'):
                        self._rwhvqt = child
                        self._rwhvqt.installEventFilter(self)
                        w = self._rwhvqt
                        if isinstance(w, QQuickWidget):
                            w.setClearColor(self.palette().color(QPalette.Window))
                QTimer.singleShot(0, xxx)
            else:
                def yyy():
                    focusProxy = self.focusProxy()
                    if focusProxy and self._rwhvqt != focusProxy:
                        self._rwhvqt = focusProxy
                        self._rwhvqt.installEventFilter(self)
                        w = self._rwhvqt
                        if isinstance(w, QQuickWidget):
                            w.setClearColor(self.palette().color(QPalette.Window))
                QTimer.singleShot(0, yyy)

        def _HANDLE_EVENT(f, t):
            wasAccepted = event.isAccepted()
            event.setAccepted(False)
            f(event)
            ret = event.isAccepted()
            event.setAccepted(wasAccepted)
            return ret
        # Forward events to WebView
        if obj == self._rwhvqt:
            if evtype == QEvent.MouseButtonPress:
                return _HANDLE_EVENT(self._mousePressEvent, QMouseEvent)
            elif evtype == QEvent.MouseButtonRelease:
                return _HANDLE_EVENT(self.mouseReleaseEvent, QMouseEvent)
            elif evtype == QEvent.MouseMove:
                return _HANDLE_EVENT(self.mouseMoveEvent, QMouseEvent)
            elif evtype == QEvent.Wheel:
                return _HANDLE_EVENT(self._wheelEvent, QWheelEvent)

        if obj == self.parentWidget():
            if evtype == QEvent.KeyPress:
                return _HANDLE_EVENT(self._keyPressEvent, QKeyEvent)
            if evtype == QEvent.KeyRelease:
                return _HANDLE_EVENT(self._keyReleaseEvent, QKeyEvent)

        # Block already handled events
        if obj == self:
            if evtype in (QEvent.KeyPress, QEvent.KeyRelease,
                    QEvent.MouseButtonPress, QEvent.MouseButtonRelease,
                    QEvent.MouseMove, QEvent.Wheel):
                return True
            if evtype == QEvent.Hide:
                if self.isFullScreen():
                    self.triggerPageAction(QWebEnginePage.ExitFullScreen)

        res = super().eventFilter(obj, event)

        if obj == self._rwhvqt:
            if evtype in (QEvent.FocusIn, QEvent.FocusOut):
                self.focusChanged.emit(self.hasFocus())

        return res
Beispiel #40
0
    def __init__(self, parent=None, initial=None):
        QDialog.__init__(self, parent)
        self.setWindowTitle(_('Choose a texture'))

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

        self.tdir = texture_dir()

        self.images = il = QListWidget(self)
        il.itemDoubleClicked.connect(self.accept, type=Qt.QueuedConnection)
        il.setIconSize(QSize(256, 256))
        il.setViewMode(il.IconMode)
        il.setFlow(il.LeftToRight)
        il.setSpacing(20)
        il.setSelectionMode(il.SingleSelection)
        il.itemSelectionChanged.connect(self.update_remove_state)
        l.addWidget(il)

        self.ad = ad = QLabel(
            _('The builtin textures come from <a href="http://subtlepatterns.com">subtlepatterns.com</a>.'
              ))
        ad.setOpenExternalLinks(True)
        ad.setWordWrap(True)
        l.addWidget(ad)
        self.bb = bb = QDialogButtonBox(QDialogButtonBox.Ok
                                        | QDialogButtonBox.Cancel)
        bb.accepted.connect(self.accept)
        bb.rejected.connect(self.reject)
        b = self.add_button = bb.addButton(_('Add texture'), bb.ActionRole)
        b.setIcon(QIcon(I('plus.png')))
        b.clicked.connect(self.add_texture)
        b = self.remove_button = bb.addButton(_('Remove texture'),
                                              bb.ActionRole)
        b.setIcon(QIcon(I('minus.png')))
        b.clicked.connect(self.remove_texture)
        l.addWidget(bb)

        images = [{
            'fname':
            ':' + os.path.basename(x),
            'path':
            x,
            'name':
            ' '.join(
                map(string.capitalize,
                    os.path.splitext(os.path.basename(x))[0].split('_')))
        } for x in glob.glob(I('textures/*.png'))] + [
            {
                'fname': os.path.basename(x),
                'path': x,
                'name': os.path.splitext(os.path.basename(x))[0],
            } for x in glob.glob(os.path.join(self.tdir, '*'))
            if x.rpartition('.')[-1].lower() in {'jpeg', 'png', 'jpg'}
        ]

        images.sort(key=lambda x: sort_key(x['name']))

        map(self.create_item, images)
        self.update_remove_state()

        if initial:
            existing = {
                unicode(i.data(Qt.UserRole) or ''): i
                for i in (self.images.item(c)
                          for c in xrange(self.images.count()))
            }
            item = existing.get(initial, None)
            if item is not None:
                item.setSelected(True)
                QTimer.singleShot(100, partial(il.scrollToItem, item))

        self.resize(QSize(950, 650))
Beispiel #41
0
 def sync_to_editor(self, name, sourceline_address):
     self.current_sync_request = (name, sourceline_address)
     QTimer.singleShot(100, self._sync_to_editor)
Beispiel #42
0
    def create_docks(self):
        def create(name, oname):
            oname += '-dock'
            d = QDockWidget(name, self)
            d.setObjectName(oname)  # Needed for saveState
            ac = d.toggleViewAction()
            desc = _('Toggle %s') % name.replace('&', '')
            self.keyboard.register_shortcut(oname,
                                            desc,
                                            description=desc,
                                            action=ac,
                                            group=_('Windows'))
            actions[oname] = ac
            setattr(self, oname.replace('-', '_'), d)
            return d

        d = create(_('File browser'), 'files-browser')
        d.setAllowedAreas(Qt.LeftDockWidgetArea | Qt.RightDockWidgetArea)
        self.file_list = FileListWidget(d)
        d.setWidget(self.file_list)
        self.addDockWidget(Qt.LeftDockWidgetArea, d)

        d = create(_('File preview'), 'preview')
        d.setAllowedAreas(Qt.LeftDockWidgetArea | Qt.RightDockWidgetArea)
        self.preview = Preview(d)
        d.setWidget(self.preview)
        self.addDockWidget(Qt.RightDockWidgetArea, d)

        d = create(_('Live CSS'), 'live-css')
        d.setAllowedAreas(Qt.LeftDockWidgetArea | Qt.RightDockWidgetArea
                          | Qt.BottomDockWidgetArea | Qt.TopDockWidgetArea)
        self.live_css = LiveCSS(self.preview, parent=d)
        d.setWidget(self.live_css)
        self.addDockWidget(Qt.RightDockWidgetArea, d)
        d.close()  # Hidden by default

        d = create(_('Check book'), 'check-book')
        d.setAllowedAreas(Qt.LeftDockWidgetArea | Qt.RightDockWidgetArea
                          | Qt.BottomDockWidgetArea | Qt.TopDockWidgetArea)
        d.setWidget(self.check_book)
        self.addDockWidget(Qt.TopDockWidgetArea, d)
        d.close()  # By default the check window is closed

        d = create(_('Inspector'), 'inspector')
        d.setAllowedAreas(Qt.LeftDockWidgetArea | Qt.RightDockWidgetArea
                          | Qt.BottomDockWidgetArea | Qt.TopDockWidgetArea)
        d.setWidget(self.preview.inspector)
        self.preview.inspector.setParent(d)
        self.addDockWidget(Qt.BottomDockWidgetArea, d)
        d.close()  # By default the inspector window is closed
        QTimer.singleShot(10, self.preview.inspector.connect_to_dock)

        d = create(_('Table of Contents'), 'toc-viewer')
        d.setAllowedAreas(Qt.LeftDockWidgetArea | Qt.RightDockWidgetArea
                          | Qt.BottomDockWidgetArea | Qt.TopDockWidgetArea)
        d.setWidget(self.toc_view)
        self.addDockWidget(Qt.LeftDockWidgetArea, d)
        d.close()  # Hidden by default

        d = create(_('Text search'), 'text-search')
        d.setAllowedAreas(Qt.LeftDockWidgetArea | Qt.RightDockWidgetArea
                          | Qt.BottomDockWidgetArea | Qt.TopDockWidgetArea)
        d.setWidget(self.text_search)
        self.addDockWidget(Qt.LeftDockWidgetArea, d)
        d.close()  # Hidden by default

        d = create(_('Checkpoints'), 'checkpoints')
        d.setAllowedAreas(Qt.LeftDockWidgetArea | Qt.RightDockWidgetArea
                          | Qt.BottomDockWidgetArea | Qt.TopDockWidgetArea)
        self.checkpoints = CheckpointView(self.boss.global_undo, parent=d)
        d.setWidget(self.checkpoints)
        self.addDockWidget(Qt.LeftDockWidgetArea, d)
        d.close()  # Hidden by default

        d = create(_('Saved searches'), 'saved-searches')
        d.setAllowedAreas(Qt.LeftDockWidgetArea | Qt.RightDockWidgetArea
                          | Qt.BottomDockWidgetArea | Qt.TopDockWidgetArea)
        d.setWidget(self.saved_searches)
        self.addDockWidget(Qt.LeftDockWidgetArea, d)
        d.close()  # Hidden by default
Beispiel #43
0
    def __init__(self, parent=None):
        super().__init__(parent)
        self._completer = None  # LocationCompleter
        self._domainCompleterModel = None  # QStringListModel

        self._bookmarkIcon = None  # BookmarksIcon
        self._goIcon = None  # GoIcon
        self._siteIcon = None  # SiteIcon
        self._autofillIcon = None  # AutoFillIcon

        self._window = None  # BrowserWindow
        self._webView = None  # TabbedWebView

        self._holdingAlt = False
        self._oldTextLength = 0
        self._currentTextLength = 0

        self._loadProgress = 0
        self._progressVisible = True
        self._progressStyle = 0  # ProgressStyle
        self._progressColor = QColor()
        self._progressTimer = None  # QTimer

        self.setObjectName('locationbar')
        self.setDragEnabled(True)

        # Disable KDE QLineEdit transitions, it breaks with setText() && home()
        self._bookmarkIcon = BookmarksIcon(self)
        self._goIcon = GoIcon(self)
        self._siteIcon = SiteIcon(self)
        self._autofillIcon = AutoFillIcon(self)
        down = DownIcon(self)

        self.addWidget(self._siteIcon, LineEdit.LeftSide)
        self.addWidget(self._autofillIcon, LineEdit.RightSide)
        self.addWidget(self._bookmarkIcon, LineEdit.RightSide)
        self.addWidget(self._goIcon, LineEdit.RightSide)
        self.addWidget(down, LineEdit.RightSide)

        self._completer = LocationCompleter(self)
        self._completer.setLocationBar(self)
        self._completer.showCompletion.connect(self._showCompletion)
        self._completer.showDomainCompletion.connect(
            self._showDomainCompletion)
        self._completer.clearCompletion.connect(self._clearCompletion)
        self._completer.loadRequested.connect(self.loadRequest)
        self._completer.popupClosed.connect(self._updateSiteIcon)

        self._domainCompleterModel = QStringListModel(self)
        domainCompleter = QCompleter(self)
        domainCompleter.setCompletionMode(QCompleter.InlineCompletion)
        domainCompleter.setModel(self._domainCompleterModel)
        self.setCompleter(domainCompleter)

        self._progressTimer = QTimer(self)
        self._progressTimer.setInterval(700)
        self._progressTimer.setSingleShot(True)
        self._progressTimer.timeout.connect(self._hideProgress)

        self.editAction(self.PasteAndGo).setText(_('Paste And &Go'))
        self.editAction(self.PasteAndGo).setIcon(QIcon.fromTheme('edit-paste'))
        self.editAction(self.PasteAndGo).triggered.connect(self._pasteAndGo)

        self.textEdited.connect(self._textEdited)
        self._goIcon.clicked.connect(self._requestLoadUrl)
        down.clicked.connect(self._completer.showMostVisited)
        # TODO:
        #gVar.app.searchEnginesManager().activeEngineChanged.connect(self._updatePlaceHolderText)
        #gVar.app.searchEnginesManager().defaultEngineChanged.connect(self._updatePlaceHolderText)

        self._loadSettings()

        self._updateSiteIcon()

        # Hide icons by default
        self._goIcon.setVisible(gVar.appSettings.alwaysShowGoIcon)
        self._autofillIcon.hide()

        QTimer.singleShot(0, self._updatePlaceHolderText)
Beispiel #44
0
 def show_frag(self):
     self.view.show_frag(self.current_frag)
     QTimer.singleShot(1, self.check_frag)
Beispiel #45
0
    def eventFilter(self, obj, e):
        'Redirect key presses from the popup to the widget'
        widget = self.completer_widget()
        if widget is None or sip.isdeleted(widget):
            return False
        etype = e.type()
        if obj is not self:
            return QObject.eventFilter(self, obj, e)

        # self.debug_event(e)

        if etype == e.KeyPress:
            try:
                key = e.key()
            except AttributeError:
                return QObject.eventFilter(self, obj, e)
            if key == Qt.Key_Escape:
                self.hide()
                e.accept()
                return True
            if key == Qt.Key_F4 and e.modifiers() & Qt.AltModifier:
                self.hide()
                e.accept()
                return True
            if key in (Qt.Key_Enter, Qt.Key_Return):
                # We handle this explicitly because on OS X activated() is
                # not emitted on pressing Enter.
                idx = self.currentIndex()
                if idx.isValid():
                    self.item_chosen(idx)
                self.hide()
                e.accept()
                return True
            if key == Qt.Key_Tab:
                idx = self.currentIndex()
                if idx.isValid():
                    self.item_chosen(idx)
                    self.hide()
                elif self.model().rowCount() > 0:
                    self.next_match()
                e.accept()
                return True
            if key in (Qt.Key_PageUp, Qt.Key_PageDown):
                # Let the list view handle these keys
                return False
            if key in (Qt.Key_Up, Qt.Key_Down):
                self.next_match(previous=key == Qt.Key_Up)
                e.accept()
                return True
            # Send to widget
            widget.eat_focus_out = False
            widget.keyPressEvent(e)
            widget.eat_focus_out = True
            if not widget.hasFocus():
                # Widget lost focus hide the popup
                self.hide()
            if e.isAccepted():
                return True
        elif isosx and etype == e.InputMethodQuery and e.queries() == (
                Qt.ImHints | Qt.ImEnabled) and self.isVisible():
            # In Qt 5 the Esc key causes this event and the line edit does not
            # handle it, which causes the parent dialog to be closed
            # See https://bugreports.qt-project.org/browse/QTBUG-41806
            e.accept()
            return True
        elif etype == e.MouseButtonPress and hasattr(
                e, 'globalPos') and not self.rect().contains(
                    self.mapFromGlobal(e.globalPos())):
            # A click outside the popup, close it
            if isinstance(widget, QComboBox):
                # This workaround is needed to ensure clicking on the drop down
                # arrow of the combobox closes the popup
                opt = QStyleOptionComboBox()
                widget.initStyleOption(opt)
                sc = widget.style().hitTestComplexControl(
                    QStyle.CC_ComboBox, opt,
                    widget.mapFromGlobal(e.globalPos()), widget)
                if sc == QStyle.SC_ComboBoxArrow:
                    QTimer.singleShot(0, self.hide)
                    e.accept()
                    return True
            self.hide()
            e.accept()
            return True
        elif etype in (e.InputMethod, e.ShortcutOverride):
            QApplication.sendEvent(widget, e)
        return False
Beispiel #46
0
 def start(self):
     t = self.thread = Thread(target=self.vacuum)
     t.daemon = True
     t.start()
     QTimer.singleShot(100, self.check)
     self.exec_()
    def __init__(self, opts):
        self.matched_ids = set()
        self.opts = opts
        self.prefs = opts.prefs
        super(FindAnnotationsDialog, self).__init__(self.opts.gui,
                                                    'find_annotations_dialog')
        self.setWindowTitle(_('Find Annotations'))
        self.setWindowIcon(self.opts.icon)
        self.l = QVBoxLayout(self)
        self.setLayout(self.l)

        self.search_criteria_gb = QGroupBox(self)
        self.search_criteria_gb.setTitle(_("Search criteria"))
        self.scgl = QGridLayout(self.search_criteria_gb)
        self.l.addWidget(self.search_criteria_gb)
        # addWidget(widget, row, col, rowspan, colspan)

        row = 0
        # ~~~~~~~~ Create the Readers comboBox ~~~~~~~~
        self.reader_label = QLabel(_('Reader'))
        self.reader_label.setAlignment(Qt.AlignRight | Qt.AlignVCenter)
        self.scgl.addWidget(self.reader_label, row, 0, 1, 1)

        self.find_annotations_reader_comboBox = QComboBox()
        self.find_annotations_reader_comboBox.setObjectName(
            'find_annotations_reader_comboBox')
        self.find_annotations_reader_comboBox.setToolTip(
            _('Reader annotations to search for'))

        self.find_annotations_reader_comboBox.addItem(self.GENERIC_READER)
        racs = ReaderApp.get_reader_app_classes()
        for ra in sorted(list(racs.keys())):
            self.find_annotations_reader_comboBox.addItem(ra)
        self.scgl.addWidget(self.find_annotations_reader_comboBox, row, 1, 1,
                            4)
        row += 1

        # ~~~~~~~~ Create the Styles comboBox ~~~~~~~~
        self.style_label = QLabel(_('Style'))
        self.style_label.setAlignment(Qt.AlignRight | Qt.AlignVCenter)
        self.scgl.addWidget(self.style_label, row, 0, 1, 1)

        self.find_annotations_color_comboBox = QComboBox()
        self.find_annotations_color_comboBox.setObjectName(
            'find_annotations_color_comboBox')
        self.find_annotations_color_comboBox.setToolTip(
            _('Annotation style to search for'))

        self.find_annotations_color_comboBox.addItem(self.GENERIC_STYLE)
        all_colors = list(COLOR_MAP.keys())
        all_colors.remove('Default')
        for color in sorted(all_colors):
            self.find_annotations_color_comboBox.addItem(color)
        self.scgl.addWidget(self.find_annotations_color_comboBox, row, 1, 1, 4)
        row += 1

        # ~~~~~~~~ Create the Text LineEdit control ~~~~~~~~
        self.text_label = QLabel(_('Text'))
        self.text_label.setAlignment(Qt.AlignRight | Qt.AlignVCenter)
        self.scgl.addWidget(self.text_label, row, 0, 1, 1)
        self.find_annotations_text_lineEdit = MyLineEdit()
        self.find_annotations_text_lineEdit.setObjectName(
            'find_annotations_text_lineEdit')
        self.scgl.addWidget(self.find_annotations_text_lineEdit, row, 1, 1, 3)
        self.reset_text_tb = QToolButton()
        self.reset_text_tb.setObjectName('reset_text_tb')
        self.reset_text_tb.setToolTip(_('Clear search criteria'))
        self.reset_text_tb.setIcon(QIcon(I('trash.png')))
        self.reset_text_tb.clicked.connect(self.clear_text_field)
        self.scgl.addWidget(self.reset_text_tb, row, 4, 1, 1)
        row += 1

        # ~~~~~~~~ Create the Note LineEdit control ~~~~~~~~
        self.note_label = QLabel(_('Note'))
        self.note_label.setAlignment(Qt.AlignRight | Qt.AlignVCenter)
        self.scgl.addWidget(self.note_label, row, 0, 1, 1)
        self.find_annotations_note_lineEdit = MyLineEdit()
        self.find_annotations_note_lineEdit.setObjectName(
            'find_annotations_note_lineEdit')
        self.scgl.addWidget(self.find_annotations_note_lineEdit, row, 1, 1, 3)
        self.reset_note_tb = QToolButton()
        self.reset_note_tb.setObjectName('reset_note_tb')
        self.reset_note_tb.setToolTip(_('Clear search criteria'))
        self.reset_note_tb.setIcon(QIcon(I('trash.png')))
        self.reset_note_tb.clicked.connect(self.clear_note_field)
        self.scgl.addWidget(self.reset_note_tb, row, 4, 1, 1)
        row += 1

        # ~~~~~~~~ Create the Date range controls ~~~~~~~~
        self.date_range_label = QLabel(_('Date range'))
        self.date_range_label.setAlignment(Qt.AlignRight | Qt.AlignVCenter)
        self.scgl.addWidget(self.date_range_label, row, 0, 1, 1)

        # Date 'From'
        self.find_annotations_date_from_dateEdit = MyDateEdit(
            self, datetime(1970, 1, 1))
        self.find_annotations_date_from_dateEdit.setObjectName(
            'find_annotations_date_from_dateEdit')
        #self.find_annotations_date_from_dateEdit.current_val = datetime(1970,1,1)
        self.find_annotations_date_from_dateEdit.clear_button.clicked.connect(
            self.find_annotations_date_from_dateEdit.reset_from_date)
        self.scgl.addWidget(self.find_annotations_date_from_dateEdit, row, 1,
                            1, 1)
        self.scgl.addWidget(
            self.find_annotations_date_from_dateEdit.clear_button, row, 2, 1,
            1)

        # Date 'To'
        self.find_annotations_date_to_dateEdit = MyDateEdit(
            self, datetime.today())
        self.find_annotations_date_to_dateEdit.setObjectName(
            'find_annotations_date_to_dateEdit')
        #self.find_annotations_date_to_dateEdit.current_val = datetime.today()
        self.find_annotations_date_to_dateEdit.clear_button.clicked.connect(
            self.find_annotations_date_to_dateEdit.reset_to_date)
        self.scgl.addWidget(self.find_annotations_date_to_dateEdit, row, 3, 1,
                            1)
        self.scgl.addWidget(
            self.find_annotations_date_to_dateEdit.clear_button, row, 4, 1, 1)
        row += 1

        # ~~~~~~~~ Create a horizontal line ~~~~~~~~
        self.hl = QFrame(self)
        self.hl.setGeometry(QRect(0, 0, 1, 3))
        self.hl.setFrameShape(QFrame.HLine)
        self.hl.setFrameShadow(QFrame.Raised)
        self.scgl.addWidget(self.hl, row, 0, 1, 5)
        row += 1

        # ~~~~~~~~ Create the results label field ~~~~~~~~
        self.result_label = QLabel('<p style="color:red">{0}</p>'.format(
            _('scanning…')))
        self.result_label.setAlignment(Qt.AlignCenter)
        self.result_label.setWordWrap(False)

        sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Minimum,
                                       QtGui.QSizePolicy.Maximum)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(
            self.result_label.sizePolicy().hasHeightForWidth())
        self.result_label.setSizePolicy(sizePolicy)
        self.result_label.setMinimumSize(QtCore.QSize(250, 0))
        self.scgl.addWidget(self.result_label, row, 0, 1, 5)
        row += 1

        # ~~~~~~~~ Create the ButtonBox ~~~~~~~~
        self.dialogButtonBox = QDialogButtonBox(self)
        self.dialogButtonBox.setOrientation(Qt.Horizontal)
        if False:
            self.update_button = QPushButton(_('Update results'))
            self.update_button.setDefault(True)
            self.update_button.setVisible(False)
            self.dialogButtonBox.addButton(self.update_button,
                                           QDialogButtonBox.ActionRole)

        self.cancel_button = self.dialogButtonBox.addButton(
            self.dialogButtonBox.Cancel)
        self.find_button = self.dialogButtonBox.addButton(
            self.dialogButtonBox.Ok)
        self.find_button.setText(_('Find Matching Books'))

        self.l.addWidget(self.dialogButtonBox)
        self.dialogButtonBox.clicked.connect(
            self.find_annotations_dialog_clicked)

        # ~~~~~~~~ Add a spacer ~~~~~~~~
        self.spacerItem = QtGui.QSpacerItem(20, 40, QtGui.QSizePolicy.Minimum,
                                            QtGui.QSizePolicy.Expanding)
        self.l.addItem(self.spacerItem)

        # ~~~~~~~~ Restore previously saved settings ~~~~~~~~
        self.restore_settings()

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

        # ~~~~~~~~ Connect all signals ~~~~~~~~
        self.find_annotations_reader_comboBox.currentIndexChanged.connect(
            partial(self.update_results, 'reader'))
        self.find_annotations_color_comboBox.currentIndexChanged.connect(
            partial(self.update_results, 'color'))
        self.find_annotations_text_lineEdit.editingFinished.connect(
            partial(self.update_results, 'text'))
        self.find_annotations_note_lineEdit.editingFinished.connect(
            partial(self.update_results, 'note'))
        #        self.connect(self.find_annotations_text_lineEdit, pyqtSignal("return_pressed"), self.return_pressed)
        self.find_annotations_text_lineEdit.return_pressed.connect(
            self.return_pressed)
        #        self.connect(self.find_annotations_note_lineEdit, pyqtSignal("return_pressed"), self.return_pressed)
        self.find_annotations_note_lineEdit.return_pressed.connect(
            self.return_pressed)

        # Date range signals connected in inventory_available()

        # ~~~~~~~~ Allow dialog to render before doing inventory ~~~~~~~~
        #field = self.prefs.get('cfg_annotations_destination_field', None)
        field = get_cc_mapping('annotations', 'field', None)
        self.annotated_books_scanner = InventoryAnnotatedBooks(
            self.opts.gui, field, get_date_range=True)
        self.annotated_books_scanner.signal.connect(self.inventory_available)
        QTimer.singleShot(1, self.start_inventory_scan)
Beispiel #48
0
    def setup_ui(self):
        self.l = l = QVBoxLayout(self)
        self.setLayout(l)

        self.h = h = QHBoxLayout()
        self.filter_text = ft = QLineEdit(self)
        ft.textChanged.connect(self.do_filter)
        ft.setPlaceholderText(_('Filter displayed searches'))
        h.addWidget(ft)
        self.cft = cft = QToolButton(self)
        cft.setToolTip(_('Clear filter')), cft.setIcon(QIcon(I('clear_left.png')))
        cft.clicked.connect(ft.clear)
        h.addWidget(cft)
        l.addLayout(h)

        self.h2 = h = QHBoxLayout()
        self.searches = searches = QListView(self)
        self.stack = stack = QStackedLayout()
        self.main_widget = mw = QWidget(self)
        stack.addWidget(mw)
        self.edit_search_widget = es = EditSearch(mw)
        stack.addWidget(es)
        es.done.connect(self.search_editing_done)
        mw.v = QVBoxLayout(mw)
        mw.v.setContentsMargins(0, 0, 0, 0)
        mw.v.addWidget(searches)
        searches.doubleClicked.connect(self.edit_search)
        self.model = SearchesModel(self.searches)
        self.model.dataChanged.connect(self.show_details)
        searches.setModel(self.model)
        searches.selectionModel().currentChanged.connect(self.show_details)
        searches.setSelectionMode(searches.ExtendedSelection)
        self.delegate = SearchDelegate(searches)
        searches.setItemDelegate(self.delegate)
        searches.setAlternatingRowColors(True)
        h.addLayout(stack, stretch=10)
        self.v = v = QVBoxLayout()
        h.addLayout(v)
        l.addLayout(h)
        stack.currentChanged.connect(self.stack_current_changed)

        def pb(text, tooltip=None):
            b = AnimatablePushButton(text, self)
            b.setToolTip(tooltip or '')
            b.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Fixed)
            return b

        mulmsg = '\n\n' + _('The entries are tried in order until the first one matches.')
        self.action_button_map = {}

        for text, action, tooltip in [
                (_('&Find'), 'find', _('Run the search using the selected entries.') + mulmsg),
                (_('&Replace'), 'replace', _('Run replace using the selected entries.') + mulmsg),
                (_('Replace a&nd Find'), 'replace-find', _('Run replace and then find using the selected entries.') + mulmsg),
                (_('Replace &all'), 'replace-all', _('Run Replace All for all selected entries in the order selected')),
                (_('&Count all'), 'count', _('Run Count All for all selected entries')),
        ]:
            self.action_button_map[action] = b = pb(text, tooltip)
            v.addWidget(b)
            b.clicked.connect(partial(self.run_search, action))

        self.d1 = d = QFrame(self)
        d.setFrameStyle(QFrame.HLine)
        v.addWidget(d)

        self.h3 = h = QHBoxLayout()
        self.upb = b = QToolButton(self)
        b.setIcon(QIcon(I('arrow-up.png'))), b.setToolTip(_('Move selected entries up'))
        b.clicked.connect(partial(self.move_entry, -1))
        self.dnb = b = QToolButton(self)
        b.setIcon(QIcon(I('arrow-down.png'))), b.setToolTip(_('Move selected entries down'))
        b.clicked.connect(partial(self.move_entry, 1))
        h.addWidget(self.upb), h.addWidget(self.dnb)
        v.addLayout(h)

        self.eb = b = pb(_('&Edit search'), _('Edit the currently selected search'))
        b.clicked.connect(self.edit_search)
        v.addWidget(b)

        self.rb = b = pb(_('Re&move search'), _('Remove the currently selected searches'))
        b.clicked.connect(self.remove_search)
        v.addWidget(b)

        self.ab = b = pb(_('&Add search'), _('Add a new saved search'))
        b.clicked.connect(self.add_search)
        v.addWidget(b)

        self.d2 = d = QFrame(self)
        d.setFrameStyle(QFrame.HLine)
        v.addWidget(d)

        self.where_box = wb = WhereBox(self, emphasize=True)
        self.where = SearchWidget.DEFAULT_STATE['where']
        v.addWidget(wb)
        self.direction_box = db = DirectionBox(self)
        self.direction = SearchWidget.DEFAULT_STATE['direction']
        v.addWidget(db)

        self.wr = wr = QCheckBox(_('&Wrap'))
        wr.setToolTip('<p>'+_('When searching reaches the end, wrap around to the beginning and continue the search'))
        self.wr.setChecked(SearchWidget.DEFAULT_STATE['wrap'])
        v.addWidget(wr)

        self.d3 = d = QFrame(self)
        d.setFrameStyle(QFrame.HLine)
        v.addWidget(d)

        self.description = d = QLabel(' \n \n ')
        d.setTextFormat(Qt.PlainText)
        d.setWordWrap(True)
        mw.v.addWidget(d)

        self.ib = b = pb(_('&Import'), _('Import saved searches'))
        b.clicked.connect(self.import_searches)
        v.addWidget(b)

        self.eb2 = b = pb(_('E&xport'), _('Export saved searches'))
        v.addWidget(b)
        self.em = m = QMenu(_('Export'))
        m.addAction(_('Export All'), lambda : QTimer.singleShot(0, partial(self.export_searches, all=True)))
        m.addAction(_('Export Selected'), lambda : QTimer.singleShot(0, partial(self.export_searches, all=False)))
        b.setMenu(m)

        self.searches.setFocus(Qt.OtherFocusReason)
Beispiel #49
0
 def update(self):
     if self.restorer.is_alive():
         QTimer.singleShot(10, self.update)
     else:
         self.restorer.progress_callback = lambda x, y: x
         self.accept()
Beispiel #50
0
    def __init__(self, type_, startUrl=QUrl()):
        super().__init__(None)
        self._startUrl = startUrl
        self._homepage = QUrl()
        self._windowType = type_
        self._startTab = None  # WebTab
        self._startPage = None  # WebPage
        self._mainLayout = None  # QVBoxLayout
        self._mainSplitter = None  # QSplitter
        self._tabWidget = None  # TabWidget
        self._sideBar = None  # QPointer<SideBar>
        self._sideBarManager = SideBarManager(self)
        self._statusBar = None

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

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

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

        self._sideBarWidth = 0
        self._webViewWidth = 0

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

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

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

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

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

        self._setupUi()
        self._setupMenu()

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

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

        QTimer.singleShot(0, self._postLaunch)

        if gVar.app.isPrivate():
            gVar.appTools.setWmClass(
                '%s Browser (Private Window)' % const.APPNAME, self)
        else:
            gVar.appTools.setWmClass('%s Browser' % const.APPNAME, self)
Beispiel #51
0
 def check_exited(self):
     if getattr(self.gui.content_server, 'is_running', False):
         QTimer.singleShot(50, self.check_exited)
         return
     self.gui.content_server = None
     self.stopping_msg.accept()
Beispiel #52
0
    widget.move(pos)


if __name__ == '__main__':
    app = QApplication(sys.argv)

    lifetime_ms = 3000
    if len(sys.argv) == 2:
        lifetime_ms = int(sys.argv[1])

    pix = QPixmap(FILE_NAME)

    mw = QLabel()
    mw.setWindowFlag(Qt.WindowStaysOnTopHint)
    mw.setWindowFlag(Qt.FramelessWindowHint)
    mw.setPixmap(pix)
    mw.setMask(pix.mask())

    mw.show()

    move_window_to_cursor(mw)

    timer = QTimer()
    timer.timeout.connect(lambda: move_window_to_cursor(mw))
    timer.start(33)

    QTimer.singleShot(lifetime_ms, app.quit)

    app.exec()
Beispiel #53
0
 def start(self):
     self.restorer.start()
     QTimer.singleShot(10, self.update)
Beispiel #54
0
    def do_add(self, data):
        from calibre.ebooks.metadata.opf2 import OPF

        gui = self.parent()
        if gui is None:
            return
        m = gui.library_view.model()
        count = 0

        needs_rescan = False
        duplicates = []
        added_ids = set()

        for fname, tdir in data:
            paths = [os.path.join(self.worker.path, fname)]
            sz = os.path.join(tdir, 'size.txt')
            try:
                with open(sz, 'rb') as f:
                    sz = int(f.read())
                if sz != os.stat(paths[0]).st_size:
                    raise Exception('Looks like the file was written to after'
                                    ' we tried to read metadata')
            except:
                needs_rescan = True
                try:
                    self.worker.staging.remove(fname)
                except KeyError:
                    pass

                continue

            mi = os.path.join(tdir, 'metadata.opf')
            if not os.access(mi, os.R_OK):
                continue
            mi = OPF(open(mi, 'rb'), tdir,
                     populate_spine=False).to_book_metadata()
            if gprefs.get('tag_map_on_add_rules'):
                from calibre.ebooks.metadata.tag_mapper import map_tags
                mi.tags = map_tags(mi.tags, gprefs['tag_map_on_add_rules'])
            mi = [mi]
            dups, ids = m.add_books(
                paths, [os.path.splitext(fname)[1][1:].upper()],
                mi,
                add_duplicates=not gprefs['auto_add_check_for_duplicates'],
                return_ids=True)
            added_ids |= set(ids)
            num = len(ids)
            if dups:
                path = dups[0][0]
                with open(
                        os.path.join(tdir, 'dup_cache.' + dups[1][0].lower()),
                        'wb') as dest, open(path, 'rb') as src:
                    shutil.copyfileobj(src, dest)
                    dups[0][0] = dest.name
                duplicates.append(dups)

            try:
                os.remove(paths[0])
                self.worker.staging.remove(fname)
            except:
                import traceback
                traceback.print_exc()
            count += num

        if duplicates:
            paths, formats, metadata = [], [], []
            for p, f, mis in duplicates:
                paths.extend(p)
                formats.extend(f)
                metadata.extend(mis)
            dups = [(mic, mic.cover, [p]) for mic, p in zip(metadata, paths)]
            d = DuplicatesQuestion(m.db, dups, parent=gui)
            dups = tuple(d.duplicates)
            if dups:
                paths, formats, metadata = [], [], []
                for mi, cover, book_paths in dups:
                    paths.extend(book_paths)
                    formats.extend([p.rpartition('.')[-1] for p in book_paths])
                    metadata.extend([mi for i in book_paths])
                ids = m.add_books(paths,
                                  formats,
                                  metadata,
                                  add_duplicates=True,
                                  return_ids=True)[1]
                added_ids |= set(ids)
                num = len(ids)
                count += num

        for fname, tdir in data:
            try:
                shutil.rmtree(tdir)
            except:
                pass

        if added_ids and gprefs['auto_add_auto_convert']:
            self.auto_convert.emit(added_ids)

        if count > 0:
            m.books_added(count)
            gui.status_bar.show_message(
                ngettext('Added a book automatically from {src}',
                         'Added {num} books automatically from {src}',
                         count).format(num=count, src=self.worker.path), 2000)
            gui.refresh_cover_browser()

        if needs_rescan:
            QTimer.singleShot(2000, self.dir_changed)
Beispiel #55
0
 def _on_spacings_combo_changed(self):
     if self.is_use_available:
         self._set_forwards_combo_to_available()
     QTimer.singleShot(0, self._check_if_valid)
 def update(self):
     if self.worker.is_alive():
         QTimer.singleShot(50, self.update)
     else:
         self.process_results()
Beispiel #57
0
    def dump(self, items, out_stream, pdf_metadata):
        opts = self.opts
        page_size = get_page_size(self.opts)
        xdpi, ydpi = self.view.logicalDpiX(), self.view.logicalDpiY()

        def margin(which):
            val = getattr(opts, 'pdf_page_margin_' + which)
            if val == 0.0:
                val = getattr(opts, 'margin_' + which)
            return val

        ml, mr, mt, mb = map(margin, 'left right top bottom'.split())
        # We cannot set the side margins in the webview as there is no right
        # margin for the last page (the margins are implemented with
        # -webkit-column-gap)
        self.doc = PdfDevice(out_stream,
                             page_size=page_size,
                             left_margin=ml,
                             top_margin=0,
                             right_margin=mr,
                             bottom_margin=0,
                             xdpi=xdpi,
                             ydpi=ydpi,
                             errors=self.log.error,
                             debug=self.log.debug,
                             compress=not opts.uncompressed_pdf,
                             opts=opts,
                             mark_links=opts.pdf_mark_links)
        self.footer = opts.pdf_footer_template
        if self.footer:
            self.footer = self.footer.strip()
        if not self.footer and opts.pdf_page_numbers:
            self.footer = '<p style="text-align:center; text-indent: 0">_PAGENUM_</p>'
        self.header = opts.pdf_header_template
        if self.header:
            self.header = self.header.strip()
        min_margin = 1.5 * opts._final_base_font_size
        if self.footer and mb < min_margin:
            self.log.warn(
                'Bottom margin is too small for footer, increasing it to %.1fpts'
                % min_margin)
            mb = min_margin
        if self.header and mt < min_margin:
            self.log.warn(
                'Top margin is too small for header, increasing it to %.1fpts'
                % min_margin)
            mt = min_margin

        self.page.setViewportSize(QSize(self.doc.width(), self.doc.height()))
        self.render_queue = items
        self.total_items = len(items)

        mt, mb = map(self.doc.to_px, (mt, mb))
        self.margin_top, self.margin_bottom = map(lambda x: int(floor(x)),
                                                  (mt, mb))

        self.painter = QPainter(self.doc)
        self.doc.set_metadata(title=pdf_metadata.title,
                              author=pdf_metadata.author,
                              tags=pdf_metadata.tags,
                              mi=pdf_metadata.mi)
        self.doc_title = pdf_metadata.title
        self.doc_author = pdf_metadata.author
        self.painter.save()
        try:
            if self.cover_data is not None:
                p = QPixmap()
                try:
                    p.loadFromData(self.cover_data)
                except TypeError:
                    self.log.warn(
                        'This ebook does not have a raster cover, cannot generate cover for PDF'
                        '. Cover type: %s' % type(self.cover_data))
                if not p.isNull():
                    self.doc.init_page()
                    draw_image_page(QRect(*self.doc.full_page_rect),
                                    self.painter,
                                    p,
                                    preserve_aspect_ratio=self.opts.
                                    preserve_cover_aspect_ratio)
                    self.doc.end_page()
        finally:
            self.painter.restore()

        QTimer.singleShot(0, self.render_book)
        if self.loop.exec_() == 1:
            raise Exception('PDF Output failed, see log for details')

        if self.toc is not None and len(self.toc) > 0:
            self.doc.add_outline(self.toc)

        self.painter.end()

        if self.doc.errors_occurred:
            raise Exception('PDF Output failed, see log for details')
Beispiel #58
0
 def cover_view_resized(self, event):
     QTimer.singleShot(1, self.resize_cover)
Beispiel #59
0
 def test(editor):
     c = editor.__c = CompletionPopup(editor.editor, max_height=100)
     items = 'a ab abc abcd abcde abcdef abcdefg abcdefgh'.split()
     m = Matcher(items)
     c.set_items(m('a'), descriptions={x: x for x in items})
     QTimer.singleShot(100, c.show)
Beispiel #60
0
    def do_book(self):
        if self.i >= len(self.book_ids):
            return self.do_queue()
        book_id = self.book_ids[self.i]
        self.i += 1

        temp_files = []

        try:
            input_format = get_input_format_for_book(self.db, book_id, None)[0]
            input_fmt = self.db.original_fmt(book_id, input_format).lower()
            same_fmt = input_fmt == self.output_format.lower()
            mi, opf_file = create_opf_file(self.db, book_id)
            in_file = PersistentTemporaryFile('.' + input_format)
            with in_file:
                self.db.copy_format_to(book_id,
                                       input_fmt,
                                       in_file,
                                       index_is_id=True)

            out_file = PersistentTemporaryFile('.' + self.output_format)
            out_file.write(as_bytes(self.output_format))
            out_file.close()
            temp_files = [in_file]

            combined_recs = GuiRecommendations()
            default_recs = bulk_defaults_for_input_format(input_format)
            for key in default_recs:
                combined_recs[key] = default_recs[key]
            if self.use_saved_single_settings:
                specific_recs = load_specifics(self.db, book_id)
                for key in specific_recs:
                    combined_recs[key] = specific_recs[key]
            for item in self.user_recs:
                combined_recs[item[0]] = item[1]
            save_specifics(self.db, book_id, combined_recs)
            lrecs = list(combined_recs.to_recommendations())
            from calibre.customize.ui import plugin_for_output_format
            op = plugin_for_output_format(self.output_format)
            if op and op.recommendations:
                prec = {x[0] for x in op.recommendations}
                for i, r in enumerate(list(lrecs)):
                    if r[0] in prec:
                        lrecs[i] = (r[0], r[1], OptionRecommendation.HIGH)

            cover_file = create_cover_file(self.db, book_id)

            if opf_file is not None:
                lrecs.append(('read_metadata_from_opf', opf_file.name,
                              OptionRecommendation.HIGH))
                temp_files.append(opf_file)
            if cover_file is not None:
                lrecs.append(
                    ('cover', cover_file.name, OptionRecommendation.HIGH))
                temp_files.append(cover_file)

            for x in list(lrecs):
                if x[0] == 'debug_pipeline':
                    lrecs.remove(x)
            try:
                dtitle = unicode_type(mi.title)
            except:
                dtitle = repr(mi.title)
            if len(dtitle) > 50:
                dtitle = dtitle[:50].rpartition(' ')[0] + '...'
            self.setLabelText(_('Queueing ') + dtitle)
            desc = _('Convert book %(num)d of %(tot)d (%(title)s)') % dict(
                num=self.i, tot=len(self.book_ids), title=dtitle)

            args = [in_file.name, out_file.name, lrecs]
            temp_files.append(out_file)
            func = 'gui_convert_override'
            if same_fmt:
                func += ':same_fmt'
            self.jobs.append((func, args, desc, self.output_format.upper(),
                              book_id, temp_files))

            self.changed = True
            self.setValue(self.i)
        except NoSupportedInputFormats:
            self.bad.append(book_id)
        QTimer.singleShot(0, self.do_book)