mirror of
https://gitee.com/vnotex/vnote.git
synced 2025-07-05 05:49:53 +08:00
add VTreeWidget with simple search and convert VDirectoryTree to it
This commit is contained in:
parent
0125251716
commit
878a272777
@ -2,33 +2,6 @@
|
||||
|
||||
#include <QtWidgets>
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
VSortDialog::VSortDialog(const QString &p_title,
|
||||
const QString &p_info,
|
||||
QWidget *p_parent)
|
||||
|
@ -3,33 +3,11 @@
|
||||
|
||||
#include <QDialog>
|
||||
#include <QVector>
|
||||
#include <QTreeWidget>
|
||||
|
||||
#include "vtreewidget.h"
|
||||
|
||||
class QPushButton;
|
||||
class QDialogButtonBox;
|
||||
class QTreeWidget;
|
||||
class QDropEvent;
|
||||
|
||||
// QTreeWidget won't emit the rowsMoved() signal after drag-and-drop.
|
||||
// VTreeWidget will emit rowsMoved() signal.
|
||||
class VTreeWidget : public QTreeWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit VTreeWidget(QWidget *p_parent = 0)
|
||||
: QTreeWidget(p_parent)
|
||||
{
|
||||
setAttribute(Qt::WA_MacShowFocusRect, false);
|
||||
}
|
||||
|
||||
protected:
|
||||
void dropEvent(QDropEvent *p_event) Q_DECL_OVERRIDE;
|
||||
|
||||
signals:
|
||||
// Rows [@p_first, @p_last] were moved to @p_row.
|
||||
void rowsMoved(int p_first, int p_last, int p_row);
|
||||
|
||||
};
|
||||
|
||||
class VSortDialog : public QDialog
|
||||
{
|
||||
|
@ -111,7 +111,8 @@ SOURCES += main.cpp\
|
||||
vvimcmdlineedit.cpp \
|
||||
vlistwidget.cpp \
|
||||
vsimplesearchinput.cpp \
|
||||
vstyleditemdelegate.cpp
|
||||
vstyleditemdelegate.cpp \
|
||||
vtreewidget.cpp
|
||||
|
||||
HEADERS += vmainwindow.h \
|
||||
vdirectorytree.h \
|
||||
@ -209,7 +210,8 @@ HEADERS += vmainwindow.h \
|
||||
vvimcmdlineedit.h \
|
||||
vlistwidget.h \
|
||||
vsimplesearchinput.h \
|
||||
vstyleditemdelegate.h
|
||||
vstyleditemdelegate.h \
|
||||
vtreewidget.h
|
||||
|
||||
RESOURCES += \
|
||||
vnote.qrc \
|
||||
|
@ -149,15 +149,6 @@ QString VUtils::generateImageFileName(const QString &path,
|
||||
return imageName;
|
||||
}
|
||||
|
||||
void VUtils::processStyle(QString &style, const QVector<QPair<QString, QString> > &varMap)
|
||||
{
|
||||
// Process style
|
||||
for (int i = 0; i < varMap.size(); ++i) {
|
||||
const QPair<QString, QString> &map = varMap[i];
|
||||
style.replace("@" + map.first, map.second);
|
||||
}
|
||||
}
|
||||
|
||||
QString VUtils::fileNameFromPath(const QString &p_path)
|
||||
{
|
||||
if (p_path.isEmpty()) {
|
||||
|
@ -104,8 +104,6 @@ public:
|
||||
static QString generateCopiedDirName(const QString &p_parentDirPath,
|
||||
const QString &p_dirName);
|
||||
|
||||
static void processStyle(QString &style, const QVector<QPair<QString, QString> > &varMap);
|
||||
|
||||
// Return the last directory name of @p_path.
|
||||
static QString directoryNameFromPath(const QString& p_path);
|
||||
|
||||
|
@ -25,13 +25,13 @@ const QString VDirectoryTree::c_cutShortcutSequence = "Ctrl+X";
|
||||
const QString VDirectoryTree::c_pasteShortcutSequence = "Ctrl+V";
|
||||
|
||||
VDirectoryTree::VDirectoryTree(QWidget *parent)
|
||||
: QTreeWidget(parent), VNavigationMode(),
|
||||
: VTreeWidget(parent),
|
||||
VNavigationMode(),
|
||||
m_editArea(NULL)
|
||||
{
|
||||
setColumnCount(1);
|
||||
setHeaderHidden(true);
|
||||
setContextMenuPolicy(Qt::CustomContextMenu);
|
||||
setAttribute(Qt::WA_MacShowFocusRect, false);
|
||||
|
||||
initShortcuts();
|
||||
initActions();
|
||||
@ -939,15 +939,11 @@ void VDirectoryTree::mousePressEvent(QMouseEvent *event)
|
||||
setCurrentItem(NULL);
|
||||
}
|
||||
|
||||
QTreeWidget::mousePressEvent(event);
|
||||
VTreeWidget::mousePressEvent(event);
|
||||
}
|
||||
|
||||
void VDirectoryTree::keyPressEvent(QKeyEvent *event)
|
||||
{
|
||||
if (VimNavigationForWidget::injectKeyPressEventForVim(this, event)) {
|
||||
return;
|
||||
}
|
||||
|
||||
int key = event->key();
|
||||
int modifiers = event->modifiers();
|
||||
|
||||
@ -980,7 +976,7 @@ void VDirectoryTree::keyPressEvent(QKeyEvent *event)
|
||||
break;
|
||||
}
|
||||
|
||||
QTreeWidget::keyPressEvent(event);
|
||||
VTreeWidget::keyPressEvent(event);
|
||||
}
|
||||
|
||||
QTreeWidgetItem *VDirectoryTree::findVDirectory(const VDirectory *p_dir, bool *p_widget)
|
||||
|
@ -1,13 +1,14 @@
|
||||
#ifndef VDIRECTORYTREE_H
|
||||
#define VDIRECTORYTREE_H
|
||||
|
||||
#include <QTreeWidget>
|
||||
#include <QJsonObject>
|
||||
#include <QPointer>
|
||||
#include <QVector>
|
||||
#include <QMap>
|
||||
#include <QList>
|
||||
#include <QHash>
|
||||
|
||||
#include "vtreewidget.h"
|
||||
#include "vdirectory.h"
|
||||
#include "vnotebook.h"
|
||||
#include "vnavigationmode.h"
|
||||
@ -16,7 +17,7 @@
|
||||
class VEditArea;
|
||||
class QLabel;
|
||||
|
||||
class VDirectoryTree : public QTreeWidget, public VNavigationMode
|
||||
class VDirectoryTree : public VTreeWidget, public VNavigationMode
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
|
@ -1,6 +1,5 @@
|
||||
#include "vlistwidget.h"
|
||||
|
||||
#include <QVBoxLayout>
|
||||
#include <QKeyEvent>
|
||||
#include <QCoreApplication>
|
||||
#include <QSet>
|
||||
@ -49,12 +48,12 @@ void VListWidget::setSearchInputVisible(bool p_visible)
|
||||
{
|
||||
m_searchInput->setVisible(p_visible);
|
||||
|
||||
int topMargin = 0;
|
||||
int bottomMargin = 0;
|
||||
if (p_visible) {
|
||||
topMargin = m_searchInput->height();
|
||||
bottomMargin = m_searchInput->height();
|
||||
}
|
||||
|
||||
setViewportMargins(0, topMargin, 0, 0);
|
||||
setViewportMargins(0, 0, 0, bottomMargin);
|
||||
}
|
||||
|
||||
void VListWidget::resizeEvent(QResizeEvent *p_event)
|
||||
@ -68,8 +67,14 @@ void VListWidget::resizeEvent(QResizeEvent *p_event)
|
||||
width -= vbar->width();
|
||||
}
|
||||
|
||||
int y = rect.bottom() - m_searchInput->height();
|
||||
QScrollBar *hbar = horizontalScrollBar();
|
||||
if (hbar && (hbar->minimum() != hbar->maximum())) {
|
||||
y -= hbar->height();
|
||||
}
|
||||
|
||||
m_searchInput->setGeometry(QRect(rect.left(),
|
||||
rect.top(),
|
||||
y,
|
||||
width,
|
||||
m_searchInput->height()));
|
||||
}
|
||||
@ -131,3 +136,9 @@ int VListWidget::totalNumberOfItems()
|
||||
{
|
||||
return count();
|
||||
}
|
||||
|
||||
void VListWidget::selectNextItem(bool p_forward)
|
||||
{
|
||||
Q_UNUSED(p_forward);
|
||||
Q_ASSERT(false);
|
||||
}
|
||||
|
@ -29,6 +29,8 @@ public:
|
||||
|
||||
virtual int totalNumberOfItems() Q_DECL_OVERRIDE;
|
||||
|
||||
virtual void selectNextItem(bool p_forward) Q_DECL_OVERRIDE;
|
||||
|
||||
private slots:
|
||||
void handleSearchModeTriggered(bool p_inSearchMode);
|
||||
|
||||
|
@ -18,7 +18,8 @@ VSimpleSearchInput::VSimpleSearchInput(ISimpleSearch *p_obj, QWidget *p_parent)
|
||||
m_obj(p_obj),
|
||||
m_inSearchMode(false),
|
||||
m_currentIdx(-1),
|
||||
m_wildCardEnabled(g_config->getEnableWildCardInSimpleSearch())
|
||||
m_wildCardEnabled(g_config->getEnableWildCardInSimpleSearch()),
|
||||
m_navigationKeyEnabled(false)
|
||||
{
|
||||
if (m_wildCardEnabled) {
|
||||
m_matchFlags = Qt::MatchWildcard | Qt::MatchWrap | Qt::MatchRecursive;
|
||||
@ -151,6 +152,23 @@ bool VSimpleSearchInput::tryHandleKeyPressEvent(QKeyEvent *p_event)
|
||||
return true;
|
||||
}
|
||||
|
||||
// Up/Down Ctrl+K/J to navigate to next item.
|
||||
// QTreeWidget may not response to the key event if it does not have the focus.
|
||||
if (m_inSearchMode && m_navigationKeyEnabled) {
|
||||
if (key == Qt::Key_Down
|
||||
|| key == Qt::Key_Up
|
||||
|| (VUtils::isControlModifierForVim(modifiers)
|
||||
&& (key == Qt::Key_J || key == Qt::Key_K))) {
|
||||
bool forward = true;
|
||||
if (key == Qt::Key_Up || key == Qt::Key_K) {
|
||||
forward = false;
|
||||
}
|
||||
|
||||
m_obj->selectNextItem(forward);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -181,13 +199,13 @@ bool VSimpleSearchInput::eventFilter(QObject *p_watched, QEvent *p_event)
|
||||
void VSimpleSearchInput::handleEditTextChanged(const QString &p_text)
|
||||
{
|
||||
if (!m_inSearchMode) {
|
||||
return;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if (p_text.isEmpty()) {
|
||||
clearSearch();
|
||||
m_obj->selectHitItem(NULL);
|
||||
return;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if (m_wildCardEnabled) {
|
||||
@ -208,6 +226,9 @@ void VSimpleSearchInput::handleEditTextChanged(const QString &p_text)
|
||||
m_currentIdx = m_hitItems.isEmpty() ? -1 : 0;
|
||||
|
||||
m_obj->selectHitItem(currentItem());
|
||||
|
||||
exit:
|
||||
emit inputTextChanged(p_text);
|
||||
}
|
||||
|
||||
void VSimpleSearchInput::updateInfoLabel(int p_nrHit, int p_total)
|
||||
|
@ -26,6 +26,9 @@ public:
|
||||
|
||||
// Get the total number of all the items.
|
||||
virtual int totalNumberOfItems() = 0;
|
||||
|
||||
// Select next item.
|
||||
virtual void selectNextItem(bool p_forward) = 0;
|
||||
};
|
||||
|
||||
|
||||
@ -42,10 +45,14 @@ public:
|
||||
// Return true if @p_event is consumed and do not need further process.
|
||||
bool tryHandleKeyPressEvent(QKeyEvent *p_event);
|
||||
|
||||
void setNavigationKeyEnabled(bool p_enabled);
|
||||
|
||||
signals:
|
||||
// Search mode is triggered.
|
||||
void triggered(bool p_inSearchMode);
|
||||
|
||||
void inputTextChanged(const QString &p_text);
|
||||
|
||||
protected:
|
||||
bool eventFilter(QObject *p_watched, QEvent *p_event) Q_DECL_OVERRIDE;
|
||||
|
||||
@ -76,6 +83,9 @@ private:
|
||||
Qt::MatchFlags m_matchFlags;
|
||||
|
||||
bool m_wildCardEnabled;
|
||||
|
||||
// Down/Up/Ctrl+J/Ctrl+K to navigate.
|
||||
bool m_navigationKeyEnabled;
|
||||
};
|
||||
|
||||
inline void *VSimpleSearchInput::currentItem() const
|
||||
@ -86,4 +96,9 @@ inline void *VSimpleSearchInput::currentItem() const
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
inline void VSimpleSearchInput::setNavigationKeyEnabled(bool p_enabled)
|
||||
{
|
||||
m_navigationKeyEnabled = p_enabled;
|
||||
}
|
||||
#endif // VSIMPLESEARCHINPUT_H
|
||||
|
321
src/vtreewidget.cpp
Normal file
321
src/vtreewidget.cpp
Normal file
@ -0,0 +1,321 @@
|
||||
#include "vtreewidget.h"
|
||||
|
||||
#include <QDropEvent>
|
||||
#include <QKeyEvent>
|
||||
#include <QCoreApplication>
|
||||
#include <QSet>
|
||||
#include <QScrollBar>
|
||||
#include <QDebug>
|
||||
#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()
|
||||
{
|
||||
setAttribute(Qt::WA_MacShowFocusRect, false);
|
||||
|
||||
m_searchInput = new VSimpleSearchInput(this, this);
|
||||
m_searchInput->setNavigationKeyEnabled(true);
|
||||
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);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
setSearchInputVisible(p_inSearchMode);
|
||||
if (!p_inSearchMode) {
|
||||
clearItemsHighlight();
|
||||
|
||||
setFocus();
|
||||
|
||||
QTreeWidgetItem *item = currentItem();
|
||||
if (item) {
|
||||
setCurrentItem(item);
|
||||
} else if (topLevelItemCount() > 0) {
|
||||
setCurrentItem(topLevelItem(0));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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),
|
||||
QItemSelectionModel::ClearAndSelect);
|
||||
}
|
||||
|
||||
// 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 *nextItem = NULL;
|
||||
if (p_forward) {
|
||||
if (item->isExpanded()) {
|
||||
nextItem = item->child(0);
|
||||
} else {
|
||||
while (!nextItem && item) {
|
||||
nextItem = nextSibling(item, true);
|
||||
item = item->parent();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
nextItem = nextSibling(item, false);
|
||||
if (!nextItem) {
|
||||
nextItem = item->parent();
|
||||
} else {
|
||||
nextItem = lastItemOfTree(nextItem);
|
||||
}
|
||||
}
|
||||
|
||||
if (nextItem) {
|
||||
setCurrentItem(nextItem);
|
||||
}
|
||||
}
|
68
src/vtreewidget.h
Normal file
68
src/vtreewidget.h
Normal file
@ -0,0 +1,68 @@
|
||||
#ifndef VTREEWIDGET_H
|
||||
#define VTREEWIDGET_H
|
||||
|
||||
#include <QTreeWidget>
|
||||
|
||||
#include "vsimplesearchinput.h"
|
||||
|
||||
class QDropEvent;
|
||||
class VStyledItemDelegate;
|
||||
class QTimer;
|
||||
class QGraphicsOpacityEffect;
|
||||
|
||||
// QTreeWidget won't emit the rowsMoved() signal after drag-and-drop.
|
||||
// VTreeWidget will emit rowsMoved() signal.
|
||||
class VTreeWidget : public QTreeWidget, public ISimpleSearch
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit VTreeWidget(QWidget *p_parent = nullptr);
|
||||
|
||||
// Clear tree widget as well as other data.
|
||||
void clearAll();
|
||||
|
||||
// Implement ISimpleSearch.
|
||||
virtual QList<void *> searchItems(const QString &p_text,
|
||||
Qt::MatchFlags p_flags) const Q_DECL_OVERRIDE;
|
||||
|
||||
virtual void highlightHitItems(const QList<void *> &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;
|
||||
|
||||
virtual void selectNextItem(bool p_forward) Q_DECL_OVERRIDE;
|
||||
|
||||
protected:
|
||||
void keyPressEvent(QKeyEvent *p_event) Q_DECL_OVERRIDE;
|
||||
|
||||
void resizeEvent(QResizeEvent *p_event) Q_DECL_OVERRIDE;
|
||||
|
||||
void dropEvent(QDropEvent *p_event) Q_DECL_OVERRIDE;
|
||||
|
||||
signals:
|
||||
// Rows [@p_first, @p_last] were moved to @p_row.
|
||||
void rowsMoved(int p_first, int p_last, int p_row);
|
||||
|
||||
private slots:
|
||||
void handleSearchModeTriggered(bool p_inSearchMode);
|
||||
|
||||
void handleSearchInputTextChanged(const QString &p_text);
|
||||
|
||||
private:
|
||||
// Show or hide search input.
|
||||
void setSearchInputVisible(bool p_visible);
|
||||
|
||||
QGraphicsOpacityEffect *getSearchInputEffect() const;
|
||||
|
||||
QTreeWidgetItem *nextSibling(QTreeWidgetItem *p_item, bool p_forward);
|
||||
|
||||
VSimpleSearchInput *m_searchInput;
|
||||
|
||||
VStyledItemDelegate *m_delegate;
|
||||
|
||||
QTimer *m_searchColdTimer;
|
||||
};
|
||||
#endif // VTREEWIDGET_H
|
Loading…
x
Reference in New Issue
Block a user