diff --git a/src/core/markdowneditorconfig.h b/src/core/markdowneditorconfig.h index 84ca9c7a..2de1e3df 100644 --- a/src/core/markdowneditorconfig.h +++ b/src/core/markdowneditorconfig.h @@ -241,7 +241,7 @@ namespace vnotex InplacePreviewSources m_inplacePreviewSources = InplacePreviewSource::NoInplacePreview; // View mode in edit mode. - EditViewMode m_editViewMode = EditViewMode::EditOnly; + EditViewMode m_editViewMode = EditViewMode::EditPreview; }; } diff --git a/src/data/core/vnotex.json b/src/data/core/vnotex.json index 6c250315..b181e80b 100644 --- a/src/data/core/vnotex.json +++ b/src/data/core/vnotex.json @@ -360,7 +360,7 @@ "//comment" : "imagelink/codeblock/math", "inplace_preview_sources" : "imagelink;codeblock;math", "//comment" : "view mode of edit mode: editonly/editpreview", - "edit_view_mode" : "editonly" + "edit_view_mode" : "editpreview" }, "image_host" : { "hosts" : [ diff --git a/src/data/extra/themes/moonlight/interface.qss b/src/data/extra/themes/moonlight/interface.qss index 3e827831..83370bd9 100644 --- a/src/data/extra/themes/moonlight/interface.qss +++ b/src/data/extra/themes/moonlight/interface.qss @@ -18,6 +18,10 @@ QWidget[DialogCentralWidget="true"] { border: none; } +QWidget[HitSettingWidget="true"] { + border: 2px solid @widgets#qwidget#info#border; +} + /* All widgets */ *[State="info"] { border: 1px solid @widgets#qwidget#info#border; diff --git a/src/data/extra/themes/native/interface.qss b/src/data/extra/themes/native/interface.qss index 90a1711e..e53ac135 100644 --- a/src/data/extra/themes/native/interface.qss +++ b/src/data/extra/themes/native/interface.qss @@ -8,6 +8,10 @@ * - $2px: 2 will be scaled by multiplying current display scaled factor. */ +QWidget[HitSettingWidget="true"] { + border: 2px solid @base#info#fg; +} + /* All widgets */ *[State="info"] { border: 1px solid @base#info#fg; diff --git a/src/data/extra/themes/pure/interface.qss b/src/data/extra/themes/pure/interface.qss index 853b18b4..83370bd9 100644 --- a/src/data/extra/themes/pure/interface.qss +++ b/src/data/extra/themes/pure/interface.qss @@ -18,6 +18,10 @@ QWidget[DialogCentralWidget="true"] { border: none; } +QWidget[HitSettingWidget="true"] { + border: 2px solid @widgets#qwidget#info#border; +} + /* All widgets */ *[State="info"] { border: 1px solid @widgets#qwidget#info#border; @@ -31,10 +35,6 @@ QWidget[DialogCentralWidget="true"] { border: 1px solid @widgets#qwidget#error#border; } -[HitSettingWidget="true"] { - border: 4px solid @widgets#qwidget#info#border; -} - /* QAbstractScrollArea */ QAbstractScrollArea { border: 1px solid @widgets#qabstractscrollarea#border; diff --git a/src/widgets/dialogs/settings/settingsdialog.cpp b/src/widgets/dialogs/settings/settingsdialog.cpp index 36ee24a9..2d7cfeef 100644 --- a/src/widgets/dialogs/settings/settingsdialog.cpp +++ b/src/widgets/dialogs/settings/settingsdialog.cpp @@ -5,10 +5,16 @@ #include #include #include +#include +#include +#include #include #include #include +#include +#include +#include #include "generalpage.h" #include "miscpage.h" @@ -22,14 +28,6 @@ #include "vipage.h" #include "notemanagementpage.h" -#include -#include -#include -#include "settingspage.h" -#include "utils/widgetutils.h" -#include "../../propertydefs.h" -#include - using namespace vnotex; SettingsDialog::SettingsDialog(QWidget *p_parent) @@ -72,24 +70,20 @@ void SettingsDialog::setupPageExplorer(QBoxLayout *p_layout, QWidget *p_parent) { auto layout = new QVBoxLayout(); + m_searchTimer = new QTimer(this); + m_searchTimer->setSingleShot(true); + m_searchTimer->setInterval(500); + connect(m_searchTimer, &QTimer::timeout, + this, &SettingsDialog::search); + m_searchEdit = WidgetsFactory::createLineEdit(p_parent); m_searchEdit->setPlaceholderText(tr("Search")); + m_searchEdit->setClearButtonEnabled(true); layout->addWidget(m_searchEdit); - connect(m_searchEdit,&QLineEdit::textChanged, - this, [this]() { QTimer::singleShot(500, this, [this](){ - forEachPage([this](SettingsPage *p_page) { - bool hit = p_page->search(m_searchEdit->text()); - if (hit) { - qDebug() << p_page->title(); - // 目前只能找到tree的 通过 外观 笔记管理,快速访问与编辑器好像没有加入到tree的搜索中 - // 不知道如何找到item并且高亮 - } - return hit; - }); - }); - }); + connect(m_searchEdit, &QLineEdit::textChanged, + m_searchTimer, QOverload<>::of(&QTimer::start)); - m_pageExplorer = new TreeWidget(TreeWidget::None, p_parent); + m_pageExplorer = new TreeWidget(TreeWidget::EnhancedStyle, p_parent); TreeWidget::setupSingleColumnHeaderlessTree(m_pageExplorer, false, false); TreeWidget::showHorizontalScrollbar(m_pageExplorer); m_pageExplorer->setMinimumWidth(128); @@ -276,7 +270,7 @@ bool SettingsDialog::savePages() void SettingsDialog::forEachPage(const std::function &p_func) { for (int i = 0; i < m_pageLayout->count(); ++i) { - auto page = dynamic_cast(m_pageLayout->widget(i)); + auto page = static_cast(m_pageLayout->widget(i)); if (!p_func(page)) { break; } @@ -300,3 +294,17 @@ QTreeWidgetItem *SettingsDialog::addSubPage(SettingsPage *p_page, QTreeWidgetIte setupPage(subItem, p_page); return subItem; } + +void SettingsDialog::search() +{ + auto keywords = m_searchEdit->text().trimmed(); + TreeWidget::forEachItem(m_pageExplorer, [this, keywords](QTreeWidgetItem *item) { + auto page = itemPage(item); + if (page->search(keywords)) { + m_pageExplorer->mark(item, 0); + } else { + m_pageExplorer->unmark(item, 0); + } + return true; + }); +} diff --git a/src/widgets/dialogs/settings/settingsdialog.h b/src/widgets/dialogs/settings/settingsdialog.h index 0b1d74c5..545dc84f 100644 --- a/src/widgets/dialogs/settings/settingsdialog.h +++ b/src/widgets/dialogs/settings/settingsdialog.h @@ -5,14 +5,15 @@ #include -class QTreeWidget; class QStackedLayout; class QLineEdit; class QTreeWidgetItem; class QScrollArea; +class QTimer; namespace vnotex { + class TreeWidget; class SettingsPage; class SettingsDialog : public Dialog @@ -50,9 +51,11 @@ namespace vnotex QTreeWidgetItem *addSubPage(SettingsPage *p_page, QTreeWidgetItem *p_parentItem); + void search(); + QLineEdit *m_searchEdit = nullptr; - QTreeWidget *m_pageExplorer = nullptr; + TreeWidget *m_pageExplorer = nullptr; QScrollArea *m_scrollArea = nullptr; @@ -61,6 +64,8 @@ namespace vnotex bool m_changesUnsaved = false; bool m_ready = false; + + QTimer *m_searchTimer = nullptr; }; } diff --git a/src/widgets/dialogs/settings/settingspage.cpp b/src/widgets/dialogs/settings/settingspage.cpp index 7597b0e1..3a906849 100644 --- a/src/widgets/dialogs/settings/settingspage.cpp +++ b/src/widgets/dialogs/settings/settingspage.cpp @@ -1,10 +1,10 @@ #include "settingspage.h" -#include "utils/widgetutils.h" -#include "../../propertydefs.h" + +#include +#include using namespace vnotex; - SettingsPage::SettingsPage(QWidget *p_parent) : QWidget(p_parent) { @@ -17,21 +17,35 @@ SettingsPage::~SettingsPage() bool SettingsPage::search(const QString &p_key) { bool hit = false; + + if (!p_key.isEmpty() && title().contains(p_key, Qt::CaseInsensitive)) { + hit = true; + } + for (const auto& item : m_searchItems) { - if (item.m_words.contains(p_key, Qt::CaseInsensitive)) { + if (!p_key.isEmpty() && item.m_words.contains(p_key, Qt::CaseInsensitive)) { // Continue to search all the matched targets. hit = true; searchHit(item.m_target, true); + } else { + searchHit(item.m_target, false); } } return hit; } -void SettingsPage::searchHit(QWidget *p_target, bool hit) +void SettingsPage::searchHit(QWidget *p_target, bool p_hit) { - Q_UNUSED(p_target); - WidgetUtils::setPropertyDynamically(p_target, PropertyDefs::c_hitSettingWidght, hit); + if (!p_target) { + return; + } + + if (p_target->property(PropertyDefs::c_hitSettingWidget).toBool() == p_hit) { + return; + } + + WidgetUtils::setPropertyDynamically(p_target, PropertyDefs::c_hitSettingWidget, p_hit); } void SettingsPage::addSearchItem(const QString &p_words, QWidget *p_target) diff --git a/src/widgets/dialogs/settings/settingspage.h b/src/widgets/dialogs/settings/settingspage.h index dcbbadd8..937fce22 100644 --- a/src/widgets/dialogs/settings/settingspage.h +++ b/src/widgets/dialogs/settings/settingspage.h @@ -34,7 +34,7 @@ namespace vnotex virtual bool saveInternal() = 0; // Subclass could override this method to highlight matched target. - virtual void searchHit(QWidget *p_target, bool hit); + virtual void searchHit(QWidget *p_target, bool p_hit); void addSearchItem(const QString &p_words, QWidget *p_target); diff --git a/src/widgets/propertydefs.cpp b/src/widgets/propertydefs.cpp index cea90a6a..a76ad19c 100644 --- a/src/widgets/propertydefs.cpp +++ b/src/widgets/propertydefs.cpp @@ -26,4 +26,4 @@ const char *PropertyDefs::c_dockWidgetIndex = "DockIndex"; const char *PropertyDefs::c_dockWidgetTitle = "DockTitle"; -const char *PropertyDefs::c_hitSettingWidght = "HitSettingWidget"; +const char *PropertyDefs::c_hitSettingWidget = "HitSettingWidget"; diff --git a/src/widgets/propertydefs.h b/src/widgets/propertydefs.h index 9d478beb..b276e4fb 100644 --- a/src/widgets/propertydefs.h +++ b/src/widgets/propertydefs.h @@ -34,7 +34,7 @@ namespace vnotex static const char *c_dockWidgetTitle; - static const char *c_hitSettingWidght; + static const char *c_hitSettingWidget; }; } diff --git a/src/widgets/styleditemdelegate.h b/src/widgets/styleditemdelegate.h index f0887691..abb3cd4f 100644 --- a/src/widgets/styleditemdelegate.h +++ b/src/widgets/styleditemdelegate.h @@ -67,6 +67,10 @@ namespace vnotex QSize sizeHint(const QStyleOptionViewItem &p_option, const QModelIndex &p_index) const Q_DECL_OVERRIDE; + static QBrush s_highlightForeground; + + static QBrush s_highlightBackground; + private: void initialize(); @@ -82,10 +86,6 @@ namespace vnotex QTextDocument *m_document = nullptr; SimpleSegmentHighlighter *m_highlighter = nullptr; - - static QBrush s_highlightForeground; - - static QBrush s_highlightBackground; }; } diff --git a/src/widgets/treewidget.cpp b/src/widgets/treewidget.cpp index 64aefc00..3b986b39 100644 --- a/src/widgets/treewidget.cpp +++ b/src/widgets/treewidget.cpp @@ -223,3 +223,45 @@ void TreeWidget::dropEvent(QDropEvent *p_event) emit itemMoved(dragItems[0]); } } + +void TreeWidget::forEachItem(const QTreeWidget *p_widget, const std::function &p_func) +{ + const int cnt = p_widget->topLevelItemCount(); + for (int i = 0; i < cnt; ++i) { + if (!forEachItem(p_widget->topLevelItem(i), p_func)) { + break; + } + } +} + +bool TreeWidget::forEachItem(QTreeWidgetItem *p_item, const std::function &p_func) +{ + if (!p_item) { + return true; + } + + if (!p_func(p_item)) { + return false; + } + + const int cnt = p_item->childCount(); + for (int i = 0; i < cnt; ++i) { + if (!forEachItem(p_item->child(i), p_func)) { + return false; + } + } + + return true; +} + +void TreeWidget::mark(QTreeWidgetItem *p_item, int p_column) +{ + p_item->setData(p_column, Qt::ForegroundRole, StyledItemDelegate::s_highlightForeground); + p_item->setData(p_column, Qt::BackgroundRole, StyledItemDelegate::s_highlightBackground); +} + +void TreeWidget::unmark(QTreeWidgetItem *p_item, int p_column) +{ + p_item->setData(p_column, Qt::ForegroundRole, QVariant()); + p_item->setData(p_column, Qt::BackgroundRole, QVariant()); +} diff --git a/src/widgets/treewidget.h b/src/widgets/treewidget.h index 1d4a4d3d..74184cc5 100644 --- a/src/widgets/treewidget.h +++ b/src/widgets/treewidget.h @@ -22,6 +22,10 @@ namespace vnotex TreeWidget(TreeWidget::Flags p_flags, QWidget *p_parent = nullptr); + void mark(QTreeWidgetItem *p_item, int p_column); + + void unmark(QTreeWidgetItem *p_item, int p_column); + static void setupSingleColumnHeaderlessTree(QTreeWidget *p_widget, bool p_contextMenu, bool p_extendedSelection); static void showHorizontalScrollbar(QTreeWidget *p_tree); @@ -35,6 +39,9 @@ namespace vnotex static QVector getVisibleItems(const QTreeWidget *p_widget); + // @p_func: return false to abort the iteration. + static void forEachItem(const QTreeWidget *p_widget, const std::function &p_func); + signals: // Emit when single item is selected and Drag&Drop to move internally. void itemMoved(QTreeWidgetItem *p_item); @@ -55,6 +62,10 @@ namespace vnotex static QTreeWidgetItem *lastItemOfTree(QTreeWidgetItem *p_item); + // @p_func: return false to abort the iteration. + // Return false to abort the ieration. + static bool forEachItem(QTreeWidgetItem *p_item, const std::function &p_func); + Flags m_flags = Flag::None; };