Commit 8ccb1080 authored by Christian Schulte zu Berge's avatar Christian Schulte zu Berge
Browse files

Resolve #383: Offer inspection of ImageSeries in DataContainerInspector

Extended the DataContainerTreeWidget and its corresponding DataContainerTreeModel to support a second level containing the DataHandles of RenderData and ImageSeries items.
parent 2693e463
......@@ -35,11 +35,14 @@
#include "core/datastructures/meshgeometry.h"
#include "core/datastructures/indexedmeshgeometry.h"
#include "core/datastructures/multiindexedgeometry.h"
#include "core/datastructures/imageseries.h"
#include "core/datastructures/imagerepresentationdisk.h"
#include "core/datastructures/imagerepresentationlocal.h"
#include "core/datastructures/imagerepresentationgl.h"
#include "core/datastructures/renderdata.h"
#include "core/tools/stringutils.h"
#ifdef CAMPVIS_HAS_MODULE_COLUMBIA
#include "modules/columbia/datastructures/fiberdata.h"
#endif
......@@ -84,6 +87,7 @@ namespace campvis {
, _name(name)
{
tgtAssert(_dataHandle.getData() != 0, "WTF - QtDataHandle with empty data?");
updateChildren();
}
QVariant DataHandleTreeItem::getData(int column, int role) const {
......@@ -124,6 +128,10 @@ namespace campvis {
else if (const RenderData* tester = dynamic_cast<const RenderData*>(data)) {
return QVariant(QString("Render Data"));
}
else if (const ImageSeries* tester = dynamic_cast<const ImageSeries*>(data)) {
return QVariant(QString("Image Series"));
}
}
else
return QVariant();
......@@ -139,6 +147,29 @@ namespace campvis {
void DataHandleTreeItem::setDataHandle(const QtDataHandle& dataHandle) {
_dataHandle = dataHandle;
updateChildren();
}
void DataHandleTreeItem::updateChildren() {
qDeleteAll(_children);
_children.clear();
if (const AbstractData* data = _dataHandle.getData()) {
if (const RenderData* tester = dynamic_cast<const RenderData*>(data)) {
for (size_t i = 0; i < tester->getNumColorTextures(); ++i) {
DataHandleTreeItem* dhti = new DataHandleTreeItem(QtDataHandle(tester->getColorDataHandle(i)), _name + "::ColorTexture" + StringUtils::toString(i), this);
}
if (tester->hasDepthTexture()) {
DataHandleTreeItem* dhti = new DataHandleTreeItem(QtDataHandle(tester->getDepthDataHandle()), _name + "::DepthTexture", this);
}
}
else if (const ImageSeries* tester = dynamic_cast<const ImageSeries*>(data)) {
for (size_t i = 0; i < tester->getNumImages(); ++i) {
DataHandleTreeItem* dhti = new DataHandleTreeItem(QtDataHandle(tester->getImage(i)), _name + "::Image" + StringUtils::toString(i), this);
}
}
}
}
// = DataContainerTreeModel ============================================================================
......@@ -239,31 +270,52 @@ namespace campvis {
}
void DataContainerTreeModel::setData(const DataContainer* dataContainer) {
beginResetModel();
_itemMap.clear();
delete _rootItem;
_rootItem = new DataContainerTreeRootItem();
if (dataContainer != 0) {
std::vector< std::pair< std::string, DataHandle> > handlesCopy = dataContainer->getDataHandlesCopy();
std::sort(handlesCopy.begin(), handlesCopy.end(), [&] (const std::pair<std::string, DataHandle>& a, const std::pair<std::string, DataHandle>& b) -> bool { return a.first < b.first; });
for (std::vector< std::pair< std::string, DataHandle> >::iterator it = handlesCopy.begin(); it != handlesCopy.end(); ++it) {
DataHandleTreeItem* dhti = new DataHandleTreeItem(QtDataHandle(it->second), it->first, _rootItem);
_itemMap.insert(std::make_pair(QString::fromStdString(it->first), dhti));
}
}
endResetModel();
}
void DataContainerTreeModel::onDataContainerChanged(const QString& key, QtDataHandle dh) {
tgtAssert(dh.getData() != 0, "WTF - QtDataHandle with empty data?");
std::map<QString, DataHandleTreeItem*>::const_iterator it = _itemMap.lower_bound(key);
std::map<QString, DataHandleTreeItem*>::iterator it = _itemMap.lower_bound(key);
if (it == _itemMap.end() || it->first != key) {
// there is no tree item with this key yet => create a new one
DataHandleTreeItem* dhti = new DataHandleTreeItem(dh, key.toStdString(), _rootItem);
_itemMap.insert(std::make_pair(key, dhti));
emit dataChanged(createIndex(dhti->getRow(), 0, dhti), createIndex(dhti->getRow(), columnCount(), dhti));
// notify views, that there is new data
emit dataChanged(createIndex(dhti->getRow(), 0, dhti), createIndex(dhti->getRow() + dhti->getChildCount(), columnCount(), dhti));
}
else {
// there is alredy a tree item with this key => update the item and its children
QModelIndex keyIndex = createIndex(it->second->getRow(), 0, it->second);
// by replacing the DataHandle in the tree item, we also replace all of the TreeItem's children
// this is effectively a remove followed by an insert
beginRemoveRows(keyIndex, 0, it->second->getChildCount());
it->second->setDataHandle(dh);
emit dataChanged(createIndex(it->second->getRow(), 0, it->second), createIndex(it->second->getRow(), columnCount(), it->second));
endRemoveRows();
beginInsertRows(keyIndex, 0, it->second->getChildCount());
endInsertRows();
// notify views, that there is new data
emit dataChanged(keyIndex, createIndex(it->second->getRow(), columnCount(), it->second));
}
}
......@@ -287,7 +339,6 @@ namespace campvis {
_treeModel->setData(dataContainer);
// adjust view
expandAll();
resizeColumnToContents(0);
resizeColumnToContents(1);
}
......
......@@ -80,6 +80,13 @@ namespace campvis {
void setDataHandle(const QtDataHandle& dataHandle);
private:
/**
* Updates this item's children.
* In case of having a ImageSeries or RenderData as DataHandle, we are a collection of
* DataHandles ourself. Hence, we create child items for us.
*/
void updateChildren();
QtDataHandle _dataHandle; ///< Base QtDataHandle
std::string _name; ///< Name of that QtDataHandle
};
......
......@@ -22,6 +22,7 @@
//
// ================================================================================================
#include "tgt/assert.h"
#include "treeitem.h"
namespace campvis {
......@@ -60,4 +61,35 @@ namespace campvis {
return false;
}
void TreeItem::insertChild(int row, TreeItem* child) {
tgtAssert(row < 0 || row > _children.size(), "Row index out of bounds!");
_children.insert(row, child);
child->_parent = this;
}
void TreeItem::removeChild(int row) {
tgtAssert(row < 0 || row > _children.size(), "Row index out of bounds!");
delete _children.takeAt(row);
}
void TreeItem::replaceChild(int row, TreeItem* child) {
tgtAssert(row < getChildCount(), "Row out of bounds!");
delete _children[row];
_children[row] = child;
child->_parent = this;
}
void TreeItem::clearChildren() {
qDeleteAll(_children);
_children.clear();
}
void TreeItem::dumpTree(TreeItem* t, int level /*= 0*/) {
std::cout << std::string(level, ' ') << t << "\n";
for (int i = 0; i < t->getChildCount(); ++i) {
TreeItem::dumpTree(t->getChild(i), level + 1);
}
}
}
\ No newline at end of file
......@@ -25,6 +25,8 @@
#ifndef TREEITEM_H__
#define TREEITEM_H__
#include <iostream>
#include <QList>
#include <QVariant>
......@@ -90,11 +92,44 @@ namespace campvis {
*/
int getChildCount();
private:
/**
* Inserts a child at the given row.
* \param row Row where to insert the child
*/
void insertChild(int row, TreeItem* child);
/**
* Removes the child at the given row.
* \param row Row index of the child to remove.
*/
void removeChild(int row);
/**
* Replaces the child with index \a row with the given TreeItem.
* \param row Child to replace, must be < than getChildCount()
* \param child New TreeItem for the child
*/
void replaceChild(int row, TreeItem* child);
/**
* Removes all children.
*/
void clearChildren();
/**
* Dumps debug output of the tree hierarchy.
* \param t TreeItem to dump
* \param level Starting indentation level
*/
static void dumpTree(TreeItem* t, int level = 0);
protected:
TreeItem* _parent; ///< Parent TreeItem.
QList<TreeItem*> _children; ///< Collection of all child items.
};
}
#endif // TREEITEM_H__
\ No newline at end of file
......@@ -109,6 +109,14 @@ namespace campvis {
return static_cast<const ImageData*>(_colorTextures[index].getData());
}
campvis::DataHandle RenderData::getColorDataHandle(size_t index /*= 0*/) const {
tgtAssert(index < _colorTextures.size(), "Index out of bounds.");
if (index >= _colorTextures.size())
return DataHandle(0);
return _colorTextures[index];
}
bool RenderData::hasDepthTexture() const {
return _depthTexture.getData() != 0;
}
......@@ -121,6 +129,10 @@ namespace campvis {
return static_cast<const ImageData*>(d);
}
campvis::DataHandle RenderData::getDepthDataHandle() const {
return _depthTexture;
}
void RenderData::addColorTexture(ImageData* texture) {
_colorTextures.push_back(DataHandle(texture));
}
......
......@@ -91,6 +91,13 @@ namespace campvis {
*/
const ImageData* getColorTexture(size_t index = 0) const;
/**
* Gets the DataHandle with the color texture in this RenderData.
* \param index Index of the color texture to return.
* \return _colorTextures[index], 0 if index out of bounds.
*/
DataHandle getColorDataHandle(size_t index = 0) const;
/**
* Returns, whether this RenderData has a depth texture.
* \return _depthTexture != 0;
......@@ -104,6 +111,12 @@ namespace campvis {
*/
const ImageData* getDepthTexture() const;
/**
* Gets the DataHandle with the depth texture in this RenderData, if present.
* Returns 0 if no depth texture is present.
* \return _depthTexture, may be 0.
*/
DataHandle getDepthDataHandle() const;
/**
* Adds \a texture to this RenderData.
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment