Currently job artifacts in CI/CD pipelines on LRZ GitLab never expire. Starting from Wed 26.1.2022 the default expiration time will be 30 days (GitLab default). Currently existing artifacts in already completed jobs will not be affected by the change. The latest artifacts for all jobs in the latest successful pipelines will be kept. More information: https://gitlab.lrz.de/help/user/admin_area/settings/continuous_integration.html#default-artifacts-expiration

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.
......
Markdown is supported
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