Move the webengine part into a separate module for clarity

This commit is contained in:
Kovid Goyal 2019-09-13 21:11:51 +05:30
parent c946f3239e
commit 3d2c8d3878
No known key found for this signature in database
GPG Key ID: 06BC317B515ACE7C
3 changed files with 21 additions and 167 deletions

View File

@ -266,6 +266,9 @@ The important part of the plugin is in two functions:
.. literalinclude:: plugin_examples/webengine_demo/ui.py
:lines: 47-
.. literalinclude:: plugin_examples/webengine_demo/main.py
:lines: 12-
The ``show_demo()`` function asks the user for a URL and then runs
the ``main()`` function passing it that URL. The ``main()`` function

View File

@ -1,154 +1,22 @@
#!/usr/bin/env python2
# vim:fileencoding=UTF-8:ts=4:sw=4:sta:et:sts=4:ai
# vim:fileencoding=utf-8
# License: GPL v3 Copyright: 2019, Kovid Goyal <kovid at kovidgoyal.net>
from __future__ import absolute_import, division, print_function, unicode_literals
__license__ = 'GPL v3'
__copyright__ = '2011, Kovid Goyal <kovid@kovidgoyal.net>'
__docformat__ = 'restructuredtext en'
from PyQt5.Qt import QUrl
from PyQt5.QtWebEngineWidgets import QWebEngineView
if False:
# This is here to keep my python error checker from complaining about
# the builtin functions that will be defined by the plugin loading system
# You do not need this code in your plugins
get_icons = get_resources = None
from PyQt5.Qt import QDialog, QVBoxLayout, QPushButton, QMessageBox, QLabel
from calibre_plugins.interface_demo.config import prefs
from calibre.gui2 import Application
class DemoDialog(QDialog):
def __init__(self, gui, icon, do_user_config):
QDialog.__init__(self, gui)
self.gui = gui
self.do_user_config = do_user_config
# The current database shown in the GUI
# db is an instance of the class LibraryDatabase from db/legacy.py
# This class has many, many methods that allow you to do a lot of
# things. For most purposes you should use db.new_api, which has
# a much nicer interface from db/cache.py
self.db = gui.current_db
self.l = QVBoxLayout()
self.setLayout(self.l)
self.label = QLabel(prefs['hello_world_msg'])
self.l.addWidget(self.label)
self.setWindowTitle('Interface Plugin Demo')
self.setWindowIcon(icon)
self.about_button = QPushButton('About', self)
self.about_button.clicked.connect(self.about)
self.l.addWidget(self.about_button)
self.marked_button = QPushButton(
'Show books with only one format in the calibre GUI', self)
self.marked_button.clicked.connect(self.marked)
self.l.addWidget(self.marked_button)
self.view_button = QPushButton(
'View the most recently added book', self)
self.view_button.clicked.connect(self.view)
self.l.addWidget(self.view_button)
self.update_metadata_button = QPushButton(
'Update metadata in a book\'s files', self)
self.update_metadata_button.clicked.connect(self.update_metadata)
self.l.addWidget(self.update_metadata_button)
self.conf_button = QPushButton(
'Configure this plugin', self)
self.conf_button.clicked.connect(self.config)
self.l.addWidget(self.conf_button)
self.resize(self.sizeHint())
def about(self):
# Get the about text from a file inside the plugin zip file
# The get_resources function is a builtin function defined for all your
# plugin code. It loads files from the plugin zip file. It returns
# the bytes from the specified file.
#
# Note that if you are loading more than one file, for performance, you
# should pass a list of names to get_resources. In this case,
# get_resources will return a dictionary mapping names to bytes. Names that
# are not found in the zip file will not be in the returned dictionary.
text = get_resources('about.txt')
QMessageBox.about(self, 'About the Interface Plugin Demo',
text.decode('utf-8'))
def marked(self):
''' Show books with only one format '''
db = self.db.new_api
matched_ids = {book_id for book_id in db.all_book_ids() if len(db.formats(book_id)) == 1}
# Mark the records with the matching ids
# new_api does not know anything about marked books, so we use the full
# db object
self.db.set_marked_ids(matched_ids)
# Tell the GUI to search for all marked records
self.gui.search.setEditText('marked:true')
self.gui.search.do_search()
def view(self):
''' View the most recently added book '''
most_recent = most_recent_id = None
db = self.db.new_api
for book_id, timestamp in db.all_field_for('timestamp', db.all_book_ids()).items():
if most_recent is None or timestamp > most_recent:
most_recent = timestamp
most_recent_id = book_id
if most_recent_id is not None:
# Get a reference to the View plugin
view_plugin = self.gui.iactions['View']
# Ask the view plugin to launch the viewer for row_number
view_plugin._view_calibre_books([most_recent_id])
def update_metadata(self):
'''
Set the metadata in the files in the selected book's record to
match the current metadata in the database.
'''
from calibre.ebooks.metadata.meta import set_metadata
from calibre.gui2 import error_dialog, info_dialog
# Get currently selected books
rows = self.gui.library_view.selectionModel().selectedRows()
if not rows or len(rows) == 0:
return error_dialog(self.gui, 'Cannot update metadata',
'No books selected', show=True)
# Map the rows to book ids
ids = list(map(self.gui.library_view.model().id, rows))
db = self.db.new_api
for book_id in ids:
# Get the current metadata for this book from the db
mi = db.get_metadata(book_id, get_cover=True, cover_as_data=True)
fmts = db.formats(book_id)
if not fmts:
continue
for fmt in fmts:
fmt = fmt.lower()
# Get a python file object for the format. This will be either
# an in memory file or a temporary on disk file
ffile = db.format(book_id, fmt, as_file=True)
ffile.seek(0)
# Set metadata in the format
set_metadata(ffile, mi, fmt)
ffile.seek(0)
# Now replace the file in the calibre library with the updated
# file. We dont use add_format_with_hooks as the hooks were
# already run when the file was first added to calibre.
db.add_format(book_id, fmt, ffile, run_hooks=False)
info_dialog(self, 'Updated files',
'Updated the metadata in the files of %d book(s)'%len(ids),
show=True)
def config(self):
self.do_user_config(parent=self)
# Apply the changes
self.label.setText(prefs['hello_world_msg'])
def main(url):
# This function is run in a separate process and can do anything it likes,
# including use QWebEngine. Here it simply opens the passed in URL
# in a QWebEngineView
app = Application([])
w = QWebEngineView()
w.setUrl(QUrl(url))
w.show()
w.raise_()
app.exec_()

View File

@ -11,7 +11,7 @@ if False:
# The class that all interface action plugins must inherit from
from calibre.gui2.actions import InterfaceAction
from PyQt5.Qt import QInputDialog, QUrl
from PyQt5.Qt import QInputDialog
class InterfacePlugin(InterfaceAction):
@ -52,21 +52,4 @@ class InterfacePlugin(InterfaceAction):
return
# Launch a separate process to view the URL in WebEngine
self.gui.job_manager.launch_gui_app('webengine-dialog', kwargs={
'module':'calibre_plugins.webengine_demo.ui', 'url':url})
def main(url):
# This function is run in a separate process and can do anything it likes,
# including use QWebEngine. Here it simply opens the passed in URL
# in a QWebEngineView
# This import must happen before creating the Application() object
from PyQt5.QtWebEngineWidgets import QWebEngineView
from calibre.gui2 import Application
app = Application([])
w = QWebEngineView()
w.setUrl(QUrl(url))
w.show()
w.raise_()
app.exec_()
'module':'calibre_plugins.webengine_demo.main', 'url':url})