Fix a crash when running with assertions turned on in Qt. Fixes #1652685 [Calibre startup crash (assert in QStyledItemDelegate)](https://bugs.launchpad.net/calibre/+bug/1652685)

This commit is contained in:
Kovid Goyal 2016-12-27 06:53:23 +05:30
parent bfa9c26c68
commit c979c784b6
8 changed files with 28 additions and 19 deletions

View File

@ -9,7 +9,7 @@ from PyQt5.QtWidgets import QStyle # Gives a nicer error message than import fr
from PyQt5.Qt import ( from PyQt5.Qt import (
QFileInfo, QObject, QBuffer, Qt, QByteArray, QTranslator, QSocketNotifier, QFileInfo, QObject, QBuffer, Qt, QByteArray, QTranslator, QSocketNotifier,
QCoreApplication, QThread, QEvent, QTimer, pyqtSignal, QDateTime, QFontMetrics, QCoreApplication, QThread, QEvent, QTimer, pyqtSignal, QDateTime, QFontMetrics,
QDesktopServices, QFileDialog, QFileIconProvider, QSettings, QIcon, QDesktopServices, QFileDialog, QFileIconProvider, QSettings, QIcon, QStringListModel,
QApplication, QDialog, QUrl, QFont, QFontDatabase, QLocale, QFontInfo) QApplication, QDialog, QUrl, QFont, QFontDatabase, QLocale, QFontInfo)
from calibre import prints from calibre import prints
@ -1414,3 +1414,7 @@ def secure_web_page(qwebpage_or_qwebsettings):
settings.setAttribute(QWebSettings.NotificationsEnabled, False) settings.setAttribute(QWebSettings.NotificationsEnabled, False)
settings.setThirdPartyCookiePolicy(QWebSettings.AlwaysBlockThirdPartyCookies) settings.setThirdPartyCookiePolicy(QWebSettings.AlwaysBlockThirdPartyCookies)
return settings return settings
empty_model = QStringListModel([''])
empty_index = empty_model.index(0)

View File

@ -13,10 +13,10 @@ from PyQt5.Qt import (QFontInfo, QFontMetrics, Qt, QFont, QFontDatabase, QPen,
QStyledItemDelegate, QSize, QStyle, QStringListModel, pyqtSignal, QStyledItemDelegate, QSize, QStyle, QStringListModel, pyqtSignal,
QDialog, QVBoxLayout, QApplication, QFontComboBox, QPushButton, QDialog, QVBoxLayout, QApplication, QFontComboBox, QPushButton,
QToolButton, QGridLayout, QListView, QWidget, QDialogButtonBox, QIcon, QToolButton, QGridLayout, QListView, QWidget, QDialogButtonBox, QIcon,
QHBoxLayout, QLabel, QModelIndex, QLineEdit, QSizePolicy) QHBoxLayout, QLabel, QLineEdit, QSizePolicy)
from calibre.constants import config_dir from calibre.constants import config_dir
from calibre.gui2 import choose_files, error_dialog, info_dialog from calibre.gui2 import choose_files, error_dialog, info_dialog, empty_index
def add_fonts(parent): def add_fonts(parent):
@ -103,7 +103,7 @@ class FontFamilyDelegate(QStyledItemDelegate):
return QSize(m.width(text), m.height()) return QSize(m.width(text), m.height())
def paint(self, painter, option, index): def paint(self, painter, option, index):
QStyledItemDelegate.paint(self, painter, option, QModelIndex()) QStyledItemDelegate.paint(self, painter, option, empty_index)
painter.save() painter.save()
try: try:
self.do_paint(painter, option, index) self.do_paint(painter, option, index)
@ -380,6 +380,6 @@ def test():
d.layout().addWidget(QFontComboBox(d)) d.layout().addWidget(QFontComboBox(d))
d.exec_() d.exec_()
if __name__ == '__main__': if __name__ == '__main__':
test() test()

View File

@ -18,14 +18,14 @@ from PyQt5.Qt import (
QImageReader, QFormLayout, QVBoxLayout, QSplitter, QGroupBox, QListWidget, QImageReader, QFormLayout, QVBoxLayout, QSplitter, QGroupBox, QListWidget,
QLineEdit, QSpinBox, QTextEdit, QSize, QListWidgetItem, QIcon, QImage, QLineEdit, QSpinBox, QTextEdit, QSize, QListWidgetItem, QIcon, QImage,
pyqtSignal, QStackedLayout, QWidget, QLabel, Qt, QComboBox, QPixmap, pyqtSignal, QStackedLayout, QWidget, QLabel, Qt, QComboBox, QPixmap,
QGridLayout, QStyledItemDelegate, QModelIndex, QApplication, QStaticText, QGridLayout, QStyledItemDelegate, QApplication, QStaticText,
QStyle, QPen, QProgressDialog QStyle, QPen, QProgressDialog
) )
from calibre import walk, fit_image, human_readable, detect_ncpus as cpu_count from calibre import walk, fit_image, human_readable, detect_ncpus as cpu_count
from calibre.constants import cache_dir, config_dir from calibre.constants import cache_dir, config_dir
from calibre.customize.ui import interface_actions from calibre.customize.ui import interface_actions
from calibre.gui2 import must_use_qt, gprefs, choose_dir, error_dialog, choose_save_file, question_dialog from calibre.gui2 import must_use_qt, gprefs, choose_dir, error_dialog, choose_save_file, question_dialog, empty_index
from calibre.gui2.dialogs.progress import ProgressDialog from calibre.gui2.dialogs.progress import ProgressDialog
from calibre.gui2.progress_indicator import ProgressIndicator from calibre.gui2.progress_indicator import ProgressIndicator
from calibre.gui2.widgets2 import Dialog from calibre.gui2.widgets2 import Dialog
@ -508,7 +508,7 @@ class Delegate(QStyledItemDelegate):
return QSize(COVER_SIZE[0] * 2, COVER_SIZE[1] + 2 * self.SPACING) return QSize(COVER_SIZE[0] * 2, COVER_SIZE[1] + 2 * self.SPACING)
def paint(self, painter, option, index): def paint(self, painter, option, index):
QStyledItemDelegate.paint(self, painter, option, QModelIndex()) QStyledItemDelegate.paint(self, painter, option, empty_index)
theme = index.data(Qt.UserRole) theme = index.data(Qt.UserRole)
if not theme: if not theme:
return return
@ -840,6 +840,7 @@ def install_icon_theme(theme, f):
buf.seek(0) buf.seek(0)
safe_copy(buf, metadata_file) safe_copy(buf, metadata_file)
if __name__ == '__main__': if __name__ == '__main__':
from calibre.gui2 import Application from calibre.gui2 import Application
app = Application([]) app = Application([])

View File

@ -25,7 +25,7 @@ from calibre import fit_image, prints, prepare_string_for_xml, human_readable
from calibre.constants import DEBUG, config_dir, islinux from calibre.constants import DEBUG, config_dir, islinux
from calibre.ebooks.metadata import fmt_sidx, rating_to_stars from calibre.ebooks.metadata import fmt_sidx, rating_to_stars
from calibre.utils import join_with_timeout from calibre.utils import join_with_timeout
from calibre.gui2 import gprefs, config, rating_font from calibre.gui2 import gprefs, config, rating_font, empty_index
from calibre.gui2.library.caches import CoverCache, ThumbnailCache from calibre.gui2.library.caches import CoverCache, ThumbnailCache
from calibre.utils.config import prefs, tweaks from calibre.utils.config import prefs, tweaks
@ -451,7 +451,7 @@ class CoverDelegate(QStyledItemDelegate):
return ans return ans
def paint(self, painter, option, index): def paint(self, painter, option, index):
QStyledItemDelegate.paint(self, painter, option, QModelIndex()) # draw the hover and selection highlights QStyledItemDelegate.paint(self, painter, option, empty_index) # draw the hover and selection highlights
m = index.model() m = index.model()
db = m.db db = m.db
try: try:

View File

@ -9,9 +9,10 @@ __docformat__ = 'restructuredtext en'
from functools import partial from functools import partial
from PyQt5.Qt import ( from PyQt5.Qt import (
pyqtSignal, QMenu, QTreeView, QStyledItemDelegate, QModelIndex, Qt, QIcon) pyqtSignal, QMenu, QTreeView, QStyledItemDelegate, Qt, QIcon)
from calibre import fit_image from calibre import fit_image
from calibre.gui2 import empty_index
from calibre.gui2.metadata.single_download import RichTextDelegate from calibre.gui2.metadata.single_download import RichTextDelegate
from calibre.gui2.store.search.models import Matches from calibre.gui2.store.search.models import Matches
@ -19,7 +20,7 @@ from calibre.gui2.store.search.models import Matches
class ImageDelegate(QStyledItemDelegate): class ImageDelegate(QStyledItemDelegate):
def paint(self, painter, option, index): def paint(self, painter, option, index):
QStyledItemDelegate.paint(self, painter, option, QModelIndex()) QStyledItemDelegate.paint(self, painter, option, empty_index)
img = index.data(Qt.DecorationRole) img = index.data(Qt.DecorationRole)
if img: if img:
h = option.rect.height() - 4 h = option.rect.height() - 4

View File

@ -22,7 +22,7 @@ from calibre.constants import config_dir
from calibre.ebooks.metadata import rating_to_stars from calibre.ebooks.metadata import rating_to_stars
from calibre.gui2.tag_browser.model import (TagTreeItem, TAG_SEARCH_STATES, from calibre.gui2.tag_browser.model import (TagTreeItem, TAG_SEARCH_STATES,
TagsModel, DRAG_IMAGE_ROLE, COUNT_ROLE) TagsModel, DRAG_IMAGE_ROLE, COUNT_ROLE)
from calibre.gui2 import config, gprefs, choose_files, pixmap_to_data, rating_font from calibre.gui2 import config, gprefs, choose_files, pixmap_to_data, rating_font, empty_index
from calibre.utils.icu import sort_key from calibre.utils.icu import sort_key
@ -91,7 +91,7 @@ class TagDelegate(QStyledItemDelegate): # {{{
painter.drawText(tr, flags, text) painter.drawText(tr, flags, text)
def paint(self, painter, option, index): def paint(self, painter, option, index):
QStyledItemDelegate.paint(self, painter, option, QModelIndex()) QStyledItemDelegate.paint(self, painter, option, empty_index)
widget = self.parent() widget = self.parent()
style = QApplication.style() if widget is None else widget.style() style = QApplication.style() if widget is None else widget.style()
self.initStyleOption(option, index) self.initStyleOption(option, index)

View File

@ -12,7 +12,7 @@ from functools import partial
from PyQt5.Qt import ( from PyQt5.Qt import (
QGridLayout, QSize, QListView, QStyledItemDelegate, QLabel, QPixmap, QGridLayout, QSize, QListView, QStyledItemDelegate, QLabel, QPixmap,
QApplication, QSizePolicy, QAbstractListModel, Qt, QRect, QCheckBox, QApplication, QSizePolicy, QAbstractListModel, Qt, QRect, QCheckBox,
QPainter, QModelIndex, QSortFilterProxyModel, QLineEdit, QToolButton, QPainter, QSortFilterProxyModel, QLineEdit, QToolButton,
QIcon, QFormLayout, pyqtSignal, QTreeWidget, QTreeWidgetItem, QVBoxLayout, QIcon, QFormLayout, pyqtSignal, QTreeWidget, QTreeWidgetItem, QVBoxLayout,
QMenu, QInputDialog, QHBoxLayout) QMenu, QInputDialog, QHBoxLayout)
@ -20,7 +20,7 @@ from calibre import fit_image
from calibre.constants import plugins from calibre.constants import plugins
from calibre.ebooks.metadata import string_to_authors from calibre.ebooks.metadata import string_to_authors
from calibre.ebooks.metadata.book.base import Metadata from calibre.ebooks.metadata.book.base import Metadata
from calibre.gui2 import choose_files, error_dialog, pixmap_to_data from calibre.gui2 import choose_files, error_dialog, pixmap_to_data, empty_index
from calibre.gui2.languages import LanguagesEdit from calibre.gui2.languages import LanguagesEdit
from calibre.gui2.tweak_book import current_container, tprefs from calibre.gui2.tweak_book import current_container, tprefs
from calibre.gui2.tweak_book.widgets import Dialog from calibre.gui2.tweak_book.widgets import Dialog
@ -101,7 +101,7 @@ class ImageDelegate(QStyledItemDelegate):
return self.item_size return self.item_size
def paint(self, painter, option, index): def paint(self, painter, option, index):
QStyledItemDelegate.paint(self, painter, option, QModelIndex()) # draw the hover and selection highlights QStyledItemDelegate.paint(self, painter, option, empty_index) # draw the hover and selection highlights
name = unicode(index.data(Qt.DisplayRole) or '') name = unicode(index.data(Qt.DisplayRole) or '')
cover = self.cover_cache.get(name, None) cover = self.cover_cache.get(name, None)
if cover is None: if cover is None:
@ -462,6 +462,7 @@ class NewBook(Dialog): # {{{
# }}} # }}}
if __name__ == '__main__': if __name__ == '__main__':
app = QApplication([]) # noqa app = QApplication([]) # noqa
from calibre.gui2.tweak_book import set_current_container from calibre.gui2.tweak_book import set_current_container

View File

@ -11,12 +11,13 @@ from threading import Thread
from PyQt5.Qt import ( from PyQt5.Qt import (
QTextBrowser, QVBoxLayout, QDialog, QDialogButtonBox, QIcon, QLabel, QTextBrowser, QVBoxLayout, QDialog, QDialogButtonBox, QIcon, QLabel,
QCheckBox, Qt, QListWidgetItem, QHBoxLayout, QListWidget, QPixmap, QCheckBox, Qt, QListWidgetItem, QHBoxLayout, QListWidget, QPixmap,
QSpinBox, QStyledItemDelegate, QSize, QModelIndex, QStyle, QPen, QSpinBox, QStyledItemDelegate, QSize, QStyle, QPen,
QProgressBar, pyqtSignal QProgressBar, pyqtSignal
) )
from calibre import human_readable, fit_image, force_unicode from calibre import human_readable, fit_image, force_unicode
from calibre.ebooks.oeb.polish.main import CUSTOMIZATION from calibre.ebooks.oeb.polish.main import CUSTOMIZATION
from calibre.gui2 import empty_index
from calibre.gui2.tweak_book import tprefs, current_container, set_current_container from calibre.gui2.tweak_book import tprefs, current_container, set_current_container
from calibre.gui2.tweak_book.widgets import Dialog from calibre.gui2.tweak_book.widgets import Dialog
from calibre.utils.icu import numeric_sort_key from calibre.utils.icu import numeric_sort_key
@ -122,7 +123,7 @@ class ImageItemDelegate(QStyledItemDelegate):
index.model().setData(index, pmap, Qt.UserRole+1) index.model().setData(index, pmap, Qt.UserRole+1)
x, y = (irect.width() - pmap.width())//2, (irect.height() - pmap.height())//2 x, y = (irect.width() - pmap.width())//2, (irect.height() - pmap.height())//2
r = irect.adjusted(x, y, -x, -y) r = irect.adjusted(x, y, -x, -y)
QStyledItemDelegate.paint(self, painter, option, QModelIndex()) QStyledItemDelegate.paint(self, painter, option, empty_index)
painter.drawPixmap(r, pmap) painter.drawPixmap(r, pmap)
trect = irect.adjusted(irect.width() + 10, 0, 0, 0) trect = irect.adjusted(irect.width() + 10, 0, 0, 0)
trect.setRight(option.rect.right()) trect.setRight(option.rect.right())
@ -253,6 +254,7 @@ class CompressImagesProgress(Dialog):
# }}} # }}}
if __name__ == '__main__': if __name__ == '__main__':
from calibre.gui2 import Application from calibre.gui2 import Application
app = Application([]) app = Application([])