diff --git a/src/iuniversalentry.h b/src/iuniversalentry.h index 1c7425f2..a2587050 100644 --- a/src/iuniversalentry.h +++ b/src/iuniversalentry.h @@ -103,6 +103,11 @@ public: m_widgetParent = p_parent; } + virtual void expandCollapseAll(int p_id) + { + Q_UNUSED(p_id); + } + signals: void widgetUpdated(); diff --git a/src/utils/vutils.cpp b/src/utils/vutils.cpp index 71b6a201..8fcfe717 100644 --- a/src/utils/vutils.cpp +++ b/src/utils/vutils.cpp @@ -1540,28 +1540,6 @@ QStringList VUtils::parseCombinedArgString(const QString &p_program) return args; } -const QTreeWidgetItem *VUtils::topLevelTreeItem(const QTreeWidgetItem *p_item) -{ - if (!p_item) { - return NULL; - } - - if (p_item->parent()) { - return topLevelTreeItem(p_item->parent()); - } else { - return p_item; - } -} - -int VUtils::childIndexOfTreeItem(const QTreeWidgetItem *p_item) -{ - if (p_item->parent()) { - return p_item->parent()->indexOfChild(const_cast(p_item)); - } else { - return 0; - } -} - QImage VUtils::imageFromFile(const QString &p_filePath) { QImage img; diff --git a/src/utils/vutils.h b/src/utils/vutils.h index 7bf5803a..0b6dcbfb 100644 --- a/src/utils/vutils.h +++ b/src/utils/vutils.h @@ -333,10 +333,6 @@ public: // From QProcess code. static QStringList parseCombinedArgString(const QString &p_program); - static const QTreeWidgetItem *topLevelTreeItem(const QTreeWidgetItem *p_item); - - static int childIndexOfTreeItem(const QTreeWidgetItem *p_item); - // Read QImage from local file @p_filePath. // Directly calling QImage(p_filePath) will judge the image format from the suffix, // resulting a null image in wrong suffix case. diff --git a/src/vconstants.h b/src/vconstants.h index 09184502..6fba82e4 100644 --- a/src/vconstants.h +++ b/src/vconstants.h @@ -80,6 +80,15 @@ namespace SnippetConfig static const QString c_autoIndent = "auto_indent"; } +namespace Shortcut +{ + static const QString c_expand = "Ctrl+B"; + static const QString c_info = "F2"; + static const QString c_copy = "Ctrl+C"; + static const QString c_cut = "Ctrl+X"; + static const QString c_paste = "Ctrl+V"; +} + static const QString c_emptyHeaderName = "[EMPTY]"; enum class TextDecoration diff --git a/src/vdirectorytree.cpp b/src/vdirectorytree.cpp index a9f682a2..2a246325 100644 --- a/src/vdirectorytree.cpp +++ b/src/vdirectorytree.cpp @@ -20,11 +20,6 @@ extern VMainWindow *g_mainWin; extern VConfigManager *g_config; extern VNote *g_vnote; -const QString VDirectoryTree::c_infoShortcutSequence = "F2"; -const QString VDirectoryTree::c_copyShortcutSequence = "Ctrl+C"; -const QString VDirectoryTree::c_cutShortcutSequence = "Ctrl+X"; -const QString VDirectoryTree::c_pasteShortcutSequence = "Ctrl+V"; - VDirectoryTree::VDirectoryTree(QWidget *parent) : VTreeWidget(parent), VNavigationMode(), @@ -49,28 +44,28 @@ VDirectoryTree::VDirectoryTree(QWidget *parent) void VDirectoryTree::initShortcuts() { - QShortcut *infoShortcut = new QShortcut(QKeySequence(c_infoShortcutSequence), this); + QShortcut *infoShortcut = new QShortcut(QKeySequence(Shortcut::c_info), this); infoShortcut->setContext(Qt::WidgetWithChildrenShortcut); connect(infoShortcut, &QShortcut::activated, this, [this](){ editDirectoryInfo(); }); - QShortcut *copyShortcut = new QShortcut(QKeySequence(c_copyShortcutSequence), this); + QShortcut *copyShortcut = new QShortcut(QKeySequence(Shortcut::c_copy), this); copyShortcut->setContext(Qt::WidgetWithChildrenShortcut); connect(copyShortcut, &QShortcut::activated, this, [this](){ copySelectedDirectories(); }); - QShortcut *cutShortcut = new QShortcut(QKeySequence(c_cutShortcutSequence), this); + QShortcut *cutShortcut = new QShortcut(QKeySequence(Shortcut::c_cut), this); cutShortcut->setContext(Qt::WidgetWithChildrenShortcut); connect(cutShortcut, &QShortcut::activated, this, [this](){ cutSelectedDirectories(); }); - QShortcut *pasteShortcut = new QShortcut(QKeySequence(c_pasteShortcutSequence), this); + QShortcut *pasteShortcut = new QShortcut(QKeySequence(Shortcut::c_paste), this); pasteShortcut->setContext(Qt::WidgetWithChildrenShortcut); connect(pasteShortcut, &QShortcut::activated, this, [this](){ @@ -389,7 +384,7 @@ void VDirectoryTree::contextMenuRequested(QPoint pos) menu.addAction(deleteDirAct); QAction *copyAct = new QAction(VIconUtils::menuIcon(":/resources/icons/copy.svg"), - tr("&Copy\t%1").arg(VUtils::getShortcutText(c_copyShortcutSequence)), + tr("&Copy\t%1").arg(VUtils::getShortcutText(Shortcut::c_copy)), &menu); copyAct->setToolTip(tr("Copy selected folders")); connect(copyAct, &QAction::triggered, @@ -397,7 +392,7 @@ void VDirectoryTree::contextMenuRequested(QPoint pos) menu.addAction(copyAct); QAction *cutAct = new QAction(VIconUtils::menuIcon(":/resources/icons/cut.svg"), - tr("C&ut\t%1").arg(VUtils::getShortcutText(c_cutShortcutSequence)), + tr("C&ut\t%1").arg(VUtils::getShortcutText(Shortcut::c_cut)), &menu); cutAct->setToolTip(tr("Cut selected folders")); connect(cutAct, &QAction::triggered, @@ -411,7 +406,7 @@ void VDirectoryTree::contextMenuRequested(QPoint pos) } QAction *pasteAct = new QAction(VIconUtils::menuIcon(":/resources/icons/paste.svg"), - tr("&Paste\t%1").arg(VUtils::getShortcutText(c_pasteShortcutSequence)), + tr("&Paste\t%1").arg(VUtils::getShortcutText(Shortcut::c_paste)), &menu); pasteAct->setToolTip(tr("Paste folders in this folder")); connect(pasteAct, &QAction::triggered, @@ -445,7 +440,7 @@ void VDirectoryTree::contextMenuRequested(QPoint pos) menu.addAction(pinToHistoryAct); QAction *dirInfoAct = new QAction(VIconUtils::menuIcon(":/resources/icons/dir_info.svg"), - tr("&Info (Rename)\t%1").arg(VUtils::getShortcutText(c_infoShortcutSequence)), + tr("&Info (Rename)\t%1").arg(VUtils::getShortcutText(Shortcut::c_info)), &menu); dirInfoAct->setToolTip(tr("View and edit current folder's information")); connect(dirInfoAct, &QAction::triggered, diff --git a/src/vdirectorytree.h b/src/vdirectorytree.h index f2a9a03f..355c35cc 100644 --- a/src/vdirectorytree.h +++ b/src/vdirectorytree.h @@ -163,11 +163,6 @@ private: // Magic number for clipboard operations. int m_magicForClipboard; - - static const QString c_infoShortcutSequence; - static const QString c_copyShortcutSequence; - static const QString c_cutShortcutSequence; - static const QString c_pasteShortcutSequence; }; inline QPointer VDirectoryTree::getVDirectory(QTreeWidgetItem *p_item) const diff --git a/src/vfilelist.cpp b/src/vfilelist.cpp index f1174e6b..85248a75 100644 --- a/src/vfilelist.cpp +++ b/src/vfilelist.cpp @@ -26,11 +26,6 @@ extern VConfigManager *g_config; extern VNote *g_vnote; extern VMainWindow *g_mainWin; -const QString VFileList::c_infoShortcutSequence = "F2"; -const QString VFileList::c_copyShortcutSequence = "Ctrl+C"; -const QString VFileList::c_cutShortcutSequence = "Ctrl+X"; -const QString VFileList::c_pasteShortcutSequence = "Ctrl+V"; - VFileList::VFileList(QWidget *parent) : QWidget(parent), VNavigationMode(), @@ -119,28 +114,28 @@ void VFileList::setupUI() void VFileList::initShortcuts() { - QShortcut *infoShortcut = new QShortcut(QKeySequence(c_infoShortcutSequence), this); + QShortcut *infoShortcut = new QShortcut(QKeySequence(Shortcut::c_info), this); infoShortcut->setContext(Qt::WidgetWithChildrenShortcut); connect(infoShortcut, &QShortcut::activated, this, [this](){ fileInfo(); }); - QShortcut *copyShortcut = new QShortcut(QKeySequence(c_copyShortcutSequence), this); + QShortcut *copyShortcut = new QShortcut(QKeySequence(Shortcut::c_copy), this); copyShortcut->setContext(Qt::WidgetWithChildrenShortcut); connect(copyShortcut, &QShortcut::activated, this, [this](){ copySelectedFiles(); }); - QShortcut *cutShortcut = new QShortcut(QKeySequence(c_cutShortcutSequence), this); + QShortcut *cutShortcut = new QShortcut(QKeySequence(Shortcut::c_cut), this); cutShortcut->setContext(Qt::WidgetWithChildrenShortcut); connect(cutShortcut, &QShortcut::activated, this, [this](){ cutSelectedFiles(); }); - QShortcut *pasteShortcut = new QShortcut(QKeySequence(c_pasteShortcutSequence), this); + QShortcut *pasteShortcut = new QShortcut(QKeySequence(Shortcut::c_paste), this); pasteShortcut->setContext(Qt::WidgetWithChildrenShortcut); connect(pasteShortcut, &QShortcut::activated, this, [this](){ @@ -605,7 +600,7 @@ void VFileList::contextMenuRequested(QPoint pos) menu.addAction(deleteFileAct); QAction *copyAct = new QAction(VIconUtils::menuIcon(":/resources/icons/copy.svg"), - tr("&Copy\t%1").arg(VUtils::getShortcutText(c_copyShortcutSequence)), + tr("&Copy\t%1").arg(VUtils::getShortcutText(Shortcut::c_copy)), &menu); copyAct->setToolTip(tr("Copy selected notes")); connect(copyAct, &QAction::triggered, @@ -613,7 +608,7 @@ void VFileList::contextMenuRequested(QPoint pos) menu.addAction(copyAct); QAction *cutAct = new QAction(VIconUtils::menuIcon(":/resources/icons/cut.svg"), - tr("C&ut\t%1").arg(VUtils::getShortcutText(c_cutShortcutSequence)), + tr("C&ut\t%1").arg(VUtils::getShortcutText(Shortcut::c_cut)), &menu); cutAct->setToolTip(tr("Cut selected notes")); connect(cutAct, &QAction::triggered, @@ -627,7 +622,7 @@ void VFileList::contextMenuRequested(QPoint pos) } QAction *pasteAct = new QAction(VIconUtils::menuIcon(":/resources/icons/paste.svg"), - tr("&Paste\t%1").arg(VUtils::getShortcutText(c_pasteShortcutSequence)), + tr("&Paste\t%1").arg(VUtils::getShortcutText(Shortcut::c_paste)), &menu); pasteAct->setToolTip(tr("Paste notes in current folder")); connect(pasteAct, &QAction::triggered, @@ -686,7 +681,7 @@ void VFileList::contextMenuRequested(QPoint pos) if (selectedSize == 1) { QAction *fileInfoAct = new QAction(VIconUtils::menuIcon(":/resources/icons/note_info.svg"), - tr("&Info (Rename)\t%1").arg(VUtils::getShortcutText(c_infoShortcutSequence)), + tr("&Info (Rename)\t%1").arg(VUtils::getShortcutText(Shortcut::c_info)), &menu); fileInfoAct->setToolTip(tr("View and edit current note's information")); connect(fileInfoAct, SIGNAL(triggered(bool)), diff --git a/src/vfilelist.h b/src/vfilelist.h index 2b6ac9a3..2a90821f 100644 --- a/src/vfilelist.h +++ b/src/vfilelist.h @@ -209,11 +209,6 @@ private: QListWidgetItem *m_itemClicked; VFile *m_fileToCloseInSingleClick; - - static const QString c_infoShortcutSequence; - static const QString c_copyShortcutSequence; - static const QString c_cutShortcutSequence; - static const QString c_pasteShortcutSequence; }; inline void VFileList::setEditArea(VEditArea *editArea) diff --git a/src/vhelpue.cpp b/src/vhelpue.cpp index 7b81f02e..894c0b6c 100644 --- a/src/vhelpue.cpp +++ b/src/vhelpue.cpp @@ -69,6 +69,7 @@ bool VHelpUE::initListWidget() m_listWidget->addItem(tr("Ctrl+K: Go to previous item")); m_listWidget->addItem(tr("Ctrl+L: Go to current item's parent item")); m_listWidget->addItem(tr("Ctrl+I: Expand/Collapse current item")); + m_listWidget->addItem(tr("Ctrl+B: Expand/Collapse all items")); m_listWidget->addItem(tr("Ctrl+S: Sort items")); m_listWidget->addItem(tr("Enter: Activate current item")); m_listWidget->addItem(tr("Ctrl+M: Browse current item folder or the folder containing current item")); diff --git a/src/voutlineue.cpp b/src/voutlineue.cpp index c159661b..1e995341 100644 --- a/src/voutlineue.cpp +++ b/src/voutlineue.cpp @@ -55,7 +55,7 @@ void VOutlineUE::init() connect(m_treeWidget, SIGNAL(itemActivated(QTreeWidgetItem *, int)), this, SLOT(activateItem(QTreeWidgetItem *, int))); - connect(m_treeWidget, &VTreeWidget::itemExpanded, + connect(m_treeWidget, &VTreeWidget::itemExpandedOrCollapsed, this, &VOutlineUE::widgetUpdated); } @@ -90,12 +90,7 @@ void VOutlineUE::processCommand(int p_id, const QString &p_cmd) const VTableOfContent &outline = tab->getOutline(); VOutline::updateTreeFromOutline(m_treeWidget, outline); - // expandAll() has some bugs with the first item. Fix it. - if (m_treeWidget->topLevelItemCount() > 0) { - m_treeWidget->topLevelItem(0)->setExpanded(true); - } - - m_treeWidget->expandAll(); + VTreeWidget::expandCollapseAll(m_treeWidget); const VHeaderPointer &header = tab->getCurrentHeader(); if (outline.isMatched(header)) { @@ -154,7 +149,7 @@ void VOutlineUE::updateWidget() delete item; } - wid = m_listWidget; + wid = m_treeWidget; } wid->updateGeometry(); @@ -252,3 +247,11 @@ void VOutlineUE::toggleItemExpanded(int p_id) } } } + +void VOutlineUE::expandCollapseAll(int p_id) +{ + Q_UNUSED(p_id); + if (m_listOutline) { + VTreeWidget::expandCollapseAll(m_treeWidget); + } +} diff --git a/src/voutlineue.h b/src/voutlineue.h index dba3de78..4f1ebe70 100644 --- a/src/voutlineue.h +++ b/src/voutlineue.h @@ -35,6 +35,8 @@ public: void toggleItemExpanded(int p_id) Q_DECL_OVERRIDE; + void expandCollapseAll(int p_id) Q_DECL_OVERRIDE; + protected: void init() Q_DECL_OVERRIDE; diff --git a/src/vsearcher.cpp b/src/vsearcher.cpp index 7ded6055..d81ca7b4 100644 --- a/src/vsearcher.cpp +++ b/src/vsearcher.cpp @@ -17,6 +17,7 @@ #include "vnote.h" #include "vconfigmanager.h" #include "vexplorer.h" +#include "vconstants.h" extern VMainWindow *g_mainWin; @@ -216,6 +217,11 @@ void VSearcher::setupUI() updateNumLabel(p_count); }); + QShortcut *expandShortcut = new QShortcut(QKeySequence(Shortcut::c_expand), this); + expandShortcut->setContext(Qt::WidgetWithChildrenShortcut); + connect(expandShortcut, &QShortcut::activated, + m_results, &VSearchResultTree::expandCollapseAll); + QFormLayout *formLayout = VUtils::getFormLayout(); formLayout->addRow(tr("Keywords:"), m_keywordCB); formLayout->addRow(tr("Scope:"), m_searchScopeCB); diff --git a/src/vsearchresulttree.cpp b/src/vsearchresulttree.cpp index 80b67b9c..3083695b 100644 --- a/src/vsearchresulttree.cpp +++ b/src/vsearchresulttree.cpp @@ -13,6 +13,7 @@ #include "vexplorer.h" #include "vuniversalentry.h" #include "vsearchue.h" +#include "vconstants.h" extern VNote *g_vnote; @@ -33,45 +34,12 @@ VSearchResultTree::VSearchResultTree(QWidget *p_parent) m_folderIcon = VIconUtils::treeViewIcon(":/resources/icons/dir_item.svg"); m_notebookIcon = VIconUtils::treeViewIcon(":/resources/icons/notebook_item.svg"); - initActions(); - connect(this, &VTreeWidget::itemActivated, this, &VSearchResultTree::activateItem); connect(this, &VTreeWidget::customContextMenuRequested, this, &VSearchResultTree::handleContextMenuRequested); } -void VSearchResultTree::initActions() -{ - m_openAct = new QAction(tr("&Open"), this); - m_openAct->setToolTip(tr("Open selected notes")); - connect(m_openAct, &QAction::triggered, - this, [this]() { - activateItem(currentItem()); - }); - - m_locateAct = new QAction(VIconUtils::menuIcon(":/resources/icons/locate_note.svg"), - tr("&Locate To Folder"), - this); - m_locateAct->setToolTip(tr("Locate the folder of current note")); - connect(m_locateAct, &QAction::triggered, - this, &VSearchResultTree::locateCurrentItem); - - m_addToCartAct = new QAction(VIconUtils::menuIcon(":/resources/icons/cart.svg"), - tr("Add To Cart"), - this); - m_addToCartAct->setToolTip(tr("Add selected notes to Cart for further processing")); - connect(m_addToCartAct, &QAction::triggered, - this, &VSearchResultTree::addSelectedItemsToCart); - - m_pinToHistoryAct = new QAction(VIconUtils::menuIcon(":/resources/icons/pin.svg"), - tr("Pin To History"), - this); - m_pinToHistoryAct->setToolTip(tr("Pin selected notes to History")); - connect(m_pinToHistoryAct, &QAction::triggered, - this, &VSearchResultTree::pinSelectedItemsToHistory); -} - void VSearchResultTree::updateResults(const QList > &p_items) { clearResults(); @@ -158,14 +126,15 @@ void VSearchResultTree::appendItem(const QSharedPointer &p_it void VSearchResultTree::handleContextMenuRequested(QPoint p_pos) { - QTreeWidgetItem *item = itemAt(p_pos); - if (!item) { - return; - } - QMenu menu(this); menu.setToolTipsVisible(true); + QTreeWidgetItem *item = itemAt(p_pos); + if (!item) { + goto global; + } + + { QList items = selectedItems(); bool hasNote = false; @@ -177,19 +146,59 @@ void VSearchResultTree::handleContextMenuRequested(QPoint p_pos) } if (items.size() == 1) { - menu.addAction(m_openAct); + QAction *openAct = new QAction(tr("&Open"), &menu); + openAct->setToolTip(tr("Open selected notes")); + connect(openAct, &QAction::triggered, + this, [this]() { + activateItem(currentItem()); + }); + menu.addAction(openAct); if (hasNote) { - menu.addAction(m_locateAct); + QAction *locateAct = new QAction(VIconUtils::menuIcon(":/resources/icons/locate_note.svg"), + tr("&Locate To Folder"), + &menu); + locateAct->setToolTip(tr("Locate the folder of current note")); + connect(locateAct, &QAction::triggered, + this, &VSearchResultTree::locateCurrentItem); + menu.addAction(locateAct); } } if (hasNote) { - menu.addAction(m_addToCartAct); - menu.addAction(m_pinToHistoryAct); + QAction *addToCartAct = new QAction(VIconUtils::menuIcon(":/resources/icons/cart.svg"), + tr("Add To Cart"), + &menu); + addToCartAct->setToolTip(tr("Add selected notes to Cart for further processing")); + connect(addToCartAct, &QAction::triggered, + this, &VSearchResultTree::addSelectedItemsToCart); + menu.addAction(addToCartAct); + + QAction *pinToHistoryAct = new QAction(VIconUtils::menuIcon(":/resources/icons/pin.svg"), + tr("Pin To History"), + &menu); + pinToHistoryAct->setToolTip(tr("Pin selected notes to History")); + connect(pinToHistoryAct, &QAction::triggered, + this, &VSearchResultTree::pinSelectedItemsToHistory); + menu.addAction(pinToHistoryAct); + } } - menu.exec(mapToGlobal(p_pos)); +global: + if (topLevelItemCount() > 0) { + if (item) { + menu.addSeparator(); + } + + QString shortcutText = VUtils::getShortcutText(Shortcut::c_expand); + QAction *expandAct = new QAction(tr("Expand/Collapse All\t%1").arg(shortcutText), + &menu); + connect(expandAct, &QAction::triggered, + this, &VSearchResultTree::expandCollapseAll); + menu.addAction(expandAct); + + menu.exec(mapToGlobal(p_pos)); + } } void VSearchResultTree::locateCurrentItem() @@ -257,7 +266,7 @@ VSearchResultItem::ItemType VSearchResultTree::itemResultType(const QTreeWidgetI const QSharedPointer &VSearchResultTree::itemResultData(const QTreeWidgetItem *p_item) const { Q_ASSERT(p_item); - const QTreeWidgetItem *topItem = VUtils::topLevelTreeItem(p_item); + const QTreeWidgetItem *topItem = VTreeWidget::topLevelTreeItem(p_item); int idx = topItem->data(0, Qt::UserRole).toInt(); Q_ASSERT(idx >= 0 && idx < m_data.size()); return m_data[idx]; @@ -269,5 +278,10 @@ void VSearchResultTree::activateItem(const QTreeWidgetItem *p_item) const return; } - VSearchUE::activateItem(itemResultData(p_item), VUtils::childIndexOfTreeItem(p_item)); + VSearchUE::activateItem(itemResultData(p_item), VTreeWidget::childIndexOfTreeItem(p_item)); +} + +void VSearchResultTree::expandCollapseAll() +{ + VTreeWidget::expandCollapseAll(this); } diff --git a/src/vsearchresulttree.h b/src/vsearchresulttree.h index f6e1216e..41c46952 100644 --- a/src/vsearchresulttree.h +++ b/src/vsearchresulttree.h @@ -6,8 +6,6 @@ #include "vtreewidget.h" #include "vsearch.h" -class QAction; - class VSearchResultTree : public VTreeWidget { @@ -26,6 +24,8 @@ public slots: void handleContextMenuRequested(QPoint p_pos); + void expandCollapseAll(); + signals: void countChanged(int p_count); @@ -39,8 +39,6 @@ private slots: private: void appendItem(const QSharedPointer &p_item); - void initActions(); - VSearchResultItem::ItemType itemResultType(const QTreeWidgetItem *p_item) const; void activateItem(const QTreeWidgetItem *p_item) const; @@ -52,14 +50,6 @@ private: QIcon m_noteIcon; QIcon m_folderIcon; QIcon m_notebookIcon; - - QAction *m_openAct; - - QAction *m_locateAct; - - QAction *m_addToCartAct; - - QAction *m_pinToHistoryAct; }; #endif // VSEARCHRESULTTREE_H diff --git a/src/vsearchue.cpp b/src/vsearchue.cpp index 755825bf..79a613f7 100644 --- a/src/vsearchue.cpp +++ b/src/vsearchue.cpp @@ -131,7 +131,7 @@ void VSearchUE::init() m_treeWidget->hide(); connect(m_treeWidget, SIGNAL(itemActivated(QTreeWidgetItem *, int)), this, SLOT(activateItem(QTreeWidgetItem *, int))); - connect(m_treeWidget, &VTreeWidget::itemExpanded, + connect(m_treeWidget, &VTreeWidget::itemExpandedOrCollapsed, this, &VSearchUE::widgetUpdated); } @@ -905,7 +905,7 @@ const QSharedPointer &VSearchUE::itemResultData(const QListWi const QSharedPointer &VSearchUE::itemResultData(const QTreeWidgetItem *p_item) const { Q_ASSERT(p_item); - const QTreeWidgetItem *topItem = VUtils::topLevelTreeItem(p_item); + const QTreeWidgetItem *topItem = VTreeWidget::topLevelTreeItem(p_item); int idx = topItem->data(0, Qt::UserRole).toInt(); Q_ASSERT(idx >= 0 && idx < m_data.size()); return m_data[idx]; @@ -1002,7 +1002,7 @@ void VSearchUE::activateItem(QTreeWidgetItem *p_item, int p_col) } emit requestHideUniversalEntry(); - activateItem(itemResultData(p_item), VUtils::childIndexOfTreeItem(p_item)); + activateItem(itemResultData(p_item), VTreeWidget::childIndexOfTreeItem(p_item)); } void VSearchUE::selectNextItem(int p_id, bool p_forward) @@ -1122,6 +1122,25 @@ void VSearchUE::toggleItemExpanded(int p_id) } } +void VSearchUE::expandCollapseAll(int p_id) +{ + switch (p_id) { + case ID::Content_Note_AllNotebook: + case ID::Content_Note_CurrentNotebook: + case ID::Content_Note_CurrentFolder: + case ID::Content_Note_ExplorerDirectory: + case ID::Content_Note_Buffer: + case ID::Outline_Note_Buffer: + { + VTreeWidget::expandCollapseAll(m_treeWidget); + break; + } + + default: + break; + } +} + void VSearchUE::sort(int p_id) { static bool noteFirst = false; diff --git a/src/vsearchue.h b/src/vsearchue.h index 9df04c53..f3c5ed97 100644 --- a/src/vsearchue.h +++ b/src/vsearchue.h @@ -95,6 +95,8 @@ public: static void activateItem(const QSharedPointer &p_item, int p_matchIndex = 0); + void expandCollapseAll(int p_id) Q_DECL_OVERRIDE; + protected: void init() Q_DECL_OVERRIDE; diff --git a/src/vtreewidget.cpp b/src/vtreewidget.cpp index f51475ce..1f77164b 100644 --- a/src/vtreewidget.cpp +++ b/src/vtreewidget.cpp @@ -47,18 +47,22 @@ VTreeWidget::VTreeWidget(QWidget *p_parent) m_delegate = new VStyledItemDelegate(NULL, this); setItemDelegate(m_delegate); + m_expandTimer = new QTimer(this); + m_expandTimer->setSingleShot(true); + m_expandTimer->setInterval(100); + connect(m_expandTimer, &QTimer::timeout, + this, [this]() { + if (m_fitContent) { + resizeColumnToContents(0); + } + + emit itemExpandedOrCollapsed(); + }); + connect(this, &VTreeWidget::itemExpanded, - this, [this]() { - if (m_fitContent) { - resizeColumnToContents(0); - } - }); + m_expandTimer, static_cast(&QTimer::start)); connect(this, &VTreeWidget::itemCollapsed, - this, [this]() { - if (m_fitContent) { - resizeColumnToContents(0); - } - }); + m_expandTimer, static_cast(&QTimer::start)); } void VTreeWidget::keyPressEvent(QKeyEvent *p_event) @@ -349,3 +353,88 @@ void VTreeWidget::selectParentItem() } } } + +static bool isItemTreeExpanded(const QTreeWidgetItem *p_item) +{ + if (!p_item) { + return true; + } + + if (p_item->isHidden() || !p_item->isExpanded()) { + return false; + } + + int cnt = p_item->childCount(); + for (int i = 0; i < cnt; ++i) { + if (!isItemTreeExpanded(p_item->child(i))) { + return false; + } + } + + return true; +} + +bool VTreeWidget::isTreeExpanded(const QTreeWidget *p_tree) +{ + int cnt = p_tree->topLevelItemCount(); + for (int i = 0; i < cnt; ++i) { + if (!isItemTreeExpanded(p_tree->topLevelItem(i))) { + return false; + } + } + + return true; +} + +void VTreeWidget::expandCollapseAll(QTreeWidget *p_tree) +{ + QTreeWidgetItem *topLevelItem = NULL; + QTreeWidgetItem *item = p_tree->currentItem(); + if (item) { + topLevelItem = const_cast(topLevelTreeItem(item)); + } + + bool expanded = isTreeExpanded(p_tree); + if (expanded) { + p_tree->collapseAll(); + } else { + p_tree->expandAll(); + + } + + VTreeWidget *vtree = dynamic_cast(p_tree); + if (vtree) { + if (vtree->m_fitContent) { + vtree->resizeColumnToContents(0); + } + + emit vtree->itemExpandedOrCollapsed(); + } + + if (topLevelItem) { + p_tree->setCurrentItem(topLevelItem, 0, QItemSelectionModel::ClearAndSelect); + p_tree->scrollToItem(topLevelItem); + } +} + +const QTreeWidgetItem *VTreeWidget::topLevelTreeItem(const QTreeWidgetItem *p_item) +{ + if (!p_item) { + return NULL; + } + + if (p_item->parent()) { + return topLevelTreeItem(p_item->parent()); + } else { + return p_item; + } +} + +int VTreeWidget::childIndexOfTreeItem(const QTreeWidgetItem *p_item) +{ + if (p_item->parent()) { + return p_item->parent()->indexOfChild(const_cast(p_item)); + } else { + return 0; + } +} diff --git a/src/vtreewidget.h b/src/vtreewidget.h index 516422e3..7007771f 100644 --- a/src/vtreewidget.h +++ b/src/vtreewidget.h @@ -50,6 +50,15 @@ public: QTreeWidgetItem *p_item, bool p_forward); + // Whether @p_tree is expanded. + static bool isTreeExpanded(const QTreeWidget *p_tree); + + static void expandCollapseAll(QTreeWidget *p_tree); + + static const QTreeWidgetItem *topLevelTreeItem(const QTreeWidgetItem *p_item); + + static int childIndexOfTreeItem(const QTreeWidgetItem *p_item); + protected: void keyPressEvent(QKeyEvent *p_event) Q_DECL_OVERRIDE; @@ -61,6 +70,8 @@ signals: // Rows [@p_first, @p_last] were moved to @p_row. void rowsMoved(int p_first, int p_last, int p_row); + void itemExpandedOrCollapsed(); + private slots: void handleSearchModeTriggered(bool p_inSearchMode, bool p_focus); @@ -81,6 +92,7 @@ private: VStyledItemDelegate *m_delegate; QTimer *m_searchColdTimer; + QTimer *m_expandTimer; bool m_fitContent; }; diff --git a/src/vuniversalentry.cpp b/src/vuniversalentry.cpp index 25b7b774..dcd2e20b 100644 --- a/src/vuniversalentry.cpp +++ b/src/vuniversalentry.cpp @@ -413,6 +413,18 @@ void VUniversalEntry::keyPressEvent(QKeyEvent *p_event) break; + case Qt::Key_B: + if (VUtils::isControlModifierForVim(modifiers)) { + // Ctrl+B to expand/collapse all the items. + if (m_lastEntry) { + m_lastEntry->m_entry->expandCollapseAll(m_lastEntry->m_id); + } + + return; + } + + break; + default: break; }