Klipper (classic widget): Use standard colour scheme to show filter errors

Instead of having Qt::red hardwired for the text colour.

New function KlipperPopup::showStatus() to implement setting
the filter line edit colours and showing the status.
Show an explicit error for an invalid regular expression.
Simplify filter regexp generation, add comment regarding case sensitivity.
No need to have single use strings as member variables.

I18N:
wilder-5.26
Jonathan Marten 4 years ago
parent b63c83e645
commit d26ba7662f
  1. 84
      klipper/klipperpopup.cpp
  2. 12
      klipper/klipperpopup.h

@ -8,11 +8,12 @@
#include "klipperpopup.h" #include "klipperpopup.h"
#include "klipper_debug.h" #include "klipper_debug.h"
#include <QApplication> #include <QGuiApplication>
#include <QKeyEvent> #include <QKeyEvent>
#include <QScreen> #include <QScreen>
#include <QWidgetAction> #include <QWidgetAction>
#include <KColorScheme>
#include <KHelpMenu> #include <KHelpMenu>
#include <KLineEdit> #include <KLineEdit>
#include <KLocalizedString> #include <KLocalizedString>
@ -56,8 +57,6 @@ kdbgstream &operator<<(kdbgstream &stream, const QKeyEvent &e)
KlipperPopup::KlipperPopup(History *history) KlipperPopup::KlipperPopup(History *history)
: m_dirty(true) : m_dirty(true)
, m_textForEmptyHistory(i18n("Clipboard is empty"))
, m_textForNoMatch(i18n("No matches"))
, m_history(history) , m_history(history)
, m_helpMenu(nullptr) , m_helpMenu(nullptr)
, m_popupProxy(nullptr) , m_popupProxy(nullptr)
@ -131,6 +130,26 @@ void KlipperPopup::buildFromScratch()
} }
} }
void KlipperPopup::showStatus(const QString &errorText)
{
const KColorScheme colorScheme(QPalette::Normal, KColorScheme::View);
QPalette palette = m_filterWidget->palette();
if (errorText.isEmpty()) { // no error
palette.setColor(m_filterWidget->foregroundRole(), colorScheme.foreground(KColorScheme::NormalText).color());
palette.setColor(m_filterWidget->backgroundRole(), colorScheme.background(KColorScheme::NormalBackground).color());
// add no action, rebuild() will fill with history items
} else { // there is an error
palette.setColor(m_filterWidget->foregroundRole(), colorScheme.foreground(KColorScheme::NegativeText).color());
palette.setColor(m_filterWidget->backgroundRole(), colorScheme.background(KColorScheme::NegativeBackground).color());
insertAction(actions().at(TOP_HISTORY_ITEM_INDEX), new QAction(errorText, this));
++m_nHistoryItems; // account for the added error item
}
m_filterWidget->setPalette(palette);
}
void KlipperPopup::rebuild(const QString &filter) void KlipperPopup::rebuild(const QString &filter)
{ {
if (actions().isEmpty()) { if (actions().isEmpty()) {
@ -148,39 +167,52 @@ void KlipperPopup::rebuild(const QString &filter)
} }
} }
// We search case insensitive until one uppercased character appears in the search term QRegularExpression filterexp(filter);
QRegularExpression filterexp(filter, filter.toLower() == filter ? QRegularExpression::CaseInsensitiveOption : QRegularExpression::NoPatternOption); // The search is case insensitive unless at least one uppercase character
// appears in the search term.
//
// This is not really a rigourous check, since the test below for an
// uppercase character should really check for an uppercase character that
// is not part of a special regexp character class or escape sequence:
// for example, using "\S" to mean a non-whitespace character should not
// force the match to be case sensitive. However, that is not possible
// without fully parsing the regexp. The user is not likely to be searching
// for complex regular expressions here.
if (filter.toLower() == filter) {
filterexp.setPatternOptions(QRegularExpression::CaseInsensitiveOption);
}
QPalette palette = m_filterWidget->palette(); QString errorText;
if (filterexp.isValid()) { if (!filterexp.isValid()) {
palette.setColor(m_filterWidget->foregroundRole(), palette.color(foregroundRole())); errorText = i18n("Invalid regular expression, %1", filterexp.errorString());
m_nHistoryItems = 0;
} else { } else {
palette.setColor(m_filterWidget->foregroundRole(), Qt::red); m_nHistoryItems = m_popupProxy->buildParent(TOP_HISTORY_ITEM_INDEX, filterexp);
} if (m_nHistoryItems == 0) {
m_nHistoryItems = m_popupProxy->buildParent(TOP_HISTORY_ITEM_INDEX, filterexp); if (m_history->empty()) {
if (m_nHistoryItems == 0) { errorText = i18n("Clipboard is empty");
if (m_history->empty()) { } else {
insertAction(actions().at(TOP_HISTORY_ITEM_INDEX), new QAction(m_textForEmptyHistory, this)); errorText = i18n("No matches");
}
} else { } else {
palette.setColor(m_filterWidget->foregroundRole(), Qt::red); if (history()->topIsUserSelected()) {
insertAction(actions().at(TOP_HISTORY_ITEM_INDEX), new QAction(m_textForNoMatch, this)); QAction *topAction = actions().at(TOP_HISTORY_ITEM_INDEX);
} topAction->setCheckable(true);
m_nHistoryItems++; topAction->setChecked(true);
} else { }
if (history()->topIsUserSelected()) {
actions().at(TOP_HISTORY_ITEM_INDEX)->setCheckable(true);
actions().at(TOP_HISTORY_ITEM_INDEX)->setChecked(true);
} }
} }
m_filterWidget->setPalette(palette);
showStatus(errorText);
m_dirty = false; m_dirty = false;
} }
void KlipperPopup::slotTopIsUserSelectedSet() void KlipperPopup::slotTopIsUserSelectedSet()
{ {
if (!m_dirty && m_nHistoryItems > 0 && history()->topIsUserSelected()) { if (!m_dirty && m_nHistoryItems > 0 && history()->topIsUserSelected()) {
actions().at(TOP_HISTORY_ITEM_INDEX)->setCheckable(true); QAction *topAction = actions().at(TOP_HISTORY_ITEM_INDEX);
actions().at(TOP_HISTORY_ITEM_INDEX)->setChecked(true); topAction->setCheckable(true);
topAction->setChecked(true);
} }
} }
@ -253,7 +285,7 @@ void KlipperPopup::keyPressEvent(QKeyEvent *e)
setActiveAction(actions().at(actions().indexOf(m_filterWidgetAction))); setActiveAction(actions().at(actions().indexOf(m_filterWidgetAction)));
QString lastString = m_filterWidget->text(); QString lastString = m_filterWidget->text();
QApplication::sendEvent(m_filterWidget, e); QCoreApplication::sendEvent(m_filterWidget, e);
if (m_filterWidget->text() != lastString) { if (m_filterWidget->text() != lastString) {
m_dirty = true; m_dirty = true;
rebuild(m_filterWidget->text()); rebuild(m_filterWidget->text());

@ -67,6 +67,7 @@ public Q_SLOTS:
private: private:
void rebuild(const QString &filter = QString()); void rebuild(const QString &filter = QString());
void buildFromScratch(); void buildFromScratch();
void showStatus(const QString &errorText);
protected: protected:
void keyPressEvent(QKeyEvent *e) override; void keyPressEvent(QKeyEvent *e) override;
@ -74,17 +75,6 @@ protected:
private: private:
bool m_dirty : 1; // true if menu contents needs to be rebuild. bool m_dirty : 1; // true if menu contents needs to be rebuild.
/**
* Contains the string shown if the menu is empty.
*/
QString m_textForEmptyHistory;
/**
* Contains the string shown if the search string has no
* matches and the menu is not empty.
*/
QString m_textForNoMatch;
/** /**
* The "document" (clipboard history) * The "document" (clipboard history)
*/ */

Loading…
Cancel
Save