193 lines
6.1 KiB
C++
193 lines
6.1 KiB
C++
|
|
/**
|
|||
|
|
* @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); // 暂不支持的排序类型使用基类排序
|
|||
|
|
}
|