mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
Merge branch 'master' of https://github.com/cbhaley/calibre
This commit is contained in:
commit
2fb78716f9
@ -8,9 +8,9 @@ from collections import namedtuple
|
|||||||
from functools import partial
|
from functools import partial
|
||||||
from qt.core import (
|
from qt.core import (
|
||||||
QAction, QApplication, QClipboard, QColor, QDialog, QEasingCurve, QIcon,
|
QAction, QApplication, QClipboard, QColor, QDialog, QEasingCurve, QIcon,
|
||||||
QKeySequence, QLayout, QMenu, QMimeData, QPainter, QPen, QPixmap,
|
QKeySequence, QMenu, QMimeData, QPainter, QPen, QPixmap,
|
||||||
QPropertyAnimation, QRect, QSize, QSizePolicy, Qt, QUrl, QWidget, pyqtProperty,
|
QPropertyAnimation, QRect, QSize, QSizePolicy, Qt, QUrl, QWidget, pyqtProperty,
|
||||||
pyqtSignal
|
QTimer, pyqtSignal
|
||||||
)
|
)
|
||||||
|
|
||||||
from calibre import fit_image, sanitize_file_name
|
from calibre import fit_image, sanitize_file_name
|
||||||
@ -30,6 +30,7 @@ from calibre.gui2.dialogs.confirm_delete import confirm, confirm as confirm_dele
|
|||||||
from calibre.gui2.dnd import (
|
from calibre.gui2.dnd import (
|
||||||
dnd_get_files, dnd_get_image, dnd_has_extension, dnd_has_image, image_extensions
|
dnd_get_files, dnd_get_image, dnd_has_extension, dnd_has_image, image_extensions
|
||||||
)
|
)
|
||||||
|
from calibre.gui2.widgets import BasicSplitter
|
||||||
from calibre.gui2.widgets2 import HTMLDisplay
|
from calibre.gui2.widgets2 import HTMLDisplay
|
||||||
from calibre.utils.config import tweaks
|
from calibre.utils.config import tweaks
|
||||||
from calibre.utils.img import blend_image, image_from_x
|
from calibre.utils.img import blend_image, image_from_x
|
||||||
@ -548,6 +549,9 @@ class CoverView(QWidget): # {{{
|
|||||||
def setCurrentPixmapSize(self, val):
|
def setCurrentPixmapSize(self, val):
|
||||||
self._current_pixmap_size = val
|
self._current_pixmap_size = val
|
||||||
|
|
||||||
|
def minimumSizeHint(self):
|
||||||
|
return QSize(100, 100)
|
||||||
|
|
||||||
def do_layout(self):
|
def do_layout(self):
|
||||||
if self.rect().width() == 0 or self.rect().height() == 0:
|
if self.rect().width() == 0 or self.rect().height() == 0:
|
||||||
return
|
return
|
||||||
@ -652,7 +656,7 @@ class CoverView(QWidget): # {{{
|
|||||||
book_id = self.data.get('id')
|
book_id = self.data.get('id')
|
||||||
if not book_id:
|
if not book_id:
|
||||||
return
|
return
|
||||||
from calibre.utils.img import image_from_x, remove_borders_from_image
|
from calibre.utils.img import remove_borders_from_image
|
||||||
img = image_from_x(self.pixmap)
|
img = image_from_x(self.pixmap)
|
||||||
nimg = remove_borders_from_image(img)
|
nimg = remove_borders_from_image(img)
|
||||||
if nimg is not img:
|
if nimg is not img:
|
||||||
@ -910,54 +914,56 @@ class BookInfo(HTMLDisplay):
|
|||||||
# }}}
|
# }}}
|
||||||
|
|
||||||
|
|
||||||
class DetailsLayout(QLayout): # {{{
|
class DetailsLayout(BasicSplitter): # {{{
|
||||||
|
|
||||||
def __init__(self, vertical, parent):
|
def __init__(self, vertical, parent):
|
||||||
QLayout.__init__(self, parent)
|
orientation = Qt.Orientation.Vertical if vertical else Qt.Orientation.Horizontal
|
||||||
|
BasicSplitter.__init__(self, orientation, parent)
|
||||||
self.vertical = vertical
|
self.vertical = vertical
|
||||||
|
self.setCollapsible(0, True)
|
||||||
|
|
||||||
self._children = []
|
self._children = []
|
||||||
|
|
||||||
self.min_size = QSize(190, 200) if vertical else QSize(120, 120)
|
self.min_size = QSize(190, 200) if vertical else QSize(120, 120)
|
||||||
self.setContentsMargins(0, 0, 0, 0)
|
self.setContentsMargins(0, 0, 0, 0)
|
||||||
|
self.restore_geometry(gprefs, 'book_details_splitter')
|
||||||
|
self.splitterMoved.connect(self.do_splitter_moved)
|
||||||
|
|
||||||
def minimumSize(self):
|
def minimumSize(self):
|
||||||
return QSize(self.min_size)
|
return QSize(self.min_size)
|
||||||
|
|
||||||
def addItem(self, child):
|
def addWidget(self, child):
|
||||||
if len(self._children) > 2:
|
if len(self._children) > 2:
|
||||||
raise ValueError('This layout can only manage two children')
|
raise ValueError('This layout can only manage two children')
|
||||||
self._children.append(child)
|
self._children.append(child)
|
||||||
|
|
||||||
def itemAt(self, i):
|
|
||||||
try:
|
|
||||||
return self._children[i]
|
|
||||||
except:
|
|
||||||
pass
|
|
||||||
return None
|
|
||||||
|
|
||||||
def takeAt(self, i):
|
|
||||||
try:
|
|
||||||
self._children.pop(i)
|
|
||||||
except:
|
|
||||||
pass
|
|
||||||
return None
|
|
||||||
|
|
||||||
def count(self):
|
def count(self):
|
||||||
return len(self._children)
|
return len(self._children)
|
||||||
|
|
||||||
def sizeHint(self):
|
def sizeHint(self):
|
||||||
return QSize(self.min_size)
|
return QSize(self.min_size)
|
||||||
|
|
||||||
|
def restore_splitter_state(self):
|
||||||
|
s = gprefs.get('book_details_widget_splitter_state')
|
||||||
|
if s is not None:
|
||||||
|
self.restoreState(s)
|
||||||
|
self.setOrientation(Qt.Orientation.Vertical if self.vertical else Qt.Orientation.Horizontal)
|
||||||
|
|
||||||
def setGeometry(self, r):
|
def setGeometry(self, r):
|
||||||
QLayout.setGeometry(self, r)
|
BasicSplitter.setGeometry(self, r)
|
||||||
self.do_layout(r)
|
self.do_layout(r)
|
||||||
|
self.restore_splitter_state()
|
||||||
|
|
||||||
|
def do_splitter_moved(self, *args):
|
||||||
|
gprefs['book_details_widget_splitter_state'] = bytearray(self.saveState())
|
||||||
|
self._children[0].do_layout()
|
||||||
|
|
||||||
def cover_height(self, r):
|
def cover_height(self, r):
|
||||||
if not self._children[0].widget().isVisible():
|
if not self._children[0].isVisible():
|
||||||
return 0
|
return 0
|
||||||
mh = min(int(r.height()//2), int(4/3 * r.width())+1)
|
mh = min(int(r.height()//2), int(4/3 * r.width())+1)
|
||||||
try:
|
try:
|
||||||
ph = self._children[0].widget().pixmap.height()
|
ph = self._children[0].pixmap.height()
|
||||||
except:
|
except:
|
||||||
ph = 0
|
ph = 0
|
||||||
if ph > 0:
|
if ph > 0:
|
||||||
@ -965,11 +971,11 @@ class DetailsLayout(QLayout): # {{{
|
|||||||
return mh
|
return mh
|
||||||
|
|
||||||
def cover_width(self, r):
|
def cover_width(self, r):
|
||||||
if not self._children[0].widget().isVisible():
|
if not self._children[0].isVisible():
|
||||||
return 0
|
return 0
|
||||||
mw = 1 + int(3/4 * r.height())
|
mw = 1 + int(3/4 * r.height())
|
||||||
try:
|
try:
|
||||||
pw = self._children[0].widget().pixmap.width()
|
pw = self._children[0].pixmap.width()
|
||||||
except:
|
except:
|
||||||
pw = 0
|
pw = 0
|
||||||
if pw > 0:
|
if pw > 0:
|
||||||
@ -979,7 +985,11 @@ class DetailsLayout(QLayout): # {{{
|
|||||||
def do_layout(self, rect):
|
def do_layout(self, rect):
|
||||||
if len(self._children) != 2:
|
if len(self._children) != 2:
|
||||||
return
|
return
|
||||||
left, top, right, bottom = self.getContentsMargins()
|
cm = self.contentsMargins()
|
||||||
|
left = cm.left()
|
||||||
|
top = cm.top()
|
||||||
|
right = cm.right()
|
||||||
|
bottom = cm.top()
|
||||||
r = rect.adjusted(+left, +top, -right, -bottom)
|
r = rect.adjusted(+left, +top, -right, -bottom)
|
||||||
x = r.x()
|
x = r.x()
|
||||||
y = r.y()
|
y = r.y()
|
||||||
@ -987,20 +997,20 @@ class DetailsLayout(QLayout): # {{{
|
|||||||
if self.vertical:
|
if self.vertical:
|
||||||
ch = self.cover_height(r)
|
ch = self.cover_height(r)
|
||||||
cover.setGeometry(QRect(x, y, r.width(), ch))
|
cover.setGeometry(QRect(x, y, r.width(), ch))
|
||||||
cover.widget().do_layout()
|
|
||||||
y += ch + 5
|
y += ch + 5
|
||||||
details.setGeometry(QRect(x, y, r.width(), r.height()-ch-5))
|
details.setGeometry(QRect(x, y, r.width(), r.height()-ch-5))
|
||||||
else:
|
else:
|
||||||
cw = self.cover_width(r)
|
cw = self.cover_width(r)
|
||||||
cover.setGeometry(QRect(x, y, cw, r.height()))
|
cover.setGeometry(QRect(x, y, cw, r.height()))
|
||||||
cover.widget().do_layout()
|
|
||||||
x += cw + 5
|
x += cw + 5
|
||||||
details.setGeometry(QRect(x, y, r.width() - cw - 5, r.height()))
|
details.setGeometry(QRect(x, y, r.width() - cw - 5, r.height()))
|
||||||
|
self.restore_splitter_state() # only required on first call to do_layout, but ...
|
||||||
|
self.save_geometry(gprefs, 'book_details_splitter')
|
||||||
|
cover.do_layout()
|
||||||
# }}}
|
# }}}
|
||||||
|
|
||||||
|
|
||||||
class BookDetails(QWidget): # {{{
|
class BookDetails(DetailsLayout): # {{{
|
||||||
|
|
||||||
show_book_info = pyqtSignal()
|
show_book_info = pyqtSignal()
|
||||||
open_containing_folder = pyqtSignal(int)
|
open_containing_folder = pyqtSignal(int)
|
||||||
@ -1072,11 +1082,10 @@ class BookDetails(QWidget): # {{{
|
|||||||
# }}}
|
# }}}
|
||||||
|
|
||||||
def __init__(self, vertical, parent=None):
|
def __init__(self, vertical, parent=None):
|
||||||
QWidget.__init__(self, parent)
|
DetailsLayout.__init__(self, vertical, parent)
|
||||||
self.last_data = {}
|
self.last_data = {}
|
||||||
self.setAcceptDrops(True)
|
self.setAcceptDrops(True)
|
||||||
self._layout = DetailsLayout(vertical, self)
|
self._layout = self
|
||||||
self.setLayout(self._layout)
|
|
||||||
self.current_path = ''
|
self.current_path = ''
|
||||||
|
|
||||||
self.cover_view = CoverView(vertical, self)
|
self.cover_view = CoverView(vertical, self)
|
||||||
|
@ -6,7 +6,7 @@ import textwrap
|
|||||||
from qt.core import (
|
from qt.core import (
|
||||||
QAction, QApplication, QBrush, QCheckBox, QDialog, QGridLayout,
|
QAction, QApplication, QBrush, QCheckBox, QDialog, QGridLayout,
|
||||||
QHBoxLayout, QIcon, QKeySequence, QLabel, QListView, QModelIndex, QPalette,
|
QHBoxLayout, QIcon, QKeySequence, QLabel, QListView, QModelIndex, QPalette,
|
||||||
QPixmap, QPushButton, QShortcut, QSize, QSplitter, Qt, QTimer, QToolButton,
|
QPixmap, QPushButton, QShortcut, QSize, Qt, QTimer, QToolButton,
|
||||||
QVBoxLayout, QWidget, pyqtSignal, QDialogButtonBox
|
QVBoxLayout, QWidget, pyqtSignal, QDialogButtonBox
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -17,7 +17,7 @@ from calibre.gui2.book_details import (
|
|||||||
set_html
|
set_html
|
||||||
)
|
)
|
||||||
from calibre.gui2.ui import get_gui
|
from calibre.gui2.ui import get_gui
|
||||||
from calibre.gui2.widgets import CoverView
|
from calibre.gui2.widgets import CoverView, BasicSplitter
|
||||||
from calibre.gui2.widgets2 import Dialog, HTMLDisplay
|
from calibre.gui2.widgets2 import Dialog, HTMLDisplay
|
||||||
|
|
||||||
|
|
||||||
@ -136,7 +136,7 @@ class BookInfo(QDialog):
|
|||||||
QDialog.__init__(self, parent)
|
QDialog.__init__(self, parent)
|
||||||
self.marked = None
|
self.marked = None
|
||||||
self.gui = parent
|
self.gui = parent
|
||||||
self.splitter = QSplitter(self)
|
self.splitter = BasicSplitter(self)
|
||||||
self._l = l = QVBoxLayout(self)
|
self._l = l = QVBoxLayout(self)
|
||||||
self.setLayout(l)
|
self.setLayout(l)
|
||||||
l.addWidget(self.splitter)
|
l.addWidget(self.splitter)
|
||||||
|
@ -9,7 +9,7 @@ import os
|
|||||||
import weakref
|
import weakref
|
||||||
from qt.core import (
|
from qt.core import (
|
||||||
QApplication, QCheckBox, QCursor, QDialog, QDialogButtonBox, QGridLayout,
|
QApplication, QCheckBox, QCursor, QDialog, QDialogButtonBox, QGridLayout,
|
||||||
QHBoxLayout, QIcon, QLabel, QLineEdit, QProgressBar, QPushButton, QSplitter,
|
QHBoxLayout, QIcon, QLabel, QLineEdit, QProgressBar, QPushButton,
|
||||||
QStackedLayout, Qt, QTextEdit, QTreeWidget, QTreeWidgetItem, QVBoxLayout,
|
QStackedLayout, Qt, QTextEdit, QTreeWidget, QTreeWidgetItem, QVBoxLayout,
|
||||||
QWidget, pyqtSignal
|
QWidget, pyqtSignal
|
||||||
)
|
)
|
||||||
@ -17,6 +17,7 @@ from threading import Thread
|
|||||||
|
|
||||||
from calibre import as_unicode, prints
|
from calibre import as_unicode, prints
|
||||||
from calibre.gui2.dialogs.confirm_delete import confirm
|
from calibre.gui2.dialogs.confirm_delete import confirm
|
||||||
|
from calibre.gui2.widgets import BasicSplitter
|
||||||
from calibre.library.check_library import CHECKS, CheckLibrary
|
from calibre.library.check_library import CHECKS, CheckLibrary
|
||||||
from calibre.utils.recycle_bin import delete_file, delete_tree
|
from calibre.utils.recycle_bin import delete_file, delete_tree
|
||||||
|
|
||||||
@ -125,13 +126,14 @@ class CheckLibraryDialog(QDialog):
|
|||||||
|
|
||||||
self._tl = QHBoxLayout()
|
self._tl = QHBoxLayout()
|
||||||
self.setLayout(self._tl)
|
self.setLayout(self._tl)
|
||||||
self.splitter = QSplitter(self)
|
self.splitter = BasicSplitter(self)
|
||||||
self.left = QWidget(self)
|
self.left = QWidget(self)
|
||||||
self.splitter.addWidget(self.left)
|
self.splitter.addWidget(self.left)
|
||||||
self.helpw = QTextEdit(self)
|
self.helpw = QTextEdit(self)
|
||||||
self.splitter.addWidget(self.helpw)
|
self.splitter.addWidget(self.helpw)
|
||||||
self._tl.addWidget(self.splitter)
|
self._tl.addWidget(self.splitter)
|
||||||
self._layout = QVBoxLayout()
|
self._layout = QVBoxLayout()
|
||||||
|
self._layout.setContentsMargins(0, 0, 0, 0)
|
||||||
self.left.setLayout(self._layout)
|
self.left.setLayout(self._layout)
|
||||||
self.helpw.setReadOnly(True)
|
self.helpw.setReadOnly(True)
|
||||||
self.helpw.setText(_('''\
|
self.helpw.setText(_('''\
|
||||||
|
@ -23,7 +23,7 @@ from calibre.gui2.library.alternate_views import GridView
|
|||||||
from calibre.gui2.library.views import BooksView, DeviceBooksView
|
from calibre.gui2.library.views import BooksView, DeviceBooksView
|
||||||
from calibre.gui2.notify import get_notifier
|
from calibre.gui2.notify import get_notifier
|
||||||
from calibre.gui2.tag_browser.ui import TagBrowserWidget
|
from calibre.gui2.tag_browser.ui import TagBrowserWidget
|
||||||
from calibre.gui2.widgets import LayoutButton, Splitter
|
from calibre.gui2.widgets import LayoutButton, Splitter, BasicSplitter
|
||||||
from calibre.utils.config import prefs
|
from calibre.utils.config import prefs
|
||||||
from calibre.utils.icu import sort_key
|
from calibre.utils.icu import sort_key
|
||||||
from calibre.utils.localization import localize_website_link
|
from calibre.utils.localization import localize_website_link
|
||||||
@ -112,10 +112,10 @@ class LibraryViewMixin: # {{{
|
|||||||
# }}}
|
# }}}
|
||||||
|
|
||||||
|
|
||||||
class QuickviewSplitter(QSplitter): # {{{
|
class QuickviewSplitter(BasicSplitter): # {{{
|
||||||
|
|
||||||
def __init__(self, parent=None, orientation=Qt.Orientation.Vertical, qv_widget=None):
|
def __init__(self, parent=None, orientation=Qt.Orientation.Vertical, qv_widget=None):
|
||||||
QSplitter.__init__(self, parent=parent, orientation=orientation)
|
BasicSplitter.__init__(self, parent=parent, orientation=orientation)
|
||||||
self.splitterMoved.connect(self.splitter_moved)
|
self.splitterMoved.connect(self.splitter_moved)
|
||||||
self.setChildrenCollapsible(False)
|
self.setChildrenCollapsible(False)
|
||||||
self.qv_widget = qv_widget
|
self.qv_widget = qv_widget
|
||||||
@ -124,7 +124,7 @@ class QuickviewSplitter(QSplitter): # {{{
|
|||||||
gprefs['quickview_dialog_heights'] = self.sizes()
|
gprefs['quickview_dialog_heights'] = self.sizes()
|
||||||
|
|
||||||
def resizeEvent(self, *args):
|
def resizeEvent(self, *args):
|
||||||
QSplitter.resizeEvent(self, *args)
|
BasicSplitter.resizeEvent(self, *args)
|
||||||
if self.sizes()[1] != 0:
|
if self.sizes()[1] != 0:
|
||||||
gprefs['quickview_dialog_heights'] = self.sizes()
|
gprefs['quickview_dialog_heights'] = self.sizes()
|
||||||
|
|
||||||
|
@ -12,7 +12,7 @@ from functools import partial
|
|||||||
from qt.core import (
|
from qt.core import (
|
||||||
QDialog, QDialogButtonBox, QFrame, QGridLayout, QGroupBox, QHBoxLayout, QIcon,
|
QDialog, QDialogButtonBox, QFrame, QGridLayout, QGroupBox, QHBoxLayout, QIcon,
|
||||||
QInputDialog, QKeySequence, QMenu, QPushButton, QScrollArea, QShortcut, QSize,
|
QInputDialog, QKeySequence, QMenu, QPushButton, QScrollArea, QShortcut, QSize,
|
||||||
QSizePolicy, QSpacerItem, QSplitter, Qt, QTabWidget, QToolButton, QVBoxLayout,
|
QSizePolicy, QSpacerItem, Qt, QTabWidget, QToolButton, QVBoxLayout,
|
||||||
QWidget, pyqtSignal
|
QWidget, pyqtSignal
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -29,6 +29,7 @@ from calibre.gui2.metadata.basic_widgets import (
|
|||||||
TitleSortEdit, show_locked_file_error
|
TitleSortEdit, show_locked_file_error
|
||||||
)
|
)
|
||||||
from calibre.gui2.metadata.single_download import FullFetch
|
from calibre.gui2.metadata.single_download import FullFetch
|
||||||
|
from calibre.gui2.widgets import BasicSplitter
|
||||||
from calibre.gui2.widgets2 import CenteredToolButton
|
from calibre.gui2.widgets2 import CenteredToolButton
|
||||||
from calibre.library.comments import merge_comments as merge_two_comments
|
from calibre.library.comments import merge_comments as merge_two_comments
|
||||||
from calibre.utils.date import local_tz
|
from calibre.utils.date import local_tz
|
||||||
@ -731,13 +732,13 @@ class MetadataSingleDialogBase(QDialog):
|
|||||||
# }}}
|
# }}}
|
||||||
|
|
||||||
|
|
||||||
class Splitter(QSplitter):
|
class Splitter(BasicSplitter):
|
||||||
|
|
||||||
frame_resized = pyqtSignal(object)
|
frame_resized = pyqtSignal(object)
|
||||||
|
|
||||||
def resizeEvent(self, ev):
|
def resizeEvent(self, ev):
|
||||||
self.frame_resized.emit(ev)
|
self.frame_resized.emit(ev)
|
||||||
return QSplitter.resizeEvent(self, ev)
|
return BasicSplitter.resizeEvent(self, ev)
|
||||||
|
|
||||||
|
|
||||||
class MetadataSingleDialog(MetadataSingleDialogBase): # {{{
|
class MetadataSingleDialog(MetadataSingleDialogBase): # {{{
|
||||||
@ -1039,7 +1040,7 @@ class MetadataSingleDialogAlt1(MetadataSingleDialogBase): # {{{
|
|||||||
QSizePolicy.Policy.Expanding))
|
QSizePolicy.Policy.Expanding))
|
||||||
wgl.addWidget(self.formats_manager)
|
wgl.addWidget(self.formats_manager)
|
||||||
|
|
||||||
self.splitter = QSplitter(Qt.Orientation.Horizontal, tab1)
|
self.splitter = BasicSplitter(Qt.Orientation.Horizontal, tab1)
|
||||||
tab1.l.addWidget(self.splitter)
|
tab1.l.addWidget(self.splitter)
|
||||||
self.splitter.addWidget(self.cover)
|
self.splitter.addWidget(self.cover)
|
||||||
self.splitter.addWidget(wsp)
|
self.splitter.addWidget(wsp)
|
||||||
@ -1207,7 +1208,7 @@ class MetadataSingleDialogAlt2(MetadataSingleDialogBase): # {{{
|
|||||||
cover_layout.addLayout(hl)
|
cover_layout.addLayout(hl)
|
||||||
sto(self.cover.buttons[-2], self.cover.buttons[-1])
|
sto(self.cover.buttons[-2], self.cover.buttons[-1])
|
||||||
# Splitter for both cover & formats boxes
|
# Splitter for both cover & formats boxes
|
||||||
self.cover_and_formats = cover_and_formats = QSplitter(Qt.Orientation.Vertical)
|
self.cover_and_formats = cover_and_formats = BasicSplitter(Qt.Orientation.Vertical)
|
||||||
# Put a very small margin on the left so that the word "Cover" doesn't
|
# Put a very small margin on the left so that the word "Cover" doesn't
|
||||||
# touch the splitter
|
# touch the splitter
|
||||||
cover_and_formats.setContentsMargins(1, 0, 0, 0)
|
cover_and_formats.setContentsMargins(1, 0, 0, 0)
|
||||||
|
@ -19,7 +19,7 @@ from qt.core import (
|
|||||||
QWidget, QTableView, QGridLayout, QPalette, QTimer, pyqtSignal,
|
QWidget, QTableView, QGridLayout, QPalette, QTimer, pyqtSignal,
|
||||||
QAbstractTableModel, QSize, QListView, QPixmap, QModelIndex,
|
QAbstractTableModel, QSize, QListView, QPixmap, QModelIndex,
|
||||||
QAbstractListModel, QRect, QTextBrowser, QStringListModel, QMenu, QItemSelectionModel,
|
QAbstractListModel, QRect, QTextBrowser, QStringListModel, QMenu, QItemSelectionModel,
|
||||||
QCursor, QHBoxLayout, QPushButton, QSizePolicy, QSplitter, QAbstractItemView)
|
QCursor, QHBoxLayout, QPushButton, QSizePolicy, QAbstractItemView)
|
||||||
|
|
||||||
from calibre.customize.ui import metadata_plugins
|
from calibre.customize.ui import metadata_plugins
|
||||||
from calibre.ebooks.metadata import authors_to_string, rating_to_stars
|
from calibre.ebooks.metadata import authors_to_string, rating_to_stars
|
||||||
@ -29,6 +29,7 @@ from calibre.ebooks.metadata.book.base import Metadata
|
|||||||
from calibre.ebooks.metadata.opf2 import OPF
|
from calibre.ebooks.metadata.opf2 import OPF
|
||||||
from calibre.gui2 import error_dialog, rating_font, gprefs
|
from calibre.gui2 import error_dialog, rating_font, gprefs
|
||||||
from calibre.gui2.progress_indicator import SpinAnimator
|
from calibre.gui2.progress_indicator import SpinAnimator
|
||||||
|
from calibre.gui2.widgets import BasicSplitter
|
||||||
from calibre.gui2.widgets2 import HTMLDisplay
|
from calibre.gui2.widgets2 import HTMLDisplay
|
||||||
from calibre.utils.date import (utcnow, fromordinal, format_date,
|
from calibre.utils.date import (utcnow, fromordinal, format_date,
|
||||||
UNDEFINED_DATE, as_utc)
|
UNDEFINED_DATE, as_utc)
|
||||||
@ -445,7 +446,7 @@ class IdentifyWidget(QWidget): # {{{
|
|||||||
self.top.setWordWrap(True)
|
self.top.setWordWrap(True)
|
||||||
l.addWidget(self.top)
|
l.addWidget(self.top)
|
||||||
|
|
||||||
self.splitter = s = QSplitter(self)
|
self.splitter = s = BasicSplitter(self)
|
||||||
s.setChildrenCollapsible(False)
|
s.setChildrenCollapsible(False)
|
||||||
l.addWidget(s, 100)
|
l.addWidget(s, 100)
|
||||||
self.results_view = ResultsView(self)
|
self.results_view = ResultsView(self)
|
||||||
|
@ -2,10 +2,11 @@
|
|||||||
# License: GPLv3 Copyright: 2018, Kovid Goyal <kovid at kovidgoyal.net>
|
# License: GPLv3 Copyright: 2018, Kovid Goyal <kovid at kovidgoyal.net>
|
||||||
|
|
||||||
|
|
||||||
from qt.core import QSplitter, QTableView
|
from qt.core import QTableView
|
||||||
|
|
||||||
from calibre.gui2.library import DEFAULT_SORT
|
from calibre.gui2.library import DEFAULT_SORT
|
||||||
from calibre.gui2 import gprefs
|
from calibre.gui2 import gprefs
|
||||||
|
from calibre.gui2.widgets import BasicSplitter
|
||||||
|
|
||||||
|
|
||||||
class PinTableView(QTableView):
|
class PinTableView(QTableView):
|
||||||
@ -124,10 +125,10 @@ class PinTableView(QTableView):
|
|||||||
self.apply_state(state)
|
self.apply_state(state)
|
||||||
|
|
||||||
|
|
||||||
class PinContainer(QSplitter):
|
class PinContainer(BasicSplitter):
|
||||||
|
|
||||||
def __init__(self, books_view, parent=None):
|
def __init__(self, books_view, parent=None):
|
||||||
QSplitter.__init__(self, parent)
|
BasicSplitter.__init__(self, parent)
|
||||||
self.setChildrenCollapsible(False)
|
self.setChildrenCollapsible(False)
|
||||||
self.books_view = books_view
|
self.books_view = books_view
|
||||||
self.addWidget(books_view)
|
self.addWidget(books_view)
|
||||||
|
@ -11,7 +11,7 @@ from calibre import isbytestring, prepare_string_for_xml
|
|||||||
from calibre.gui2 import error_dialog, info_dialog
|
from calibre.gui2 import error_dialog, info_dialog
|
||||||
from calibre.gui2.preferences import AbortCommit, ConfigWidgetBase, test_widget
|
from calibre.gui2.preferences import AbortCommit, ConfigWidgetBase, test_widget
|
||||||
from calibre.gui2.search_box import SearchBox2
|
from calibre.gui2.search_box import SearchBox2
|
||||||
from calibre.gui2.widgets import PythonHighlighter
|
from calibre.gui2.widgets import PythonHighlighter, BasicSplitter
|
||||||
from calibre.utils.config_base import (default_tweaks_raw, exec_tweaks,
|
from calibre.utils.config_base import (default_tweaks_raw, exec_tweaks,
|
||||||
normalize_tweak, read_custom_tweaks,
|
normalize_tweak, read_custom_tweaks,
|
||||||
write_custom_tweaks)
|
write_custom_tweaks)
|
||||||
@ -22,7 +22,7 @@ from qt.core import (QAbstractItemView, QAbstractListModel, QApplication,
|
|||||||
QComboBox, QDialog, QDialogButtonBox, QFont, QGridLayout,
|
QComboBox, QDialog, QDialogButtonBox, QFont, QGridLayout,
|
||||||
QGroupBox, QIcon, QItemSelectionModel, QLabel, QListView,
|
QGroupBox, QIcon, QItemSelectionModel, QLabel, QListView,
|
||||||
QMenu, QModelIndex, QPlainTextEdit, QPushButton,
|
QMenu, QModelIndex, QPlainTextEdit, QPushButton,
|
||||||
QSizePolicy, QSplitter, Qt, QVBoxLayout, QWidget,
|
QSizePolicy, Qt, QVBoxLayout, QWidget,
|
||||||
pyqtSignal)
|
pyqtSignal)
|
||||||
|
|
||||||
ROOT = QModelIndex()
|
ROOT = QModelIndex()
|
||||||
@ -371,7 +371,7 @@ class ConfigWidget(ConfigWidgetBase):
|
|||||||
_("Values for the tweaks are shown below. Edit them to change the behavior of calibre."
|
_("Values for the tweaks are shown below. Edit them to change the behavior of calibre."
|
||||||
" Your changes will only take effect <b>after a restart</b> of calibre."))
|
" Your changes will only take effect <b>after a restart</b> of calibre."))
|
||||||
l.addWidget(la), la.setWordWrap(True)
|
l.addWidget(la), la.setWordWrap(True)
|
||||||
self.splitter = s = QSplitter(self)
|
self.splitter = s = BasicSplitter(self)
|
||||||
s.setChildrenCollapsible(False)
|
s.setChildrenCollapsible(False)
|
||||||
l.addWidget(s, 10)
|
l.addWidget(s, 10)
|
||||||
|
|
||||||
|
@ -434,6 +434,9 @@ class Main(MainWindow, MainWindowMixin, DeviceMixin, EmailMixin, # {{{
|
|||||||
# layout button. We need to let a book be selected in the book list
|
# layout button. We need to let a book be selected in the book list
|
||||||
# before initializing quickview, so run it after an event loop tick
|
# before initializing quickview, so run it after an event loop tick
|
||||||
QTimer.singleShot(0, self.start_quickview)
|
QTimer.singleShot(0, self.start_quickview)
|
||||||
|
# Force repaint of the book details splitter because it otherwise ends
|
||||||
|
# up with the wrong size. I don't know why.
|
||||||
|
QTimer.singleShot(0, self.bd_splitter.repaint)
|
||||||
|
|
||||||
def start_quickview(self):
|
def start_quickview(self):
|
||||||
from calibre.gui2.actions.show_quickview import get_quickview_action_plugin
|
from calibre.gui2.actions.show_quickview import get_quickview_action_plugin
|
||||||
|
@ -980,13 +980,48 @@ class PythonHighlighter(QSyntaxHighlighter): # {{{
|
|||||||
|
|
||||||
# Splitter {{{
|
# Splitter {{{
|
||||||
|
|
||||||
|
class BasicSplitterHandle(QSplitterHandle):
|
||||||
|
|
||||||
class SplitterHandle(QSplitterHandle):
|
def __init__(self, orientation, splitter):
|
||||||
|
QSplitterHandle.__init__(self, orientation, splitter)
|
||||||
|
self.handle_width = splitter.handleWidth()
|
||||||
|
|
||||||
|
def paintEvent(self, event):
|
||||||
|
rect = event.rect()
|
||||||
|
painter = QPainter(self)
|
||||||
|
# draw the separator bar.
|
||||||
|
painter.setPen(Qt.NoPen)
|
||||||
|
palette = QApplication.palette()
|
||||||
|
painter.setBrush(palette.color(QPalette.ColorGroup.Normal, QPalette.ColorRole.AlternateBase))
|
||||||
|
painter.drawRect(rect)
|
||||||
|
# draw the dots
|
||||||
|
painter.setBrush(palette.color(QPalette.ColorGroup.Normal, QPalette.ColorRole.Shadow))
|
||||||
|
horizontal = self.orientation() == Qt.Orientation.Horizontal
|
||||||
|
dot_count = 6
|
||||||
|
dot_size = int(max(1, self.handle_width/2))
|
||||||
|
start_point = max(0, int((rect.height()/2 if horizontal else rect.width()/2) - (dot_count*dot_size/2)))
|
||||||
|
for i in range(dot_count):
|
||||||
|
# Move the rect to leave 2 dot spaces between the dots
|
||||||
|
if horizontal:
|
||||||
|
dot_rect = QRect(1, start_point + i*dot_size*3, dot_size, dot_size)
|
||||||
|
else:
|
||||||
|
dot_rect = QRect(start_point + i*dot_size*3, 1, dot_size, dot_size)
|
||||||
|
painter.drawRect(dot_rect)
|
||||||
|
painter.end()
|
||||||
|
|
||||||
|
|
||||||
|
class BasicSplitter(QSplitter):
|
||||||
|
|
||||||
|
def createHandle(self):
|
||||||
|
return BasicSplitterHandle(self.orientation(), self)
|
||||||
|
|
||||||
|
|
||||||
|
class SplitterHandle(BasicSplitterHandle):
|
||||||
|
|
||||||
double_clicked = pyqtSignal(object)
|
double_clicked = pyqtSignal(object)
|
||||||
|
|
||||||
def __init__(self, orientation, splitter):
|
def __init__(self, orientation, splitter):
|
||||||
QSplitterHandle.__init__(self, orientation, splitter)
|
BasicSplitterHandle.__init__(self, orientation, splitter)
|
||||||
splitter.splitterMoved.connect(self.splitter_moved,
|
splitter.splitterMoved.connect(self.splitter_moved,
|
||||||
type=Qt.ConnectionType.QueuedConnection)
|
type=Qt.ConnectionType.QueuedConnection)
|
||||||
self.double_clicked.connect(splitter.double_clicked,
|
self.double_clicked.connect(splitter.double_clicked,
|
||||||
@ -1066,7 +1101,7 @@ class LayoutButton(QToolButton):
|
|||||||
return QToolButton.mouseReleaseEvent(self, ev)
|
return QToolButton.mouseReleaseEvent(self, ev)
|
||||||
|
|
||||||
|
|
||||||
class Splitter(QSplitter):
|
class Splitter(BasicSplitter):
|
||||||
|
|
||||||
state_changed = pyqtSignal(object)
|
state_changed = pyqtSignal(object)
|
||||||
reapply_sizes = pyqtSignal(object)
|
reapply_sizes = pyqtSignal(object)
|
||||||
@ -1075,7 +1110,7 @@ class Splitter(QSplitter):
|
|||||||
initial_side_size=120, connect_button=True,
|
initial_side_size=120, connect_button=True,
|
||||||
orientation=Qt.Orientation.Horizontal, side_index=0, parent=None,
|
orientation=Qt.Orientation.Horizontal, side_index=0, parent=None,
|
||||||
shortcut=None, hide_handle_on_single_panel=True):
|
shortcut=None, hide_handle_on_single_panel=True):
|
||||||
QSplitter.__init__(self, parent)
|
BasicSplitter.__init__(self, parent)
|
||||||
self.reapply_sizes.connect(self.setSizes, type=Qt.ConnectionType.QueuedConnection)
|
self.reapply_sizes.connect(self.setSizes, type=Qt.ConnectionType.QueuedConnection)
|
||||||
self.hide_handle_on_single_panel = hide_handle_on_single_panel
|
self.hide_handle_on_single_panel = hide_handle_on_single_panel
|
||||||
if hide_handle_on_single_panel:
|
if hide_handle_on_single_panel:
|
||||||
@ -1189,7 +1224,7 @@ class Splitter(QSplitter):
|
|||||||
|
|
||||||
def do_resize(self, *args):
|
def do_resize(self, *args):
|
||||||
orig = self.desired_side_size
|
orig = self.desired_side_size
|
||||||
QSplitter.resizeEvent(self, self._resize_ev)
|
BasicSplitter.resizeEvent(self, self._resize_ev)
|
||||||
if orig > 20 and self.desired_show:
|
if orig > 20 and self.desired_show:
|
||||||
c = 0
|
c = 0
|
||||||
while abs(self.side_index_size - orig) > 10 and c < 5:
|
while abs(self.side_index_size - orig) > 10 and c < 5:
|
||||||
|
Loading…
x
Reference in New Issue
Block a user