Add context menu entries to clear metadata edit spinboxes for date and number fields

This commit is contained in:
Kovid Goyal 2014-10-23 22:00:09 +05:30
parent ecce202556
commit 270b6f403f
3 changed files with 77 additions and 35 deletions

View File

@ -8,12 +8,13 @@ __docformat__ = 'restructuredtext en'
import sys
from PyQt5.Qt import (Qt, QApplication, QStyle, QIcon, QDoubleSpinBox, QStyleOptionViewItem,
QSpinBox, QStyledItemDelegate, QComboBox, QTextDocument, QSize,
QSpinBox, QStyledItemDelegate, QComboBox, QTextDocument, QSize, QMenu, QKeySequence,
QAbstractTextDocumentLayout, QFont, QFontInfo, QDate, QDateTimeEdit, QDateTime)
from calibre.gui2 import UNDEFINED_QDATETIME, error_dialog, rating_font
from calibre.constants import iswindows
from calibre.gui2.widgets import EnLineEdit
from calibre.gui2.widgets2 import populate_standard_spinbox_context_menu
from calibre.gui2.complete2 import EditWithComplete
from calibre.utils.date import now, format_date, qt_to_dt, is_date_undefined
from calibre.utils.config import tweaks
@ -33,10 +34,21 @@ class DateTimeEdit(QDateTimeEdit): # {{{
self.setCalendarPopup(True)
self.setDisplayFormat(format)
def contextMenuEvent(self, ev):
m = QMenu(self)
m.addAction(_('Set date to undefined') + '\t' + QKeySequence(Qt.Key_Minus).toString(QKeySequence.NativeText),
self.clear_date)
m.addSeparator()
populate_standard_spinbox_context_menu(self, m)
m.popup(ev.globalPos())
def clear_date(self):
self.setDateTime(UNDEFINED_QDATETIME)
def keyPressEvent(self, ev):
if ev.key() == Qt.Key_Minus:
ev.accept()
self.setDateTime(UNDEFINED_QDATETIME)
self.clear_date()
elif ev.key() == Qt.Key_Equal:
ev.accept()
self.setDateTime(QDateTime.currentDateTime())
@ -44,20 +56,33 @@ class DateTimeEdit(QDateTimeEdit): # {{{
return QDateTimeEdit.keyPressEvent(self, ev)
# }}}
class ClearingSpinBox(QSpinBox): # {{{
def keyPressEvent(self, ev):
if ev.key() == Qt.Key_Space:
self.setValue(-1000000)
else:
return QSpinBox.keyPressEvent(self, ev)
# }}}
# Number Editor {{{
def make_clearing_spinbox(spinbox):
class SpinBox(spinbox):
def contextMenuEvent(self, ev):
m = QMenu(self)
m.addAction(_('Set to undefined') + '\t' + QKeySequence(Qt.Key_Space).toString(QKeySequence.NativeText),
self.clear_to_undefined)
m.addSeparator()
populate_standard_spinbox_context_menu(self, m)
m.popup(ev.globalPos())
def clear_to_undefined(self):
self.setValue(self.minimum())
def keyPressEvent(self, ev):
if ev.key() == Qt.Key_Space:
self.clear_to_undefined()
else:
return spinbox.keyPressEvent(self, ev)
return SpinBox
ClearingSpinBox = make_clearing_spinbox(QSpinBox)
ClearingDoubleSpinBox = make_clearing_spinbox(QDoubleSpinBox)
class ClearingDoubleSpinBox(QDoubleSpinBox): # {{{
def keyPressEvent(self, ev):
if ev.key() == Qt.Key_Space:
self.setValue(-1000000.0)
else:
return QDoubleSpinBox.keyPressEvent(self, ev)
# }}}
class RatingDelegate(QStyledItemDelegate): # {{{
@ -145,6 +170,7 @@ class PubDateDelegate(QStyledItemDelegate): # {{{
# }}}
class TextDelegate(QStyledItemDelegate): # {{{
def __init__(self, parent):
'''
Delegate for text data. If auto_complete_function needs to return a list
@ -179,9 +205,10 @@ class TextDelegate(QStyledItemDelegate): # {{{
else:
QStyledItemDelegate.setModelData(self, editor, model, index)
#}}}
# }}}
class CompleteDelegate(QStyledItemDelegate): # {{{
def __init__(self, parent, sep, items_func_name, space_before_sep=False):
QStyledItemDelegate.__init__(self, parent)
self.sep = sep
@ -239,6 +266,7 @@ class LanguagesDelegate(QStyledItemDelegate): # {{{
# }}}
class CcDateDelegate(QStyledItemDelegate): # {{{
'''
Delegate for custom columns dates. Because this delegate stores the
format as an instance variable, a new instance must be created for each
@ -278,6 +306,7 @@ class CcDateDelegate(QStyledItemDelegate): # {{{
# }}}
class CcTextDelegate(QStyledItemDelegate): # {{{
'''
Delegate for text data.
'''
@ -303,6 +332,7 @@ class CcTextDelegate(QStyledItemDelegate): # {{{
# }}}
class CcNumberDelegate(QStyledItemDelegate): # {{{
'''
Delegate for text/int/float data.
'''
@ -338,6 +368,7 @@ class CcNumberDelegate(QStyledItemDelegate): # {{{
# }}}
class CcEnumDelegate(QStyledItemDelegate): # {{{
'''
Delegate for text/int/float data.
'''
@ -370,6 +401,7 @@ class CcEnumDelegate(QStyledItemDelegate): # {{{
# }}}
class CcCommentsDelegate(QStyledItemDelegate): # {{{
'''
Delegate for comments data.
'''
@ -422,6 +454,7 @@ class DelegateCB(QComboBox): # {{{
# }}}
class CcBoolDelegate(QStyledItemDelegate): # {{{
def __init__(self, parent):
'''
Delegate for custom_column bool data.
@ -470,6 +503,7 @@ class CcBoolDelegate(QStyledItemDelegate): # {{{
# }}}
class CcTemplateDelegate(QStyledItemDelegate): # {{{
def __init__(self, parent):
'''
Delegate for custom_column bool data.
@ -506,5 +540,3 @@ class CcTemplateDelegate(QStyledItemDelegate): # {{{
# }}}

View File

@ -17,6 +17,7 @@ from PyQt5.Qt import (
QUndoStack)
from calibre.gui2.widgets import EnLineEdit, FormatList as _FormatList, ImageView
from calibre.gui2.widgets2 import access_key, populate_standard_spinbox_context_menu
from calibre.utils.icu import sort_key
from calibre.utils.config import tweaks, prefs
from calibre.ebooks.metadata import (
@ -109,11 +110,6 @@ class ToMetadataMixin(object):
def make_undoable(spinbox):
'Add a proper undo/redo capability to spinbox which must be a sub-class of QAbstractSpinBox'
def access_key(k):
if QKeySequence.keyBindings(k):
return '\t' + QKeySequence(k).toString(QKeySequence.NativeText)
return ''
class UndoCommand(QUndoCommand):
def __init__(self, widget, val):
@ -157,20 +153,13 @@ def make_undoable(spinbox):
def contextMenuEvent(self, ev):
m = QMenu(self)
if hasattr(self, 'setDateTime'):
m.addAction(_('Set date to undefined') + '\t' + QKeySequence(Qt.Key_Minus).toString(QKeySequence.NativeText),
lambda : self.setDateTime(self.minimumDateTime()))
m.addAction(_('&Undo') + access_key(QKeySequence.Undo), self.undo).setEnabled(self.undo_stack.canUndo())
m.addAction(_('&Redo') + access_key(QKeySequence.Redo), self.redo).setEnabled(self.undo_stack.canRedo())
m.addSeparator()
le = self.lineEdit()
m.addAction(_('Cu&t') + access_key(QKeySequence.Cut), le.cut).setEnabled(not le.isReadOnly() and le.hasSelectedText())
m.addAction(_('&Copy') + access_key(QKeySequence.Copy), le.copy).setEnabled(le.hasSelectedText())
m.addAction(_('&Paste') + access_key(QKeySequence.Paste), le.paste).setEnabled(not le.isReadOnly())
m.addAction(_('Delete') + access_key(QKeySequence.Delete), le.del_).setEnabled(not le.isReadOnly() and le.hasSelectedText())
m.addSeparator()
m.addAction(_('Select &All') + access_key(QKeySequence.SelectAll), self.selectAll)
m.addSeparator()
m.addAction(_('&Step up'), self.stepUp)
m.addAction(_('Step &down'), self.stepDown)
m.setAttribute(Qt.WA_DeleteOnClose)
populate_standard_spinbox_context_menu(self, m)
m.popup(ev.globalPos())
def set_spinbox_value(self, val):

View File

@ -6,7 +6,7 @@ from __future__ import (unicode_literals, division, absolute_import,
__license__ = 'GPL v3'
__copyright__ = '2013, Kovid Goyal <kovid at kovidgoyal.net>'
from PyQt5.Qt import QPushButton, QPixmap, QIcon, QColor, Qt, QColorDialog, pyqtSignal
from PyQt5.Qt import QPushButton, QPixmap, QIcon, QColor, Qt, QColorDialog, pyqtSignal, QKeySequence
from calibre.gui2.complete2 import LineEdit, EditWithComplete
from calibre.gui2.widgets import history
@ -99,3 +99,24 @@ class ColorButton(QPushButton):
if col.isValid():
self.color = unicode(col.name())
def access_key(k):
'Return shortcut text suitable for adding to a menu item'
if QKeySequence.keyBindings(k):
return '\t' + QKeySequence(k).toString(QKeySequence.NativeText)
return ''
def populate_standard_spinbox_context_menu(spinbox, menu, add_clear=False):
m = menu
le = spinbox.lineEdit()
m.addAction(_('Cu&t') + access_key(QKeySequence.Cut), le.cut).setEnabled(not le.isReadOnly() and le.hasSelectedText())
m.addAction(_('&Copy') + access_key(QKeySequence.Copy), le.copy).setEnabled(le.hasSelectedText())
m.addAction(_('&Paste') + access_key(QKeySequence.Paste), le.paste).setEnabled(not le.isReadOnly())
m.addAction(_('Delete') + access_key(QKeySequence.Delete), le.del_).setEnabled(not le.isReadOnly() and le.hasSelectedText())
m.addSeparator()
m.addAction(_('Select &All') + access_key(QKeySequence.SelectAll), spinbox.selectAll)
m.addSeparator()
m.addAction(_('&Step up'), spinbox.stepUp)
m.addAction(_('Step &down'), spinbox.stepDown)
m.setAttribute(Qt.WA_DeleteOnClose)