mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
Dont subclass QLineEdit in QDateEdit
This causes crashed on Linux with accessibility enabled. Fixes #1892646 [Mysterious crash in Qt since bug #1885004 when clicking "Edit Metadata"](https://bugs.launchpad.net/calibre/+bug/1892646)
This commit is contained in:
parent
bf508e306d
commit
35f770955e
@ -8,10 +8,10 @@ import weakref
|
|||||||
from PyQt5.Qt import (
|
from PyQt5.Qt import (
|
||||||
QApplication, QByteArray, QCalendarWidget, QCheckBox, QColor, QColorDialog,
|
QApplication, QByteArray, QCalendarWidget, QCheckBox, QColor, QColorDialog,
|
||||||
QComboBox, QDate, QDateTime, QDateTimeEdit, QDialog, QDialogButtonBox, QFont,
|
QComboBox, QDate, QDateTime, QDateTimeEdit, QDialog, QDialogButtonBox, QFont,
|
||||||
QFontInfo, QFontMetrics, QIcon, QKeySequence, QLabel, QLayout, QLineEdit, QMenu,
|
QFontInfo, QFontMetrics, QIcon, QKeySequence, QLabel, QLayout, QMenu,
|
||||||
QMimeData, QPalette, QPixmap, QPoint, QPushButton, QRect, QScrollArea, QSize,
|
QMimeData, QPalette, QPixmap, QPoint, QPushButton, QRect, QScrollArea, QSize,
|
||||||
QSizePolicy, QStyle, QStyledItemDelegate, Qt, QTabWidget, QTextBrowser,
|
QSizePolicy, QStyle, QStyledItemDelegate, Qt, QTabWidget, QTextBrowser,
|
||||||
QToolButton, QUndoCommand, QUndoStack, QWidget, pyqtSignal, pyqtSlot
|
QToolButton, QUndoCommand, QUndoStack, QWidget, pyqtSignal
|
||||||
)
|
)
|
||||||
|
|
||||||
from calibre.ebooks.metadata import rating_to_stars
|
from calibre.ebooks.metadata import rating_to_stars
|
||||||
@ -127,12 +127,13 @@ def access_key(k):
|
|||||||
return ''
|
return ''
|
||||||
|
|
||||||
|
|
||||||
def populate_standard_spinbox_context_menu(spinbox, menu, add_clear=False):
|
def populate_standard_spinbox_context_menu(spinbox, menu, add_clear=False, use_self_for_copy_actions=False):
|
||||||
m = menu
|
m = menu
|
||||||
le = spinbox.lineEdit()
|
le = spinbox.lineEdit()
|
||||||
m.addAction(_('Cu&t') + access_key(QKeySequence.Cut), le.cut).setEnabled(not le.isReadOnly() and le.hasSelectedText())
|
ca = spinbox if use_self_for_copy_actions else le
|
||||||
m.addAction(_('&Copy') + access_key(QKeySequence.Copy), le.copy).setEnabled(le.hasSelectedText())
|
m.addAction(_('Cu&t') + access_key(QKeySequence.Cut), ca.cut).setEnabled(not le.isReadOnly() and le.hasSelectedText())
|
||||||
m.addAction(_('&Paste') + access_key(QKeySequence.Paste), le.paste).setEnabled(not le.isReadOnly())
|
m.addAction(_('&Copy') + access_key(QKeySequence.Copy), ca.copy).setEnabled(le.hasSelectedText())
|
||||||
|
m.addAction(_('&Paste') + access_key(QKeySequence.Paste), ca.paste).setEnabled(not le.isReadOnly())
|
||||||
m.addAction(_('Delete') + access_key(QKeySequence.Delete), le.del_).setEnabled(not le.isReadOnly() and le.hasSelectedText())
|
m.addAction(_('Delete') + access_key(QKeySequence.Delete), le.del_).setEnabled(not le.isReadOnly() and le.hasSelectedText())
|
||||||
m.addSeparator()
|
m.addSeparator()
|
||||||
m.addAction(_('Select &all') + access_key(QKeySequence.SelectAll), spinbox.selectAll)
|
m.addAction(_('Select &all') + access_key(QKeySequence.SelectAll), spinbox.selectAll)
|
||||||
@ -556,25 +557,6 @@ def to_plain_text(self):
|
|||||||
return ans.rstrip('\0')
|
return ans.rstrip('\0')
|
||||||
|
|
||||||
|
|
||||||
class LineEditForDateTimeEdit(QLineEdit):
|
|
||||||
|
|
||||||
date_time_pasted = pyqtSignal(object)
|
|
||||||
date_time_copied = pyqtSignal(object)
|
|
||||||
MIME_TYPE = 'application/x-calibre-datetime-value'
|
|
||||||
|
|
||||||
@pyqtSlot()
|
|
||||||
def copy(self):
|
|
||||||
self.date_time_copied.emit(self.selectedText())
|
|
||||||
|
|
||||||
@pyqtSlot()
|
|
||||||
def paste(self):
|
|
||||||
md = QApplication.instance().clipboard().mimeData()
|
|
||||||
if md.hasFormat(self.MIME_TYPE):
|
|
||||||
self.date_time_pasted.emit(QDateTime.fromString(md.data(self.MIME_TYPE).data().decode('ascii'), Qt.ISODate))
|
|
||||||
else:
|
|
||||||
QLineEdit.paste(self)
|
|
||||||
|
|
||||||
|
|
||||||
class CalendarWidget(QCalendarWidget):
|
class CalendarWidget(QCalendarWidget):
|
||||||
|
|
||||||
def showEvent(self, ev):
|
def showEvent(self, ev):
|
||||||
@ -584,12 +566,10 @@ class CalendarWidget(QCalendarWidget):
|
|||||||
|
|
||||||
class DateTimeEdit(QDateTimeEdit):
|
class DateTimeEdit(QDateTimeEdit):
|
||||||
|
|
||||||
|
MIME_TYPE = 'application/x-calibre-datetime-value'
|
||||||
|
|
||||||
def __init__(self, parent=None):
|
def __init__(self, parent=None):
|
||||||
QDateTimeEdit.__init__(self, parent)
|
QDateTimeEdit.__init__(self, parent)
|
||||||
self.custom_line_edit = le = LineEditForDateTimeEdit(self)
|
|
||||||
self.setLineEdit(le)
|
|
||||||
le.date_time_pasted.connect(self.date_time_pasted, type=Qt.QueuedConnection)
|
|
||||||
le.date_time_copied.connect(self.date_time_copied, type=Qt.QueuedConnection)
|
|
||||||
self.setMinimumDateTime(UNDEFINED_QDATETIME)
|
self.setMinimumDateTime(UNDEFINED_QDATETIME)
|
||||||
self.setCalendarPopup(True)
|
self.setCalendarPopup(True)
|
||||||
self.cw = CalendarWidget(self)
|
self.cw = CalendarWidget(self)
|
||||||
@ -597,14 +577,27 @@ class DateTimeEdit(QDateTimeEdit):
|
|||||||
self.setCalendarWidget(self.cw)
|
self.setCalendarWidget(self.cw)
|
||||||
self.setSpecialValueText(_('Undefined'))
|
self.setSpecialValueText(_('Undefined'))
|
||||||
|
|
||||||
def date_time_copied(self, text):
|
@property
|
||||||
|
def mime_data_for_copy(self):
|
||||||
md = QMimeData()
|
md = QMimeData()
|
||||||
md.setText(text or self.dateTime().toString())
|
md.setText(self.dateTime().toString())
|
||||||
md.setData(self.custom_line_edit.MIME_TYPE, self.dateTime().toString(Qt.ISODate).encode('ascii'))
|
md.setData(self.MIME_TYPE, self.dateTime().toString(Qt.ISODate).encode('ascii'))
|
||||||
|
return md
|
||||||
|
|
||||||
|
def copy(self):
|
||||||
|
QApplication.instance().clipboard().setMimeData(self.mime_data_for_copy)
|
||||||
|
|
||||||
|
def cut(self):
|
||||||
|
md = self.mime_data_for_copy
|
||||||
|
self.lineEdit().cut()
|
||||||
QApplication.instance().clipboard().setMimeData(md)
|
QApplication.instance().clipboard().setMimeData(md)
|
||||||
|
|
||||||
def date_time_pasted(self, qt_dt):
|
def paste(self):
|
||||||
self.setDateTime(qt_dt)
|
md = QApplication.instance().clipboard().mimeData()
|
||||||
|
if md.hasFormat(self.MIME_TYPE):
|
||||||
|
self.setDateTime(QDateTime.fromString(md.data(self.MIME_TYPE).data().decode('ascii'), Qt.ISODate))
|
||||||
|
else:
|
||||||
|
self.lineEdit().paste()
|
||||||
|
|
||||||
def create_context_menu(self):
|
def create_context_menu(self):
|
||||||
m = QMenu(self)
|
m = QMenu(self)
|
||||||
@ -613,7 +606,7 @@ class DateTimeEdit(QDateTimeEdit):
|
|||||||
m.addAction(_('Set date to today') + '\t' + QKeySequence(Qt.Key_Equal).toString(QKeySequence.NativeText),
|
m.addAction(_('Set date to today') + '\t' + QKeySequence(Qt.Key_Equal).toString(QKeySequence.NativeText),
|
||||||
self.today_date)
|
self.today_date)
|
||||||
m.addSeparator()
|
m.addSeparator()
|
||||||
populate_standard_spinbox_context_menu(self, m)
|
populate_standard_spinbox_context_menu(self, m, use_self_for_copy_actions=True)
|
||||||
return m
|
return m
|
||||||
|
|
||||||
def contextMenuEvent(self, ev):
|
def contextMenuEvent(self, ev):
|
||||||
@ -634,10 +627,13 @@ class DateTimeEdit(QDateTimeEdit):
|
|||||||
self.today_date()
|
self.today_date()
|
||||||
ev.accept()
|
ev.accept()
|
||||||
elif ev.matches(QKeySequence.Copy):
|
elif ev.matches(QKeySequence.Copy):
|
||||||
self.lineEdit().copy()
|
self.copy()
|
||||||
|
ev.accept()
|
||||||
|
elif ev.matches(QKeySequence.Cut):
|
||||||
|
self.cut()
|
||||||
ev.accept()
|
ev.accept()
|
||||||
elif ev.matches(QKeySequence.Paste):
|
elif ev.matches(QKeySequence.Paste):
|
||||||
self.lineEdit().paste()
|
self.paste()
|
||||||
ev.accept()
|
ev.accept()
|
||||||
else:
|
else:
|
||||||
return QDateTimeEdit.keyPressEvent(self, ev)
|
return QDateTimeEdit.keyPressEvent(self, ev)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user