mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
Several changes:
1) Remove the ability to open book-details link windows using a query. It was never documented and ui.py didn't support it. 2) Simplify management of book details windows. There can now only be three windows, all non-modal on top of calibre, all with calibre as the parent. Each window has a "purpose". The first is the normal book details slave window, the second is a locked book details window, and the third is a book-details link window. 3) Add more menu actions to Show Book Details: open a locked window and close all book details windows. Use this menu where the menuless qaction was previously used.
This commit is contained in:
parent
c3a83fd891
commit
3e4ce5a341
@ -8,69 +8,88 @@ __docformat__ = 'restructuredtext en'
|
|||||||
from qt.core import Qt, sip
|
from qt.core import Qt, sip
|
||||||
|
|
||||||
from calibre.gui2.actions import InterfaceAction
|
from calibre.gui2.actions import InterfaceAction
|
||||||
from calibre.gui2.dialogs.book_info import BookInfo
|
from calibre.gui2.dialogs.book_info import BookInfo, DialogNumbers
|
||||||
from calibre.gui2 import error_dialog
|
from calibre.gui2 import error_dialog
|
||||||
|
|
||||||
|
|
||||||
class ShowBookDetailsAction(InterfaceAction):
|
class ShowBookDetailsAction(InterfaceAction):
|
||||||
|
|
||||||
name = 'Show Book Details'
|
name = 'Show Book Details'
|
||||||
action_spec = (_('Show Book details'), 'dialog_information.png',
|
action_spec = (_('Book details'), 'dialog_information.png',
|
||||||
_('Show the detailed metadata for the current book in a separate window'), _('I'))
|
_('Show the detailed metadata for the current book in a separate window'), _('I'))
|
||||||
|
action_shortcut_name = _('Show Book details in a separate window')
|
||||||
dont_add_to = frozenset(('context-menu-device',))
|
dont_add_to = frozenset(('context-menu-device',))
|
||||||
action_type = 'current'
|
action_type = 'current'
|
||||||
|
action_add_menu = True
|
||||||
|
action_menu_clone_qaction = _('Show Book details in a separate window')
|
||||||
|
|
||||||
def genesis(self):
|
def genesis(self):
|
||||||
|
self.dialogs = [None, None, None]
|
||||||
|
m = self.qaction.menu()
|
||||||
|
self.show_info_locked = l = self.create_menu_action(m,
|
||||||
|
'show_locked_details', _('Show Book details in a separate locked window'),
|
||||||
|
icon='drm-locked.png', shortcut=None)
|
||||||
|
l.triggered.connect(self.open_locked_window)
|
||||||
|
l = self.create_menu_action(m,
|
||||||
|
'close_all_details', _('Close all book details windows'), icon='close.png', shortcut=None)
|
||||||
|
l.triggered.connect(self.close_all_windows)
|
||||||
self.qaction.triggered.connect(self.show_book_info)
|
self.qaction.triggered.connect(self.show_book_info)
|
||||||
self.dialogs = [None, ]
|
|
||||||
|
|
||||||
def show_book_info(self, *args, **kwargs):
|
def show_book_info(self, *args, **kwargs):
|
||||||
library_path = kwargs.get('library_path', None)
|
library_path = kwargs.get('library_path', None)
|
||||||
book_id = kwargs.get('book_id', None)
|
book_id = kwargs.get('book_id', None)
|
||||||
library_id = kwargs.get('library_id', None)
|
library_id = kwargs.get('library_id', None)
|
||||||
query = kwargs.get('query', None)
|
locked = kwargs.get('locked', False)
|
||||||
index = self.gui.library_view.currentIndex()
|
index = self.gui.library_view.currentIndex()
|
||||||
if self.gui.current_view() is not self.gui.library_view and not library_path:
|
if self.gui.current_view() is not self.gui.library_view and not library_path:
|
||||||
error_dialog(self.gui, _('No detailed info available'),
|
error_dialog(self.gui, _('No detailed info available'),
|
||||||
_('No detailed information is available for books '
|
_('No detailed information is available for books '
|
||||||
'on the device.')).exec()
|
'on the device.')).exec()
|
||||||
return
|
return
|
||||||
if library_path or index.isValid():
|
if library_path:
|
||||||
# Window #0 is slaved to changes in the book list. As such
|
dn = DialogNumbers.DetailsLink
|
||||||
# it must not be used for details from other libraries.
|
else:
|
||||||
for dn,v in enumerate(self.dialogs):
|
if not index.isValid():
|
||||||
if dn == 0 and library_path:
|
|
||||||
continue
|
|
||||||
if v is None:
|
|
||||||
break
|
|
||||||
else:
|
|
||||||
self.dialogs.append(None)
|
|
||||||
dn += 1
|
|
||||||
|
|
||||||
try:
|
|
||||||
d = BookInfo(self.gui, self.gui.library_view, index,
|
|
||||||
self.gui.book_details.handle_click, dialog_number=dn,
|
|
||||||
library_id=library_id, library_path=library_path, book_id=book_id, query=query)
|
|
||||||
except ValueError as e:
|
|
||||||
error_dialog(self.gui, _('Book not found'), str(e)).exec()
|
|
||||||
return
|
return
|
||||||
|
dn = DialogNumbers.Locked if locked else DialogNumbers.Slaved
|
||||||
|
if self.dialogs[dn] is not None:
|
||||||
|
if dn == DialogNumbers.Slaved:
|
||||||
|
# This is the slaved window. It will update automatically
|
||||||
|
return
|
||||||
|
else:
|
||||||
|
# Replace the other windows. There is a signals race condition
|
||||||
|
# between closing the existing window and opening the new one,
|
||||||
|
# so do all the work here
|
||||||
|
d = self.dialogs[dn]
|
||||||
|
d.closed.disconnect(self.closed)
|
||||||
|
d.done(0)
|
||||||
|
self.dialogs[dn] = None
|
||||||
|
try:
|
||||||
|
d = BookInfo(self.gui, self.gui.library_view, index,
|
||||||
|
self.gui.book_details.handle_click, dialog_number=dn,
|
||||||
|
library_id=library_id, library_path=library_path, book_id=book_id)
|
||||||
|
except ValueError as e:
|
||||||
|
error_dialog(self.gui, _('Book not found'), str(e)).exec()
|
||||||
|
return
|
||||||
|
|
||||||
d.open_cover_with.connect(self.gui.bd_open_cover_with, type=Qt.ConnectionType.QueuedConnection)
|
d.open_cover_with.connect(self.gui.bd_open_cover_with, type=Qt.ConnectionType.QueuedConnection)
|
||||||
self.dialogs[dn] = d
|
self.dialogs[dn] = d
|
||||||
d.closed.connect(self.closed, type=Qt.ConnectionType.QueuedConnection)
|
d.closed.connect(self.closed, type=Qt.ConnectionType.QueuedConnection)
|
||||||
d.show()
|
d.show()
|
||||||
|
|
||||||
|
def open_locked_window(self):
|
||||||
|
self.show_book_info(locked=True)
|
||||||
|
|
||||||
def shutting_down(self):
|
def shutting_down(self):
|
||||||
for d in self.dialogs:
|
self.close_all_windows()
|
||||||
if d:
|
|
||||||
d.done(0)
|
def close_all_windows(self):
|
||||||
|
for dialog in [d for d in self.dialogs if d is not None]:
|
||||||
|
dialog.done(0)
|
||||||
|
|
||||||
def library_about_to_change(self, *args):
|
def library_about_to_change(self, *args):
|
||||||
for i,d in enumerate(self.dialogs):
|
for dialog in [d for d in self.dialogs[1:] if d is not None]:
|
||||||
if i == 0:
|
dialog.done(0)
|
||||||
continue
|
|
||||||
if d:
|
|
||||||
d.done(0)
|
|
||||||
|
|
||||||
def closed(self, d):
|
def closed(self, d):
|
||||||
try:
|
try:
|
||||||
|
@ -541,8 +541,7 @@ def details_context_menu_event(view, ev, book_info, add_popup_action=False, edit
|
|||||||
menu.addSeparator()
|
menu.addSeparator()
|
||||||
from calibre.gui2.ui import get_gui
|
from calibre.gui2.ui import get_gui
|
||||||
if add_popup_action:
|
if add_popup_action:
|
||||||
ema = get_gui().iactions['Show Book Details'].menuless_qaction
|
menu.addMenu(get_gui().iactions['Show Book Details'].qaction.menu())
|
||||||
menu.addAction(_('Open the Book details window') + '\t' + ema.shortcut().toString(QKeySequence.SequenceFormat.NativeText), book_info.show_book_info)
|
|
||||||
else:
|
else:
|
||||||
ema = get_gui().iactions['Edit Metadata'].menuless_qaction
|
ema = get_gui().iactions['Edit Metadata'].menuless_qaction
|
||||||
menu.addAction(_('Open the Edit metadata window') + '\t' + ema.shortcut().toString(QKeySequence.SequenceFormat.NativeText), edit_metadata)
|
menu.addAction(_('Open the Edit metadata window') + '\t' + ema.shortcut().toString(QKeySequence.SequenceFormat.NativeText), edit_metadata)
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
# License: GPLv3 Copyright: 2008, Kovid Goyal <kovid at kovidgoyal.net>
|
# License: GPLv3 Copyright: 2008, Kovid Goyal <kovid at kovidgoyal.net>
|
||||||
|
|
||||||
|
|
||||||
|
from enum import IntEnum
|
||||||
import textwrap
|
import textwrap
|
||||||
|
|
||||||
from qt.core import (
|
from qt.core import (
|
||||||
@ -130,14 +131,20 @@ class Details(HTMLDisplay):
|
|||||||
details_context_menu_event(self, ev, self.book_info, edit_metadata=self.edit_metadata)
|
details_context_menu_event(self, ev, self.book_info, edit_metadata=self.edit_metadata)
|
||||||
|
|
||||||
|
|
||||||
|
class DialogNumbers(IntEnum):
|
||||||
|
Slaved = 0
|
||||||
|
Locked = 1
|
||||||
|
DetailsLink = 2
|
||||||
|
|
||||||
|
|
||||||
class BookInfo(QDialog):
|
class BookInfo(QDialog):
|
||||||
|
|
||||||
closed = pyqtSignal(object)
|
closed = pyqtSignal(object)
|
||||||
open_cover_with = pyqtSignal(object, object)
|
open_cover_with = pyqtSignal(object, object)
|
||||||
|
|
||||||
def __init__(self, parent, view, row, link_delegate, dialog_number=None,
|
def __init__(self, parent, view, row, link_delegate, dialog_number=None,
|
||||||
library_id=None, library_path=None, book_id=None, query=None):
|
library_id=None, library_path=None, book_id=None):
|
||||||
QDialog.__init__(self, None, flags=Qt.WindowType.Window)
|
QDialog.__init__(self, parent)
|
||||||
self.dialog_number = dialog_number
|
self.dialog_number = dialog_number
|
||||||
self.library_id = library_id
|
self.library_id = library_id
|
||||||
self.marked = None
|
self.marked = None
|
||||||
@ -179,7 +186,7 @@ class BookInfo(QDialog):
|
|||||||
hl.setContentsMargins(0, 0, 0, 0)
|
hl.setContentsMargins(0, 0, 0, 0)
|
||||||
l2.addLayout(hl, l2.rowCount(), 0, 1, -1)
|
l2.addLayout(hl, l2.rowCount(), 0, 1, -1)
|
||||||
hl.addWidget(self.fit_cover), hl.addStretch()
|
hl.addWidget(self.fit_cover), hl.addStretch()
|
||||||
if self.dialog_number == 0:
|
if self.dialog_number == DialogNumbers.Slaved:
|
||||||
self.previous_button = QPushButton(QIcon.ic('previous.png'), _('&Previous'), self)
|
self.previous_button = QPushButton(QIcon.ic('previous.png'), _('&Previous'), self)
|
||||||
self.previous_button.clicked.connect(self.previous)
|
self.previous_button.clicked.connect(self.previous)
|
||||||
l2.addWidget(self.previous_button, l2.rowCount(), 0)
|
l2.addWidget(self.previous_button, l2.rowCount(), 0)
|
||||||
@ -201,11 +208,6 @@ class BookInfo(QDialog):
|
|||||||
if library_path is not None:
|
if library_path is not None:
|
||||||
self.view = None
|
self.view = None
|
||||||
db = get_gui().library_broker.get_library(library_path)
|
db = get_gui().library_broker.get_library(library_path)
|
||||||
if book_id is None:
|
|
||||||
ids = db.new_api.search(query)
|
|
||||||
if len(ids) == 0:
|
|
||||||
raise ValueError(_('Query "{}" found no books').format(query))
|
|
||||||
book_id = sorted(ids)[0]
|
|
||||||
if not db.new_api.has_id(book_id):
|
if not db.new_api.has_id(book_id):
|
||||||
raise ValueError(_("Book {} doesn't exist").format(book_id))
|
raise ValueError(_("Book {} doesn't exist").format(book_id))
|
||||||
mi = db.new_api.get_metadata(book_id, get_cover=False)
|
mi = db.new_api.get_metadata(book_id, get_cover=False)
|
||||||
@ -219,7 +221,7 @@ class BookInfo(QDialog):
|
|||||||
self.refresh(row, mi)
|
self.refresh(row, mi)
|
||||||
else:
|
else:
|
||||||
self.view = view
|
self.view = view
|
||||||
if dialog_number == 0:
|
if dialog_number == DialogNumbers.Slaved:
|
||||||
self.slave_connected = True
|
self.slave_connected = True
|
||||||
self.view.model().new_bookdisplay_data.connect(self.slave)
|
self.view.model().new_bookdisplay_data.connect(self.slave)
|
||||||
self.refresh(row)
|
self.refresh(row)
|
||||||
@ -246,9 +248,9 @@ class BookInfo(QDialog):
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
def geometry_string(self, txt):
|
def geometry_string(self, txt):
|
||||||
if self.dialog_number is None or self.dialog_number == 0:
|
if self.dialog_number is None or self.dialog_number == DialogNumbers.Slaved:
|
||||||
return txt
|
return txt
|
||||||
return txt + '_' + str(self.dialog_number)
|
return txt + '_' + str(int(self.dialog_number))
|
||||||
|
|
||||||
def sizeHint(self):
|
def sizeHint(self):
|
||||||
try:
|
try:
|
||||||
@ -379,7 +381,7 @@ class BookInfo(QDialog):
|
|||||||
# Indicates books was deleted from library, or row numbers have
|
# Indicates books was deleted from library, or row numbers have
|
||||||
# changed
|
# changed
|
||||||
return
|
return
|
||||||
if self.dialog_number == 0:
|
if self.dialog_number == DialogNumbers.Slaved:
|
||||||
self.previous_button.setEnabled(False if row == 0 else True)
|
self.previous_button.setEnabled(False if row == 0 else True)
|
||||||
self.next_button.setEnabled(False if row == self.view.model().rowCount(QModelIndex())-1 else True)
|
self.next_button.setEnabled(False if row == self.view.model().rowCount(QModelIndex())-1 else True)
|
||||||
self.setWindowTitle(mi.title + ' ' + _('(the current book)'))
|
self.setWindowTitle(mi.title + ' ' + _('(the current book)'))
|
||||||
|
Loading…
x
Reference in New Issue
Block a user