diff --git a/src/calibre/gui2/__init__.py b/src/calibre/gui2/__init__.py index 1e397c42ff..024e403ca7 100644 --- a/src/calibre/gui2/__init__.py +++ b/src/calibre/gui2/__init__.py @@ -1291,10 +1291,6 @@ class Application(QApplication): ans.setDevicePixelRatio(device_pixel_ratio) return ans - def stylesheet_for_line_edit(self, is_error=False): - col = '#FF2400' if is_error else '#50c878' - return f'QLineEdit {{ border: 2px solid {col}; border-radius: 3px }}' - def _send_file_open_events(self): with self._file_open_lock: if self._file_open_paths: diff --git a/src/calibre/gui2/dialogs/metadata_bulk.py b/src/calibre/gui2/dialogs/metadata_bulk.py index ee84c037e9..f09d28329e 100644 --- a/src/calibre/gui2/dialogs/metadata_bulk.py +++ b/src/calibre/gui2/dialogs/metadata_bulk.py @@ -7,9 +7,8 @@ import regex from collections import defaultdict, namedtuple from io import BytesIO from qt.core import ( - QApplication, QComboBox, QCompleter, QDateTime, QDialog, QDialogButtonBox, QFont, - QGridLayout, QInputDialog, QLabel, QLineEdit, QProgressBar, QSize, Qt, QVBoxLayout, - pyqtSignal, + QComboBox, QCompleter, QDateTime, QDialog, QDialogButtonBox, QFont, QGridLayout, + QInputDialog, QLabel, QLineEdit, QProgressBar, QSize, Qt, QVBoxLayout, pyqtSignal, ) from threading import Thread @@ -27,7 +26,9 @@ from calibre.gui2.custom_column_widgets import populate_metadata_page from calibre.gui2.dialogs.metadata_bulk_ui import Ui_MetadataBulkDialog from calibre.gui2.dialogs.tag_editor import TagEditor from calibre.gui2.dialogs.template_line_editor import TemplateLineEditor -from calibre.gui2.widgets import LineEditECM +from calibre.gui2.widgets import ( + LineEditECM, setup_status_actions, update_status_actions, +) from calibre.startup import connect_lambda from calibre.utils.config import JSONConfig, dynamic, prefs, tweaks from calibre.utils.date import internal_iso_format_string, qt_to_dt @@ -499,6 +500,7 @@ class MetadataBulkDialog(QDialog, Ui_MetadataBulkDialog): def __init__(self, window, rows, model, tab, refresh_books): QDialog.__init__(self, window) self.setupUi(self) + setup_status_actions(self.test_result) self.series.set_sort_func(title_sort) self.model = model self.db = model.db @@ -899,10 +901,11 @@ class MetadataBulkDialog(QDialog, Ui_MetadataBulkDialog): self.s_r_search_field_changed(self.search_field.currentIndex()) def s_r_set_colors(self): + tt = '' if self.s_r_error is not None: - self.test_result.setText(error_message(self.s_r_error)) - self.test_result.setStyleSheet( - QApplication.instance().stylesheet_for_line_edit(self.s_r_error is not None)) + tt = error_message(self.s_r_error) + self.test_result.setText(tt) + update_status_actions(self.test_result, self.s_r_error is None, tt) for i in range(0,self.s_r_number_of_books): getattr(self, 'book_%d_result'%(i+1)).setText('') diff --git a/src/calibre/gui2/metadata/basic_widgets.py b/src/calibre/gui2/metadata/basic_widgets.py index 10a616d3e8..d1130e5aa7 100644 --- a/src/calibre/gui2/metadata/basic_widgets.py +++ b/src/calibre/gui2/metadata/basic_widgets.py @@ -37,7 +37,7 @@ from calibre.gui2.comments_editor import Editor from calibre.gui2.complete2 import EditWithComplete from calibre.gui2.dialogs.tag_editor import TagEditor from calibre.gui2.languages import LanguagesEdit as LE -from calibre.gui2.widgets import EnLineEdit, FormatList as _FormatList, ImageView +from calibre.gui2.widgets import EnLineEdit, FormatList as _FormatList, ImageView, LineEditIndicators from calibre.gui2.widgets2 import ( DateTimeEdit, Dialog, RatingEditor, RightClickButton, access_key, populate_standard_spinbox_context_menu, @@ -261,7 +261,7 @@ class TitleEdit(EnLineEdit, ToMetadataMixin): self.dialog = None -class TitleSortEdit(TitleEdit, ToMetadataMixin): +class TitleSortEdit(TitleEdit, ToMetadataMixin, LineEditIndicators): TITLE_ATTR = FIELD_NAME = 'title_sort' TOOLTIP = _('Specify how this book should be sorted when by title.' @@ -270,15 +270,16 @@ class TitleSortEdit(TitleEdit, ToMetadataMixin): def __init__(self, parent, title_edit, autogen_button, languages_edit): TitleEdit.__init__(self, parent) + self.setup_status_actions() self.title_edit = title_edit self.languages_edit = languages_edit base = self.TOOLTIP ok_tooltip = '
' + textwrap.fill(base+'
' + _(
- ' The green color indicates that the current '
+ ' The ok icon indicates that the current '
'title sort matches the current title'))
bad_tooltip = '
'+textwrap.fill(base + '
' + _(
- ' The red color warns that the current '
+ ' The error icon warns that the current '
'title sort does not match the current title. '
'No action is required if this is what you want.'))
self.tooltips = (ok_tooltip, bad_tooltip)
@@ -314,8 +315,8 @@ class TitleSortEdit(TitleEdit, ToMetadataMixin):
def update_state(self, *args):
ts = title_sort(self.title_edit.current_val, lang=self.book_lang)
normal = ts == self.current_val
- self.setStyleSheet(QApplication.instance().stylesheet_for_line_edit(not normal))
tt = self.tooltips[0 if normal else 1]
+ self.update_status_actions(normal, tt)
self.setToolTip(tt)
self.setWhatsThis(tt)
@@ -456,7 +457,7 @@ class AuthorsEdit(EditWithComplete, ToMetadataMixin):
pass
-class AuthorSortEdit(EnLineEdit, ToMetadataMixin):
+class AuthorSortEdit(EnLineEdit, ToMetadataMixin, LineEditIndicators):
TOOLTIP = _('Specify how the author(s) of this book should be sorted. '
'For example Charles Dickens should be sorted as Dickens, '
@@ -470,15 +471,16 @@ class AuthorSortEdit(EnLineEdit, ToMetadataMixin):
def __init__(self, parent, authors_edit, autogen_button, db,
copy_a_to_as_action, copy_as_to_a_action, a_to_as, as_to_a):
EnLineEdit.__init__(self, parent)
+ self.setup_status_actions()
self.authors_edit = authors_edit
self.db = db
base = self.TOOLTIP
ok_tooltip = '
' + textwrap.fill(base+'
' + _(
- ' The green color indicates that the current '
+ ' The ok icon indicates that the current '
'author sort matches the current author'))
bad_tooltip = '
'+textwrap.fill(base + '
'+ _(
- ' The red color indicates that the current '
+ ' The error icon indicates that the current '
'author sort does not match the current author. '
'No action is required if this is what you want.'))
self.tooltips = (ok_tooltip, bad_tooltip)
@@ -529,8 +531,8 @@ class AuthorSortEdit(EnLineEdit, ToMetadataMixin):
au = self.author_sort_from_authors(string_to_authors(au))
normal = au == self.current_val
- self.setStyleSheet(QApplication.instance().stylesheet_for_line_edit(not normal))
tt = self.tooltips[0 if normal else 1]
+ self.update_status_actions(normal, tt)
self.setToolTip(tt)
self.setWhatsThis(tt)
@@ -1572,7 +1574,7 @@ class Identifiers(Dialog):
Dialog.accept(self)
-class IdentifiersEdit(QLineEdit, ToMetadataMixin):
+class IdentifiersEdit(QLineEdit, ToMetadataMixin, LineEditIndicators):
LABEL = _('&Ids:')
BASE_TT = _('Edit the identifiers for this book. '
'For example: \n\n%s\n\nIf an identifier value contains a comma, you can use the | character to represent it.')%(
@@ -1582,6 +1584,7 @@ class IdentifiersEdit(QLineEdit, ToMetadataMixin):
def __init__(self, parent):
QLineEdit.__init__(self, parent)
+ self.setup_status_actions()
self.pat = re.compile(r'[^0-9a-zA-Z]')
self.textChanged.connect(self.validate)
self.textChanged.connect(self.data_changed)
@@ -1652,16 +1655,17 @@ class IdentifiersEdit(QLineEdit, ToMetadataMixin):
isbn = identifiers.get('isbn', '')
tt = self.BASE_TT
extra = ''
+ ok = None
if not isbn:
- sheet = ''
+ pass
elif check_isbn(isbn) is not None:
- sheet = QApplication.instance().stylesheet_for_line_edit()
+ ok = True
extra = '\n\n'+_('This ISBN is valid')
else:
- sheet = QApplication.instance().stylesheet_for_line_edit(True)
+ ok = False
extra = '\n\n' + _('This ISBN is invalid')
self.setToolTip(tt+extra)
- self.setStyleSheet(sheet)
+ self.update_status_actions(ok, self.toolTip())
def paste_identifier(self):
identifier_found = self.parse_clipboard_for_identifier()
@@ -1751,6 +1755,9 @@ class IdentifiersEdit(QLineEdit, ToMetadataMixin):
return False
# }}}
+class IndicatorLineEdit(QLineEdit, LineEditIndicators):
+ pass
+
class ISBNDialog(QDialog): # {{{
@@ -1763,7 +1770,8 @@ class ISBNDialog(QDialog): # {{{
l.addWidget(w, 0, 0, 1, 2)
w = QLabel(_('ISBN:'))
l.addWidget(w, 1, 0, 1, 1)
- self.line_edit = w = QLineEdit()
+ self.line_edit = w = IndicatorLineEdit()
+ w.setup_status_actions()
w.setText(txt)
w.selectAll()
w.textChanged.connect(self.checkText)
@@ -1787,17 +1795,17 @@ class ISBNDialog(QDialog): # {{{
def checkText(self, txt):
isbn = str(txt)
+ ok = None
if not isbn:
- sheet = ''
- extra = ''
+ pass
elif check_isbn(isbn) is not None:
- sheet = QApplication.instance().stylesheet_for_line_edit()
extra = _('This ISBN is valid')
+ ok = True
else:
- sheet = QApplication.instance().stylesheet_for_line_edit(True)
extra = _('This ISBN is invalid')
+ ok = False
self.line_edit.setToolTip(extra)
- self.line_edit.setStyleSheet(sheet)
+ self.line_edit.update_status_actions(ok, extra)
def text(self):
return check_isbn(str(self.line_edit.text()))
diff --git a/src/calibre/gui2/search_box.py b/src/calibre/gui2/search_box.py
index 4f2b5dc3ff..6070a5fe7a 100644
--- a/src/calibre/gui2/search_box.py
+++ b/src/calibre/gui2/search_box.py
@@ -158,7 +158,6 @@ class SearchBox2(QComboBox): # {{{
items.append(item)
self.addItems(items)
self.line_edit.setPlaceholderText(help_text)
- self.colorize = colorize
self.clear()
def clear_history(self):
@@ -210,10 +209,6 @@ class SearchBox2(QComboBox): # {{{
self.clear(emit_search=False)
return
self._in_a_search = ok
- if self.colorize:
- self.line_edit.setStyleSheet(QApplication.instance().stylesheet_for_line_edit(not ok))
- else:
- self.line_edit.setStyleSheet('')
# Comes from the lineEdit control
def key_pressed(self, event):
@@ -337,7 +332,7 @@ class SearchBoxMixin: # {{{
pass
def init_search_box_mixin(self):
- self.search.initialize('main_search_history', colorize=True,
+ self.search.initialize('main_search_history',
help_text=_('Search (For advanced search click the gear icon to the left)'))
self.search.cleared.connect(self.search_box_cleared)
# Queued so that search.current_text will be correct
diff --git a/src/calibre/gui2/widgets.py b/src/calibre/gui2/widgets.py
index da290e9832..aff4faf2df 100644
--- a/src/calibre/gui2/widgets.py
+++ b/src/calibre/gui2/widgets.py
@@ -546,6 +546,35 @@ class EnLineEdit(LineEditECM, QLineEdit): # {{{
# }}}
+# LineEditIndicators {{{
+
+def setup_status_actions(self: QLineEdit):
+ self.status_actions = (
+ self.addAction(QIcon.ic('ok.png'), QLineEdit.ActionPosition.TrailingPosition),
+ self.addAction(QIcon.ic('dialog_error.png'), QLineEdit.ActionPosition.TrailingPosition))
+ self.status_actions[0].setVisible(False)
+ self.status_actions[1].setVisible(False)
+
+def update_status_actions(self: QLineEdit, ok, tooltip: str = ''):
+ self.status_actions[0].setVisible(bool(ok))
+ self.status_actions[1].setVisible(not ok)
+ if ok:
+ self.status_actions[0].setToolTip(tooltip)
+ elif ok is None:
+ self.status_actions[1].setVisible(False)
+ else:
+ self.status_actions[1].setToolTip(tooltip)
+
+class LineEditIndicators:
+
+ def setup_status_actions(self):
+ setup_status_actions(self)
+
+ def update_status_actions(self, ok, tooltip=''):
+ update_status_actions(self, ok, tooltip)
+# }}}
+
+
class ItemsCompleter(QCompleter): # {{{
'''