diff --git a/src/resources/themes/v_moonlight/v_moonlight.palette b/src/resources/themes/v_moonlight/v_moonlight.palette index d7722e2c..1fe3c1c0 100644 --- a/src/resources/themes/v_moonlight/v_moonlight.palette +++ b/src/resources/themes/v_moonlight/v_moonlight.palette @@ -6,7 +6,7 @@ qss_file=v_moonlight.qss mdhl_file=v_moonlight.mdhl css_file=v_moonlight.css codeblock_css_file=v_moonlight_codeblock.css -version=1 +version=2 ; This mapping will be used to translate colors when the content of HTML is copied ; without background. You could just specify the foreground colors mapping here. @@ -108,6 +108,10 @@ tab_indicator_label_fg=@base_fg template_title_flash_light_fg=@master_light_bg template_title_flash_dark_fg=@master_bg +; Search hit items in list or tree view. +search_hit_item_fg=@selected_fg +search_hit_item_bg=@master_dark_bg + [widgets] ; Widget color attributes. diff --git a/src/resources/themes/v_pure/v_pure.palette b/src/resources/themes/v_pure/v_pure.palette index e89a182c..18deb20a 100644 --- a/src/resources/themes/v_pure/v_pure.palette +++ b/src/resources/themes/v_pure/v_pure.palette @@ -6,7 +6,7 @@ qss_file=v_pure.qss mdhl_file=v_pure.mdhl css_file=v_pure.css codeblock_css_file=v_pure_codeblock.css -version=1 +version=2 [phony] ; Abstract color attributes. @@ -102,6 +102,10 @@ tab_indicator_label_fg=@base_fg template_title_flash_light_fg=@master_light_bg template_title_flash_dark_fg=@master_bg +; Search hit items in list or tree view. +search_hit_item_fg=@selected_fg +search_hit_item_bg=@master_light_bg + [widgets] ; Widget color attributes. diff --git a/src/resources/themes/v_white/v_white.palette b/src/resources/themes/v_white/v_white.palette index 16fd1e60..f6e4abf3 100644 --- a/src/resources/themes/v_white/v_white.palette +++ b/src/resources/themes/v_white/v_white.palette @@ -6,7 +6,7 @@ qss_file=v_white.qss mdhl_file=v_white.mdhl css_file=v_white.css codeblock_css_file=v_white_codeblock.css -version=1 +version=2 [phony] ; Abstract color attributes. @@ -90,6 +90,10 @@ tab_indicator_label_fg=@base_fg template_title_flash_light_fg=#80CBC4 template_title_flash_dark_fg=#00897B +; Search hit items in list or tree view. +search_hit_item_fg=@selected_fg +search_hit_item_bg=#80CBC4 + [widgets] ; Widget color attributes. diff --git a/src/resources/vnote.ini b/src/resources/vnote.ini index 005cd693..95c0a434 100644 --- a/src/resources/vnote.ini +++ b/src/resources/vnote.ini @@ -195,6 +195,9 @@ custom_colors=White:#FFFFFF,LightGrey:#EEEEEE ; Single click to open a file then close previous tab single_click_close_previous_tab=true +; Whether enable auto wildcard match in simple search like list and tree widgets +enable_wildcard_in_simple_search=true + [web] ; Location and configuration for Mathjax mathjax_javascript=https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.2/MathJax.js?config=TeX-MML-AM_CHTML diff --git a/src/src.pro b/src/src.pro index 330b627b..e3a40cd9 100644 --- a/src/src.pro +++ b/src/src.pro @@ -108,7 +108,10 @@ SOURCES += main.cpp\ utils/vwebutils.cpp \ vlineedit.cpp \ vcart.cpp \ - vvimcmdlineedit.cpp + vvimcmdlineedit.cpp \ + vlistwidget.cpp \ + vsimplesearchinput.cpp \ + vstyleditemdelegate.cpp HEADERS += vmainwindow.h \ vdirectorytree.h \ @@ -203,7 +206,10 @@ HEADERS += vmainwindow.h \ utils/vwebutils.h \ vlineedit.h \ vcart.h \ - vvimcmdlineedit.h + vvimcmdlineedit.h \ + vlistwidget.h \ + vsimplesearchinput.h \ + vstyleditemdelegate.h RESOURCES += \ vnote.qrc \ diff --git a/src/utils/viconutils.h b/src/utils/viconutils.h index 8a7422f7..e1b0b10a 100644 --- a/src/utils/viconutils.h +++ b/src/utils/viconutils.h @@ -17,9 +17,9 @@ public: const QString &p_fg = QString(), bool p_addDisabled = true); - static QIcon toolButtonIcon(const QString &p_file) + static QIcon toolButtonIcon(const QString &p_file, bool p_addDisabled = true) { - return icon(p_file, g_palette->color("toolbutton_icon_fg")); + return icon(p_file, g_palette->color("toolbutton_icon_fg"), p_addDisabled); } static QIcon toolButtonDangerIcon(const QString &p_file) diff --git a/src/vconfigmanager.h b/src/vconfigmanager.h index 6e08f2ae..48185af4 100644 --- a/src/vconfigmanager.h +++ b/src/vconfigmanager.h @@ -440,6 +440,8 @@ public: bool getSingleClickClosePreviousTab() const; + bool getEnableWildCardInSimpleSearch() const; + private: // Look up a config from user and default settings. QVariant getConfigFromSettings(const QString §ion, const QString &key) const; @@ -2046,4 +2048,10 @@ inline bool VConfigManager::getSingleClickClosePreviousTab() const { return m_singleClickClosePreviousTab; } + +inline bool VConfigManager::getEnableWildCardInSimpleSearch() const +{ + return getConfigFromSettings("global", + "enable_wildcard_in_simple_search").toBool(); +} #endif // VCONFIGMANAGER_H diff --git a/src/vfilelist.cpp b/src/vfilelist.cpp index 5c17fe2f..7e8502bc 100644 --- a/src/vfilelist.cpp +++ b/src/vfilelist.cpp @@ -17,7 +17,6 @@ #include "dialog/vconfirmdeletiondialog.h" #include "dialog/vsortdialog.h" #include "vmainwindow.h" -#include "utils/vimnavigationforwidget.h" #include "utils/viconutils.h" #include "dialog/vtipsdialog.h" #include "vcart.h" @@ -61,7 +60,7 @@ VFileList::VFileList(QWidget *parent) void VFileList::setupUI() { - fileList = new QListWidget(this); + fileList = new VListWidget(this); fileList->setContextMenuPolicy(Qt::CustomContextMenu); fileList->setSelectionMode(QAbstractItemView::ExtendedSelection); fileList->setObjectName("FileList"); @@ -202,7 +201,7 @@ void VFileList::setDirectory(VDirectory *p_directory) // be NULL. if (m_directory == p_directory) { if (!m_directory) { - fileList->clear(); + fileList->clearAll(); } return; @@ -210,7 +209,7 @@ void VFileList::setDirectory(VDirectory *p_directory) m_directory = p_directory; if (!m_directory) { - fileList->clear(); + fileList->clearAll(); return; } @@ -219,7 +218,7 @@ void VFileList::setDirectory(VDirectory *p_directory) void VFileList::updateFileList() { - fileList->clear(); + fileList->clearAll(); if (!m_directory->open()) { return; } @@ -921,11 +920,6 @@ void VFileList::pasteFiles(VDirectory *p_destDir, void VFileList::keyPressEvent(QKeyEvent *p_event) { - if (VimNavigationForWidget::injectKeyPressEventForVim(fileList, - p_event)) { - return; - } - if (p_event->key() == Qt::Key_Return) { QListWidgetItem *item = fileList->currentItem(); if (item) { diff --git a/src/vfilelist.h b/src/vfilelist.h index 2238f75f..fcfdf83c 100644 --- a/src/vfilelist.h +++ b/src/vfilelist.h @@ -13,6 +13,7 @@ #include "vdirectory.h" #include "vnotefile.h" #include "vnavigationmode.h" +#include "vlistwidget.h" class QAction; class VNote; @@ -166,7 +167,7 @@ private: void activateItem(QListWidgetItem *p_item, bool p_restoreFocus = false); VEditArea *editArea; - QListWidget *fileList; + VListWidget *fileList; QPointer m_directory; // Magic number for clipboard operations. diff --git a/src/vlineedit.cpp b/src/vlineedit.cpp index f1616ced..79f43091 100644 --- a/src/vlineedit.cpp +++ b/src/vlineedit.cpp @@ -5,12 +5,12 @@ #include "utils/vutils.h" VLineEdit::VLineEdit(QWidget *p_parent) - : QLineEdit(p_parent) + : QLineEdit(p_parent), m_ctrlKEnabled(true) { } VLineEdit::VLineEdit(const QString &p_contents, QWidget *p_parent) - : QLineEdit(p_contents, p_parent) + : QLineEdit(p_contents, p_parent), m_ctrlKEnabled(true) { } @@ -64,6 +64,16 @@ void VLineEdit::keyPressEvent(QKeyEvent *p_event) break; } + case Qt::Key_K: + { + if (VUtils::isControlModifierForVim(modifiers) && !m_ctrlKEnabled) { + QWidget::keyPressEvent(p_event); + accept = true; + } + + break; + } + default: break; } diff --git a/src/vlineedit.h b/src/vlineedit.h index 2cc1b367..dc7349a8 100644 --- a/src/vlineedit.h +++ b/src/vlineedit.h @@ -12,8 +12,20 @@ public: VLineEdit(const QString &p_contents, QWidget *p_parent = nullptr); + void setCtrlKEnabled(bool p_enabled); + protected: void keyPressEvent(QKeyEvent *p_event) Q_DECL_OVERRIDE; + +private: + // Enable Ctrl+K shortcut. + // In QLineEdit, Ctrl+K will delete till the end. + bool m_ctrlKEnabled; }; +inline void VLineEdit::setCtrlKEnabled(bool p_enabled) +{ + m_ctrlKEnabled = p_enabled; +} + #endif // VLINEEDIT_H diff --git a/src/vlistwidget.cpp b/src/vlistwidget.cpp new file mode 100644 index 00000000..7198f2b8 --- /dev/null +++ b/src/vlistwidget.cpp @@ -0,0 +1,133 @@ +#include "vlistwidget.h" + +#include +#include +#include +#include +#include + +#include "utils/vutils.h" +#include "utils/vimnavigationforwidget.h" +#include "vstyleditemdelegate.h" + +VListWidget::VListWidget(QWidget *parent) + : QListWidget(parent), + ISimpleSearch() +{ + m_searchInput = new VSimpleSearchInput(this, this); + connect(m_searchInput, &VSimpleSearchInput::triggered, + this, &VListWidget::handleSearchModeTriggered); + + m_searchInput->hide(); + + m_delegate = new VStyledItemDelegate(this); + setItemDelegate(m_delegate); +} + +void VListWidget::keyPressEvent(QKeyEvent *p_event) +{ + if (m_searchInput->tryHandleKeyPressEvent(p_event)) { + return; + } + + if (VimNavigationForWidget::injectKeyPressEventForVim(this, p_event)) { + return; + } + + QListWidget::keyPressEvent(p_event); +} + +void VListWidget::clearAll() +{ + m_searchInput->clear(); + setSearchInputVisible(false); + + QListWidget::clear(); +} + +void VListWidget::setSearchInputVisible(bool p_visible) +{ + m_searchInput->setVisible(p_visible); + + int topMargin = 0; + if (p_visible) { + topMargin = m_searchInput->height(); + } + + setViewportMargins(0, topMargin, 0, 0); +} + +void VListWidget::resizeEvent(QResizeEvent *p_event) +{ + QListWidget::resizeEvent(p_event); + + QRect rect = contentsRect(); + int width = rect.width(); + QScrollBar *vbar = verticalScrollBar(); + if (vbar && (vbar->minimum() != vbar->maximum())) { + width -= vbar->width(); + } + + m_searchInput->setGeometry(QRect(rect.left(), + rect.top(), + width, + m_searchInput->height())); +} + +void VListWidget::handleSearchModeTriggered(bool p_inSearchMode) +{ + setSearchInputVisible(p_inSearchMode); + if (!p_inSearchMode) { + clearItemsHighlight(); + setFocus(); + } +} + +QList VListWidget::searchItems(const QString &p_text, + Qt::MatchFlags p_flags) const +{ + QList items = findItems(p_text, p_flags); + + QList res; + res.reserve(items.size()); + for (int i = 0; i < items.size(); ++i) { + res.append(items[i]); + } + + return res; +} + +void VListWidget::highlightHitItems(const QList &p_items) +{ + clearItemsHighlight(); + + QSet hitIndexes; + for (auto it : p_items) { + QModelIndex index = indexFromItem(static_cast(it)); + if (index.isValid()) { + hitIndexes.insert(index); + } + } + + if (!hitIndexes.isEmpty()) { + m_delegate->setHitItems(hitIndexes); + update(); + } +} + +void VListWidget::clearItemsHighlight() +{ + m_delegate->clearHitItems(); + update(); +} + +void VListWidget::selectHitItem(void *p_item) +{ + setCurrentItem(static_cast(p_item), + QItemSelectionModel::ClearAndSelect); +} + +int VListWidget::totalNumberOfItems() +{ + return count(); +} diff --git a/src/vlistwidget.h b/src/vlistwidget.h new file mode 100644 index 00000000..ecf9a039 --- /dev/null +++ b/src/vlistwidget.h @@ -0,0 +1,49 @@ +#ifndef VLISTWIDGET_H +#define VLISTWIDGET_H + +#include + +#include "vsimplesearchinput.h" + +class VStyledItemDelegate; + + +class VListWidget : public QListWidget, public ISimpleSearch +{ +public: + explicit VListWidget(QWidget *parent = Q_NULLPTR); + + // Clear list widget as well as other data. + // clear() is not virtual to override. + void clearAll(); + + // Implement ISimpleSearch. + virtual QList searchItems(const QString &p_text, + Qt::MatchFlags p_flags) const Q_DECL_OVERRIDE; + + virtual void highlightHitItems(const QList &p_items) Q_DECL_OVERRIDE; + + virtual void clearItemsHighlight() Q_DECL_OVERRIDE; + + virtual void selectHitItem(void *p_item) Q_DECL_OVERRIDE; + + virtual int totalNumberOfItems() Q_DECL_OVERRIDE; + +private slots: + void handleSearchModeTriggered(bool p_inSearchMode); + +protected: + void keyPressEvent(QKeyEvent *p_event) Q_DECL_OVERRIDE; + + void resizeEvent(QResizeEvent *p_event) Q_DECL_OVERRIDE; + +private: + // Show or hide search input. + void setSearchInputVisible(bool p_visible); + + VSimpleSearchInput *m_searchInput; + + VStyledItemDelegate *m_delegate; +}; + +#endif // VLISTWIDGET_H diff --git a/src/vsimplesearchinput.cpp b/src/vsimplesearchinput.cpp new file mode 100644 index 00000000..3b952003 --- /dev/null +++ b/src/vsimplesearchinput.cpp @@ -0,0 +1,216 @@ +#include "vsimplesearchinput.h" + +#include +#include +#include +#include +#include +#include + +#include "vlineedit.h" +#include "utils/vutils.h" +#include "vconfigmanager.h" + +extern VConfigManager *g_config; + +VSimpleSearchInput::VSimpleSearchInput(ISimpleSearch *p_obj, QWidget *p_parent) + : QWidget(p_parent), + m_obj(p_obj), + m_inSearchMode(false), + m_currentIdx(-1), + m_wildCardEnabled(g_config->getEnableWildCardInSimpleSearch()) +{ + if (m_wildCardEnabled) { + m_matchFlags = Qt::MatchWildcard | Qt::MatchWrap | Qt::MatchRecursive; + } else { + m_matchFlags = Qt::MatchContains | Qt::MatchWrap | Qt::MatchRecursive; + } + + m_searchEdit = new VLineEdit(); + m_searchEdit->setPlaceholderText(tr("Type to search")); + m_searchEdit->setCtrlKEnabled(false); + connect(m_searchEdit, &QLineEdit::textChanged, + this, &VSimpleSearchInput::handleEditTextChanged); + + QValidator *validator = new QRegExpValidator(QRegExp(VUtils::c_fileNameRegExp), + m_searchEdit); + m_searchEdit->setValidator(validator); + m_searchEdit->installEventFilter(this); + + m_infoLabel = new QLabel(); + + QLayout *layout = new QHBoxLayout(); + layout->addWidget(m_searchEdit); + layout->addWidget(m_infoLabel); + layout->setContentsMargins(0, 0, 0, 0); + + setLayout(layout); +} + +void VSimpleSearchInput::clear() +{ + m_inSearchMode = false; + clearSearch(); +} + +// If it is the / leader key to trigger search mode. +static bool isLeaderKey(int p_key, int p_modifiers) +{ + return p_key == Qt::Key_Slash && p_modifiers == Qt::NoModifier; +} + +static bool isCharKey(int p_key, int p_modifiers) +{ + return p_key >= Qt::Key_A + && p_key <= Qt::Key_Z + && (p_modifiers == Qt::NoModifier || p_modifiers == Qt::ShiftModifier); +} + +static bool isDigitKey(int p_key, int p_modifiers) +{ + return p_key >= Qt::Key_0 + && p_key <= Qt::Key_9 + && (p_modifiers == Qt::NoModifier || p_modifiers == Qt::KeypadModifier); +} + +static QChar keyToChar(int p_key, int p_modifiers) +{ + if (isCharKey(p_key, p_modifiers)) { + char ch = p_modifiers == Qt::ShiftModifier ? 'A' : 'a'; + return QChar(ch + (p_key - Qt::Key_A)); + } else if (isDigitKey(p_key, p_modifiers)) { + return QChar('0' + (p_key - Qt::Key_0)); + } + + return QChar(); +} + +bool VSimpleSearchInput::tryHandleKeyPressEvent(QKeyEvent *p_event) +{ + int key = p_event->key(); + Qt::KeyboardModifiers modifiers = p_event->modifiers(); + + if (!m_inSearchMode) { + // Try to trigger search mode. + QChar ch; + if (isCharKey(key, modifiers) + || isDigitKey(key, modifiers)) { + m_inSearchMode = true; + ch = keyToChar(key, modifiers); + } else if (isLeaderKey(key, modifiers)) { + m_inSearchMode = true; + } + + if (m_inSearchMode) { + emit triggered(m_inSearchMode); + + clearSearch(); + m_searchEdit->setFocus(); + + if (!ch.isNull()) { + m_searchEdit->setText(ch); + } + + return true; + } + } else { + // Try to exit search mode. + if (key == Qt::Key_Escape + || (key == Qt::Key_BracketLeft + && VUtils::isControlModifierForVim(modifiers))) { + m_inSearchMode = false; + emit triggered(m_inSearchMode); + return true; + } + } + + // Ctrl+N/P to activate next hit item. + if (VUtils::isControlModifierForVim(modifiers) + && (key == Qt::Key_N || key == Qt::Key_P)) { + int delta = key == Qt::Key_N ? 1 : -1; + + if (!m_inSearchMode) { + m_inSearchMode = true; + emit triggered(m_inSearchMode); + m_searchEdit->setFocus(); + + m_obj->highlightHitItems(m_hitItems); + } + + if (!m_hitItems.isEmpty()) { + m_currentIdx += delta; + if (m_currentIdx < 0) { + m_currentIdx = m_hitItems.size() - 1; + } else if (m_currentIdx >= m_hitItems.size()) { + m_currentIdx = 0; + } + + m_obj->selectHitItem(currentItem()); + } + + return true; + } + + return false; +} + +void VSimpleSearchInput::clearSearch() +{ + m_searchEdit->clear(); + m_hitItems.clear(); + m_currentIdx = -1; + m_obj->clearItemsHighlight(); + + updateInfoLabel(0, m_obj->totalNumberOfItems()); +} + +bool VSimpleSearchInput::eventFilter(QObject *p_watched, QEvent *p_event) +{ + Q_UNUSED(p_watched); + if (p_event->type() == QEvent::FocusOut) { + QFocusEvent *eve = static_cast(p_event); + if (eve->reason() != Qt::ActiveWindowFocusReason) { + m_inSearchMode = false; + emit triggered(m_inSearchMode); + } + } + + return QWidget::eventFilter(p_watched, p_event); +} + +void VSimpleSearchInput::handleEditTextChanged(const QString &p_text) +{ + if (!m_inSearchMode) { + return; + } + + if (p_text.isEmpty()) { + clearSearch(); + m_obj->selectHitItem(NULL); + return; + } + + if (m_wildCardEnabled) { + QString wildcardText(p_text.size() * 2 + 1, '*'); + for (int i = 0, j = 1; i < p_text.size(); ++i, j += 2) { + wildcardText[j] = p_text[i]; + } + + m_hitItems = m_obj->searchItems(wildcardText, m_matchFlags); + } else { + m_hitItems = m_obj->searchItems(p_text, m_matchFlags); + } + + updateInfoLabel(m_hitItems.size(), m_obj->totalNumberOfItems()); + + m_obj->highlightHitItems(m_hitItems); + + m_currentIdx = m_hitItems.isEmpty() ? -1 : 0; + + m_obj->selectHitItem(currentItem()); +} + +void VSimpleSearchInput::updateInfoLabel(int p_nrHit, int p_total) +{ + m_infoLabel->setText(tr("%1/%2").arg(p_nrHit).arg(p_total)); +} diff --git a/src/vsimplesearchinput.h b/src/vsimplesearchinput.h new file mode 100644 index 00000000..87611ae8 --- /dev/null +++ b/src/vsimplesearchinput.h @@ -0,0 +1,89 @@ +#ifndef VSIMPLESEARCHINPUT_H +#define VSIMPLESEARCHINPUT_H + +#include +#include + +class VLineEdit; +class QLabel; + +class ISimpleSearch +{ +public: + // Return items matching the search. + virtual QList searchItems(const QString &p_text, + Qt::MatchFlags p_flags) const = 0; + + // Highlight hit items to denote the search result. + virtual void highlightHitItems(const QList &p_items) = 0; + + // Clear the highlight. + virtual void clearItemsHighlight() = 0; + + // Select @p_item. + // @p_item sets to NULL to clear selection. + virtual void selectHitItem(void *p_item) = 0; + + // Get the total number of all the items. + virtual int totalNumberOfItems() = 0; +}; + + +class VSimpleSearchInput : public QWidget +{ + Q_OBJECT +public: + explicit VSimpleSearchInput(ISimpleSearch *p_obj, QWidget *p_parent = nullptr); + + // Clear input. + void clear(); + + // Try to handle key press event from outside widget. + // Return true if @p_event is consumed and do not need further process. + bool tryHandleKeyPressEvent(QKeyEvent *p_event); + +signals: + // Search mode is triggered. + void triggered(bool p_inSearchMode); + +protected: + bool eventFilter(QObject *p_watched, QEvent *p_event) Q_DECL_OVERRIDE; + +private slots: + // Text in the input changed. + void handleEditTextChanged(const QString &p_text); + +private: + // Clear last search. + void clearSearch(); + + void *currentItem() const; + + void updateInfoLabel(int p_nrHit, int p_total); + + ISimpleSearch *m_obj; + + VLineEdit *m_searchEdit; + + QLabel *m_infoLabel; + + bool m_inSearchMode; + + QList m_hitItems; + + int m_currentIdx; + + Qt::MatchFlags m_matchFlags; + + bool m_wildCardEnabled; +}; + +inline void *VSimpleSearchInput::currentItem() const +{ + if (m_currentIdx >= 0 && m_currentIdx < m_hitItems.size()) { + return m_hitItems[m_currentIdx]; + } + + return NULL; +} +#endif // VSIMPLESEARCHINPUT_H diff --git a/src/vstyleditemdelegate.cpp b/src/vstyleditemdelegate.cpp new file mode 100644 index 00000000..d0dd0a36 --- /dev/null +++ b/src/vstyleditemdelegate.cpp @@ -0,0 +1,31 @@ +#include "vstyleditemdelegate.h" + +#include +#include + +#include "vpalette.h" + +extern VPalette *g_palette; + +VStyledItemDelegate::VStyledItemDelegate(QObject *p_parent) + : QStyledItemDelegate(p_parent) +{ + m_itemHitBg = QBrush(QColor(g_palette->color("search_hit_item_bg"))); + m_itemHitFg = QBrush(QColor(g_palette->color("search_hit_item_fg"))); +} + +void VStyledItemDelegate::paint(QPainter *p_painter, + const QStyleOptionViewItem &p_option, + const QModelIndex &p_index) const +{ + if (isHit(p_index)) { + QStyleOptionViewItem option(p_option); + p_painter->fillRect(option.rect, m_itemHitBg); + // Does not work anyway. + // option.palette.setBrush(QPalette::Base, m_itemHitBg); + option.palette.setBrush(QPalette::Text, m_itemHitFg); + QStyledItemDelegate::paint(p_painter, option, p_index); + } else { + QStyledItemDelegate::paint(p_painter, p_option, p_index); + } +} diff --git a/src/vstyleditemdelegate.h b/src/vstyleditemdelegate.h new file mode 100644 index 00000000..a6c062ca --- /dev/null +++ b/src/vstyleditemdelegate.h @@ -0,0 +1,50 @@ +#ifndef VSTYLEDITEMDELEGATE_H +#define VSTYLEDITEMDELEGATE_H + +#include +#include +#include + + +class VStyledItemDelegate : public QStyledItemDelegate +{ +public: + explicit VStyledItemDelegate(QObject *p_parent = Q_NULLPTR); + + virtual void paint(QPainter *p_painter, + const QStyleOptionViewItem &p_option, + const QModelIndex &p_index) const Q_DECL_OVERRIDE; + + void setHitItems(const QSet &p_hitItems); + + void clearHitItems(); + +private: + bool isHit(const QModelIndex &p_index) const; + + QBrush m_itemHitBg; + + QBrush m_itemHitFg; + + QSet m_hitItems; +}; + +inline void VStyledItemDelegate::setHitItems(const QSet &p_hitItems) +{ + m_hitItems = p_hitItems; +} + +inline void VStyledItemDelegate::clearHitItems() +{ + m_hitItems.clear(); +} + +inline bool VStyledItemDelegate::isHit(const QModelIndex &p_index) const +{ + if (m_hitItems.isEmpty()) { + return false; + } + + return m_hitItems.contains(p_index); +} +#endif // VSTYLEDITEMDELEGATE_H diff --git a/src/vvimcmdlineedit.cpp b/src/vvimcmdlineedit.cpp index 4cacd867..99e67100 100644 --- a/src/vvimcmdlineedit.cpp +++ b/src/vvimcmdlineedit.cpp @@ -206,6 +206,8 @@ void VVimCmdLineEdit::focusOutEvent(QFocusEvent *p_event) if (p_event->reason() != Qt::ActiveWindowFocusReason) { emit commandCancelled(); } + + VLineEdit::focusOutEvent(p_event); } void VVimCmdLineEdit::setCommand(const QString &p_cmd)