Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
home:epopov:branches:openSUSE:Factory
kate
2004-better-quick-open-window.patch
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File 2004-better-quick-open-window.patch of Package kate
diff --git a/apps/lib/katemainwindow.cpp b/apps/lib/katemainwindow.cpp index a054a39504be1a25689533345148b65491edb6e3..0331cbd4c88ed1a1796ec7eb73184cfc39d81560 100644 --- a/apps/lib/katemainwindow.cpp +++ b/apps/lib/katemainwindow.cpp @@ -1534,8 +1534,6 @@ void KateMainWindow::slotQuickOpen() * show quick open and pass focus to it */ KateQuickOpen *quickOpen = new KateQuickOpen(this); - centralWidget()->setFocusProxy(quickOpen); - quickOpen->raise(); quickOpen->show(); } diff --git a/apps/lib/quickopen/katequickopen.cpp b/apps/lib/quickopen/katequickopen.cpp index 699236a05a783d992f0881568166dbe4a2f5fd2f..e529f678a2b37cfb0d006269229824f77e96c70c 100644 --- a/apps/lib/quickopen/katequickopen.cpp +++ b/apps/lib/quickopen/katequickopen.cpp @@ -20,16 +20,18 @@ #include <QCoreApplication> #include <QEvent> +#include <QGraphicsEffect> +#include <QLabel> #include <QPainter> #include <QPointer> #include <QSortFilterProxyModel> +#include <QStatusBar> #include <QStyledItemDelegate> #include <QToolBar> #include <QTreeView> #include <drawing_utils.h> #include <kfts_fuzzy_match.h> -#include <qgraphicseffect.h> class QuickOpenFilterProxyModel final : public QSortFilterProxyModel { @@ -194,8 +196,7 @@ public: } QTextCharFormat fmt; - fmt.setForeground(options.palette.link().color()); - fmt.setFontWeight(QFont::Bold); + fmt.setForeground(options.palette.link()); const int nameLen = name.length(); // space between name and path @@ -215,15 +216,11 @@ public: auto nameFormats = kfts::get_fuzzy_match_formats(m_filterString, name, 0, fmt); formats.append(nameFormats); } - QTextCharFormat boldFmt; - boldFmt.setFontWeight(QFont::Bold); - boldFmt.setFontPointSize(options.font.pointSize() - 1); - pathFormats = kfts::get_fuzzy_match_formats(m_filterString, path, nameLen + space, boldFmt); + pathFormats = kfts::get_fuzzy_match_formats(m_filterString, path, nameLen + space, fmt); } QTextCharFormat gray; - gray.setForeground(Qt::gray); - gray.setFontPointSize(options.font.pointSize() - 1); + gray.setForeground(option.palette.placeholderText()); formats.append({nameLen + space, static_cast<int>(path.length()), gray}); if (!pathFormats.isEmpty()) { formats.append(pathFormats); @@ -232,14 +229,11 @@ public: painter->save(); // paint background - if (option.state & QStyle::State_Selected) { - painter->fillRect(option.rect, option.palette.highlight()); - } else { - painter->fillRect(option.rect, option.palette.base()); - } + QStyle *style = option.widget->style(); + style->drawPrimitive(QStyle::PE_PanelItemViewItem, &option, painter); options.text = QString(); // clear old text - options.widget->style()->drawControl(QStyle::CE_ItemViewItem, &options, painter, options.widget); + style->drawControl(QStyle::CE_ItemViewItem, &options, painter, options.widget); // space for icon painter->translate(25, 0); @@ -269,128 +263,149 @@ private: Q_DECLARE_METATYPE(QPointer<KTextEditor::Document>) KateQuickOpen::KateQuickOpen(KateMainWindow *mainWindow) - : QFrame(mainWindow) + : QWidget(mainWindow, Qt::Popup) , m_mainWindow(mainWindow) { - QGraphicsDropShadowEffect *e = new QGraphicsDropShadowEffect(this); - e->setColor(palette().color(QPalette::Shadow)); - e->setOffset(2.); - e->setBlurRadius(8.); - setGraphicsEffect(e); - - setAutoFillBackground(true); - setFrameShadow(QFrame::Raised); - setFrameShape(QFrame::Box); - - // handle resizing - mainWindow->installEventFilter(this); + setAttribute(Qt::WA_DeleteOnClose); + setProperty("_KDE_NET_WM_FORCE_SHADOW", true); // ensure the components have some proper frame - QVBoxLayout *layout = new QVBoxLayout(); + QVBoxLayout *layout = new QVBoxLayout; layout->setSpacing(0); - layout->setContentsMargins(2, 2, 2, 2); + layout->setContentsMargins(QMargins() + 1); // for frame setLayout(layout); m_inputLine = new QuickOpenLineEdit(this); + m_inputLine->setClearButtonEnabled(true); + m_inputLine->addAction(QIcon::fromTheme(QStringLiteral("search")), QLineEdit::LeadingPosition); setFocusProxy(m_inputLine); - layout->addWidget(m_inputLine); + QHBoxLayout *inputLineLayout = new QHBoxLayout; + inputLineLayout->setContentsMargins(QMargins() + 6); + inputLineLayout->addWidget(m_inputLine); + layout->addLayout(inputLineLayout); m_listView = new QTreeView(this); - layout->addWidget(m_listView, 1); + m_listView->setFocusPolicy(Qt::NoFocus); m_listView->setTextElideMode(Qt::ElideLeft); m_listView->setUniformRowHeights(true); + m_listView->setProperty("_breeze_borders_sides", QVariant::fromValue(QFlags(Qt::TopEdge))); + layout->addWidget(m_listView); m_model = new KateQuickOpenModel(this); m_styleDelegate = new QuickOpenStyleDelegate(this); m_listView->setItemDelegate(m_styleDelegate); connect(m_inputLine, &QuickOpenLineEdit::textChanged, this, &KateQuickOpen::reselectFirst, Qt::QueuedConnection); - connect(m_inputLine, &QuickOpenLineEdit::returnPressed, this, &KateQuickOpen::slotReturnPressed); connect(m_inputLine, &QuickOpenLineEdit::listModeChanged, this, &KateQuickOpen::slotListModeChanged); connect(m_inputLine, &QuickOpenLineEdit::filterModeChanged, this, &KateQuickOpen::setFilterMode); connect(m_listView, &QTreeView::activated, this, &KateQuickOpen::slotReturnPressed); - connect(m_listView, &QTreeView::clicked, this, &KateQuickOpen::slotReturnPressed); // for single click + connect(m_listView, &QTreeView::clicked, m_listView, &QTreeView::activated); // for single click m_inputLine->installEventFilter(this); - m_listView->installEventFilter(this); + m_listView->setHeaderHidden(true); m_listView->setRootIsDecorated(false); m_listView->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); - m_listView->setModel(m_model); - connect(m_inputLine, &QuickOpenLineEdit::textChanged, this, [this](const QString &text) { - // We init the proxy model when there is something to filter - if (!m_proxyModel) { - m_proxyModel = new QuickOpenFilterProxyModel(this); - m_proxyModel->setFilterCaseSensitivity(Qt::CaseInsensitive); - m_proxyModel->setFilterMode(m_inputLine->filterMode()); - bool filtered = m_proxyModel->setFilterText(text); - m_proxyModel->setSourceModel(m_model); - m_listView->setModel(m_proxyModel); - if (filtered) { - m_styleDelegate->setFilterString(text); - m_listView->viewport()->update(); - } + m_proxyModel = new QuickOpenFilterProxyModel(this); + m_proxyModel->setFilterCaseSensitivity(Qt::CaseInsensitive); + m_proxyModel->setFilterMode(m_inputLine->filterMode()); + m_proxyModel->setSourceModel(m_model); + m_listView->setModel(m_proxyModel); + + QLabel *placeholderLabel = new QLabel; + placeholderLabel->setAlignment(Qt::AlignCenter); + placeholderLabel->setTextInteractionFlags(Qt::NoTextInteraction); + placeholderLabel->setWordWrap(true); + // To match the size of a level 2 Heading/KTitleWidget + QFont placeholderLabelFont = placeholderLabel->font(); + placeholderLabelFont.setPointSize(qRound(placeholderLabelFont.pointSize() * 1.3)); + placeholderLabel->setFont(placeholderLabelFont); + // Match opacity of QML placeholder label component + QGraphicsOpacityEffect *opacityEffect = new QGraphicsOpacityEffect(placeholderLabel); + opacityEffect->setOpacity(0.5); + placeholderLabel->setGraphicsEffect(opacityEffect); + + QHBoxLayout *placeholderLayout = new QHBoxLayout; + placeholderLayout->addWidget(placeholderLabel); + m_listView->setLayout(placeholderLayout); + + connect(m_proxyModel, &QuickOpenFilterProxyModel::modelReset, this, [this, placeholderLabel]() { + if (m_proxyModel->rowCount() > 0) { + placeholderLabel->hide(); } else { - if (m_proxyModel->setFilterText(text)) { - m_styleDelegate->setFilterString(text); - m_listView->viewport()->update(); + if (m_model->rowCount() == 0) { + placeholderLabel->setText(i18n("No items to display")); + } else { + placeholderLabel->setText(i18n("No items matching the filter")); } + placeholderLabel->show(); } }); - setHidden(true); + connect(m_inputLine, &QuickOpenLineEdit::textChanged, this, [this](const QString &text) { + if (m_proxyModel->setFilterText(text)) { + m_styleDelegate->setFilterString(text); + m_listView->viewport()->update(); + } + }); setFilterMode(); m_model->setListMode(m_inputLine->listMode()); // fill stuff - updateState(); + refreshModel(); } bool KateQuickOpen::eventFilter(QObject *obj, QEvent *event) { - // catch key presses + shortcut overrides to allow to have ESC as application wide shortcut, too, see bug 409856 - if (event->type() == QEvent::KeyPress || event->type() == QEvent::ShortcutOverride) { - QKeyEvent *keyEvent = static_cast<QKeyEvent *>(event); - if (obj == m_inputLine) { - const bool forward2list = (keyEvent->key() == Qt::Key_Up) || (keyEvent->key() == Qt::Key_Down) || (keyEvent->key() == Qt::Key_PageUp) - || (keyEvent->key() == Qt::Key_PageDown); - if (forward2list) { - QCoreApplication::sendEvent(m_listView, event); - return true; - } - - } else if (obj == m_listView) { - const bool forward2input = (keyEvent->key() != Qt::Key_Up) && (keyEvent->key() != Qt::Key_Down) && (keyEvent->key() != Qt::Key_PageUp) - && (keyEvent->key() != Qt::Key_PageDown) && (keyEvent->key() != Qt::Key_Tab) && (keyEvent->key() != Qt::Key_Backtab); - if (forward2input) { - QCoreApplication::sendEvent(m_inputLine, event); - return true; - } + if (obj == m_inputLine && event->type() == QEvent::KeyPress) { + const QKeyEvent *keyEvent = static_cast<QKeyEvent*>(event); + if (keyEvent->modifiers() & Qt::MetaModifier) { + return true; } - if (keyEvent->key() == Qt::Key_Escape) { - hide(); - deleteLater(); + switch (keyEvent->key()) { + case Qt::Key_Up: + case Qt::Key_Down: + case Qt::Key_PageUp: + case Qt::Key_PageDown: + case Qt::Key_Enter: + case Qt::Key_Return: + QCoreApplication::sendEvent(m_listView, event); return true; + case Qt::Key_Escape: + close(); + return true; + default: + break; } } - if (event->type() == QEvent::FocusOut && !(m_inputLine->hasFocus() || m_listView->hasFocus())) { - hide(); - deleteLater(); - return true; - } + return QWidget::eventFilter(obj, event); +} - // handle resizing - if (m_mainWindow == obj && event->type() == QEvent::Resize) { - updateViewGeometry(); - } +void KateQuickOpen::paintEvent(QPaintEvent *event) +{ + Q_UNUSED(event); - return QWidget::eventFilter(obj, event); + QStyleOptionMenuItem option; + option.initFrom(this); + + QPainter painter(this); + + style()->drawPrimitive(QStyle::PE_PanelMenu, &option, &painter); +} + +void KateQuickOpen::showEvent(QShowEvent *event) +{ + adjustSizeAndPosition(); + + QWidget::showEvent(event); + + setFocus(Qt::PopupFocusReason); } void KateQuickOpen::reselectFirst() @@ -405,14 +420,10 @@ void KateQuickOpen::reselectFirst() m_listView->setCurrentIndex(index); } -void KateQuickOpen::updateState() +void KateQuickOpen::refreshModel() { m_model->refresh(m_mainWindow); reselectFirst(); - - updateViewGeometry(); - show(); - setFocus(); } void KateQuickOpen::slotReturnPressed() @@ -425,15 +436,23 @@ void KateQuickOpen::slotReturnPressed() // either get view via document pointer or url const QModelIndex index = m_listView->currentIndex(); - KTextEditor::View *view = nullptr; + if (!index.isValid()) { + return; + } + + KTextEditor::View *view; if (auto doc = index.data(KateQuickOpenModel::Document).value<KTextEditor::Document *>()) { view = m_mainWindow->activateView(doc); } else { view = m_mainWindow->wrapper()->openUrl(index.data(Qt::UserRole).toUrl()); } + if (!view) { + return; + } + const auto strs = m_inputLine->text().split(QLatin1Char(':')); - if (view && strs.count() > 1) { + if (strs.count() > 1) { // helper to convert String => Number auto stringToInt = [](const QString &s) { bool ok = false; @@ -458,22 +477,19 @@ void KateQuickOpen::slotReturnPressed() } } - hide(); - deleteLater(); + close(); m_mainWindow->slotWindowActivated(); // store the new position in location history - if (view) { - vm->addPositionToHistory(view->document()->url(), view->cursorPosition()); - } + vm->addPositionToHistory(view->document()->url(), view->cursorPosition()); } void KateQuickOpen::slotListModeChanged(KateQuickOpenModel::List mode) { m_model->setListMode(mode); // this changes things again, needs refresh, let's go all the way - updateState(); + refreshModel(); } void KateQuickOpen::setFilterMode() @@ -487,7 +503,7 @@ void KateQuickOpen::setFilterMode() m_listView->viewport()->update(); } -static QRect getQuickOpenBoundingRect(QMainWindow *mainWindow) +static QRect getQuickOpenBoundingRect(KateMainWindow *mainWindow) { QRect boundingRect = mainWindow->contentsRect(); @@ -498,6 +514,13 @@ static QRect getQuickOpenBoundingRect(QMainWindow *mainWindow) } } + // exclude the status bar from the bounding rect + if (const QStatusBar *statusBar = mainWindow->findChild<QStatusBar *>()) { + if (!statusBar->isHidden()) { + boundingRect.setBottom(boundingRect.bottom() - statusBar->height()); + } + } + // exclude any undocked toolbar from the bounding rect const QList<QToolBar *> toolBars = mainWindow->findChildren<QToolBar *>(); for (QToolBar *toolBar : toolBars) { @@ -505,15 +528,28 @@ static QRect getQuickOpenBoundingRect(QMainWindow *mainWindow) continue; } - if (mainWindow->toolBarArea(toolBar) == Qt::TopToolBarArea) { + switch (mainWindow->toolBarArea(toolBar)) { + case Qt::TopToolBarArea: boundingRect.setTop(std::max(boundingRect.top(), toolBar->geometry().bottom())); + break; + case Qt::RightToolBarArea: + boundingRect.setRight(std::min(boundingRect.right(), toolBar->geometry().left())); + break; + case Qt::BottomToolBarArea: + boundingRect.setBottom(std::min(boundingRect.bottom(), toolBar->geometry().top())); + break; + case Qt::LeftToolBarArea: + boundingRect.setLeft(std::max(boundingRect.left(), toolBar->geometry().right())); + break; + default: + break; } } - return boundingRect; + return boundingRect.translated(mainWindow->geometry().topLeft()); } -void KateQuickOpen::updateViewGeometry() +void KateQuickOpen::adjustSizeAndPosition() { const QRect boundingRect = getQuickOpenBoundingRect(m_mainWindow); @@ -525,16 +561,13 @@ void KateQuickOpen::updateViewGeometry() const int maxHeight = boundingRect.height(); const int preferredHeight = maxHeight / 2; - const QSize size{std::min(maxWidth, std::max(preferredWidth, minWidth)), std::min(maxHeight, std::max(preferredHeight, minHeight))}; + const QSize size(std::min(maxWidth, std::max(preferredWidth, minWidth)), std::min(maxHeight, std::max(preferredHeight, minHeight))); - // resize() doesn't work here, so use setFixedSize() instead - setFixedSize(size); + resize(size); // set the position to the top-center of the parent // just below the menubar/toolbar (if any) - const QPoint position{boundingRect.center().x() - size.width() / 2, boundingRect.y()}; - - move(position); + move(boundingRect.center().x() - size.width() / 2, boundingRect.y() + 6); } #include "moc_katequickopen.cpp" diff --git a/apps/lib/quickopen/katequickopen.h b/apps/lib/quickopen/katequickopen.h index afaa20ad3ce2e872feea2da7793cc60d31115c5c..1c9ecf908eea58a097385306301084bfe51dc209 100644 --- a/apps/lib/quickopen/katequickopen.h +++ b/apps/lib/quickopen/katequickopen.h @@ -21,21 +21,22 @@ enum KateQuickOpenModelList : int; class QuickOpenFilterProxyModel; -class KateQuickOpen : public QFrame +class KateQuickOpen : public QWidget { Q_OBJECT public: KateQuickOpen(KateMainWindow *mainWindow); /** - * update state + * refresh model * will fill model with current open documents, project documents, ... */ - void updateState(); - void updateViewGeometry(); + void refreshModel(); protected: bool eventFilter(QObject *obj, QEvent *event) override; + void paintEvent(QPaintEvent *event) override; + void showEvent(QShowEvent *event) override; private Q_SLOTS: void reselectFirst(); @@ -51,6 +52,8 @@ private Q_SLOTS: void setFilterMode(); private: + void adjustSizeAndPosition(); + KateMainWindow *m_mainWindow; QTreeView *m_listView; QuickOpenLineEdit *m_inputLine; diff --git a/apps/lib/quickopen/katequickopenmodel.cpp b/apps/lib/quickopen/katequickopenmodel.cpp index 915aa8da97ecf64037835263c39a65c330363175..39742f8b04edd117ba7fd031a189b7bf85fa328a 100644 --- a/apps/lib/quickopen/katequickopenmodel.cpp +++ b/apps/lib/quickopen/katequickopenmodel.cpp @@ -54,14 +54,6 @@ QVariant KateQuickOpenModel::data(const QModelIndex &idx, int role) const const auto &path = entry.filePath; return path.startsWith(m_projectBase) ? path.mid(m_projectBase.size()) : path; } - case Qt::FontRole: { - if (entry.document) { - QFont font; - font.setBold(true); - return font; - } - return {}; - } case Qt::DecorationRole: return QIcon::fromTheme(QMimeDatabase().mimeTypeForFile(entry.fileName, QMimeDatabase::MatchExtension).iconName()); case Qt::UserRole:
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor