| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327 |
- #include "vtreewidget.h"
- #include <QDropEvent>
- #include <QKeyEvent>
- #include <QCoreApplication>
- #include <QSet>
- #include <QScrollBar>
- #include <QGraphicsOpacityEffect>
- #include <QTimer>
- #include "utils/vutils.h"
- #include "utils/vimnavigationforwidget.h"
- #include "vstyleditemdelegate.h"
- #define SEARCH_INPUT_NORMAL_OPACITY 0.8
- #define SEARCH_INPUT_IDLE_OPACITY 0.2
- VTreeWidget::VTreeWidget(QWidget *p_parent)
- : QTreeWidget(p_parent),
- ISimpleSearch(),
- m_fitContent(false)
- {
- setAttribute(Qt::WA_MacShowFocusRect, false);
- m_searchInput = new VSimpleSearchInput(this, this);
- connect(m_searchInput, &VSimpleSearchInput::triggered,
- this, &VTreeWidget::handleSearchModeTriggered);
- connect(m_searchInput, &VSimpleSearchInput::inputTextChanged,
- this, &VTreeWidget::handleSearchInputTextChanged);
- QGraphicsOpacityEffect * effect = new QGraphicsOpacityEffect(m_searchInput);
- effect->setOpacity(SEARCH_INPUT_NORMAL_OPACITY);
- m_searchInput->setGraphicsEffect(effect);
- m_searchInput->hide();
- m_searchColdTimer = new QTimer(this);
- m_searchColdTimer->setSingleShot(true);
- m_searchColdTimer->setInterval(1000);
- connect(m_searchColdTimer, &QTimer::timeout,
- this, [this]() {
- QGraphicsOpacityEffect *effect = getSearchInputEffect();
- Q_ASSERT(effect);
- effect->setOpacity(SEARCH_INPUT_IDLE_OPACITY);
- });
- m_delegate = new VStyledItemDelegate(this);
- setItemDelegate(m_delegate);
- connect(this, &VTreeWidget::itemExpanded,
- this, [this]() {
- if (m_fitContent) {
- resizeColumnToContents(0);
- }
- });
- }
- void VTreeWidget::keyPressEvent(QKeyEvent *p_event)
- {
- if (m_searchInput->tryHandleKeyPressEvent(p_event)) {
- return;
- }
- if (VimNavigationForWidget::injectKeyPressEventForVim(this, p_event)) {
- return;
- }
- QTreeWidget::keyPressEvent(p_event);
- }
- void VTreeWidget::clearAll()
- {
- m_searchInput->clear();
- setSearchInputVisible(false);
- VTreeWidget::clear();
- }
- void VTreeWidget::setSearchInputVisible(bool p_visible)
- {
- m_searchInput->setVisible(p_visible);
- // setViewportMargins() and setContentsMargins() do not work for QTreeWidget.
- // setStyleSheet(QString("padding-bottom: %1px").arg(bottomMargin));
- QGraphicsOpacityEffect *effect = getSearchInputEffect();
- Q_ASSERT(effect);
- effect->setOpacity(SEARCH_INPUT_NORMAL_OPACITY);
- }
- void VTreeWidget::resizeEvent(QResizeEvent *p_event)
- {
- QTreeWidget::resizeEvent(p_event);
- QRect contentRect = contentsRect();
- int width = contentRect.width();
- QScrollBar *vbar = verticalScrollBar();
- if (vbar && (vbar->minimum() != vbar->maximum())) {
- width -= vbar->width();
- }
- int y = height() - m_searchInput->height();
- QScrollBar *hbar = horizontalScrollBar();
- if (hbar && (hbar->minimum() != hbar->maximum())) {
- y -= hbar->height();
- }
- m_searchInput->setGeometry(QRect(contentRect.left(),
- y,
- width,
- m_searchInput->height()));
- }
- void VTreeWidget::handleSearchModeTriggered(bool p_inSearchMode, bool p_focus)
- {
- setSearchInputVisible(p_inSearchMode);
- if (!p_inSearchMode) {
- clearItemsHighlight();
- }
- if (p_focus) {
- setFocus();
- }
- }
- void VTreeWidget::dropEvent(QDropEvent *p_event)
- {
- QList<QTreeWidgetItem *> dragItems = selectedItems();
- int first = -1, last = -1;
- QTreeWidgetItem *firstItem = NULL;
- for (int i = 0; i < dragItems.size(); ++i) {
- int row = indexFromItem(dragItems[i]).row();
- if (row > last) {
- last = row;
- }
- if (first == -1 || row < first) {
- first = row;
- firstItem = dragItems[i];
- }
- }
- Q_ASSERT(firstItem);
- QTreeWidget::dropEvent(p_event);
- int target = indexFromItem(firstItem).row();
- emit rowsMoved(first, last, target);
- }
- QList<void *> VTreeWidget::searchItems(const QString &p_text,
- Qt::MatchFlags p_flags) const
- {
- QList<QTreeWidgetItem *> items = findItems(p_text, p_flags);
- QList<void *> res;
- res.reserve(items.size());
- for (int i = 0; i < items.size(); ++i) {
- res.append(items[i]);
- }
- return res;
- }
- void VTreeWidget::highlightHitItems(const QList<void *> &p_items)
- {
- clearItemsHighlight();
- QSet<QModelIndex> hitIndexes;
- for (auto it : p_items) {
- QModelIndex index = indexFromItem(static_cast<QTreeWidgetItem *>(it));
- if (index.isValid()) {
- hitIndexes.insert(index);
- }
- }
- if (!hitIndexes.isEmpty()) {
- m_delegate->setHitItems(hitIndexes);
- update();
- }
- }
- void VTreeWidget::clearItemsHighlight()
- {
- m_delegate->clearHitItems();
- update();
- }
- void VTreeWidget::selectHitItem(void *p_item)
- {
- setCurrentItem(static_cast<QTreeWidgetItem *>(p_item));
- }
- // Count the total number of tree @p_item.
- static int treeItemCount(QTreeWidgetItem *p_item)
- {
- if (!p_item) {
- return 0;
- }
- int child = p_item->childCount();
- int total = 1;
- for (int i = 0; i < child; ++i) {
- total += treeItemCount(p_item->child(i));
- }
- return total;
- }
- int VTreeWidget::totalNumberOfItems()
- {
- int total = 0;
- int cn = topLevelItemCount();
- for (int i = 0; i < cn; ++i) {
- total += treeItemCount(topLevelItem(i));
- }
- return total;
- }
- void VTreeWidget::handleSearchInputTextChanged(const QString &p_text)
- {
- m_searchColdTimer->stop();
- m_searchColdTimer->start();
- Q_UNUSED(p_text);
- QGraphicsOpacityEffect *effect = getSearchInputEffect();
- Q_ASSERT(effect);
- effect->setOpacity(0.8);
- }
- QGraphicsOpacityEffect *VTreeWidget::getSearchInputEffect() const
- {
- return static_cast<QGraphicsOpacityEffect *>(m_searchInput->graphicsEffect());
- }
- static QTreeWidgetItem *lastItemOfTree(QTreeWidgetItem *p_item)
- {
- if (p_item->isExpanded()) {
- Q_ASSERT(p_item->childCount() > 0);
- return p_item->child(p_item->childCount() - 1);
- } else {
- return p_item;
- }
- }
- QTreeWidgetItem *VTreeWidget::nextSibling(QTreeWidgetItem *p_item, bool p_forward)
- {
- if (!p_item) {
- return NULL;
- }
- QTreeWidgetItem *pa = p_item->parent();
- if (pa) {
- int idx = pa->indexOfChild(p_item);
- if (p_forward) {
- ++idx;
- if (idx >= pa->childCount()) {
- return NULL;
- }
- } else {
- --idx;
- if (idx < 0) {
- return NULL;
- }
- }
- return pa->child(idx);
- } else {
- // Top level item.
- int idx = indexOfTopLevelItem(p_item);
- if (p_forward) {
- ++idx;
- if (idx >= topLevelItemCount()) {
- return NULL;
- }
- } else {
- --idx;
- if (idx < 0) {
- return NULL;
- }
- }
- return topLevelItem(idx);
- }
- }
- void VTreeWidget::selectNextItem(bool p_forward)
- {
- if (topLevelItemCount() == 0) {
- return;
- }
- QTreeWidgetItem *item = currentItem();
- if (!item) {
- setCurrentItem(topLevelItem(0));
- return;
- }
- QTreeWidgetItem *nItem = nextItem(item, p_forward);
- if (nItem) {
- setCurrentItem(nItem);
- }
- }
- QTreeWidgetItem *VTreeWidget::nextItem(QTreeWidgetItem *p_item, bool p_forward)
- {
- QTreeWidgetItem *nItem = NULL;
- if (p_forward) {
- if (p_item->isExpanded()) {
- nItem = p_item->child(0);
- } else {
- while (!nItem && p_item) {
- nItem = nextSibling(p_item, true);
- p_item = p_item->parent();
- }
- }
- } else {
- nItem = nextSibling(p_item, false);
- if (!nItem) {
- nItem = p_item->parent();
- } else {
- nItem = lastItemOfTree(nItem);
- }
- }
- return nItem;
- }
|