Get rid of BasicSplitter

Move custom drawing of splitter handle into the style where it belongs.
This means all splitters now use the custom handle without needing to
sprinkle a special class everywhere.

Note that this only works when using the calibre style not the system
one. This is by design, since we do not want to override drawing of
"system" components.
This commit is contained in:
Kovid Goyal 2022-10-26 20:53:45 +05:30
parent 98811a1999
commit 957953a212
No known key found for this signature in database
GPG Key ID: 06BC317B515ACE7C
10 changed files with 56 additions and 72 deletions

View File

@ -8,7 +8,7 @@ from collections import namedtuple
from functools import partial
from qt.core import (
QAction, QApplication, QClipboard, QColor, QDialog, QEasingCurve, QIcon,
QKeySequence, QMenu, QMimeData, QPainter, QPen, QPixmap,
QKeySequence, QMenu, QMimeData, QPainter, QPen, QPixmap, QSplitter,
QPropertyAnimation, QRect, QSize, QSizePolicy, Qt, QUrl, QWidget, pyqtProperty,
pyqtSignal
)
@ -30,7 +30,6 @@ from calibre.gui2.dialogs.confirm_delete import confirm, confirm as confirm_dele
from calibre.gui2.dnd import (
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.utils.config import tweaks
from calibre.utils.img import blend_image, image_from_x
@ -914,11 +913,11 @@ class BookInfo(HTMLDisplay):
# }}}
class DetailsLayout(BasicSplitter): # {{{
class DetailsLayout(QSplitter): # {{{
def __init__(self, vertical, parent):
orientation = Qt.Orientation.Vertical if vertical else Qt.Orientation.Horizontal
BasicSplitter.__init__(self, orientation, parent)
super().__init__(orientation, parent)
self.vertical = vertical
self._children = []
self.min_size = QSize(190, 200) if vertical else QSize(120, 120)

View File

@ -7,7 +7,7 @@ from qt.core import (
QAction, QApplication, QBrush, QCheckBox, QDialog, QGridLayout,
QHBoxLayout, QIcon, QKeySequence, QLabel, QListView, QModelIndex, QPalette,
QPixmap, QPushButton, QShortcut, QSize, Qt, QTimer, QToolButton,
QVBoxLayout, QWidget, pyqtSignal, QDialogButtonBox
QVBoxLayout, QWidget, pyqtSignal, QDialogButtonBox, QSplitter
)
from calibre import fit_image
@ -17,7 +17,7 @@ from calibre.gui2.book_details import (
set_html
)
from calibre.gui2.ui import get_gui
from calibre.gui2.widgets import CoverView, BasicSplitter
from calibre.gui2.widgets import CoverView
from calibre.gui2.widgets2 import Dialog, HTMLDisplay
@ -136,7 +136,7 @@ class BookInfo(QDialog):
QDialog.__init__(self, parent)
self.marked = None
self.gui = parent
self.splitter = BasicSplitter(self)
self.splitter = QSplitter(self)
self._l = l = QVBoxLayout(self)
self.setLayout(l)
l.addWidget(self.splitter)

View File

@ -11,13 +11,12 @@ from qt.core import (
QApplication, QCheckBox, QCursor, QDialog, QDialogButtonBox, QGridLayout,
QHBoxLayout, QIcon, QLabel, QLineEdit, QProgressBar, QPushButton,
QStackedLayout, Qt, QTextEdit, QTreeWidget, QTreeWidgetItem, QVBoxLayout,
QWidget, pyqtSignal
QWidget, pyqtSignal, QSplitter
)
from threading import Thread
from calibre import as_unicode, prints
from calibre.gui2.dialogs.confirm_delete import confirm
from calibre.gui2.widgets import BasicSplitter
from calibre.library.check_library import CHECKS, CheckLibrary
from calibre.utils.recycle_bin import delete_file, delete_tree
@ -126,7 +125,7 @@ class CheckLibraryDialog(QDialog):
self._tl = QHBoxLayout()
self.setLayout(self._tl)
self.splitter = BasicSplitter(self)
self.splitter = QSplitter(self)
self.left = QWidget(self)
self.splitter.addWidget(self.left)
self.helpw = QTextEdit(self)

View File

@ -8,7 +8,7 @@ __docformat__ = 'restructuredtext en'
import functools
from qt.core import (
QAction, QApplication, QDialog, QEvent, QIcon, QLabel, QMenu, QPixmap, QUrl,
QSizePolicy, QStackedWidget, QStatusBar, QStyle, QStyleOption,
QSizePolicy, QStackedWidget, QStatusBar, QStyle, QStyleOption, QSplitter,
QStylePainter, Qt, QTabBar, QTimer, QToolButton, QVBoxLayout, QWidget
)
@ -23,7 +23,7 @@ from calibre.gui2.library.alternate_views import GridView
from calibre.gui2.library.views import BooksView, DeviceBooksView
from calibre.gui2.notify import get_notifier
from calibre.gui2.tag_browser.ui import TagBrowserWidget
from calibre.gui2.widgets import LayoutButton, Splitter, BasicSplitter
from calibre.gui2.widgets import LayoutButton, Splitter
from calibre.utils.config import prefs
from calibre.utils.icu import sort_key
from calibre.utils.localization import localize_website_link
@ -112,10 +112,10 @@ class LibraryViewMixin: # {{{
# }}}
class QuickviewSplitter(BasicSplitter): # {{{
class QuickviewSplitter(QSplitter): # {{{
def __init__(self, parent=None, orientation=Qt.Orientation.Vertical, qv_widget=None):
BasicSplitter.__init__(self, parent=parent, orientation=orientation)
super().__init__(parent=parent, orientation=orientation)
self.splitterMoved.connect(self.splitter_moved)
self.setChildrenCollapsible(False)
self.qv_widget = qv_widget
@ -124,7 +124,7 @@ class QuickviewSplitter(BasicSplitter): # {{{
gprefs['quickview_dialog_heights'] = self.sizes()
def resizeEvent(self, *args):
BasicSplitter.resizeEvent(self, *args)
super().resizeEvent(*args)
if self.sizes()[1] != 0:
gprefs['quickview_dialog_heights'] = self.sizes()

View File

@ -12,8 +12,8 @@ from functools import partial
from qt.core import (
QDialog, QDialogButtonBox, QFrame, QGridLayout, QGroupBox, QHBoxLayout, QIcon,
QInputDialog, QKeySequence, QMenu, QPushButton, QScrollArea, QShortcut, QSize,
QSizePolicy, QSpacerItem, Qt, QTabWidget, QToolButton, QVBoxLayout,
QWidget, pyqtSignal
QSizePolicy, QSpacerItem, QSplitter, Qt, QTabWidget, QToolButton, QVBoxLayout,
QWidget, pyqtSignal,
)
from calibre.constants import ismacos
@ -26,10 +26,9 @@ from calibre.gui2.metadata.basic_widgets import (
AuthorsEdit, AuthorSortEdit, BuddyLabel, CommentsEdit, Cover, DateEdit,
FormatsManager, IdentifiersEdit, LanguagesEdit, PubdateEdit, PublisherEdit,
RatingEdit, RightClickButton, SeriesEdit, SeriesIndexEdit, TagsEdit, TitleEdit,
TitleSortEdit, show_locked_file_error
TitleSortEdit, show_locked_file_error,
)
from calibre.gui2.metadata.single_download import FullFetch
from calibre.gui2.widgets import BasicSplitter
from calibre.gui2.widgets2 import CenteredToolButton
from calibre.library.comments import merge_comments as merge_two_comments
from calibre.utils.date import local_tz
@ -732,13 +731,13 @@ class MetadataSingleDialogBase(QDialog):
# }}}
class Splitter(BasicSplitter):
class Splitter(QSplitter):
frame_resized = pyqtSignal(object)
def resizeEvent(self, ev):
self.frame_resized.emit(ev)
return BasicSplitter.resizeEvent(self, ev)
return super().resizeEvent(ev)
class MetadataSingleDialog(MetadataSingleDialogBase): # {{{
@ -1040,7 +1039,7 @@ class MetadataSingleDialogAlt1(MetadataSingleDialogBase): # {{{
QSizePolicy.Policy.Expanding))
wgl.addWidget(self.formats_manager)
self.splitter = BasicSplitter(Qt.Orientation.Horizontal, tab1)
self.splitter = Splitter(Qt.Orientation.Horizontal, tab1)
tab1.l.addWidget(self.splitter)
self.splitter.addWidget(self.cover)
self.splitter.addWidget(wsp)
@ -1208,7 +1207,7 @@ class MetadataSingleDialogAlt2(MetadataSingleDialogBase): # {{{
cover_layout.addLayout(hl)
sto(self.cover.buttons[-2], self.cover.buttons[-1])
# Splitter for both cover & formats boxes
self.cover_and_formats = cover_and_formats = BasicSplitter(Qt.Orientation.Vertical)
self.cover_and_formats = cover_and_formats = Splitter(Qt.Orientation.Vertical)
# Put a very small margin on the left so that the word "Cover" doesn't
# touch the splitter
cover_and_formats.setContentsMargins(1, 0, 0, 0)

View File

@ -17,7 +17,7 @@ from qt.core import (
QStyledItemDelegate, QTextDocument, QRectF, QIcon, Qt, QApplication,
QDialog, QVBoxLayout, QLabel, QDialogButtonBox, QStyle, QStackedWidget,
QWidget, QTableView, QGridLayout, QPalette, QTimer, pyqtSignal,
QAbstractTableModel, QSize, QListView, QPixmap, QModelIndex,
QAbstractTableModel, QSize, QListView, QPixmap, QModelIndex, QSplitter,
QAbstractListModel, QRect, QTextBrowser, QStringListModel, QMenu, QItemSelectionModel,
QCursor, QHBoxLayout, QPushButton, QSizePolicy, QAbstractItemView)
@ -29,7 +29,6 @@ from calibre.ebooks.metadata.book.base import Metadata
from calibre.ebooks.metadata.opf2 import OPF
from calibre.gui2 import error_dialog, rating_font, gprefs
from calibre.gui2.progress_indicator import SpinAnimator
from calibre.gui2.widgets import BasicSplitter
from calibre.gui2.widgets2 import HTMLDisplay
from calibre.utils.date import (utcnow, fromordinal, format_date,
UNDEFINED_DATE, as_utc)
@ -446,7 +445,7 @@ class IdentifyWidget(QWidget): # {{{
self.top.setWordWrap(True)
l.addWidget(self.top)
self.splitter = s = BasicSplitter(self)
self.splitter = s = QSplitter(self)
s.setChildrenCollapsible(False)
l.addWidget(s, 100)
self.results_view = ResultsView(self)

View File

@ -2,11 +2,10 @@
# License: GPLv3 Copyright: 2018, Kovid Goyal <kovid at kovidgoyal.net>
from qt.core import QTableView
from qt.core import QTableView, QSplitter
from calibre.gui2.library import DEFAULT_SORT
from calibre.gui2 import gprefs
from calibre.gui2.widgets import BasicSplitter
class PinTableView(QTableView):
@ -125,10 +124,10 @@ class PinTableView(QTableView):
self.apply_state(state)
class PinContainer(BasicSplitter):
class PinContainer(QSplitter):
def __init__(self, books_view, parent=None):
BasicSplitter.__init__(self, parent)
super().__init__(parent)
self.setChildrenCollapsible(False)
self.books_view = books_view
self.addWidget(books_view)

View File

@ -11,7 +11,7 @@ from calibre import isbytestring, prepare_string_for_xml
from calibre.gui2 import error_dialog, info_dialog
from calibre.gui2.preferences import AbortCommit, ConfigWidgetBase, test_widget
from calibre.gui2.search_box import SearchBox2
from calibre.gui2.widgets import PythonHighlighter, BasicSplitter
from calibre.gui2.widgets import PythonHighlighter
from calibre.utils.config_base import (default_tweaks_raw, exec_tweaks,
normalize_tweak, read_custom_tweaks,
write_custom_tweaks)
@ -22,7 +22,7 @@ from qt.core import (QAbstractItemView, QAbstractListModel, QApplication,
QComboBox, QDialog, QDialogButtonBox, QFont, QGridLayout,
QGroupBox, QIcon, QItemSelectionModel, QLabel, QListView,
QMenu, QModelIndex, QPlainTextEdit, QPushButton,
QSizePolicy, Qt, QVBoxLayout, QWidget,
QSizePolicy, Qt, QVBoxLayout, QWidget, QSplitter,
pyqtSignal)
ROOT = QModelIndex()
@ -371,7 +371,7 @@ class ConfigWidget(ConfigWidgetBase):
_("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."))
l.addWidget(la), la.setWordWrap(True)
self.splitter = s = BasicSplitter(self)
self.splitter = s = QSplitter(self)
s.setChildrenCollapsible(False)
l.addWidget(s, 10)

View File

@ -336,6 +336,29 @@ void CalibreStyle::drawPrimitive(PrimitiveElement element, const QStyleOption *
void CalibreStyle::drawControl(ControlElement element, const QStyleOption *option, QPainter *painter, const QWidget *widget) const {
const QStyleOptionViewItem *vopt = NULL;
switch(element) {
case CE_Splitter: {
painter->save();
// draw the separator bar.
painter->setPen(Qt::PenStyle::NoPen);
painter->setBrush(option->palette.color(QPalette::ColorGroup::Normal, QPalette::ColorRole::AlternateBase));
painter->drawRect(option->rect);
// draw the dots
painter->setBrush(option->palette.color(QPalette::ColorGroup::Normal, QPalette::ColorRole::Shadow));
bool horizontal = option->state & QStyle::State_Horizontal ? true : false;
static const int dot_count = 4;
int handle_width = horizontal ? option->rect.width() : option->rect.height();
int dot_size = std::max(1, handle_width);
int start_point = (horizontal ? option->rect.height()/2 : option->rect.width()/2) - (dot_count*dot_size/2);
QRect dot_rect;
for (int i = 0; i < dot_count; i++) {
// Move the rect to leave spaces between the dots
if (horizontal) dot_rect = QRect(0, start_point + i*dot_size*2, dot_size, dot_size);
else dot_rect = QRect(start_point + i*dot_size*2, 0, dot_size, dot_size);
painter->drawEllipse(dot_rect);
}
painter->restore();
return;
} break;
case CE_ItemViewItem: {
if (option->state & QStyle::State_HasFocus && (vopt = qstyleoption_cast<const QStyleOptionViewItem *>(option)) && widget && widget->property("highlight_current_item").toBool()) {
if (is_color_dark(option->palette.color(QPalette::Window))) {

View File

@ -980,46 +980,12 @@ class PythonHighlighter(QSyntaxHighlighter): # {{{
# Splitter {{{
class BasicSplitterHandle(QSplitterHandle):
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 = 4
cr = self.contentsRect()
handle_width = cr.width() if horizontal else cr.height()
dot_size = int(max(1, handle_width))
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 spaces between the dots
if horizontal:
dot_rect = QRect(0, start_point + i*dot_size*2, dot_size, dot_size)
else:
dot_rect = QRect(start_point + i*dot_size*2, 0, dot_size, dot_size)
painter.drawEllipse(dot_rect)
painter.end()
class BasicSplitter(QSplitter):
def createHandle(self):
return BasicSplitterHandle(self.orientation(), self)
class SplitterHandle(BasicSplitterHandle):
class SplitterHandle(QSplitterHandle):
double_clicked = pyqtSignal(object)
def __init__(self, orientation, splitter):
BasicSplitterHandle.__init__(self, orientation, splitter)
super().__init__(orientation, splitter)
splitter.splitterMoved.connect(self.splitter_moved,
type=Qt.ConnectionType.QueuedConnection)
self.double_clicked.connect(splitter.double_clicked,
@ -1099,7 +1065,7 @@ class LayoutButton(QToolButton):
return QToolButton.mouseReleaseEvent(self, ev)
class Splitter(BasicSplitter):
class Splitter(QSplitter):
state_changed = pyqtSignal(object)
reapply_sizes = pyqtSignal(object)
@ -1108,7 +1074,7 @@ class Splitter(BasicSplitter):
initial_side_size=120, connect_button=True,
orientation=Qt.Orientation.Horizontal, side_index=0, parent=None,
shortcut=None, hide_handle_on_single_panel=True):
BasicSplitter.__init__(self, parent)
super().__init__(parent)
self.reapply_sizes.connect(self.setSizes, type=Qt.ConnectionType.QueuedConnection)
self.hide_handle_on_single_panel = hide_handle_on_single_panel
if hide_handle_on_single_panel:
@ -1222,7 +1188,7 @@ class Splitter(BasicSplitter):
def do_resize(self, *args):
orig = self.desired_side_size
BasicSplitter.resizeEvent(self, self._resize_ev)
super().resizeEvent(self._resize_ev)
if orig > 20 and self.desired_show:
c = 0
while abs(self.side_index_size - orig) > 10 and c < 5: