logplus/Workflow/WFWidget/src/PaiTreeWidget.cpp
2026-01-16 17:18:41 +08:00

193 lines
6.1 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* @file PaiTreeWidget.cpp
* @brief P.A.I系统定制发布的树控件
* @date 2012-10-18
*/
#include <QLabel>
#include <QHeaderView>
#include "PaiTreeWidget.h"
#include "GlobalUtility.h"
// 设置树标题栏的最小高度
const int HEADER_MINHEIGHT = 27;
using namespace pai::gui;
PaiTreeWidget::PaiTreeWidget(QWidget *pParent) :
QTreeWidget(pParent),
m_InSearching(false),
m_pTipLabel(NULL)
{
this->header()->setMinimumHeight(HEADER_MINHEIGHT);
}
PaiTreeWidget::~PaiTreeWidget()
{
}
void PaiTreeWidget::Filter(const QString & keyword, int column)
{
Filter(keyword, QList<int>() << column);
}
void PaiTreeWidget::Filter(const QString & keyword, QList<int> columns)
{
// 去掉搜索结果为空的提示
if(m_pTipLabel)
{
m_pTipLabel->hide();
}
// 记住搜索前树的状态,以便搜索之后重新显示
if(!m_InSearching)
{
for(QTreeWidgetItemIterator it(this); *it; ++it)
{
(*it)->setData(1, pai::gui::SearchRole, (*it)->isExpanded());
(*it)->setData(2, pai::gui::SearchRole, (*it)->isSelected());
}
m_InSearching = true;
}
// 如果搜索字符为空,认为搜索结束,恢复搜索前树的状态
if(keyword.isEmpty())
{
// 此处必须用两次循环来实现,第一次来表示选中与否,第二次来表示展开与否
// 之所以这样做,是因为在选中某节点的时候其相应的父节点也会自动展开,
// 造成还原效果与之前记录的效果不一致的问题defect:17515
clearSelection();
for(QTreeWidgetItemIterator it(this); *it; ++it)
{
(*it)->setHidden(false);
(*it)->setSelected((*it)->data(2, pai::gui::SearchRole).toBool());
}
for(QTreeWidgetItemIterator it(this); *it; ++it)
{
(*it)->setExpanded((*it)->data(1, pai::gui::SearchRole).toBool());
}
m_InSearching = false;
emit SearchFinished(invisibleRootItem());
return;
}
// 遍历树,来搜索符合条件的节点, 建于绝大多数用户对正则表达式的了解,目前只支持到‘*
bool bWildcard = keyword.contains('*') || keyword.contains('?');
QList<QTreeWidgetItem*> searchResult;
for(int col=0; col<columns.size(); ++col)
{
searchResult <<
findItems(keyword, bWildcard ? (Qt::MatchRecursive
| Qt::MatchContains
| Qt::MatchWildcard) : Qt::MatchRecursive | Qt::MatchContains, col);
}
clearSelection();
if(!searchResult.empty())
{
// 首先显示全体
for(QTreeWidgetItemIterator it(this); *it; ++it)
{
(*it)->setHidden(false);
}
}
foreach(QTreeWidgetItem *pItem, searchResult)
{
pItem->setHidden(true); // 隐藏搜索结果集本身
pItem->setSelected(true);
pItem->setExpanded(false);
}
if(!searchResult.empty())
{
for(QTreeWidgetItemIterator it(this); *it; ++it)
{
bool bGenerationOfResult = IsGenerationOfFoundItem(*it);
(*it)->setHidden(bGenerationOfResult); // 隐藏搜索结果集的子代,显示结果集的父母和兄弟
}
foreach(QTreeWidgetItem *pItem, searchResult)
{
QTreeWidgetItem *pParentItem = pItem->parent();
while(pParentItem)
{
pParentItem->setHidden(true); // 隐藏搜索结果集的直系父代
pParentItem->setExpanded(true); // 顺便置展开状态
pParentItem = pParentItem->parent();
}
}
for(QTreeWidgetItemIterator it(this); *it; ++it)
{
(*it)->setHidden((!(*it)->isHidden()));//取反来显示所有搜索结果
}
}
// 如果没搜到任何东西,则显示未找到提示
if(searchResult.empty())
{
for(int i = 0; i < topLevelItemCount(); ++i)
{
topLevelItem(i)->setHidden(true);
}
if(!m_pTipLabel)
{
m_pTipLabel = new QLabel(tr("found nothing!"), this);
}
m_pTipLabel->move((width() - m_pTipLabel->width()) / 2, HEADER_MINHEIGHT);
m_pTipLabel->show(); // 必须调用此函数,否则显示不出来
}
else // 如果搜索到结果,就将搜索到的第一个节点滚动到顶端显示
{
scrollToItem(searchResult.first(), QAbstractItemView::PositionAtTop);
}
emit SearchFinished(invisibleRootItem());
}
bool PaiTreeWidget::IsGenerationOfFoundItem(QTreeWidgetItem *pItem)
{
// 本函数的逻辑依赖于Filter函数的实现请不要在其他函数中调用
// 调本函数之前已经将搜索结果集及其父代全部隐藏根据setHidden的传递性此时搜索结果集的子代也是处于hidden状态
if(pItem->isHidden())
{
return true;
}
QTreeWidgetItem *pParentItem = pItem->parent();
while((pParentItem != NULL) && (pParentItem != invisibleRootItem()))
{
if(pParentItem->isHidden())
{
return true;
}
pParentItem = pParentItem->parent();
}
return false;
}
/////////////////////////////// PaiTreeWidgetItem ///////////////////////////////////
PaiTreeWidgetItem::PaiTreeWidgetItem() : QTreeWidgetItem()
{
}
PaiTreeWidgetItem::PaiTreeWidgetItem(QTreeWidgetItem *pParent) : QTreeWidgetItem(pParent)
{
}
PaiTreeWidgetItem::~PaiTreeWidgetItem()
{
}
bool PaiTreeWidgetItem::operator < (const QTreeWidgetItem & otherItem) const
{
if(data(0, pai::gui::DataSortRole).isValid() && otherItem.data(0, pai::gui::DataSortRole).isValid())
{
if((data(0, pai::gui::DataSortRole).type() == QVariant::Int)
&& (otherItem.data(0, pai::gui::DataSortRole).type() == QVariant::Int)) // 整形比较
{
return data(0, pai::gui::DataSortRole).toInt() < otherItem.data(0, pai::gui::DataSortRole).toInt();
}
}
return QTreeWidgetItem::operator < (otherItem); // 暂不支持的排序类型使用基类排序
}