You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
nmWTAI-Platform/3rd/VTK7.1/source/VTK-7.1.1/GUISupport/Qt/vtkQtTreeModelAdapter.cxx

586 lines
15 KiB
C++

/*=========================================================================
Program: Visualization Toolkit
Module: vtkQtTreeModelAdapter.cxx
Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
All rights reserved.
See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the above copyright notice for more information.
=========================================================================*/
/*-------------------------------------------------------------------------
Copyright 2008 Sandia Corporation.
Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
the U.S. Government retains certain rights in this software.
-------------------------------------------------------------------------*/
#include "vtkQtTreeModelAdapter.h"
#include "vtkAdjacentVertexIterator.h"
#include "vtkAnnotation.h"
#include "vtkArrayIteratorIncludes.h"
#include "vtkConvertSelection.h"
#include "vtkIdList.h"
#include "vtkIdTypeArray.h"
#include "vtkInformation.h"
#include "vtkPointData.h"
#include "vtkSelection.h"
#include "vtkSelectionNode.h"
#include "vtkSmartPointer.h"
#include "vtkStdString.h"
#include "vtkStringArray.h"
#include "vtkTree.h"
#include "vtkUnicodeStringArray.h"
#include "vtkUnsignedCharArray.h"
#include "vtkVariantArray.h"
#include <algorithm>
#include <QIcon>
#include <QPainter>
#include <QBrush>
#include <QPen>
#include <QPixmap>
#include <QMimeData>
#include <sstream>
#include <set>
vtkQtTreeModelAdapter::vtkQtTreeModelAdapter(QObject* p, vtkTree* t)
: vtkQtAbstractModelAdapter(p)
{
this->TreeMTime = 0;
this->Tree = 0;
this->setTree(t);
this->ChildIterator = vtkAdjacentVertexIterator::New();
}
vtkQtTreeModelAdapter::~vtkQtTreeModelAdapter()
{
if (this->Tree)
{
this->Tree->Delete();
}
this->ChildIterator->Delete();
}
void vtkQtTreeModelAdapter::SetColorColumnName(const char* name)
{
if (name == 0)
{
this->ColorColumn = -1;
}
else
{
this->ColorColumn = -1;
for (int i = 0; i < this->Tree->GetVertexData()->GetNumberOfArrays(); i++)
{
if (!strcmp(name, this->Tree->GetVertexData()->GetAbstractArray(i)->GetName()))
{
this->ColorColumn = i;
break;
}
}
}
}
void vtkQtTreeModelAdapter::SetKeyColumnName(const char* name)
{
if (name == 0)
{
this->KeyColumn = -1;
}
else
{
this->KeyColumn = -1;
for (int i = 0; i < this->Tree->GetVertexData()->GetNumberOfArrays(); i++)
{
if (!strcmp(name, this->Tree->GetVertexData()->GetAbstractArray(i)->GetName()))
{
this->KeyColumn = i;
break;
}
}
}
}
void vtkQtTreeModelAdapter::SetVTKDataObject(vtkDataObject *obj)
{
vtkTree *t = vtkTree::SafeDownCast(obj);
if (obj && !t)
{
cerr << "vtkQtTreeModelAdapter needs a vtkTree for SetVTKDataObject" << endl;
return;
}
// Okay it's a tree so set it :)
this->setTree(t);
}
vtkDataObject* vtkQtTreeModelAdapter::GetVTKDataObject() const
{
return this->Tree;
}
vtkMTimeType vtkQtTreeModelAdapter::GetVTKDataObjectMTime() const
{
return this->TreeMTime;
}
void vtkQtTreeModelAdapter::setTree(vtkTree* t)
{
if (!t || (t != this->Tree))
{
vtkTree* tempSGMacroVar = this->Tree;
this->Tree = t;
if (this->Tree != NULL)
{
this->Tree->Register(0);
vtkIdType root = this->Tree->GetRoot();
this->VTKIndexToQtModelIndex.clear();
this->VTKIndexToQtModelIndex.resize(this->Tree->GetNumberOfVertices());
if (root >= 0)
{
this->GenerateVTKIndexToQtModelIndex(root,
this->createIndex(0, 0, static_cast<int>(root)));
}
this->TreeMTime = this->Tree->GetMTime();
}
if (tempSGMacroVar != NULL)
{
tempSGMacroVar->UnRegister(0);
}
emit reset();
}
// Okay it's the same pointer but the contents
// of the tree might have been modified so
// check for that condition
else if (this->Tree->GetMTime() != this->TreeMTime)
{
this->treeModified();
}
}
void vtkQtTreeModelAdapter::treeModified()
{
this->VTKIndexToQtModelIndex.clear();
if (this->Tree->GetNumberOfVertices() > 0)
{
vtkIdType root = this->Tree->GetRoot();
this->VTKIndexToQtModelIndex.resize(this->Tree->GetNumberOfVertices());
this->GenerateVTKIndexToQtModelIndex(root,
this->createIndex(0, 0, static_cast<int>(root)));
}
this->TreeMTime = this->Tree->GetMTime();
emit reset();
}
// Description:
// Selection conversion from VTK land to Qt land
vtkSelection* vtkQtTreeModelAdapter::QModelIndexListToVTKIndexSelection(
const QModelIndexList qmil) const
{
// Create vtk index selection
vtkSelection* IndexSelection = vtkSelection::New(); // Caller needs to delete
vtkSmartPointer<vtkSelectionNode> node =
vtkSmartPointer<vtkSelectionNode>::New();
node->SetContentType(vtkSelectionNode::INDICES);
node->SetFieldType(vtkSelectionNode::VERTEX);
vtkSmartPointer<vtkIdTypeArray> index_arr =
vtkSmartPointer<vtkIdTypeArray>::New();
node->SetSelectionList(index_arr);
IndexSelection->AddNode(node);
// Run through the QModelIndexList pulling out vtk indexes
std::set<int> unique_ids;
for (int i = 0; i < qmil.size(); i++)
{
unique_ids.insert(qmil.at(i).internalId());
}
std::set<int>::iterator iter;
for (iter = unique_ids.begin(); iter != unique_ids.end(); ++iter)
{
index_arr->InsertNextValue(*iter);
}
return IndexSelection;
}
QItemSelection vtkQtTreeModelAdapter::VTKIndexSelectionToQItemSelection(
vtkSelection *vtksel) const
{
QItemSelection qis_list;
for(unsigned int j=0; j<vtksel->GetNumberOfNodes(); ++j)
{
vtkSelectionNode* node = vtksel->GetNode(j);
if (node && node->GetFieldType() == vtkSelectionNode::VERTEX)
{
vtkIdTypeArray* arr = vtkArrayDownCast<vtkIdTypeArray>(node->GetSelectionList());
if (arr)
{
for (vtkIdType i = 0; i < arr->GetNumberOfTuples(); i++)
{
vtkIdType vtk_index = arr->GetValue(i);
QModelIndex qmodel_index = this->VTKIndexToQtModelIndex[vtk_index];
qis_list.select(qmodel_index, qmodel_index);
}
}
}
}
return qis_list;
}
void vtkQtTreeModelAdapter::GenerateVTKIndexToQtModelIndex(vtkIdType vtk_index, QModelIndex qmodel_index)
{
// Store the QModelIndex for selection conversions later
this->VTKIndexToQtModelIndex.replace(vtk_index, qmodel_index);
// Iterate through the children of this tree nodes
vtkAdjacentVertexIterator* it = vtkAdjacentVertexIterator::New();
this->Tree->GetChildren(vtk_index, it);
int i = 0;
while (it->HasNext())
{
vtkIdType vtk_child_index = it->Next();
this->GenerateVTKIndexToQtModelIndex(vtk_child_index,
this->createIndex(i, 0, static_cast<int>(vtk_child_index)));
++i;
}
it->Delete();
}
//----------------------------------------------------------------------------
QVariant vtkQtTreeModelAdapterArrayValue(vtkAbstractArray* arr, vtkIdType i, vtkIdType j)
{
int comps = arr->GetNumberOfComponents();
if(vtkDataArray* const data = vtkArrayDownCast<vtkDataArray>(arr))
{
return QVariant(data->GetComponent(i, j));
}
if(vtkStringArray* const data = vtkArrayDownCast<vtkStringArray>(arr))
{
return QVariant(data->GetValue(i*comps + j));
}
if(vtkUnicodeStringArray* const data = vtkArrayDownCast<vtkUnicodeStringArray>(arr))
{
return QVariant(QString::fromUtf8(data->GetValue(i*comps + j).utf8_str()));
}
if(vtkVariantArray* const data = vtkArrayDownCast<vtkVariantArray>(arr))
{
return QVariant(QString(data->GetValue(i*comps + j).ToString().c_str()));
}
vtkGenericWarningMacro("Unknown array type in vtkQtTreeModelAdapterArrayValue.");
return QVariant();
}
QVariant vtkQtTreeModelAdapter::data(const QModelIndex &idx, int role) const
{
if (!this->Tree)
{
return QVariant();
}
if (!idx.isValid())
{
return QVariant();
}
//if (role == Qt::DecorationRole)
// {
// return this->IndexToDecoration[idx];
// }
vtkIdType vertex = static_cast<vtkIdType>(idx.internalId());
int column = this->ModelColumnToFieldDataColumn(idx.column());
vtkAbstractArray* arr = this->Tree->GetVertexData()->GetAbstractArray(column);
if (role == Qt::DisplayRole)
{
return QString::fromUtf8(arr->GetVariantValue(vertex).ToUnicodeString().utf8_str()).trimmed();
}
else if (role == Qt::UserRole)
{
return vtkQtTreeModelAdapterArrayValue(arr, vertex, 0);
}
if(this->ColorColumn >= 0)
{
int colorColumn = this->ModelColumnToFieldDataColumn(this->ColorColumn);
vtkUnsignedCharArray* colors = vtkArrayDownCast<vtkUnsignedCharArray>(this->Tree->GetVertexData()->GetAbstractArray(colorColumn));
if (!colors)
{
return QVariant();
}
const int nComponents = colors->GetNumberOfComponents();
if(nComponents < 3)
{
return QVariant();
}
unsigned char rgba[4];
colors->GetTypedTuple(vertex, rgba);
int rgb[3];
rgb[0] = static_cast<int>(0x0ff & rgba[0]);
rgb[1] = static_cast<int>(0x0ff & rgba[1]);
rgb[2] = static_cast<int>(0x0ff & rgba[2]);
if(role == Qt::DecorationRole)
{
QPixmap pixmap(12, 12);
pixmap.fill(QColor(0, 0, 0, 0));
QPainter painter(&pixmap);
painter.setRenderHint(QPainter::Antialiasing);
painter.setPen(Qt::NoPen);
painter.setBrush(QBrush(QColor(rgb[0],rgb[1],rgb[2])));
if (this->rowCount(idx) > 0)
{
painter.drawEllipse(0, 0, 11, 11);
}
else
{
painter.drawEllipse(2, 2, 7, 7);
}
return QVariant(pixmap);
}
else if(role == Qt::TextColorRole)
{
//return QVariant(QColor(rgb[0],rgb[1],rgb[2]));
}
}
return QVariant();
}
bool vtkQtTreeModelAdapter::setData(const QModelIndex &idx, const QVariant &value, int role)
{
if (role == Qt::DecorationRole)
{
this->IndexToDecoration[idx] = value;
emit this->dataChanged(idx, idx);
return true;
}
return false;
}
Qt::ItemFlags vtkQtTreeModelAdapter::flags(const QModelIndex &idx) const
{
if (!idx.isValid())
{
return Qt::ItemIsEnabled;
}
Qt::ItemFlags itemFlags = Qt::ItemIsEnabled | Qt::ItemIsSelectable;
if(!this->hasChildren(idx))
{
itemFlags = itemFlags | Qt::ItemIsDragEnabled;
}
return itemFlags;
}
QVariant vtkQtTreeModelAdapter::headerData(int section, Qt::Orientation orientation,
int role) const
{
// For horizontal headers, try to convert the column names to double.
// If it doesn't work, return a string.
if (orientation == Qt::Horizontal &&
(role == Qt::DisplayRole || role == Qt::UserRole))
{
section = this->ModelColumnToFieldDataColumn(section);
QVariant svar(this->Tree->GetVertexData()->GetArrayName(section));
bool ok;
double value = svar.toDouble(&ok);
if (ok)
{
return QVariant(value);
}
return svar;
}
// For vertical headers, return values in the key column if
// KeyColumn is valid.
if (orientation == Qt::Vertical && this->KeyColumn != -1 &&
(role == Qt::DisplayRole || role == Qt::UserRole))
{
return QVariant(this->Tree->GetVertexData()->GetArrayName(this->KeyColumn));
}
return QVariant();
}
QModelIndex vtkQtTreeModelAdapter::index(int row, int column,
const QModelIndex &parentIdx) const
{
if (!this->Tree)
{
return QModelIndex();
}
vtkIdType parentItem;
if (!parentIdx.isValid())
{
if (row == 0)
{
return createIndex(row, column, static_cast<int>(this->Tree->GetRoot()));
}
else
{
return QModelIndex();
}
}
else
{
parentItem = static_cast<vtkIdType>(parentIdx.internalId());
}
this->Tree->GetChildren(parentItem, this->ChildIterator);
if (row < this->Tree->GetNumberOfChildren(parentItem))
{
vtkIdType child = this->ChildIterator->Next();
for (int i = 0; i < row; ++i)
{
child = this->ChildIterator->Next();
}
return createIndex(row, column, static_cast<int>(child));
}
else
{
return QModelIndex();
}
}
QModelIndex vtkQtTreeModelAdapter::parent(const QModelIndex &idx) const
{
if (!this->Tree)
{
return QModelIndex();
}
if (!idx.isValid())
{
return QModelIndex();
}
vtkIdType child = static_cast<vtkIdType>(idx.internalId());
if (child == this->Tree->GetRoot())
{
return QModelIndex();
}
vtkIdType parentId = this->Tree->GetParent(child);
if (parentId == this->Tree->GetRoot())
{
return createIndex(0, 0, static_cast<int>(parentId));
}
vtkIdType grandparentId = this->Tree->GetParent(parentId);
vtkIdType row = -1;
this->Tree->GetChildren(grandparentId, this->ChildIterator);
int i = 0;
while (this->ChildIterator->HasNext())
{
if (this->ChildIterator->Next() == parentId)
{
row = i;
break;
}
++i;
}
return createIndex(row, 0, static_cast<int>(parentId));
}
int vtkQtTreeModelAdapter::rowCount(const QModelIndex &idx) const
{
if (!this->Tree)
{
return 1;
}
if (!idx.isValid())
{
return 1;
}
vtkIdType parentId = static_cast<vtkIdType>(idx.internalId());
return this->Tree->GetNumberOfChildren(parentId);
}
int vtkQtTreeModelAdapter::columnCount(const QModelIndex & vtkNotUsed(parentIdx)) const
{
if (!this->Tree)
{
return 0;
}
int numArrays = this->Tree->GetVertexData()->GetNumberOfArrays();
int numDataArrays = this->DataEndColumn - this->DataStartColumn + 1;
switch (this->ViewType)
{
case FULL_VIEW:
return numArrays;
case DATA_VIEW:
return numDataArrays;
default:
vtkGenericWarningMacro("vtkQtTreeModelAdapter: Bad view type.");
};
return 0;
}
QStringList vtkQtTreeModelAdapter::mimeTypes() const
{
QStringList types;
types << "vtk/selection";
return types;
}
QMimeData *vtkQtTreeModelAdapter::mimeData(const QModelIndexList &indexes) const
{
// Only supports dragging single item right now ...
if(indexes.size() == 0)
{
return 0;
}
vtkSmartPointer<vtkSelection> indexSelection = vtkSmartPointer<vtkSelection>::New();
indexSelection.TakeReference(QModelIndexListToVTKIndexSelection(indexes));
vtkSmartPointer<vtkSelection> pedigreeIdSelection = vtkSmartPointer<vtkSelection>::New();
pedigreeIdSelection.TakeReference(vtkConvertSelection::ToSelectionType(indexSelection, this->Tree, vtkSelectionNode::PEDIGREEIDS));
if(pedigreeIdSelection->GetNode(0) == 0 || pedigreeIdSelection->GetNode(0)->GetSelectionList()->GetNumberOfTuples() == 0)
{
return 0;
}
std::ostringstream buffer;
buffer << pedigreeIdSelection;
QMimeData *mime_data = new QMimeData();
mime_data->setData("vtk/selection", buffer.str().c_str());
return mime_data;
}
Qt::DropActions vtkQtTreeModelAdapter::supportedDragActions() const
{
return Qt::CopyAction;
}