┌   ┐
54
└   ┘

summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/dolphinviewcontainer.cpp13
-rw-r--r--src/kitemviews/kitemlistcontroller.cpp1
-rw-r--r--src/kitemviews/kitemlistcontroller.h7
-rw-r--r--src/statusbar/dolphinstatusbar.cpp101
-rw-r--r--src/statusbar/dolphinstatusbar.h42
-rw-r--r--src/views/dolphinview.cpp19
-rw-r--r--src/views/dolphinview.h5
7 files changed, 121 insertions, 67 deletions
diff --git a/src/dolphinviewcontainer.cpp b/src/dolphinviewcontainer.cpp
index 3db6ca553..968919b63 100644
--- a/src/dolphinviewcontainer.cpp
+++ b/src/dolphinviewcontainer.cpp
@@ -149,10 +149,10 @@ DolphinViewContainer::DolphinViewContainer(const QUrl &url, QWidget *parent)
m_statusBar->setZoomLevel(m_view->zoomLevel());
connect(m_view, &DolphinView::urlChanged, m_statusBar, &DolphinStatusBar::setUrl);
connect(m_view, &DolphinView::zoomLevelChanged, m_statusBar, &DolphinStatusBar::setZoomLevel);
- connect(m_view, &DolphinView::infoMessage, m_statusBar, &DolphinStatusBar::setText);
- connect(m_view, &DolphinView::operationCompletedMessage, m_statusBar, &DolphinStatusBar::setText);
+ connect(m_view, &DolphinView::infoMessage, m_statusBar, &DolphinStatusBar::setTemporaryRichText);
+ connect(m_view, &DolphinView::operationCompletedMessage, m_statusBar, &DolphinStatusBar::setTemporaryRichText);
+ connect(m_view, &DolphinView::showTypeAheadFeedback, m_statusBar, &DolphinStatusBar::setTemporaryRichText);
connect(m_view, &DolphinView::statusBarTextChanged, m_statusBar, &DolphinStatusBar::setDefaultText);
- connect(m_view, &DolphinView::statusBarTextChanged, m_statusBar, &DolphinStatusBar::resetToDefaultText);
connect(m_view, &DolphinView::directoryLoadingProgress, m_statusBar, [this](int percent) {
m_statusBar->showProgress(i18nc("@info:progress", "Loading folder…"), percent);
});
@@ -696,7 +696,7 @@ void DolphinViewContainer::slotDirectoryLoadingCompleted()
if (isSearchUrl(url()) && m_view->itemsCount() == 0) {
// The dir lister has been completed on a Baloo-URI and no items have been found. Instead
// of showing the default status bar information ("0 items") a more helpful information is given:
- m_statusBar->setText(i18nc("@info:status", "No items found."));
+ m_statusBar->setDefaultText(i18nc("@info:status", "No items found."));
} else {
updateStatusBar();
}
@@ -720,7 +720,6 @@ void DolphinViewContainer::slotDirectoryLoadingCompleted()
void DolphinViewContainer::slotDirectoryLoadingCanceled()
{
m_statusBar->showProgress(QString(), 100);
- m_statusBar->setText(QString());
}
void DolphinViewContainer::slotUrlIsFileError(const QUrl &url)
@@ -839,9 +838,9 @@ void DolphinViewContainer::slotItemsActivated(const KFileItemList &items)
void DolphinViewContainer::showItemInfo(const KFileItem &item)
{
if (item.isNull()) {
- m_statusBar->resetToDefaultText();
+ m_statusBar->setHoveredItemText(QString());
} else {
- m_statusBar->setText(item.getStatusBarInfo());
+ m_statusBar->setHoveredItemText(item.getStatusBarInfo());
}
}
diff --git a/src/kitemviews/kitemlistcontroller.cpp b/src/kitemviews/kitemlistcontroller.cpp
index ef0f9dc14..e87ed3c18 100644
--- a/src/kitemviews/kitemlistcontroller.cpp
+++ b/src/kitemviews/kitemlistcontroller.cpp
@@ -547,6 +547,7 @@ void KItemListController::slotChangeCurrentItem(const QString &text, bool search
m_view->scrollToItem(index, KItemListView::ViewItemPosition::Beginning);
*found = true;
}
+ Q_EMIT typeAheadUsed(text, index >= 0 ? std::make_optional<int>(index) : std::nullopt);
}
void KItemListController::slotAutoActivationTimeout()
diff --git a/src/kitemviews/kitemlistcontroller.h b/src/kitemviews/kitemlistcontroller.h
index 48a518610..6379acbd8 100644
--- a/src/kitemviews/kitemlistcontroller.h
+++ b/src/kitemviews/kitemlistcontroller.h
@@ -190,6 +190,13 @@ Q_SIGNALS:
void aboveItemDropEvent(int index, QGraphicsSceneDragDropEvent *event);
/**
+ * Emits the keys the user typed for searching so they can be displayed back to the user.
+ * @param typedString A string of basic interpretation of key presses e.g. "qwert".
+ * @param foundIndex The index of the item that was marked as current in response to this search.
+ */
+ void typeAheadUsed(const QString &typedString, std::optional<int> foundIndex);
+
+ /**
* Is emitted if the Escape key is pressed.
*/
void escapePressed();
diff --git a/src/statusbar/dolphinstatusbar.cpp b/src/statusbar/dolphinstatusbar.cpp
index 5d7e8e674..4b2bb6f0f 100644
--- a/src/statusbar/dolphinstatusbar.cpp
+++ b/src/statusbar/dolphinstatusbar.cpp
@@ -24,17 +24,24 @@
#include <QProgressBar>
#include <QSlider>
#include <QStyleOption>
+#include <QTextDocumentFragment>
#include <QTimer>
#include <QToolButton>
+#include <chrono>
+
+using namespace std::chrono_literals;
+
namespace
{
-const int UpdateDelay = 50;
+constexpr std::chrono::milliseconds minimumTimeBetweenTextChanges = 50ms;
+constexpr std::chrono::seconds temporaryRichTextTimeout = 1s;
}
DolphinStatusBar::DolphinStatusBar(QWidget *parent)
: AnimatedHeightWidget(parent)
- , m_text()
+ , m_temporaryRichText()
+ , m_hoveredItemText()
, m_defaultText()
, m_label(nullptr)
, m_zoomLabel(nullptr)
@@ -44,8 +51,8 @@ DolphinStatusBar::DolphinStatusBar(QWidget *parent)
, m_stopButton(nullptr)
, m_progress(100)
, m_showProgressBarTimer(nullptr)
- , m_delayUpdateTimer(nullptr)
- , m_textTimestamp()
+ , m_clearTemporaryRichTextTimer(nullptr)
+ , m_updateLabelTextTimer(nullptr)
{
setProperty("_breeze_statusbar_separator", true);
@@ -53,7 +60,7 @@ DolphinStatusBar::DolphinStatusBar(QWidget *parent)
contentsContainer->setContentsMargins(0, 0, 0, 0);
// Initialize text label
- m_label = new KSqueezedTextLabel(m_text, contentsContainer);
+ m_label = new KSqueezedTextLabel{contentsContainer};
m_label->setTextFormat(Qt::PlainText);
m_label->setTextInteractionFlags(Qt::TextBrowserInteraction | Qt::TextSelectableByKeyboard); // for accessibility but also to allow copy-pasting this text.
@@ -101,11 +108,16 @@ DolphinStatusBar::DolphinStatusBar(QWidget *parent)
m_showProgressBarTimer->setSingleShot(true);
connect(m_showProgressBarTimer, &QTimer::timeout, this, &DolphinStatusBar::updateProgressInfo);
- // initialize text updater delay timer
- m_delayUpdateTimer = new QTimer(this);
- m_delayUpdateTimer->setInterval(UpdateDelay);
- m_delayUpdateTimer->setSingleShot(true);
- connect(m_delayUpdateTimer, &QTimer::timeout, this, &DolphinStatusBar::updateLabelText);
+ // initialize timers for delayed replacing which text is shown
+ m_clearTemporaryRichTextTimer = new QTimer(this);
+ m_clearTemporaryRichTextTimer->setInterval(temporaryRichTextTimeout);
+ m_clearTemporaryRichTextTimer->setSingleShot(true);
+ connect(m_clearTemporaryRichTextTimer, &QTimer::timeout, this, &DolphinStatusBar::clearTemporaryRichText);
+
+ m_updateLabelTextTimer = new QTimer(this);
+ m_updateLabelTextTimer->setInterval(minimumTimeBetweenTextChanges);
+ m_updateLabelTextTimer->setSingleShot(true);
+ connect(m_updateLabelTextTimer, &QTimer::timeout, this, &DolphinStatusBar::updateLabelText);
// Initialize top layout and size policies
const int fontHeight = QFontMetrics(m_label->font()).height();
@@ -153,24 +165,6 @@ DolphinStatusBar::DolphinStatusBar(QWidget *parent)
DolphinStatusBar::~DolphinStatusBar() = default;
-void DolphinStatusBar::setText(const QString &text)
-{
- if (m_text == text) {
- return;
- }
-
- m_textTimestamp = QTime::currentTime();
-
- m_text = text;
- // will update status bar text in 50ms
- m_delayUpdateTimer->start();
-}
-
-QString DolphinStatusBar::text() const
-{
- return m_text;
-}
-
void DolphinStatusBar::showProgress(const QString &currentlyRunningTaskTitle, int progressPercent, CancelLoading cancelLoading)
{
m_cancelLoading = cancelLoading;
@@ -215,27 +209,28 @@ int DolphinStatusBar::progress() const
return m_progress;
}
-void DolphinStatusBar::resetToDefaultText()
+void DolphinStatusBar::setTemporaryRichText(const QString &temporaryRichText)
{
- m_text.clear();
-
- QTime currentTime;
- if (currentTime.msecsTo(m_textTimestamp) < UpdateDelay) {
- m_delayUpdateTimer->start();
- } else {
- updateLabelText();
+ if (m_temporaryRichText == temporaryRichText) {
+ return;
}
+
+ m_temporaryRichText = temporaryRichText;
+ updateLabelText(); // Show the text instantly because we only show it temporarily anyway.
+ m_clearTemporaryRichTextTimer->start();
}
-void DolphinStatusBar::setDefaultText(const QString &text)
+void DolphinStatusBar::setHoveredItemText(const QString &hoveredItemText)
{
- m_defaultText = text;
- updateLabelText();
+ m_hoveredItemText = hoveredItemText;
+ m_updateLabelTextTimer->start();
}
-QString DolphinStatusBar::defaultText() const
+void DolphinStatusBar::setDefaultText(const QString &text)
{
- return m_defaultText;
+ m_defaultText = text;
+ m_hoveredItemText.clear(); // We want to show the new default text instead of whatever was hovered.
+ m_updateLabelTextTimer->start();
}
void DolphinStatusBar::setUrl(const QUrl &url)
@@ -280,7 +275,9 @@ void DolphinStatusBar::updateWidthToContent()
QStyleOptionSlider opt;
opt.initFrom(this);
opt.orientation = Qt::Vertical;
- const QSize labelSize = QFontMetrics(font()).size(Qt::TextSingleLine, m_label->fullText());
+ const QSize labelSize = m_label->textFormat() == Qt::PlainText
+ ? QFontMetrics(font()).size(Qt::TextSingleLine, m_label->fullText())
+ : QFontMetrics(font()).size(Qt::TextSingleLine, QTextDocumentFragment::fromHtml(m_label->fullText()).toPlainText());
// Make sure minimum height takes clipping into account.
setMinimumHeight(m_label->height() + clippingAmount());
const int scrollbarWidth = style()->pixelMetric(QStyle::PM_ScrollBarExtent, &opt, this);
@@ -389,10 +386,26 @@ void DolphinStatusBar::updateProgressInfo()
updateWidthToContent();
}
+void DolphinStatusBar::clearTemporaryRichText()
+{
+ if (m_clearTemporaryRichTextTimer->isActive()) {
+ return;
+ }
+ m_temporaryRichText.clear();
+ m_updateLabelTextTimer->start();
+}
+
void DolphinStatusBar::updateLabelText()
{
- const QString text = m_text.isEmpty() ? m_defaultText : m_text;
- m_label->setText(text);
+ if (!m_temporaryRichText.isEmpty()) {
+ m_label->setTextFormat(Qt::RichText);
+ m_label->setTextElideMode(Qt::ElideNone);
+ m_label->setText(m_temporaryRichText);
+ } else {
+ m_label->setTextFormat(Qt::PlainText);
+ m_label->setTextElideMode(Qt::ElideMiddle);
+ m_label->setText(m_hoveredItemText.isEmpty() ? m_defaultText : m_hoveredItemText);
+ }
updateWidthToContent();
}
diff --git a/src/statusbar/dolphinstatusbar.h b/src/statusbar/dolphinstatusbar.h
index b4ddcd95e..232a4ba07 100644
--- a/src/statusbar/dolphinstatusbar.h
+++ b/src/statusbar/dolphinstatusbar.h
@@ -11,8 +11,6 @@
#include <KMessageWidget>
-#include <QTime>
-
class QUrl;
class StatusBarSpaceInfo;
class QLabel;
@@ -37,8 +35,6 @@ public:
explicit DolphinStatusBar(QWidget *parent);
~DolphinStatusBar() override;
- QString text() const;
-
enum class CancelLoading {
Allowed,
Disallowed
@@ -62,18 +58,21 @@ public:
int progress() const;
/**
- * Replaces the text set by setText() by the text that
- * has been set by setDefaultText(). DolphinStatusBar::text()
- * will return an empty string after the reset has been done.
+ * Sets a text that is shown with priority as a Qt::RichText for a short amount of time.
*/
- void resetToDefaultText();
-
+ void setTemporaryRichText(const QString &temporaryRichText);
+ /**
+ * Sets a text describing the hovered item. This text is immediately shown if no m_temporaryRichText is currently shown.
+ * When no item is hovered, call this method with an empty string so the m_defaultText is shown.
+ * @see setTemporaryRichText()
+ * @see setDefaultText()
+ */
+ void setHoveredItemText(const QString &hoveredItemText);
/**
- * Sets the default text, which is shown if the status bar
- * is rest by DolphinStatusBar::resetToDefaultText().
+ * Sets the default text. This text is immediately shown if no m_temporaryRichText is currently shown.
+ * @see setTemporaryRichText()
*/
void setDefaultText(const QString &text);
- QString defaultText() const;
QUrl url() const;
int zoomLevel() const;
@@ -105,7 +104,6 @@ public:
int clippingAmount() const;
public Q_SLOTS:
- void setText(const QString &text);
void setUrl(const QUrl &url);
void setZoomLevel(int zoomLevel);
@@ -147,6 +145,12 @@ private Q_SLOTS:
void updateProgressInfo();
/**
+ * Replaces the text set by setTemporaryRichText() by the text set by setHoveredItemText() or setDefaultText().
+ * Is only called when m_clearTemporaryRichTextTimer times out.
+ */
+ void clearTemporaryRichText();
+
+ /**
* Updates the text for m_label and does an eliding in
* case if the text does not fit into the available width.
*/
@@ -173,7 +177,11 @@ private:
int preferredHeight() const override;
private:
- QString m_text;
+ /** @see setTemporaryRichText() */
+ QString m_temporaryRichText;
+ /** @see setHoveredItemText() */
+ QString m_hoveredItemText;
+ /** @see setDefaultText() */
QString m_defaultText;
KSqueezedTextLabel *m_label;
QLabel *m_zoomLabel;
@@ -188,8 +196,10 @@ private:
int m_progress;
QTimer *m_showProgressBarTimer;
- QTimer *m_delayUpdateTimer;
- QTime m_textTimestamp;
+ /** Clears the temporary rich text from the status bar and shows a non-temporary text instead. */
+ QTimer *m_clearTemporaryRichTextTimer;
+ /** Very frequent updates to the status bar text look ugly. Most updates go through this timer to avoid this. */
+ QTimer *m_updateLabelTextTimer;
QHBoxLayout *m_topLayout;
};
diff --git a/src/views/dolphinview.cpp b/src/views/dolphinview.cpp
index 794223861..3c973618c 100644
--- a/src/views/dolphinview.cpp
+++ b/src/views/dolphinview.cpp
@@ -130,6 +130,25 @@ DolphinView::DolphinView(const QUrl &url, QWidget *parent)
KItemListController *controller = new KItemListController(m_model, m_view, this);
controller->setAutoActivationEnabled(GeneralSettings::autoExpandFolders());
connect(controller, &KItemListController::doubleClickViewBackground, this, &DolphinView::doubleClickViewBackground);
+ connect(controller, &KItemListController::typeAheadUsed, this, [this](const QString &typedString, std::optional<int> foundIndex) {
+ if (foundIndex.has_value()) {
+ const KFileItem item = m_model->fileItem(foundIndex.value());
+ if (item.isNull()) {
+ return;
+ }
+ const KColorScheme colorScheme = KColorScheme(QPalette::Normal, KColorScheme::Tooltip);
+ const QColor autoCompleteTextColor = colorScheme.foreground(KColorScheme::InactiveText).color();
+
+ Q_EMIT showTypeAheadFeedback(QStringLiteral("%1<font color=\"%2\">%3</font>")
+ .arg(typedString.toHtmlEscaped())
+ .arg(autoCompleteTextColor.name())
+ .arg(item.name().toHtmlEscaped().mid(typedString.size())));
+ } else {
+ const KColorScheme colorScheme = KColorScheme(QPalette::Normal, KColorScheme::Tooltip);
+ const QColor noMatchTextColor = colorScheme.foreground(KColorScheme::NegativeText).color();
+ Q_EMIT showTypeAheadFeedback(QStringLiteral("<font color=\"%1\">%2</font>").arg(noMatchTextColor.name()).arg(typedString.toHtmlEscaped()));
+ }
+ });
// The EnlargeSmallPreviews setting can only be changed after the model
// has been set in the view by KItemListController.
diff --git a/src/views/dolphinview.h b/src/views/dolphinview.h
index 6aa5b595d..9b068f92e 100644
--- a/src/views/dolphinview.h
+++ b/src/views/dolphinview.h
@@ -635,6 +635,11 @@ Q_SIGNALS:
void operationCompletedMessage(const QString &msg);
/**
+ * Is emitted so the \a typeAheadFeedback is displayed to the user. Beware: \a typeAheadFeedback is HTML-escaped rich text.
+ */
+ void showTypeAheadFeedback(const QString &typeAheadFeedback);
+
+ /**
* Is emitted after DolphinView::setUrl() has been invoked and
* the current directory is loaded. If this signal is emitted,
* it is assured that the view contains already the correct root