diff --git a/AddInManager/addInManager.cpp b/AddInManager/addInManager.cpp index 0bc7595dd..f6e74c269 100644 --- a/AddInManager/addInManager.cpp +++ b/AddInManager/addInManager.cpp @@ -829,6 +829,7 @@ AddInManager::AddInManager(QString itomSettingsFile, void **apiFuncsGraph, QObje qRegisterMetaType >("QMap"); qRegisterMetaType > >("QSharedPointer >"); qRegisterMetaType > >("QVector >"); + qRegisterMetaType > >("QSharedPointer >"); #if ITOM_POINTCLOUDLIBRARY > 0 qRegisterMetaType("ito::PCLPointCloud"); diff --git a/AddInManager/pluginModel.cpp b/AddInManager/pluginModel.cpp index 69b3e587b..7cd143b28 100644 --- a/AddInManager/pluginModel.cpp +++ b/AddInManager/pluginModel.cpp @@ -29,39 +29,39 @@ namespace ito { -class PlugInModelPrivate -{ -public: + class PlugInModelPrivate + { + public: PlugInModelPrivate() : m_pAIM(nullptr), m_bgColorItemsWithPythonRef(QColor(255, 255, 175)){}; - ~PlugInModelPrivate(){}; + ~PlugInModelPrivate() {}; -public: - QList m_headers; //!< string list of names of column headers - QList m_alignment; //!< list of alignments for the corresponding headers + public: + QList m_headers; //!< string list of names of column headers + QList m_alignment; //!< list of alignments for the corresponding headers - int m_treeFixNodes[6]; - QModelIndex m_treeFixIndizes[6]; + int m_treeFixNodes[6]; + QModelIndex m_treeFixIndizes[6]; - QIcon m_iconActuator; - QIcon m_iconGrabber; - QIcon m_iconADDA; - QIcon m_iconRawIO; - QIcon m_iconFilter; - QIcon m_iconDataIO; - QIcon m_iconAlgo; - QIcon m_iconWidget; - QIcon m_iconPlots; + QIcon m_iconActuator; + QIcon m_iconGrabber; + QIcon m_iconADDA; + QIcon m_iconRawIO; + QIcon m_iconFilter; + QIcon m_iconDataIO; + QIcon m_iconAlgo; + QIcon m_iconWidget; + QIcon m_iconPlots; - QColor m_bgColorItemsWithPythonRef; + QColor m_bgColorItemsWithPythonRef; - ito::AddInManager* m_pAIM; -}; + ito::AddInManager *m_pAIM; + }; //------------------------------------------------------------------------------------- /** constructor - * - * contructor, creating column headers for the tree view - */ +* +* contructor, creating column headers for the tree view +*/ PlugInModel::PlugInModel(ito::AddInManager* addInManager, QObject* parent /*= nullptr*/) : QAbstractItemModel(parent), d_ptr(new PlugInModelPrivate()) { @@ -92,18 +92,18 @@ PlugInModel::PlugInModel(ito::AddInManager* addInManager, QObject* parent /*= nu d->m_treeFixNodes[4] = typeDataIO | typeADDA; d->m_treeFixNodes[5] = typeDataIO | typeRawIO; - d->m_treeFixIndizes[0] = createIndex(0, 0, &(d->m_treeFixNodes[0])); // level 0 - d->m_treeFixIndizes[1] = createIndex(1, 0, &(d->m_treeFixNodes[1])); // level 0 - d->m_treeFixIndizes[2] = createIndex(2, 0, &(d->m_treeFixNodes[2])); // level 0 - d->m_treeFixIndizes[3] = createIndex(0, 0, &(d->m_treeFixNodes[3])); // level 1 - d->m_treeFixIndizes[4] = createIndex(1, 0, &(d->m_treeFixNodes[4])); // level 1 - d->m_treeFixIndizes[5] = createIndex(2, 0, &(d->m_treeFixNodes[5])); // level 1 + d->m_treeFixIndizes[0] = createIndex(0, 0, &(d->m_treeFixNodes[0])); //level 0 + d->m_treeFixIndizes[1] = createIndex(1, 0, &(d->m_treeFixNodes[1])); //level 0 + d->m_treeFixIndizes[2] = createIndex(2, 0, &(d->m_treeFixNodes[2])); //level 0 + d->m_treeFixIndizes[3] = createIndex(0, 0, &(d->m_treeFixNodes[3])); //level 1 + d->m_treeFixIndizes[4] = createIndex(1, 0, &(d->m_treeFixNodes[4])); //level 1 + d->m_treeFixIndizes[5] = createIndex(2, 0, &(d->m_treeFixNodes[5])); //level 1 } //------------------------------------------------------------------------------------- /** destructor - clean up, clear header and alignment list - * - */ +* +*/ PlugInModel::~PlugInModel() { Q_D(PlugInModel); @@ -119,7 +119,7 @@ QModelIndex PlugInModel::getTypeNode(const int type) const for (unsigned int i = 0; i < (sizeof(d->m_treeFixNodes) / sizeof(d->m_treeFixNodes[0])); i++) { - if (type == d->m_treeFixNodes[i]) + if(type == d->m_treeFixNodes[i]) { return d->m_treeFixIndizes[i]; } @@ -129,10 +129,10 @@ QModelIndex PlugInModel::getTypeNode(const int type) const //------------------------------------------------------------------------------------- /** - * @param - * @return - */ -Qt::ItemFlags PlugInModel::flags(const QModelIndex& index) const +* @param +* @return +*/ +Qt::ItemFlags PlugInModel::flags(const QModelIndex &index) const { Q_D(const PlugInModel); @@ -144,14 +144,14 @@ Qt::ItemFlags PlugInModel::flags(const QModelIndex& index) const tItemType itemType; size_t itemInternalData; - if (!getModelIndexInfo(index, itemType, itemInternalData)) + if (!getModelIndexInfo(index, itemType, itemInternalData) ) { return Qt::NoItemFlags; } - if (itemType == itemInstance) + if(itemType == itemInstance) { - ito::AddInBase* aib = (ito::AddInBase*)(itemInternalData); + ito::AddInBase *aib = (ito::AddInBase*)(itemInternalData); if (d->m_pAIM->isPluginInstanceDead(aib)) { @@ -174,11 +174,11 @@ Qt::ItemFlags PlugInModel::flags(const QModelIndex& index) const //------------------------------------------------------------------------------------- /** return parent element - * @param [in] index the element's index for which the parent should be returned - * @return the parent element. - * - */ -QModelIndex PlugInModel::parent(const QModelIndex& index) const +* @param [in] index the element's index for which the parent should be returned +* @return the parent element. +* +*/ +QModelIndex PlugInModel::parent(const QModelIndex &index) const { Q_D(const PlugInModel); @@ -190,115 +190,115 @@ QModelIndex PlugInModel::parent(const QModelIndex& index) const tItemType itemType; size_t itemInternalData; - if (!getModelIndexInfo(index, itemType, itemInternalData)) + if (!getModelIndexInfo(index, itemType, itemInternalData) ) { return QModelIndex(); } switch (itemType) { - case itemCatDataIO: - case itemCatActuator: + case itemCatDataIO: + case itemCatActuator: case itemCatAlgo: { - return QModelIndex(); - } - case itemSubCategoryDataIO_Grabber: - case itemSubCategoryDataIO_ADDA: + return QModelIndex(); + } + case itemSubCategoryDataIO_Grabber: + case itemSubCategoryDataIO_ADDA: case itemSubCategoryDataIO_RawIO: { - return d->m_treeFixIndizes[0]; - } + return d->m_treeFixIndizes[0]; + } case itemPlugin: { - ito::AddInInterfaceBase* aiib = (ito::AddInInterfaceBase*)(itemInternalData); - return getTypeNode(aiib->getType()); - /*for (int i = 0 ; i < sizeof(m_treeFixNodes) / sizeof(m_treeFixNodes[0]) ; i++) - { - if (aiib->getType() == m_treeFixNodes[i]) + ito::AddInInterfaceBase *aiib = (ito::AddInInterfaceBase*)(itemInternalData); + return getTypeNode(aiib->getType()); + /*for (int i = 0 ; i < sizeof(m_treeFixNodes) / sizeof(m_treeFixNodes[0]) ; i++) { - return m_treeFixIndizes[i]; - } - }*/ - } + if (aiib->getType() == m_treeFixNodes[i]) + { + return m_treeFixIndizes[i]; + } + }*/ + } case itemInstance: { - ito::AddInBase* aib = (ito::AddInBase*)(itemInternalData); - ito::AddInInterfaceBase* aiib = aib->getBasePlugin(); + ito::AddInBase *aib = (ito::AddInBase*)(itemInternalData); + ito::AddInInterfaceBase *aiib = aib->getBasePlugin(); - if (aiib->getType() & ito::typeActuator) - { - for (int i = 0; i < d->m_pAIM->getActList()->count(); i++) + if (aiib->getType() & ito::typeActuator) { - if (d->m_pAIM->getActList()->at(i) == (QObject*)aiib) + for (int i = 0; i < d->m_pAIM->getActList()->count(); i++) { - return createIndex(i, 0, (void*)aiib); + if (d->m_pAIM->getActList()->at(i) == (QObject*)aiib) + { + return createIndex(i, 0, (void*)aiib); + } } - } - return QModelIndex(); - } - else if (aiib->getType() & ito::typeDataIO) - { - int rowCounter = -1; - ito::AddInInterfaceBase* aiib2 = nullptr; - - for (int i = 0; i < d->m_pAIM->getDataIOList()->count(); i++) + return QModelIndex(); + } + else if (aiib->getType() & ito::typeDataIO) { - aiib2 = (ito::AddInInterfaceBase*)d->m_pAIM->getDataIOList()->at(i); + int rowCounter = -1; + ito::AddInInterfaceBase* aiib2 = nullptr; - if (aiib2->getType() == aiib->getType()) + for (int i = 0; i < d->m_pAIM->getDataIOList()->count(); i++) { - rowCounter++; - } + aiib2 = (ito::AddInInterfaceBase*)d->m_pAIM->getDataIOList()->at(i); - if (aiib2 == aiib) - { - return createIndex(rowCounter, 0, (void*)aiib); + if (aiib2->getType() == aiib->getType()) + { + rowCounter++; + } + + if (aiib2 == aiib) + { + return createIndex(rowCounter, 0, (void*)aiib); + } } - } - return QModelIndex(); - } - else - { - return QModelIndex(); + return QModelIndex(); + } + else + { + return QModelIndex(); + } } - } case itemFilter: { - ito::AddInAlgo::FilterDef* filter = (ito::AddInAlgo::FilterDef*)(itemInternalData); + ito::AddInAlgo::FilterDef* filter = (ito::AddInAlgo::FilterDef*)(itemInternalData); - for (int i = 0; i < d->m_pAIM->getAlgList()->count(); i++) - { - if (d->m_pAIM->getAlgList()->at(i) == (QObject*)filter->m_pBasePlugin) + for (int i = 0; i < d->m_pAIM->getAlgList()->count(); i++) { - return createIndex(i, 0, (void*)filter->m_pBasePlugin); + if (d->m_pAIM->getAlgList()->at(i) == (QObject*)filter->m_pBasePlugin) + { + return createIndex(i, 0, (void*)filter->m_pBasePlugin); + } } - } - return QModelIndex(); - } + return QModelIndex(); + } case itemWidget: { - ito::AddInAlgo::AlgoWidgetDef* widget = (ito::AddInAlgo::AlgoWidgetDef*)(itemInternalData); + ito::AddInAlgo::AlgoWidgetDef* widget = (ito::AddInAlgo::AlgoWidgetDef*)(itemInternalData); - for (int i = 0; i < d->m_pAIM->getAlgList()->count(); i++) - { - if (d->m_pAIM->getAlgList()->at(i) == (QObject*)widget->m_pBasePlugin) + for (int i = 0; i < d->m_pAIM->getAlgList()->count(); i++) { - return createIndex(i, 0, (void*)widget->m_pBasePlugin); + if (d->m_pAIM->getAlgList()->at(i) == (QObject*)widget->m_pBasePlugin) + { + return createIndex(i, 0, (void*)widget->m_pBasePlugin); + } } + return QModelIndex(); } - return QModelIndex(); - } default: { - return QModelIndex(); - } + return QModelIndex(); + } } } //------------------------------------------------------------------------------------- /** return number of rows - * @param [in] parent parent of current item +* @param [in] parent parent of current item * @return returns 0 for all child-child elements, the number of instances for child elements * (a plugin) and the number of plugins for a root element - */ -int PlugInModel::rowCount(const QModelIndex& parent) const +*/ +int PlugInModel::rowCount(const QModelIndex &parent) const { Q_D(const PlugInModel); @@ -306,7 +306,7 @@ int PlugInModel::rowCount(const QModelIndex& parent) const { return 3; } - else // parent valid + else //parent valid { tItemType parentType; size_t parentInternalData; @@ -319,63 +319,63 @@ int PlugInModel::rowCount(const QModelIndex& parent) const switch (parentType) { case itemCatDataIO: { - return 3; // three sub-categories of dataIO - } + return 3; //three sub-categories of dataIO + } case itemCatActuator: { - return d->m_pAIM->getActList()->count(); - } + return d->m_pAIM->getActList()->count(); + } case itemCatAlgo: { - return d->m_pAIM->getAlgList()->count(); - } - case itemSubCategoryDataIO_Grabber: - case itemSubCategoryDataIO_ADDA: + return d->m_pAIM->getAlgList()->count(); + } + case itemSubCategoryDataIO_Grabber: + case itemSubCategoryDataIO_ADDA: case itemSubCategoryDataIO_RawIO: { - int counter = 0; - const QList* dataIOs = d->m_pAIM->getDataIOList(); + int counter = 0; + const QList *dataIOs = d->m_pAIM->getDataIOList(); ito::AddInInterfaceBase* aiib = nullptr; - for (int i = 0; i < dataIOs->count(); i++) - { - aiib = qobject_cast(dataIOs->at(i)); - if ((size_t)aiib->getType() == parentInternalData /*subtype*/) + for (int i = 0; i < dataIOs->count(); i++) { - counter++; + aiib = qobject_cast(dataIOs->at(i)); + if ((size_t)aiib->getType() == parentInternalData /*subtype*/) + { + counter++; + } } + return counter; } - return counter; - } case itemPlugin: { - ito::AddInInterfaceBase* aiib = (ito::AddInInterfaceBase*)(parentInternalData); - if (aiib->getType() & ito::typeAlgo) - { - ito::AddInAlgo* aia = (ito::AddInAlgo*)(aiib->getInstList()[0]); - QHash filters; - QHash widgets; - aia->getFilterList(filters); - aia->getAlgoWidgetList(widgets); - return filters.size() + widgets.size(); - } - else - { - return aiib->getInstList().count(); + ito::AddInInterfaceBase *aiib = (ito::AddInInterfaceBase*)(parentInternalData); + if (aiib->getType() & ito::typeAlgo) + { + ito::AddInAlgo *aia = (ito::AddInAlgo*)(aiib->getInstList()[0]); + QHash filters; + QHash widgets; + aia->getFilterList(filters); + aia->getAlgoWidgetList(widgets); + return filters.size() + widgets.size(); + } + else + { + return aiib->getInstList().count(); + } } - } - /*case itemInstance: - case itemFilter: - case itemWidget: - case itemUnknown:*/ + /*case itemInstance: + case itemFilter: + case itemWidget: + case itemUnknown:*/ default: { - return 0; - } + return 0; + } } } } //------------------------------------------------------------------------------------- /** return column count - * @param [in] parent parent of current item - * @return 2 for child elements (instances) and the header size for root elements (plugins) - */ -int PlugInModel::columnCount(const QModelIndex& /*parent*/) const +* @param [in] parent parent of current item +* @return 2 for child elements (instances) and the header size for root elements (plugins) +*/ +int PlugInModel::columnCount(const QModelIndex & /*parent*/) const { Q_D(const PlugInModel); @@ -384,11 +384,11 @@ int PlugInModel::columnCount(const QModelIndex& /*parent*/) const //------------------------------------------------------------------------------------- /** return current index element - * @param [in] row row of current element - * @param [in] column column of current element - * @param [in] parent parent of current element - * @return QModelIndex - element at current index - * +* @param [in] row row of current element +* @param [in] column column of current element +* @param [in] parent parent of current element +* @return QModelIndex - element at current index +* * This method returns the QModelIndex for the current element. As the tree structure is not * cached it has to be "calculated" on each call. An invalid parent means were in the top most * "plane" of the tree, i.e. the plugin-plane. If the passed index is out of range we return an @@ -397,8 +397,8 @@ int PlugInModel::columnCount(const QModelIndex& /*parent*/) const * In that case it is first checked if the index for a child child element is queried. In that case * again an empty element is returned else the plugin for the selected instance is searched in the * plugin lists and an according index is created. - */ -QModelIndex PlugInModel::index(int row, int column, const QModelIndex& parent) const +*/ +QModelIndex PlugInModel::index(int row, int column, const QModelIndex &parent) const { Q_D(const PlugInModel); @@ -416,7 +416,7 @@ QModelIndex PlugInModel::index(int row, int column, const QModelIndex& parent) c return QModelIndex(); } - else // parent valid + else //parent valid { tItemType parentType; size_t parentInternalData; @@ -429,77 +429,77 @@ QModelIndex PlugInModel::index(int row, int column, const QModelIndex& parent) c switch (parentType) { case itemCatDataIO: { - return createIndex(row, column, (void*)(&d->m_treeFixNodes[row + 3])); - } + return createIndex(row, column, (void*)(&d->m_treeFixNodes[row + 3])); + } case itemCatActuator: { - return createIndex(row, column, (void*)d->m_pAIM->getActList()->at(row)); - } + return createIndex(row, column, (void*)d->m_pAIM->getActList()->at(row)); + } case itemCatAlgo: { - return createIndex(row, column, (void*)d->m_pAIM->getAlgList()->at(row)); - } - case itemSubCategoryDataIO_Grabber: - case itemSubCategoryDataIO_ADDA: + return createIndex(row, column, (void*)d->m_pAIM->getAlgList()->at(row)); + } + case itemSubCategoryDataIO_Grabber: + case itemSubCategoryDataIO_ADDA: case itemSubCategoryDataIO_RawIO: { - int counter = -1; - const QList* dataIOs = d->m_pAIM->getDataIOList(); + int counter = -1; + const QList *dataIOs = d->m_pAIM->getDataIOList(); ito::AddInInterfaceBase* aiib = nullptr; - for (int i = 0; i < dataIOs->count(); i++) - { - aiib = qobject_cast(dataIOs->at(i)); - if ((size_t)aiib->getType() == parentInternalData /*subtype*/) + for (int i = 0; i < dataIOs->count(); i++) { - counter++; - if (counter == row) + aiib = qobject_cast(dataIOs->at(i)); + if ((size_t)aiib->getType() == parentInternalData /*subtype*/) { - return createIndex(row, column, (void*)aiib); + counter++; + if (counter == row) + { + return createIndex(row, column, (void*)aiib); + } } } } - } case itemPlugin: { - ito::AddInInterfaceBase* aiib = (ito::AddInInterfaceBase*)(parentInternalData); - - if (aiib->getType() & ito::typeAlgo) - { - ito::AddInAlgo* aia = (ito::AddInAlgo*)(aiib->getInstList()[0]); - QHash filters; - QHash widgets; - aia->getFilterList(filters); - aia->getAlgoWidgetList(widgets); + ito::AddInInterfaceBase *aiib = (ito::AddInInterfaceBase*)(parentInternalData); - if (filters.count() > row) - { - return createIndex(row, column, (void*)filters.values()[row]); - } - else + if (aiib->getType() & ito::typeAlgo) { + ito::AddInAlgo *aia = (ito::AddInAlgo*)(aiib->getInstList()[0]); + QHash filters; + QHash widgets; + aia->getFilterList(filters); aia->getAlgoWidgetList(widgets); + + if (filters.count() > row) + { + return createIndex(row, column, (void*)filters.values()[row]); + } + else + { + aia->getAlgoWidgetList(widgets); // qDebug() << "AlgoWidget: r" << row << ", c:" << column << ", p:" << // (void*)widgets.values()[row - filters.count()]; - return createIndex(row, column, (void*)widgets.values()[row - filters.count()]); + return createIndex(row, column, (void*)widgets.values()[row - filters.count()]); + } + } + else + { + return createIndex(row, column, (void*)aiib->getInstList()[row]); } } - else - { - return createIndex(row, column, (void*)aiib->getInstList()[row]); - } - } - /*case itemInstance: - case itemFilter: - case itemWidget: - case itemUnknown:*/ + /*case itemInstance: + case itemFilter: + case itemWidget: + case itemUnknown:*/ default: { - return QModelIndex(); - } + return QModelIndex(); + } } } } //------------------------------------------------------------------------------------- /** return the header / captions for the tree view model - * - */ +* +*/ QVariant PlugInModel::headerData(int section, Qt::Orientation orientation, int role) const { Q_D(const PlugInModel); @@ -525,7 +525,7 @@ QColor PlugInModel::backgroundColorInstancesWithPythonRef() const } //------------------------------------------------------------------------------------- -void PlugInModel::setBackgroundColorInstancesWithPythonRef(const QColor& bgColor) +void PlugInModel::setBackgroundColorInstancesWithPythonRef(const QColor &bgColor) { Q_D(PlugInModel); @@ -539,13 +539,13 @@ void PlugInModel::setBackgroundColorInstancesWithPythonRef(const QColor& bgColor //------------------------------------------------------------------------------------- /** - * @param index - * @param type - * @param internalData - * @return bool - * - * - */ +* @param index +* @param type +* @param internalData +* @return bool +* +* +*/ bool PlugInModel::getModelIndexInfo( const QModelIndex& index, tItemType& type, size_t& internalData) const { @@ -559,75 +559,75 @@ bool PlugInModel::getModelIndexInfo( return false; } - // table of type vs. internalData - // itemUnknown -> 0 - // itemCatDataIO -> ito::typeDataIO - // itemCatActuator -> ito::typeActuator - // itemCatAlgo -> ito::typeAlgo + //table of type vs. internalData + //itemUnknown -> 0 + //itemCatDataIO -> ito::typeDataIO + //itemCatActuator -> ito::typeActuator + //itemCatAlgo -> ito::typeAlgo // itemSubCategoryDataIO_... -> Content of m_treeFixNodes[3,4,5] (OR-combination of // ito::typeDataIO and sub-type) itemPlugin -> Pointer to corresponding // AddInInterfaceBase itemInstance -> Pointer to corresponding AddInBase itemFilter -> // Pointer to corresponding FilterDef itemWidget -> Pointer to corresponding // AlgoWidgetDef - // check if item is of type itemCategory or itemSubCategory - const int* ptr1 = &d->m_treeFixNodes[0]; - void* internalPtr = index.internalPointer(); + //check if item is of type itemCategory or itemSubCategory + const int *ptr1 = &d->m_treeFixNodes[0]; + void *internalPtr = index.internalPointer(); QObject* obj = nullptr; - // int rowIndex; +// int rowIndex; if (internalPtr >= ptr1 && internalPtr <= (ptr1 + sizeof(d->m_treeFixNodes))) { - switch (*(int*)index.internalPointer()) + switch (* (int*)index.internalPointer()) { case typeAlgo: { - type = itemCatAlgo; - internalData = ito::typeAlgo; - break; - } + type = itemCatAlgo; + internalData = ito::typeAlgo; + break; + } case typeDataIO: { - type = itemCatDataIO; - internalData = ito::typeDataIO; - break; - } + type = itemCatDataIO; + internalData = ito::typeDataIO; + break; + } case typeActuator: { - type = itemCatActuator; - internalData = ito::typeActuator; - break; - } + type = itemCatActuator; + internalData = ito::typeActuator; + break; + } case typeDataIO | typeGrabber: { - // sub category of dataIO - type = itemSubCategoryDataIO_Grabber; - internalData = *(int*)index.internalPointer(); - break; - } + //sub category of dataIO + type = itemSubCategoryDataIO_Grabber; + internalData = * (int*)index.internalPointer(); + break; + } case typeDataIO | typeADDA: { - // sub category of dataIO - type = itemSubCategoryDataIO_ADDA; - internalData = *(int*)index.internalPointer(); - break; - } + //sub category of dataIO + type = itemSubCategoryDataIO_ADDA; + internalData = * (int*)index.internalPointer(); + break; + } case typeDataIO | typeRawIO: { - // sub category of dataIO - type = itemSubCategoryDataIO_RawIO; - internalData = *(int*)index.internalPointer(); - break; - } + //sub category of dataIO + type = itemSubCategoryDataIO_RawIO; + internalData = * (int*)index.internalPointer(); + break; + } default: { - return false; - } + return false; + } } return true; } else { - // check if item is a filter - // check type of element - const QHash* filters = d->m_pAIM->getFilterList(); - QHash::const_iterator i = filters->constBegin(); + //check if item is a filter + //check type of element + const QHash *filters = d->m_pAIM->getFilterList(); + QHash::const_iterator i = filters->constBegin(); while (i != filters->constEnd()) { - // check if index corresponds to this filter + //check if index corresponds to this filter if ((void*)i.value() == internalPtr) { type = itemFilter; @@ -637,13 +637,13 @@ bool PlugInModel::getModelIndexInfo( ++i; } - // check if item is a widget + //check if item is a widget const QHash* widgets = d->m_pAIM->getAlgoWidgetList(); - QHash::const_iterator j = widgets->constBegin(); + QHash::const_iterator j = widgets->constBegin(); while (j != widgets->constEnd()) { - // check if index corresponds to this widget + //check if index corresponds to this widget if ((void*)j.value() == internalPtr) { type = itemWidget; @@ -657,18 +657,18 @@ bool PlugInModel::getModelIndexInfo( // instance of a plugin obj = (QObject*)internalPtr; - ito::AddInInterfaceBase* aiib = qobject_cast(obj); - if (aiib) // it is a plugin + ito::AddInInterfaceBase *aiib = qobject_cast(obj); + if (aiib) //it is a plugin { type = itemPlugin; internalData = (size_t)aiib; return true; } - if (obj->inherits("ito::AddInBase")) + if(obj->inherits("ito::AddInBase")) { - ito::AddInBase* aib = reinterpret_cast(obj); - if (aib) // it is an instance + ito::AddInBase *aib = reinterpret_cast(obj); + if (aib) //it is an instance { type = itemInstance; internalData = (size_t)aib; @@ -682,15 +682,15 @@ bool PlugInModel::getModelIndexInfo( //------------------------------------------------------------------------------------- /** - * @param index - * @param name - * @param itemType - * @param role - * @param icon - * @return QVariant - * - * - */ +* @param index +* @param name +* @param itemType +* @param role +* @param icon +* @return QVariant +* +* +*/ QVariant PlugInModel::getFixedNodeInfo( const QModelIndex& index, const QVariant& name, @@ -744,31 +744,31 @@ QVariant PlugInModel::getFixedNodeInfo( return QVariant(); } } - else if (role == Qt::UserRole + 1) // returns type (OR-combination) + else if (role == Qt::UserRole + 1) //returns type (OR-combination) { - switch (itemType) + switch(itemType) { case itemCatDataIO: { - return ito::typeDataIO; - } + return ito::typeDataIO; + } case itemCatActuator: { - return ito::typeActuator; - } + return ito::typeActuator; + } case itemCatAlgo: { - return ito::typeAlgo; - } + return ito::typeAlgo; + } case itemSubCategoryDataIO_Grabber: { - return ito::typeDataIO | ito::typeGrabber; - } + return ito::typeDataIO | ito::typeGrabber; + } case itemSubCategoryDataIO_ADDA: { - return ito::typeDataIO | ito::typeADDA; - } + return ito::typeDataIO | ito::typeADDA; + } case itemSubCategoryDataIO_RawIO: { - return ito::typeDataIO | ito::typeRawIO; - } + return ito::typeDataIO | ito::typeRawIO; + } default: { - return QVariant(); - } + return QVariant(); + } } return itemType; } @@ -788,87 +788,87 @@ QVariant PlugInModel::getFixedNodeInfo( //------------------------------------------------------------------------------------- /** - * @param index - * @param role - * @return QVariant - * - * - */ -QVariant PlugInModel::getPluginNodeInfo(const QModelIndex& index, const int& role) const +* @param index +* @param role +* @return QVariant +* +* +*/ +QVariant PlugInModel::getPluginNodeInfo(const QModelIndex &index, const int &role) const { Q_D(const PlugInModel); - ito::AddInInterfaceBase* aib = (ito::AddInInterfaceBase*)index.internalPointer(); + ito::AddInInterfaceBase *aib = (ito::AddInInterfaceBase *)index.internalPointer(); if (role == Qt::DisplayRole) { switch (index.column()) { - case 0: // name - { - return aib->objectName(); - } - case 1: // type - switch (aib->getType()) + case 0: //name { - case typeActuator: { - return tr("Actuator"); + return aib->objectName(); } + case 1: //type + switch (aib->getType()) + { + case typeActuator: { + return tr("Actuator"); + } case typeDataIO | typeGrabber: { - return tr("Grabber"); - } + return tr("Grabber"); + } case typeDataIO | typeADDA: { - return tr("ADDA"); - } + return tr("ADDA"); + } case typeDataIO | typeRawIO: { - return tr("Raw IO"); - } + return tr("Raw IO"); + } case typeAlgo: { - return tr("Algorithm"); + return tr("Algorithm"); + } + default: + return QVariant(); + } + case 2: //version + { + SemVerVersion version = SemVerVersion::fromInt(aib->getVersion()); + return version.toString(); } - default: - return QVariant(); + case 3: //filename + { + QFileInfo filename; + filename = QFileInfo(aib->getFilename()); + return filename.fileName(); } - case 2: // version - { - SemVerVersion version = SemVerVersion::fromInt(aib->getVersion()); - return version.toString(); - } - case 3: // filename - { - QFileInfo filename; - filename = QFileInfo(aib->getFilename()); - return filename.fileName(); - } - case 4: // autor - { - return aib->getAuthor(); - } - case 5: // minversion - { - SemVerVersion version = SemVerVersion::fromInt(aib->getMinItomVer()); - if (version.toInt() != MINVERSION) + case 4: //autor { - return version.toString(); + return aib->getAuthor(); } - return QString("-"); - } - case 6: // maxversion - { - SemVerVersion version = SemVerVersion::fromInt(aib->getMaxItomVer()); - if (version.toInt() != MAXVERSION) + case 5: //minversion { - return version.toString(); + SemVerVersion version = SemVerVersion::fromInt(aib->getMinItomVer()); + if (version.toInt() != MINVERSION) + { + return version.toString(); + } + return QString("-"); + } + case 6: //maxversion + { + SemVerVersion version = SemVerVersion::fromInt(aib->getMaxItomVer()); + if (version.toInt() != MAXVERSION) + { + return version.toString(); + } + return QString("-"); + } + case 7: //description + { + return aib->getDescription(); } - return QString("-"); - } - case 7: // description - { - return aib->getDescription(); - } default: { - return QVariant(); - } + return QVariant(); + } } } else if (role == Qt::DecorationRole) @@ -877,23 +877,23 @@ QVariant PlugInModel::getPluginNodeInfo(const QModelIndex& index, const int& rol { switch (aib->getType()) { - case typeActuator: - return d->m_iconActuator; + case typeActuator: + return d->m_iconActuator; break; - case typeDataIO | typeGrabber: - return d->m_iconGrabber; + case typeDataIO | typeGrabber: + return d->m_iconGrabber; break; - case typeDataIO | typeADDA: - return d->m_iconADDA; + case typeDataIO | typeADDA: + return d->m_iconADDA; break; - case typeDataIO | typeRawIO: - return d->m_iconRawIO; + case typeDataIO | typeRawIO: + return d->m_iconRawIO; break; - case typeAlgo: - return d->m_iconAlgo; + case typeAlgo: + return d->m_iconAlgo; break; - default: - return QVariant(); + default: + return QVariant(); } } else @@ -903,16 +903,16 @@ QVariant PlugInModel::getPluginNodeInfo(const QModelIndex& index, const int& rol } else if (role == Qt::ToolTipRole) { - switch (index.column()) + switch(index.column()) { - case 0: // name - return aib->objectName(); - case 3: // filename - return aib->getFilename(); - case 7: // description - return aib->getDescription(); - default: - return QVariant(); + case 0: //name + return aib->objectName(); + case 3: //filename + return aib->getFilename(); + case 7: //description + return aib->getDescription(); + default: + return QVariant(); } } else if (role == Qt::TextAlignmentRole) @@ -936,7 +936,7 @@ QVariant PlugInModel::getPluginNodeInfo(const QModelIndex& index, const int& rol // returns true if item is a category or sub-category, else false return false; } - else if (role == Qt::UserRole + 3) // returns tItemType + else if (role == Qt::UserRole + 3) //returns tItemType { return itemPlugin; } @@ -946,38 +946,38 @@ QVariant PlugInModel::getPluginNodeInfo(const QModelIndex& index, const int& rol //------------------------------------------------------------------------------------- /** - * @param index - * @param role - * @return QVariant - * - * - */ -QVariant PlugInModel::getInstanceNodeInfo(const QModelIndex& index, const int& role) const +* @param index +* @param role +* @return QVariant +* +* +*/ +QVariant PlugInModel::getInstanceNodeInfo(const QModelIndex &index, const int &role) const { Q_D(const PlugInModel); - ito::AddInBase* ai = (ito::AddInBase*)index.internalPointer(); + ito::AddInBase *ai = (ito::AddInBase *)index.internalPointer(); if (role == Qt::DisplayRole) { switch (index.column()) { - case 0: // name - { - QString ident = ai->getIdentifier(); - if (ident.size() > 0) + case 0: //name { - return ident; + QString ident = ai->getIdentifier(); + if(ident.size() > 0) + { + return ident; + } + return QString("ID: %1").arg(ai->getID()); + } + case 7: //description + { + //return aib->getDescription(); } - return QString("ID: %1").arg(ai->getID()); - } - case 7: // description - { - // return aib->getDescription(); - } default: { - return QVariant(); - } + return QVariant(); + } } } else if (role == Qt::ToolTipRole) @@ -986,7 +986,7 @@ QVariant PlugInModel::getInstanceNodeInfo(const QModelIndex& index, const int& r { QString ident = ai->getIdentifier(); - if (ident.size() > 0) + if(ident.size() > 0) { return ident; } @@ -1019,13 +1019,13 @@ QVariant PlugInModel::getInstanceNodeInfo(const QModelIndex& index, const int& r // returns true if item is a category or sub-category, else false return false; } - else if (role == Qt::UserRole + 3) // returns tItemType + else if (role == Qt::UserRole + 3) //returns tItemType { return itemInstance; } else if (role == Qt::BackgroundRole) { - ito::AddInBase* ais = (ito::AddInBase*)index.internalPointer(); + ito::AddInBase *ais = (ito::AddInBase *)index.internalPointer(); if (ais) { @@ -1045,19 +1045,19 @@ QVariant PlugInModel::getInstanceNodeInfo(const QModelIndex& index, const int& r //------------------------------------------------------------------------------------- /** - * @param index - * @param role - * @param filterNotWidget - * @return QVariant - * - * - */ +* @param index +* @param role +* @param filterNotWidget +* @return QVariant +* +* +*/ QVariant PlugInModel::getFilterOrWidgetNodeInfo( const QModelIndex& index, const int& role, bool filterNotWidget) const { Q_D(const PlugInModel); - QString* name; - QString* description; + QString *name; + QString *description; if (filterNotWidget) { @@ -1078,35 +1078,35 @@ QVariant PlugInModel::getFilterOrWidgetNodeInfo( { switch (index.column()) { - case 0: // name - { - return *name; - } - case 1: // type - { - if (filterNotWidget) + case 0: //name { - return tr("Filter"); + return *name; } - return tr("Widget"); - } - case 7: // description - { - int firstLineBreak = description->indexOf('\n'); - QString shortDesc; - if (firstLineBreak > 0) + case 1: //type { - shortDesc = description->left(firstLineBreak); + if (filterNotWidget) + { + return tr("Filter"); + } + return tr("Widget"); } - else + case 7: //description { - shortDesc = *description; + int firstLineBreak = description->indexOf('\n'); + QString shortDesc; + if (firstLineBreak > 0) + { + shortDesc = description->left(firstLineBreak); + } + else + { + shortDesc = *description; + } + return shortDesc; } - return shortDesc; - } default: { - return QVariant(); - } + return QVariant(); + } } } else if (role == Qt::DecorationRole) @@ -1126,53 +1126,53 @@ QVariant PlugInModel::getFilterOrWidgetNodeInfo( } else if (role == Qt::ToolTipRole) { - switch (index.column()) - { - case 0: // name - case 7: // description + switch(index.column()) { - QString text = *name; - if (description->size() > 0) + case 0: //name + case 7: //description { - QString lb; - lb.fill('-', text.length() * 1.5); + QString text = *name; + if (description->size() > 0) + { + QString lb; + lb.fill('-', text.length() * 1.5); - QStringList desc = description->split('\n'); - text += "\n" + lb; + QStringList desc = description->split('\n'); + text += "\n" + lb; - foreach (const QString& s, desc) - { - if (s.size() < 200) + foreach(const QString &s, desc) { - text += "\n" + s; - } - else - { - QStringList words = s.split(" "); - int curLen = 0; - text += "\n"; - foreach (const QString& w, words) + if (s.size() < 200) { - curLen += w.size(); - if (curLen < 200) - { - text += w + " "; - curLen++; - } - else + text += "\n" + s; + } + else + { + QStringList words = s.split(" "); + int curLen = 0; + text += "\n"; + foreach (const QString &w, words) { - curLen = w.size() + 1; - text += "\n" + w + " "; + curLen += w.size(); + if (curLen < 200) + { + text += w + " "; + curLen++; + } + else + { + curLen = w.size()+1; + text += "\n" + w + " "; + } } } } } + return text; } - return text; - } default: { - return QVariant(); - } + return QVariant(); + } } } else if (role == Qt::TextAlignmentRole) @@ -1186,7 +1186,7 @@ QVariant PlugInModel::getFilterOrWidgetNodeInfo( return QVariant(); } } - else if (role == Qt::UserRole + 1) // returns type (OR-combination) + else if (role == Qt::UserRole + 1) //returns type (OR-combination) { return ito::typeAlgo; } @@ -1195,9 +1195,9 @@ QVariant PlugInModel::getFilterOrWidgetNodeInfo( { return false; } - else if (role == Qt::UserRole + 3) // returns tItemType + else if (role == Qt::UserRole + 3) //returns tItemType { - if (filterNotWidget) + if(filterNotWidget) { return itemFilter; } @@ -1212,17 +1212,17 @@ QVariant PlugInModel::getFilterOrWidgetNodeInfo( //------------------------------------------------------------------------------------- /** return data elements for a given row - * @param [in] index index for which the data elements should be delivered - * @param [in] role the current role of the model +* @param [in] index index for which the data elements should be delivered +* @param [in] role the current role of the model * @return data of the selected element, depending on the element's row and column (passed in * index.row and index.column) - * +* * This method is actually used to fill the tree view. It returns the data for the selected * element, depending as well on the column of the selected element, passed in index.column. The * method here is divded into two parts. The first one handels requests for root elements (plugins) * the second one is used for child elements (instances of plugins). - */ -QVariant PlugInModel::data(const QModelIndex& index, int role) const +*/ +QVariant PlugInModel::data(const QModelIndex &index, int role) const { Q_D(const PlugInModel); @@ -1237,72 +1237,72 @@ QVariant PlugInModel::data(const QModelIndex& index, int role) const switch (itemType) { case itemCatDataIO: { - return getFixedNodeInfo(index, tr("DataIO"), itemType, role, d->m_iconDataIO); - } + return getFixedNodeInfo(index, tr("DataIO"), itemType, role, d->m_iconDataIO); + } case itemCatActuator: { - return getFixedNodeInfo(index, tr("Actuator"), itemType, role, d->m_iconActuator); - } + return getFixedNodeInfo(index, tr("Actuator"), itemType, role, d->m_iconActuator); + } case itemCatAlgo: { - return getFixedNodeInfo(index, tr("Algorithm"), itemType, role, d->m_iconAlgo); - } + return getFixedNodeInfo(index, tr("Algorithm"), itemType, role, d->m_iconAlgo); + } case itemSubCategoryDataIO_Grabber: { - return getFixedNodeInfo(index, tr("Grabber"), itemType, role, d->m_iconGrabber); - } + return getFixedNodeInfo(index, tr("Grabber"), itemType, role, d->m_iconGrabber); + } case itemSubCategoryDataIO_ADDA: { - return getFixedNodeInfo(index, tr("ADDA"), itemType, role, d->m_iconADDA); - } + return getFixedNodeInfo(index, tr("ADDA"), itemType, role, d->m_iconADDA); + } case itemSubCategoryDataIO_RawIO: { - return getFixedNodeInfo(index, tr("Raw IO"), itemType, role, d->m_iconRawIO); - } + return getFixedNodeInfo(index, tr("Raw IO"), itemType, role, d->m_iconRawIO); + } case itemPlugin: { - ito::AddInInterfaceBase* aiib = (ito::AddInInterfaceBase*)(itemInternalData); + ito::AddInInterfaceBase *aiib = (ito::AddInInterfaceBase*)(itemInternalData); - for (int i = 0; i < sizeof(d->m_treeFixNodes) / sizeof(d->m_treeFixNodes[0]); i++) - { - if (aiib->getType() == d->m_treeFixNodes[i]) + for (int i = 0; i < sizeof(d->m_treeFixNodes) / sizeof(d->m_treeFixNodes[0]); i++) { - return getPluginNodeInfo(index, role); + if (aiib->getType() == d->m_treeFixNodes[i]) + { + return getPluginNodeInfo(index, role); + } } + break; } - break; - } case itemInstance: { - ito::AddInBase* aib = (ito::AddInBase*)(itemInternalData); - ito::AddInInterfaceBase* aiib = aib->getBasePlugin(); - - if (aiib->getType() & ito::typeActuator) - { - int count = d->m_pAIM->getActList()->count(); + ito::AddInBase *aib = (ito::AddInBase*)(itemInternalData); + ito::AddInInterfaceBase *aiib = aib->getBasePlugin(); - for (int i = 0; i < count; i++) + if (aiib->getType() & ito::typeActuator) { - if (d->m_pAIM->getActList()->at(i) == (QObject*)aiib) + int count = d->m_pAIM->getActList()->count(); + + for (int i = 0 ; i < count ; i++) { - return getInstanceNodeInfo(index, role); + if (d->m_pAIM->getActList()->at(i) == (QObject*)aiib) + { + return getInstanceNodeInfo(index, role); + } } } - } - else if (aiib->getType() & ito::typeDataIO) - { - int count = d->m_pAIM->getDataIOList()->count(); - - for (int i = 0; i < count; i++) + else if(aiib->getType() & ito::typeDataIO) { - if (d->m_pAIM->getDataIOList()->at(i) == (QObject*)aiib) + int count = d->m_pAIM->getDataIOList()->count(); + + for (int i = 0; i < count; i++) { - return getInstanceNodeInfo(index, role); + if (d->m_pAIM->getDataIOList()->at(i) == (QObject*)aiib) + { + return getInstanceNodeInfo(index, role); + } } } + break; } - break; - } case itemFilter: { - return getFilterOrWidgetNodeInfo(index, role, true); - } + return getFilterOrWidgetNodeInfo(index, role, true); + } case itemWidget: { - return getFilterOrWidgetNodeInfo(index, role, false); - } - // default: + return getFilterOrWidgetNodeInfo(index, role, false); + } + //default: //{ // return QVariant(); //} @@ -1313,12 +1313,12 @@ QVariant PlugInModel::data(const QModelIndex& index, int role) const //------------------------------------------------------------------------------------- /** - * @param ai - * @return QModelIndex - * - * - */ -QModelIndex PlugInModel::getIndexByAddIn(ito::AddInBase* ai) const +* @param ai +* @return QModelIndex +* +* +*/ +QModelIndex PlugInModel::getIndexByAddIn(ito::AddInBase *ai) const { if (ai == nullptr) { @@ -1327,7 +1327,7 @@ QModelIndex PlugInModel::getIndexByAddIn(ito::AddInBase* ai) const QModelIndex baseIndex = getIndexByAddInInterface(ai->getBasePlugin()); - if (baseIndex.isValid() == false) + if(baseIndex.isValid() == false) { return QModelIndex(); } @@ -1349,12 +1349,12 @@ QModelIndex PlugInModel::getIndexByAddIn(ito::AddInBase* ai) const //------------------------------------------------------------------------------------- /** - * @param aib - * @return QModelIndex - * - * - */ -QModelIndex PlugInModel::getIndexByAddInInterface(AddInInterfaceBase* aib) const +* @param aib +* @return QModelIndex +* +* +*/ +QModelIndex PlugInModel::getIndexByAddInInterface(AddInInterfaceBase *aib) const { Q_D(const PlugInModel); @@ -1365,79 +1365,79 @@ QModelIndex PlugInModel::getIndexByAddInInterface(AddInInterfaceBase* aib) const switch (aib->getType()) { case ito::typeActuator: { - list = d->m_pAIM->getActList(); + list = d->m_pAIM->getActList(); - for (int i = 0; i < list->count(); i++) - { - if (qobject_cast(list->at(i)) == aib) - { - return index(i, 0, d->m_treeFixIndizes[1]); + for (int i = 0; i < list->count(); i++) + { + if (qobject_cast(list->at(i)) == aib) + { + return index(i, 0, d->m_treeFixIndizes[1]); + } + } } - } - } - break; + break; case ito::typeAlgo: { - list = d->m_pAIM->getAlgList(); + list = d->m_pAIM->getAlgList(); - for (int i = 0; i < list->count(); i++) - { - if (qobject_cast(list->at(i)) == aib) - { - return index(i, 0, d->m_treeFixIndizes[2]); + for (int i = 0; i < list->count(); i++) + { + if (qobject_cast(list->at(i)) == aib) + { + return index(i, 0, d->m_treeFixIndizes[2]); + } + } } - } - } - break; - case ito::typeDataIO | ito::typeGrabber: - case ito::typeDataIO | ito::typeRawIO: + break; + case ito::typeDataIO | ito::typeGrabber: + case ito::typeDataIO | ito::typeRawIO: case ito::typeDataIO | ito::typeADDA: { - list = d->m_pAIM->getDataIOList(); - int countGrabber = 0; - int countRawIO = 0; - int countADDA = 0; + list = d->m_pAIM->getDataIOList(); + int countGrabber = 0; + int countRawIO = 0; + int countADDA = 0; ito::AddInInterfaceBase* aib2 = nullptr; - for (int i = 0; i < list->count(); i++) - { - aib2 = qobject_cast(list->at(i)); - - if (aib2 == aib) - { - if (aib->getType() & ito::typeGrabber) - { - return index(countGrabber, 0, d->m_treeFixIndizes[3]); - } - else if (aib->getType() & ito::typeRawIO) + for (int i = 0; i < list->count(); i++) { - return index(countRawIO, 0, d->m_treeFixIndizes[5]); - } - else if (aib->getType() & ito::typeADDA) - { - return index(countADDA, 0, d->m_treeFixIndizes[4]); - } - else - { - return QModelIndex(); - } - } + aib2 = qobject_cast(list->at(i)); - if (aib2->getType() & ito::typeGrabber) - { - countGrabber++; - } + if (aib2 == aib) + { + if (aib->getType() & ito::typeGrabber) + { + return index(countGrabber, 0, d->m_treeFixIndizes[3]); + } + else if (aib->getType() & ito::typeRawIO) + { + return index(countRawIO, 0, d->m_treeFixIndizes[5]); + } + else if (aib->getType() & ito::typeADDA) + { + return index(countADDA, 0, d->m_treeFixIndizes[4]); + } + else + { + return QModelIndex(); + } + } - if (aib2->getType() & ito::typeRawIO) - { - countRawIO++; - } + if (aib2->getType() & ito::typeGrabber) + { + countGrabber++; + } - if (aib2->getType() & ito::typeADDA) - { - countADDA++; + if (aib2->getType() & ito::typeRawIO) + { + countRawIO++; + } + + if (aib2->getType() & ito::typeADDA) + { + countADDA++; + } + } } - } - } - break; + break; } } @@ -1446,19 +1446,19 @@ QModelIndex PlugInModel::getIndexByAddInInterface(AddInInterfaceBase* aib) const //------------------------------------------------------------------------------------- /** - * @param itemType - * @param internalData - * @return bool - * - * - */ -bool PlugInModel::getIsAlgoPlugIn(tItemType& itemType, size_t& internalData) const +* @param itemType +* @param internalData +* @return bool +* +* +*/ +bool PlugInModel::getIsAlgoPlugIn(tItemType &itemType, size_t &internalData) const { Q_D(const PlugInModel); - if (itemType == PlugInModel::itemPlugin) + if(itemType == PlugInModel::itemPlugin) { - ito::AddInInterfaceBase* aiib = (ito::AddInInterfaceBase*)(internalData); + ito::AddInInterfaceBase *aiib = (ito::AddInInterfaceBase*)(internalData); return (aiib->getType() == d->m_treeFixNodes[2]); } @@ -1467,19 +1467,18 @@ bool PlugInModel::getIsAlgoPlugIn(tItemType& itemType, size_t& internalData) con //------------------------------------------------------------------------------------- /** - * @param itemType - * @param internalData - * @return bool - * - * - */ -bool PlugInModel::getIsGrabberInstance(tItemType& itemType, size_t& internalData) const +* @param itemType +* @param internalData +* @return bool +* +* +*/ +bool PlugInModel::getIsGrabberInstance(tItemType &itemType, size_t &internalData) const { - if (itemType == PlugInModel::itemInstance) // internalData can be casted to AddInBase + if(itemType == PlugInModel::itemInstance) //internalData can be casted to AddInBase { - ito::AddInBase* aib = (ito::AddInBase*)(internalData); - - if (aib->inherits("ito::AddInGrabber")) + ito::AddInBase *aib = (ito::AddInBase*)(internalData); + if(aib->inherits("ito::AbstractAddInGrabber")) { return true; } @@ -1489,12 +1488,12 @@ bool PlugInModel::getIsGrabberInstance(tItemType& itemType, size_t& internalData //------------------------------------------------------------------------------------- /** - * @param addInInterface - * @param beginOperation - * @return bool - * - * - */ +* @param addInInterface +* @param beginOperation +* @return bool +* +* +*/ bool PlugInModel::insertInstance(ito::AddInInterfaceBase* addInInterface, bool beginOperation) { if (beginOperation) @@ -1504,7 +1503,7 @@ bool PlugInModel::insertInstance(ito::AddInInterfaceBase* addInInterface, bool b if (baseIndex.isValid()) { int rows = rowCount(baseIndex); - beginInsertRows(baseIndex, rows, rows); // append element + beginInsertRows(baseIndex, rows, rows); //append element return true; } @@ -1519,14 +1518,14 @@ bool PlugInModel::insertInstance(ito::AddInInterfaceBase* addInInterface, bool b //------------------------------------------------------------------------------------- /** - * @param addInInterface - * @param addInInstance - * @param beginOperation - * @return bool - * - * - */ -bool PlugInModel::deleteInstance(ito::AddInBase* addInInstance, const bool beginOperation) +* @param addInInterface +* @param addInInstance +* @param beginOperation +* @return bool +* +* +*/ +bool PlugInModel::deleteInstance(ito::AddInBase *addInInstance, const bool beginOperation) { if (beginOperation) { @@ -1551,11 +1550,11 @@ bool PlugInModel::deleteInstance(ito::AddInBase* addInInstance, const bool begin //------------------------------------------------------------------------------------- /** - * @param beginOperation - * @return bool - * - * - */ +* @param beginOperation +* @return bool +* +* +*/ bool PlugInModel::resetModel(bool beginOperation) { if (beginOperation) @@ -1571,7 +1570,7 @@ bool PlugInModel::resetModel(bool beginOperation) } //------------------------------------------------------------------------------------- -QString PlugInModel::getInitCommand(const QModelIndex& item) const +QString PlugInModel::getInitCommand(const QModelIndex &item) const { Q_D(const PlugInModel); @@ -1580,12 +1579,12 @@ QString PlugInModel::getInitCommand(const QModelIndex& item) const getModelIndexInfo(item, type, internalData); QString command; - if (type & itemPlugin) // check if item is a plugin + if (type & itemPlugin) //check if item is a plugin { - ito::AddInInterfaceBase* aiib = (ito::AddInInterfaceBase*)(internalData); + ito::AddInInterfaceBase *aiib = (ito::AddInInterfaceBase*)(internalData); int aiibType = aiib->getType(); - if (aiibType & d->m_treeFixNodes[0]) // dataIO + if (aiibType & d->m_treeFixNodes[0]) //dataIO { QVector* mandParam(aiib->getInitParamsMand()); QStringList listParam; @@ -1605,7 +1604,7 @@ QString PlugInModel::getInitCommand(const QModelIndex& item) const .toLatin1() .data(); } - else if (aiibType & d->m_treeFixNodes[1]) // actuator + else if (aiibType & d->m_treeFixNodes[1]) //actuator { QVector* mandParam(aiib->getInitParamsMand()); QStringList listParam; @@ -1626,28 +1625,28 @@ QString PlugInModel::getInitCommand(const QModelIndex& item) const .data(); } } - else if (type & itemFilter) + else if(type & itemFilter) { - ito::AddInAlgo::FilterDef* fd = (AddInAlgo::FilterDef*)(internalData); + ito::AddInAlgo::FilterDef *fd = (AddInAlgo::FilterDef*)(internalData); - QStringList listParam; - AddInAlgo::t_filterParam paramFunc = fd->m_paramFunc; - QVector mandParams; - QVector optParams; - QVector outParams; - paramFunc(&mandParams, &optParams, &outParams); + QStringList listParam; + AddInAlgo::t_filterParam paramFunc = fd->m_paramFunc; + QVector mandParams; + QVector optParams; + QVector outParams; + paramFunc(&mandParams, &optParams, &outParams); foreach (const auto& item, mandParams) - { - listParam.append(item.getName()); - } + { + listParam.append(item.getName()); + } command = QString("algorithms.%1(%2)").arg(fd->m_name, listParam.join(", ")); } else if (type & itemWidget) { QStringList listParam; - AddInAlgo::AlgoWidgetDef* aw = (AddInAlgo::AlgoWidgetDef*)(internalData); + AddInAlgo::AlgoWidgetDef *aw = (AddInAlgo::AlgoWidgetDef*)(internalData); AddInAlgo::t_filterParam paramFunc = aw->m_paramFunc; QVector mandParams; QVector optParams; @@ -1672,9 +1671,9 @@ QString PlugInModel::getInitCommand(const QModelIndex& item) const } //------------------------------------------------------------------------------------- -QMimeData* PlugInModel::mimeData(const QModelIndexList& indexes) const +QMimeData* PlugInModel::mimeData(const QModelIndexList &indexes) const { - QMimeData* mimeData = QAbstractItemModel::mimeData(indexes); + QMimeData *mimeData = QAbstractItemModel::mimeData(indexes); QStringList texts; foreach (const QModelIndex& item, indexes) @@ -1690,4 +1689,4 @@ QMimeData* PlugInModel::mimeData(const QModelIndexList& indexes) const mimeData->setData("text/plain", texts.join("\n").toUtf8()); return mimeData; } -} // end namespace ito +} //end namespace ito diff --git a/DataObject/CMakeLists.txt b/DataObject/CMakeLists.txt index 27ba612f8..001c772fb 100644 --- a/DataObject/CMakeLists.txt +++ b/DataObject/CMakeLists.txt @@ -1,6 +1,6 @@ # - itom software # URL: http://www.uni-stuttgart.de/ito -# Copyright (C) 2020, Institut fuer Technische Optik (ITO), +# Copyright (C) 2023, Institut fuer Technische Optik (ITO), # Universitaet Stuttgart, Germany # # This file is part of itom and its software development toolkit (SDK). diff --git a/DataObject/dataobj.cpp b/DataObject/dataobj.cpp index 3eefb5ba2..88f936d58 100644 --- a/DataObject/dataobj.cpp +++ b/DataObject/dataobj.cpp @@ -1,7 +1,7 @@ /* ******************************************************************** itom software URL: http://www.uni-stuttgart.de/ito - Copyright (C) 2020, Institut fuer Technische Optik (ITO), + Copyright (C) 2023, Institut fuer Technische Optik (ITO), Universitaet Stuttgart, Germany This file is part of itom and its software development toolkit (SDK). @@ -3158,7 +3158,7 @@ MAKEFUNCLIST(DeepCopyPartialFunc); \throws cv::Exception(CV_StsAssert) if sizes or type of both matrices are not equal \sa DeepCopyPartialFunc */ -RetVal DataObject::deepCopyPartial(DataObject& copyTo) +RetVal DataObject::deepCopyPartial(DataObject& copyTo) const { if (m_type != copyTo.m_type) { @@ -3167,29 +3167,35 @@ RetVal DataObject::deepCopyPartial(DataObject& copyTo) } // calc and compare squeezed dimensions - int thisDims = this->getDims(); + int thisDims = getDims(); int rhsDims = copyTo.getDims(); int* thisSizes = new int[thisDims]; int* rhsSizes = new int[rhsDims]; - int j = 0; + for (int i = 0; i < thisDims; i++) { thisSizes[j] = this->getSize(i); + if (thisSizes[j] > 1) + { j++; + } } - thisDims = j; + thisDims = j; j = 0; + for (int i = 0; i < rhsDims; i++) { rhsSizes[j] = copyTo.getSize(i); + if (rhsSizes[j] > 1) { j++; } } + rhsDims = j; if (thisDims != rhsDims) @@ -3227,6 +3233,7 @@ RetVal DataObject::deepCopyPartial(DataObject& copyTo) // this->copyTagMapTo(rhs); //Deepcopy the tagspace // this->copyAxisTagsTo(rhs); //Deepcopy the tagspace //} + return ret; } @@ -10495,7 +10502,7 @@ dimensions is allowed to have a size greter than one. \param *mats sequence of i //---------------------------------------------------------------------------------------------------------------------------------- -DataObject DataObject::pow(const ito::float64& power) +DataObject DataObject::pow(const ito::float64& power) const { DataObject result(m_dims, getSize(), m_type); pow(power, result); @@ -10503,7 +10510,7 @@ DataObject DataObject::pow(const ito::float64& power) } //---------------------------------------------------------------------------------------------------------------------------------- -void DataObject::pow(const ito::float64& power, DataObject& dst) +void DataObject::pow(const ito::float64& power, DataObject& dst) const { if (dst.getDims() == 0) { @@ -10573,7 +10580,7 @@ void DataObject::pow(const ito::float64& power, DataObject& dst) } //---------------------------------------------------------------------------------------------------------------------------------- -DataObject DataObject::sqrt() +DataObject DataObject::sqrt() const { DataObject result(m_dims, getSize(), m_type); sqrt(result); @@ -10581,7 +10588,7 @@ DataObject DataObject::sqrt() } //---------------------------------------------------------------------------------------------------------------------------------- -void DataObject::sqrt(DataObject& dst) +void DataObject::sqrt(DataObject& dst) const { if (dst.getDims() == 0) { diff --git a/DataObject/dataobj.h b/DataObject/dataobj.h index 951dd925b..894f5c930 100644 --- a/DataObject/dataobj.h +++ b/DataObject/dataobj.h @@ -1,7 +1,7 @@ /* ******************************************************************** itom software URL: http://www.uni-stuttgart.de/ito - Copyright (C) 2020, Institut fuer Technische Optik (ITO), + Copyright (C) 2023, Institut fuer Technische Optik (ITO), Universitaet Stuttgart, Germany This file is part of itom and its software development toolkit (SDK). @@ -25,8 +25,7 @@ along with itom. If not, see . *********************************************************************** */ -#ifndef __DATAOBJH -#define __DATAOBJH +#pragma once #include "defines.h" @@ -1089,7 +1088,7 @@ namespace ito { RetVal setTo(const ito::TimeDelta &value, const DataObject &mask = DataObject()); /*!< Sets all or some (if uint8 mask is given) of the array elements to the specified value. */ //! copy all values of this data object to the copyTo data object. The copyTo-data object must be allocated and have the same type and size (of its roi) than this data object. The compared sequence of sizes only contains dimensions whose size is bigger than one (e.g. it is possible to copy a 5x1 object to a 1x1x5 object) - RetVal deepCopyPartial(DataObject ©To); + RetVal deepCopyPartial(DataObject ©To) const; //! Returns the matrix iterator and sets it to the first matrix element. DObjIterator begin(); @@ -1244,11 +1243,11 @@ namespace ito { // power (power of 0.5 is the square root) - DataObject pow(const ito::float64 &power); // returns a new data object with the same size and type than this data object and calculates src**power if power is an integer, else |src|**power (only for float32 and float64 data objects) - void pow(const ito::float64 &power, DataObject &dst); // this function raises every element of this data object to *power* and saves the result in dst. Dst must be of the same size and type than this data object or empty. In the latter case, it is reassigned to the right size and type. + DataObject pow(const ito::float64 &power) const; // returns a new data object with the same size and type than this data object and calculates src**power if power is an integer, else |src|**power (only for float32 and float64 data objects) + void pow(const ito::float64 &power, DataObject &dst) const; // this function raises every element of this data object to *power* and saves the result in dst. Dst must be of the same size and type than this data object or empty. In the latter case, it is reassigned to the right size and type. - DataObject sqrt(); // returns a new data object of the same size and type than this data object where the square root of every element is calculated. Is the same than pow(0.5) - void sqrt(DataObject &dst); // this function calculates the square root of every element and saves the result in dst. Dst must be of the same size and type than this data object or empty. In the latter case, it is reassigned to the right size and type.. Is the same than pow(0.5, dst) + DataObject sqrt() const; // returns a new data object of the same size and type than this data object where the square root of every element is calculated. Is the same than pow(0.5) + void sqrt(DataObject &dst) const; // this function calculates the square root of every element and saves the result in dst. Dst must be of the same size and type than this data object or empty. In the latter case, it is reassigned to the right size and type.. Is the same than pow(0.5, dst) DataObject squeeze() const; DataObject reshape(int newDims, const int *newSizes) const; @@ -1433,10 +1432,17 @@ namespace ito { DataObject lineCut(const double* coordinates, const int& len) const; // ROI - DataObject & adjustROI(const int dtop, const int dbottom, const int dleft, const int dright); /*!< changes the boundaries of the ROI of a two-dimensional data object by the given incremental values */ - DataObject & adjustROI(const unsigned char dims, const int *lims); /*!< changes the boundaries of the ROI of a n-dimensional data object by the given incremental values */ - RetVal locateROI(int *wholeSizes, int *offsets) const; /*!< locates the boundaries of the ROI of a n-dimensional data object and returns the original size and the distances to the physical borders */ - RetVal locateROI(int *lims) const; /*!< locates the boundaries of the ROI of a n-dimensional data object the distances to the physical borders */ + /*!< changes the boundaries of the ROI of a two-dimensional data object by the given incremental values */ + DataObject& adjustROI(const int dtop, const int dbottom, const int dleft, const int dright); + + /*!< changes the boundaries of the ROI of a n-dimensional data object by the given incremental values */ + DataObject& adjustROI(const unsigned char dims, const int *lims); + + /*!< locates the boundaries of the ROI of a n-dimensional data object and returns the original size and the distances to the physical borders */ + RetVal locateROI(int *wholeSizes, int *offsets) const; + + /*!< locates the boundaries of the ROI of a n-dimensional data object the distances to the physical borders */ + RetVal locateROI(int *lims) const; //! copies the externally given source data inside this data object /*! @@ -1454,7 +1460,11 @@ namespace ito { \param sizeY is the height of the array and must fit to the plane height of the data object \return RetVal error if sizeX or sizeY does not fit to the size of the data object or if the type of the given array does not fit to the type of the data object */ - template RetVal copyFromData2D(const _Tp* src, const int sizeX, const int sizeY) { return copyFromData2DInternal((const uchar*)src, sizeof(_Tp), sizeX, sizeY); } // copies 2D continuous data into data object, data object must have correct size and type, otherwise an error is returned + template RetVal copyFromData2D(const _Tp* src, const int sizeX, const int sizeY) + { + // copies 2D continuous data into data object, data object must have correct size and type, otherwise an error is returned + return copyFromData2DInternal((const uchar*)src, sizeof(_Tp), sizeX, sizeY); + } //! copies the externally given source data inside this data object /*! @@ -1481,9 +1491,13 @@ namespace ito { \param height is the height of the sub-region of the source data that should be copied (must fit to the height of the data object) \return RetVal error if sizeX or sizeY does not fit to the size of the data object or if the type of the given array does not fit to the type of the data object */ - template RetVal copyFromData2D(const _Tp *src, const int sizeX, const int sizeY, const int x0, const int y0, const int width, const int height) { return copyFromData2DInternal((const uchar*)src, sizeof(_Tp), sizeX, x0, y0, width, height); } // copies 2D continuous data into data object, data object must have correct size and type, otherwise an error is returned + template RetVal copyFromData2D(const _Tp *src, const int sizeX, const int sizeY, const int x0, const int y0, const int width, const int height) + { + // copies 2D continuous data into data object, data object must have correct size and type, otherwise an error is returned + return copyFromData2DInternal((const uchar*)src, sizeof(_Tp), sizeX, x0, y0, width, height); + } - template operator T2 (); /*!< cast operator, tries to cast this data object to another element type */ + template operator T2(); /*!< cast operator, tries to cast this data object to another element type */ template RetVal linspace(const _Tp start, const _Tp end, const _Tp inc, const int transposed); @@ -1721,5 +1735,3 @@ namespace ito { template<> inline ito::tDataType getDataType2() { return ito::tTimeDelta; } } //namespace ito - -#endif //__DATAOBJH diff --git a/DataObject/dataobjVersion.h b/DataObject/dataobjVersion.h index fe310e009..9d2a3f26f 100644 --- a/DataObject/dataobjVersion.h +++ b/DataObject/dataobjVersion.h @@ -1,7 +1,7 @@ /* ******************************************************************** itom software URL: http://www.uni-stuttgart.de/ito - Copyright (C) 2022, Institut fuer Technische Optik (ITO), + Copyright (C) 2023, Institut fuer Technische Optik (ITO), Universitaet Stuttgart, Germany This file is part of itom and its software development toolkit (SDK). @@ -25,8 +25,8 @@ along with itom. If not, see . *********************************************************************** */ -#define DATAOBJ_VERSION_MAJOR 1 -#define DATAOBJ_VERSION_MINOR 10 +#define DATAOBJ_VERSION_MAJOR 2 +#define DATAOBJ_VERSION_MINOR 0 #define DATAOBJ_VERSION_PATCH 0 #define DATAOBJ_VERSION_REVISION 0 -#define DATAOBJ_VERSION_STRING "1.10.0.0" +#define DATAOBJ_VERSION_STRING "2.0.0.0" diff --git a/Qitom/CMakeLists.txt b/Qitom/CMakeLists.txt index 932560b92..e659f83b7 100644 --- a/Qitom/CMakeLists.txt +++ b/Qitom/CMakeLists.txt @@ -245,6 +245,7 @@ link_directories( set(qitom_HEADERS_NOMOC ${CMAKE_CURRENT_SOURCE_DIR}/benchmarks.h ${CMAKE_CURRENT_SOURCE_DIR}/../common/addInGrabber.h + ${CMAKE_CURRENT_SOURCE_DIR}/../common/sources/addInMultiChannelGrabber.h ${CMAKE_CURRENT_SOURCE_DIR}/../common/addInInterface.h ${CMAKE_CURRENT_SOURCE_DIR}/../common/helperCommon.h ${CMAKE_CURRENT_SOURCE_DIR}/../common/sharedFunctionsQt.h diff --git a/Qitom/python/pythonCommon.cpp b/Qitom/python/pythonCommon.cpp index 0be68a71f..e7c70ad90 100644 --- a/Qitom/python/pythonCommon.cpp +++ b/Qitom/python/pythonCommon.cpp @@ -886,19 +886,19 @@ PyObject* printOutParams(const QVector *params, bool asErr, bool add values["values"].append("empty"); break; case 1: - temp = QString("[%1]").arg(ptr[0].data()); + temp = QString("[\"%1\"]").arg(ptr[0].data()); values["values"].append(temp); break; case 2: - temp = QString("[%1,%2]").arg(ptr[0].data()).arg(ptr[1].data()); + temp = QString("[\"%1\",\"%2\"]").arg(ptr[0].data()).arg(ptr[1].data()); values["values"].append(temp); break; case 3: - temp = QString("[%1,%2,%3]").arg(ptr[0].data()).arg(ptr[1].data()).arg(ptr[2].data()); + temp = QString("[\"%1\",\"%2\",\"%3\"]").arg(ptr[0].data()).arg(ptr[1].data()).arg(ptr[2].data()); values["values"].append(temp); break; case 4: - temp = QString("[%1,%2,%3,%4]").arg(ptr[0].data()).arg(ptr[1].data()).arg(ptr[2].data()).arg(ptr[3].data()); + temp = QString("[\"%1\",\"%2\",\"%3\",\"%4\"]").arg(ptr[0].data()).arg(ptr[1].data()).arg(ptr[2].data()).arg(ptr[3].data()); values["values"].append(temp); break; default: diff --git a/Qitom/python/pythonEngine.cpp b/Qitom/python/pythonEngine.cpp index 373b2f9c5..9ee297a0e 100644 --- a/Qitom/python/pythonEngine.cpp +++ b/Qitom/python/pythonEngine.cpp @@ -91,16 +91,16 @@ namespace ito { QMutex PythonEngine::instancePtrProtection; -PythonEngine* PythonEngine::instance = NULL; +PythonEngine* PythonEngine::instance = nullptr; QString PythonEngine::fctHashPrefix = ":::itomfcthash:::"; //---------------------------------------------------------------------------------------------------------------------------------- -FuncWeakRef::FuncWeakRef() : m_proxyObject(NULL), m_argument(NULL), m_handle(0) +FuncWeakRef::FuncWeakRef() : m_proxyObject(nullptr), m_argument(nullptr), m_handle(0) { } //---------------------------------------------------------------------------------------------------------------------------------- -FuncWeakRef::FuncWeakRef(PythonProxy::PyProxy *proxyObject, PyObject *argTuple /*= NULL*/) : +FuncWeakRef::FuncWeakRef(PythonProxy::PyProxy *proxyObject, PyObject *argTuple /*= nullptr*/) : m_proxyObject(proxyObject), m_argument(argTuple), m_handle(0) @@ -265,7 +265,7 @@ PythonEngine::PythonEngine() : qRegisterMetaType("ito::JediAssignment"); qRegisterMetaType >("QVector"); qRegisterMetaType >("QSharedPointer"); - + qRegisterMetaType >>("QSharedPointer>"); m_autoReload.modAutoReload = nullptr; m_autoReload.classAutoReload = nullptr; m_autoReload.checkFctExec = false; @@ -438,7 +438,7 @@ void PythonEngine::pythonSetup(ito::RetVal *retValue, QSharedPointer= 0x030B0000) @@ -849,7 +849,7 @@ ito::RetVal PythonEngine::startupLoadAndImportAdditionalModules(QSharedPointer(p_exc)) != NULL) + if ((p_cvexc = dynamic_cast(p_exc)) != nullptr) { const char* errorStr = cvErrorStr(p_cvexc->code); return PyErr_Format(PyExc_RuntimeError, "OpenCV Error: %s (%s) in %s, file %s, line %d", @@ -1443,7 +1443,7 @@ ito::RetVal PythonEngine::stringEncodingChanged() // QList qtCodecNames = QTextCodec::codecForCStrings()->aliases(); // qtCodecNames.append(QTextCodec::codecForCStrings()->name()); //QList qtCodecNames = QTextCodec::availableCodecs(); - QTextCodec *codec = NULL; + QTextCodec *codec = nullptr; QByteArray curQtCodec; #if linux @@ -1690,15 +1690,15 @@ void PythonEngine::setAutoReloader(bool enabled, bool checkFile, bool checkCmd, if (!m_autoReload.classAutoReload) { PyObject *dictItem = PyDict_GetItemString(PyModule_GetDict(m_autoReload.modAutoReload), "ItomAutoreloader"); // both borrowed references - if (dictItem == NULL) + if (dictItem == nullptr) { std::cerr << "Failed to enable 'auto reload'.\nThe class 'ItomAutoreloader' in module 'autoreload' could not be found:\n" << std::endl; PyErr_PrintEx(0); } else { - m_autoReload.classAutoReload = PyObject_CallObject(dictItem, NULL); //!< http://bytes.com/topic/python/answers/649229-_pyobject_new-pyobject_init-pyinstance_new-etc, new reference - if (m_autoReload.classAutoReload == NULL) + m_autoReload.classAutoReload = PyObject_CallObject(dictItem, nullptr); //!< http://bytes.com/topic/python/answers/649229-_pyobject_new-pyobject_init-pyinstance_new-etc, new reference + if (m_autoReload.classAutoReload == nullptr) { std::cerr << "Failed to enable 'auto reload'.\nThe class 'ItomAutoreloader' could not be instantiated.\n" << std::endl; PyErr_PrintEx(0); @@ -1895,8 +1895,8 @@ ito::RetVal PythonEngine::runString(const QString &command) //---------------------------------------------------------------------------------------------------------------------------------- ito::RetVal PythonEngine::runPyFile(const QString &pythonFileName) { - PyObject* result = NULL; - PyObject* compile = NULL; + PyObject* result = nullptr; + PyObject* compile = nullptr; RetVal retValue = RetVal(retOk); int method = 2; //1: direct, 2: by itomDebugger.py (sets the system path to folder of executed file) @@ -1942,7 +1942,7 @@ ito::RetVal PythonEngine::runPyFile(const QString &pythonFileName) compile = Py_CompileString(fileContent.constData(), filename.constData(), Py_file_input); - if (compile == NULL) + if (compile == nullptr) { if (PyErr_Occurred() && PyErr_ExceptionMatches(PyExc_SystemExit)) { @@ -1955,7 +1955,7 @@ ito::RetVal PythonEngine::runPyFile(const QString &pythonFileName) modifyTracebackDepth(2, true); PyErr_PrintEx(0); - if (oldTBLimit != NULL) + if (oldTBLimit != nullptr) { PySys_SetObject("tracebacklimit", oldTBLimit); } @@ -1966,9 +1966,9 @@ ito::RetVal PythonEngine::runPyFile(const QString &pythonFileName) } else { - result = PyEval_EvalCode(compile, m_pMainDictionary, NULL); + result = PyEval_EvalCode(compile, m_pMainDictionary, nullptr); - if (result == NULL) + if (result == nullptr) { if (PyErr_Occurred() && PyErr_ExceptionMatches(PyExc_SystemExit)) { @@ -2004,7 +2004,7 @@ ito::RetVal PythonEngine::runPyFile(const QString &pythonFileName) } else if (method == 2) { - if (m_itomDbgInstance == NULL) + if (m_itomDbgInstance == nullptr) { return RetVal(retError); } @@ -2033,7 +2033,7 @@ ito::RetVal PythonEngine::runPyFile(const QString &pythonFileName) result = PyErr_Format(PyExc_RuntimeError, "Unknown runtime error when executing python script (maybe stack overflow?)"); } - if (result == NULL) + if (result == nullptr) { if (PyErr_Occurred() && PyErr_ExceptionMatches(PyExc_SystemExit)) { @@ -2046,7 +2046,7 @@ ito::RetVal PythonEngine::runPyFile(const QString &pythonFileName) modifyTracebackDepth(2, true); PyErr_PrintEx(0); - if (oldTBLimit != NULL) + if (oldTBLimit != nullptr) { PySys_SetObject("tracebacklimit", oldTBLimit); } @@ -2111,7 +2111,7 @@ ito::RetVal PythonEngine::runFunction(PyObject *callable, PyObject *argTuple, bo ret = PyErr_Format(PyExc_RuntimeError, "Unknown runtime error when executing python method (maybe stack overflow?)"); } - if (ret == NULL) + if (ret == nullptr) { PyErr_PrintEx(0); retValue += RetVal(retError); @@ -2141,10 +2141,10 @@ ito::RetVal PythonEngine::runFunction(PyObject *callable, PyObject *argTuple, bo ito::RetVal PythonEngine::debugFunction(PyObject *callable, PyObject *argTuple, bool gilExternal /*= false*/) { - PyObject* result = NULL; + PyObject* result = nullptr; RetVal retValue = RetVal(retOk); m_interruptCounter = 0; - if (m_itomDbgInstance == NULL) + if (m_itomDbgInstance == nullptr) { return RetVal(retError); } @@ -2158,7 +2158,7 @@ ito::RetVal PythonEngine::debugFunction(PyObject *callable, PyObject *argTuple, //!< first, clear all existing breakpoints result = PyObject_CallMethod(m_itomDbgInstance, "clear_all_breaks", ""); - if (result == NULL) + if (result == nullptr) { std::cerr << tr("Error while clearing all breakpoints in itoDebugger.").toLatin1().data() << "\n" << std::endl; printPythonErrorWithoutTraceback(); //traceback is sense-less, since the traceback is in itoDebugger.py only! @@ -2202,7 +2202,7 @@ ito::RetVal PythonEngine::debugFunction(PyObject *callable, PyObject *argTuple, clearDbgCmdLoop(); - if (result == NULL) //!< syntax error + if (result == nullptr) //!< syntax error { if (PyErr_Occurred() && PyErr_ExceptionMatches(PyExc_SystemExit)) { @@ -2215,7 +2215,7 @@ ito::RetVal PythonEngine::debugFunction(PyObject *callable, PyObject *argTuple, modifyTracebackDepth(3, true); PyErr_PrintEx(0); - if (oldTBLimit != NULL) + if (oldTBLimit != nullptr) { PySys_SetObject("tracebacklimit", oldTBLimit); } @@ -2235,7 +2235,7 @@ ito::RetVal PythonEngine::debugFunction(PyObject *callable, PyObject *argTuple, } setGlobalDictionary(); - setLocalDictionary(NULL); + setLocalDictionary(nullptr); //!< disconnect connections for live-changes in breakpoints shutdownBreakPointDebugConnections(); @@ -2253,7 +2253,7 @@ ito::RetVal PythonEngine::debugFunction(PyObject *callable, PyObject *argTuple, //---------------------------------------------------------------------------------------------------------------------------------- ito::RetVal PythonEngine::debugFile(const QString &pythonFileName) { - PyObject* result = NULL; + PyObject* result = nullptr; RetVal retValue = RetVal(retOk); QString desiredPath = QFileInfo(pythonFileName).canonicalPath(); @@ -2265,7 +2265,7 @@ ito::RetVal PythonEngine::debugFile(const QString &pythonFileName) emit pythonCurrentDirChanged(); } - if (m_itomDbgInstance == NULL) + if (m_itomDbgInstance == nullptr) { return RetVal(retError); } @@ -2275,7 +2275,7 @@ ito::RetVal PythonEngine::debugFile(const QString &pythonFileName) //!< first, clear all existing breakpoints result = PyObject_CallMethod(m_itomDbgInstance, "clear_all_breaks", ""); - if (result == NULL) + if (result == nullptr) { std::cerr << tr("Error while clearing all breakpoints in itoDebugger.").toLatin1().data() << "\n" << std::endl; printPythonErrorWithoutTraceback(); //traceback is sense-less, since the traceback is in itoDebugger.py only! @@ -2316,7 +2316,7 @@ ito::RetVal PythonEngine::debugFile(const QString &pythonFileName) clearDbgCmdLoop(); - if (result == NULL) //!< syntax error + if (result == nullptr) //!< syntax error { if (PyErr_Occurred() && PyErr_ExceptionMatches(PyExc_SystemExit)) { @@ -2329,7 +2329,7 @@ ito::RetVal PythonEngine::debugFile(const QString &pythonFileName) modifyTracebackDepth(3, true); PyErr_PrintEx(0); - if (oldTBLimit != NULL) + if (oldTBLimit != nullptr) { PySys_SetObject("tracebacklimit", oldTBLimit); } @@ -2349,7 +2349,7 @@ ito::RetVal PythonEngine::debugFile(const QString &pythonFileName) } setGlobalDictionary(); - setLocalDictionary(NULL); + setLocalDictionary(nullptr); //!< disconnect connections for live-changes in breakpoints shutdownBreakPointDebugConnections(); @@ -2467,7 +2467,7 @@ ito::RetVal PythonEngine::debugString(const QString &command) } setGlobalDictionary(); - setLocalDictionary(NULL); + setLocalDictionary(nullptr); //!< disconnect connections for live-changes in breakpoints shutdownBreakPointDebugConnections(); @@ -3041,15 +3041,15 @@ ito::RetVal PythonEngine::pythonDeleteBreakpoint(const int pyBpNumber) { ito::RetVal retval; //when calling this method, the Python GIL must already be locked - PyObject *result = NULL; - if (m_itomDbgInstance == NULL) + PyObject *result = nullptr; + if (m_itomDbgInstance == nullptr) { retval += RetVal(retError, 0, tr("Debugger not available").toLatin1().data()); } else if (pyBpNumber >= 0) { result = PyObject_CallMethod(m_itomDbgInstance, "clearBreakPoint", "i", pyBpNumber); //returns 0 (int) or str with error message - if (result == NULL) + if (result == nullptr) { //this is an exception case that should not occure under normal circumstances std::cerr << "Error while clearing breakpoint in debugger." << "\n" << std::endl; @@ -3079,7 +3079,7 @@ ito::RetVal PythonEngine::pythonDeleteBreakpoint(const int pyBpNumber) } Py_XDECREF(result); - result = NULL; + result = nullptr; } return retval; } @@ -3089,9 +3089,9 @@ ito::RetVal PythonEngine::modifyTracebackDepth(int NrOfLevelsToPopAtFront, bool { if (PyErr_Occurred()) { - PyObject* pyErrType = NULL; - PyObject* pyErrValue = NULL; - PyObject* pyErrTrace = NULL; + PyObject* pyErrType = nullptr; + PyObject* pyErrValue = nullptr; + PyObject* pyErrTrace = nullptr; PyErr_Fetch(&pyErrType, &pyErrValue, &pyErrTrace); PyTracebackObject* tb = (PyTracebackObject*)pyErrTrace; @@ -3099,7 +3099,7 @@ ito::RetVal PythonEngine::modifyTracebackDepth(int NrOfLevelsToPopAtFront, bool int depth=0; // int line; - while(tb != NULL) + while(tb != nullptr) { depth++; // line = tb->tb_lineno; @@ -3114,7 +3114,7 @@ ito::RetVal PythonEngine::modifyTracebackDepth(int NrOfLevelsToPopAtFront, bool else if (depth - NrOfLevelsToPopAtFront <= 0 && NrOfLevelsToPopAtFront > -1) { //PyException_SetTraceback(pyErrValue,Py_None); - PyErr_Restore(pyErrType, pyErrValue, NULL); + PyErr_Restore(pyErrType, pyErrValue, nullptr); } return RetVal(retOk); @@ -3130,12 +3130,12 @@ ito::RetVal PythonEngine::modifyTracebackDepth(int NrOfLevelsToPopAtFront, bool void PythonEngine::printPythonErrorWithoutTraceback() { PyObject *exception, *v, *tb; - tb = NULL; + tb = nullptr; if (PyErr_Occurred()) { PyErr_Fetch(&exception, &v, &tb); - if (exception == NULL) + if (exception == nullptr) { return; } @@ -3145,7 +3145,7 @@ void PythonEngine::printPythonErrorWithoutTraceback() tb = Py_None; Py_INCREF(tb); PyException_SetTraceback(v, tb); - if (exception == NULL) + if (exception == nullptr) { return; } @@ -3857,29 +3857,29 @@ void PythonEngine::registerWorkspaceContainer(PyWorkspaceContainer *container, b The path name is a delimiter (/) separated string list where each item has the following form XY:name. The meaning for XY:name corresponds to PyWorkspaceItem::m_key. -This method returns a new reference to the found PyObject* or NULL. This function can only be +This method returns a new reference to the found PyObject* or nullptr. This function can only be called if the Python GIL is already locked. \TODO: up to now, validVariableName is the name of the item at the deepest level (for nested variables) only. We should think about if the validVariableName should be a underscore-joined string of all variable names along the tree, beginning from the root level. */ -PyObject* PythonEngine::getPyObjectByFullName(bool globalNotLocal, const QStringList &fullNameSplittedByDelimiter, QString *validVariableName /*= NULL*/) +PyObject* PythonEngine::getPyObjectByFullName(bool globalNotLocal, const QStringList &fullNameSplittedByDelimiter, QString *validVariableName /*= nullptr*/) { #if defined _DEBUG if (!PyGILState_Check()) { std::cerr << "Python GIL must be locked when calling getPyObjectByFullName\n" << std::endl; - return NULL; + return nullptr; } #endif - PyObject *obj = NULL; - PyObject *current_obj = NULL; + PyObject *obj = nullptr; + PyObject *current_obj = nullptr; QStringList items = fullNameSplittedByDelimiter; int i=0; float f=0.0; - PyObject *tempObj = NULL; - PyObject *number = NULL; + PyObject *tempObj = nullptr; + PyObject *number = nullptr; char itemKeyType, itemType; QString itemName; @@ -4304,7 +4304,7 @@ PyObject* PythonEngine::getPyObjectByFullName(bool globalNotLocal, const QString } //---------------------------------------------------------------------------------------------------------------------------------- -PyObject *PythonEngine::getPyObjectByFullName(bool globalNotLocal, const QString &fullName, QString *validVariableName /*= NULL*/) +PyObject *PythonEngine::getPyObjectByFullName(bool globalNotLocal, const QString &fullName, QString *validVariableName /*= nullptr*/) { return getPyObjectByFullName(globalNotLocal, fullName.split(ito::PyWorkspaceContainer::delimiter), validVariableName); } @@ -4332,14 +4332,14 @@ void PythonEngine::workspaceGetValueInformation(PyWorkspaceContainer *container, PyObject *obj = getPyObjectByFullName(container->isGlobalWorkspace(), fullItemName); - if (obj == NULL) + if (obj == nullptr) { *extendedValue = ""; } else { PyObject *repr = PyObject_Repr(obj); - if (repr == NULL) + if (repr == nullptr) { PyErr_Clear(); *extendedValue = ""; @@ -4574,7 +4574,7 @@ void PythonEngine::addFunctionCancellationAndObserver(QWeakPointer >::iterator it = m_activeFunctionCancellations.begin(); @@ -4633,7 +4633,7 @@ int PythonEngine::queuedInterrupt(void* /*arg*/) } //---------------------------------------------------------------------------------------------------------------------------------- -void PythonEngine::pythonInterruptExecutionThreadSafe(bool *interruptActuatorsAndTimers /*= NULL*/) +void PythonEngine::pythonInterruptExecutionThreadSafe(bool *interruptActuatorsAndTimers /*= nullptr*/) { // only queue the interrupt event if not yet done. // ==operator(int) of QAtomicInt does not exist for all versions of Qt5. @@ -4648,7 +4648,7 @@ void PythonEngine::pythonInterruptExecutionThreadSafe(bool *interruptActuatorsAn } else { - int result = Py_AddPendingCall(&PythonEngine::queuedInterrupt, NULL); + int result = Py_AddPendingCall(&PythonEngine::queuedInterrupt, nullptr); } } @@ -4696,15 +4696,15 @@ void PythonEngine::pythonInterruptExecutionThreadSafe(bool *interruptActuatorsAn PyObject* PythonEngine::PyDbgCommandLoop(PyObject * /*pSelf*/, PyObject *pArgs) { - PyObject *self = NULL; - PyObject *frame = NULL; - PyObject *frame2 = NULL; - PyObject *frame_next = NULL; + PyObject *self = nullptr; + PyObject *frame = nullptr; + PyObject *frame2 = nullptr; + PyObject *frame_next = nullptr; PyObject* temp; PyObject* temp2; - PyObject* globalDict = NULL; - PyObject* localDict = NULL; - PyObject* callRet = NULL; + PyObject* globalDict = nullptr; + PyObject* localDict = nullptr; + PyObject* callRet = nullptr; tPythonDbgCmd recentDbgCmd = pyDbgNone; @@ -4745,7 +4745,7 @@ PyObject* PythonEngine::PyDbgCommandLoop(PyObject * /*pSelf*/, PyObject *pArgs) frame2 = PyObject_GetAttrString(frame, "f_back"); - while(frame2 != NULL && frame2 != Py_None) + while(frame2 != nullptr && frame2 != Py_None) { temp = PyObject_GetAttrString(frame2, "f_code"); temp2 = PyObject_GetAttrString(temp, "co_filename"); @@ -4843,7 +4843,7 @@ PyObject* PythonEngine::PyDbgCommandLoop(PyObject * /*pSelf*/, PyObject *pArgs) Py_CLEAR(pArgs); Py_CLEAR(globalDict); - pyEngine->setLocalDictionary(NULL); + pyEngine->setLocalDictionary(nullptr); Py_CLEAR(localDict); return PyErr_Occurred(); } @@ -5031,7 +5031,7 @@ bool PythonEngine::renameVariable(bool globalNotLocal, const QString &oldFullIte PyLong_FromLong(old[1].toInt()); //new reference char parentContainerType = old[0][0].toLatin1(); fullNameSplit.removeLast(); - PyObject *parentContainer = NULL; + PyObject *parentContainer = nullptr; if (fullNameSplit.size() > 0) { @@ -5356,7 +5356,7 @@ ito::RetVal PythonEngine::saveMatlabVariables(bool globalNotLocal, QString filen tPythonState oldState = m_pythonState; RetVal retVal; - PyObject* dict = NULL; + PyObject* dict = nullptr; if ((m_pythonState & pyStateRunning) || (m_pythonState & pyStateDebugging) || (m_pythonState & pyStateDebuggingWaitingButBusy)) { @@ -5382,7 +5382,7 @@ ito::RetVal PythonEngine::saveMatlabVariables(bool globalNotLocal, QString filen dict = getLocalDictionary(); } - if (dict == NULL) + if (dict == nullptr) { retVal += RetVal(retError, 0, tr("Variables cannot be saved since dictionary is not available").toLatin1().data()); } @@ -5392,26 +5392,26 @@ ito::RetVal PythonEngine::saveMatlabVariables(bool globalNotLocal, QString filen //build dictionary, which should be pickled PyObject* pArgs = PyTuple_New(3); - PyTuple_SetItem(pArgs,0, PyUnicode_DecodeLatin1(filename.toLatin1().data(), filename.length(), NULL)); + PyTuple_SetItem(pArgs,0, PyUnicode_DecodeLatin1(filename.toLatin1().data(), filename.length(), nullptr)); PyObject* keyList = PyList_New(0); PyObject* valueList = PyList_New(0); - PyObject* tempElem = NULL; - PyObject* keyListItem = NULL; + PyObject* tempElem = nullptr; + PyObject* keyListItem = nullptr; QString validVariableName; for (int i = 0 ; i < varNames.size() ; i++) { tempElem = getPyObjectByFullName(globalNotLocal, varNames[i], &validVariableName); //new reference - if (tempElem == NULL) + if (tempElem == nullptr) { std::cerr << "variable '" << varNames.at(i).toLatin1().data() << "' cannot be found in dictionary and will not be exported.\n" << std::endl; } else { - keyListItem = PyUnicode_DecodeLatin1(validVariableName.toLatin1().constData(), validVariableName.length(), NULL); //new ref + keyListItem = PyUnicode_DecodeLatin1(validVariableName.toLatin1().constData(), validVariableName.length(), nullptr); //new ref PyList_Append(keyList, keyListItem); PyList_Append(valueList, tempElem); Py_DECREF(tempElem); @@ -5421,7 +5421,7 @@ ito::RetVal PythonEngine::saveMatlabVariables(bool globalNotLocal, QString filen PyTuple_SetItem(pArgs,1,valueList); PyTuple_SetItem(pArgs,2,keyList); - PyObject* pyRet = ito::PythonItom::PySaveMatlabMat(NULL, pArgs); + PyObject* pyRet = ito::PythonItom::PySaveMatlabMat(nullptr, pArgs); retVal += PythonCommon::checkForPyExceptions(true); @@ -5442,7 +5442,7 @@ ito::RetVal PythonEngine::saveMatlabVariables(bool globalNotLocal, QString filen } } - if (semaphore != NULL) + if (semaphore != nullptr) { semaphore->returnValue = retVal; semaphore->release(); @@ -5467,7 +5467,7 @@ ito::RetVal PythonEngine::saveMatlabSingleParam(QString filename, QSharedPointer tPythonState oldState = m_pythonState; RetVal retVal; - PyObject* dict = NULL; + PyObject* dict = nullptr; if ((m_pythonState & pyStateRunning) || (m_pythonState & pyStateDebugging) || (m_pythonState & pyStateDebuggingWaitingButBusy)) { @@ -5484,7 +5484,7 @@ ito::RetVal PythonEngine::saveMatlabSingleParam(QString filename, QSharedPointer pythonStateTransition(pyTransDebugExecCmdBegin); } - PyObject *item = NULL; + PyObject *item = nullptr; if (value.isNull()) { @@ -5547,7 +5547,7 @@ ito::RetVal PythonEngine::saveMatlabSingleParam(QString filename, QSharedPointer retVal += ito::RetVal(retError, 0, tr("Unsupported data type to save to matlab.").toLatin1().data()); } - if (item == NULL) + if (item == nullptr) { retVal += ito::RetVal(retError, 0, tr("Error converting object to Python object. Save to matlab not possible.").toLatin1().data()); } @@ -5558,10 +5558,10 @@ ito::RetVal PythonEngine::saveMatlabSingleParam(QString filename, QSharedPointer PyGILState_STATE gstate = PyGILState_Ensure(); PyObject* pArgs = PyTuple_New(3); - PyTuple_SetItem(pArgs, 0, PyUnicode_DecodeLatin1(filename.toLatin1().data(), filename.length(), NULL)); //steals ref. + PyTuple_SetItem(pArgs, 0, PyUnicode_DecodeLatin1(filename.toLatin1().data(), filename.length(), nullptr)); //steals ref. PyTuple_SetItem(pArgs, 1, item); //steals ref. - PyTuple_SetItem(pArgs, 2, PyUnicode_DecodeLatin1(valueName.toLatin1().data(), valueName.length(), NULL)); //steals ref. - PyObject *pyRet = ito::PythonItom::PySaveMatlabMat(NULL, pArgs); + PyTuple_SetItem(pArgs, 2, PyUnicode_DecodeLatin1(valueName.toLatin1().data(), valueName.length(), nullptr)); //steals ref. + PyObject *pyRet = ito::PythonItom::PySaveMatlabMat(nullptr, pArgs); retVal += PythonCommon::checkForPyExceptions(true); Py_XDECREF(pyRet); Py_XDECREF(pArgs); @@ -5580,7 +5580,7 @@ ito::RetVal PythonEngine::saveMatlabSingleParam(QString filename, QSharedPointer } } - if (semaphore != NULL) + if (semaphore != nullptr) { semaphore->returnValue = retVal; semaphore->release(); @@ -5598,7 +5598,7 @@ ito::RetVal PythonEngine::loadMatlabVariables(bool globalNotLocal, QString filen ItomSharedSemaphoreLocker locker(semaphore); tPythonState oldState = m_pythonState; RetVal retVal; - PyObject* destinationDict = NULL; + PyObject* destinationDict = nullptr; bool released = false; if ((m_pythonState & pyStateRunning) || (m_pythonState & pyStateDebugging) || (m_pythonState & pyStateDebuggingWaitingButBusy)) @@ -5625,7 +5625,7 @@ ito::RetVal PythonEngine::loadMatlabVariables(bool globalNotLocal, QString filen destinationDict = getLocalDictionary(); } - if (destinationDict == NULL) + if (destinationDict == nullptr) { retVal += RetVal(retError, 0, tr("Variables cannot be loaded since dictionary is not available").toLatin1().data()); } @@ -5633,15 +5633,15 @@ ito::RetVal PythonEngine::loadMatlabVariables(bool globalNotLocal, QString filen { PyGILState_STATE gstate = PyGILState_Ensure(); - PyObject *filenameUnicode = PyUnicode_DecodeLatin1(filename.toLatin1().data(), filename.length(), NULL); + PyObject *filenameUnicode = PyUnicode_DecodeLatin1(filename.toLatin1().data(), filename.length(), nullptr); PyObject *pArgs = PyTuple_Pack(1, filenameUnicode); Py_DECREF(filenameUnicode); - PyObject *dict = ito::PythonItom::PyLoadMatlabMat(NULL, pArgs); + PyObject *dict = ito::PythonItom::PyLoadMatlabMat(nullptr, pArgs); Py_DECREF(pArgs); retVal += PythonCommon::checkForPyExceptions(true); - if (dict == NULL || retVal.containsError()) + if (dict == nullptr || retVal.containsError()) { } else @@ -5730,13 +5730,13 @@ ito::RetVal PythonEngine::loadMatlabVariables(bool globalNotLocal, QString filen } //---------------------------------------------------------------------------------------------------------------------------------- -ito::RetVal PythonEngine::checkVarnamesInWorkspace(bool globalNotLocal, const QStringList &names, QSharedPointer existing, ItomSharedSemaphore *semaphore /*= NULL*/) +ito::RetVal PythonEngine::checkVarnamesInWorkspace(bool globalNotLocal, const QStringList &names, QSharedPointer existing, ItomSharedSemaphore *semaphore /*= nullptr*/) { ItomSharedSemaphoreLocker locker(semaphore); tPythonState oldState = m_pythonState; ito::RetVal retVal; - PyObject* destinationDict = NULL; - PyObject* value = NULL; + PyObject* destinationDict = nullptr; + PyObject* value = nullptr; bool released = false; if ((m_pythonState & pyStateRunning) || (m_pythonState & pyStateDebugging) || (m_pythonState & pyStateDebuggingWaitingButBusy)) @@ -5763,7 +5763,7 @@ ito::RetVal PythonEngine::checkVarnamesInWorkspace(bool globalNotLocal, const QS destinationDict = getLocalDictionary(); } - if (destinationDict == NULL) + if (destinationDict == nullptr) { retVal += ito::RetVal(ito::retError, 0, tr("Values cannot be saved since workspace dictionary not available.").toLatin1().data()); } @@ -5771,8 +5771,8 @@ ito::RetVal PythonEngine::checkVarnamesInWorkspace(bool globalNotLocal, const QS { PyGILState_STATE gstate = PyGILState_Ensure(); - PyObject *existingItem = NULL; - PyObject *varname = NULL; + PyObject *existingItem = nullptr; + PyObject *varname = nullptr; existing->clear(); existing->reserve(names.size()); @@ -5780,7 +5780,7 @@ ito::RetVal PythonEngine::checkVarnamesInWorkspace(bool globalNotLocal, const QS for (int i = 0; (i < names.size()) && (!retVal.containsError()); i++) { varname = getAndCheckIdentifier(names[i], retVal); //new ref - existingItem = varname ? PyDict_GetItem(destinationDict, varname) : NULL; //borrowed ref + existingItem = varname ? PyDict_GetItem(destinationDict, varname) : nullptr; //borrowed ref if (existingItem) { @@ -5805,7 +5805,7 @@ ito::RetVal PythonEngine::checkVarnamesInWorkspace(bool globalNotLocal, const QS PyGILState_Release(gstate); - if (semaphore != NULL) + if (semaphore != nullptr) { semaphore->returnValue = retVal; semaphore->release(); @@ -5823,7 +5823,7 @@ ito::RetVal PythonEngine::checkVarnamesInWorkspace(bool globalNotLocal, const QS } } - if (semaphore != NULL && !released) + if (semaphore != nullptr && !released) { semaphore->returnValue = retVal; semaphore->release(); @@ -5833,13 +5833,13 @@ ito::RetVal PythonEngine::checkVarnamesInWorkspace(bool globalNotLocal, const QS } //---------------------------------------------------------------------------------------------------------------------------------- -ito::RetVal PythonEngine::getVarnamesListInWorkspace(bool globalNotLocal, const QString &find, QSharedPointer varnameList, ItomSharedSemaphore *semaphore /*= NULL*/) +ito::RetVal PythonEngine::getVarnamesListInWorkspace(bool globalNotLocal, const QString &find, QSharedPointer varnameList, ItomSharedSemaphore *semaphore /*= nullptr*/) { ItomSharedSemaphoreLocker locker(semaphore); tPythonState oldState = m_pythonState; ito::RetVal retVal; - PyObject* destinationDict = NULL; - PyObject* value = NULL; + PyObject* destinationDict = nullptr; + PyObject* value = nullptr; bool released = false; if ((m_pythonState & pyStateRunning) || (m_pythonState & pyStateDebugging) || (m_pythonState & pyStateDebuggingWaitingButBusy)) @@ -5866,7 +5866,7 @@ ito::RetVal PythonEngine::getVarnamesListInWorkspace(bool globalNotLocal, const destinationDict = getLocalDictionary(); } - if (destinationDict == NULL) + if (destinationDict == nullptr) { retVal += ito::RetVal(ito::retError, 0, tr("Values cannot be saved since workspace dictionary not available.").toLatin1().data()); } @@ -5890,7 +5890,7 @@ ito::RetVal PythonEngine::getVarnamesListInWorkspace(bool globalNotLocal, const PyGILState_Release(gstate); - if (semaphore != NULL) + if (semaphore != nullptr) { semaphore->returnValue = retVal; semaphore->release(); @@ -5908,7 +5908,7 @@ ito::RetVal PythonEngine::getVarnamesListInWorkspace(bool globalNotLocal, const } } - if (semaphore != NULL && !released) + if (semaphore != nullptr && !released) { semaphore->returnValue = retVal; semaphore->release(); @@ -5929,8 +5929,8 @@ ito::RetVal PythonEngine::putParamsToWorkspace(bool globalNotLocal, const QStrin ItomSharedSemaphoreLocker locker(semaphore); //tPythonState oldState = m_pythonState; ito::RetVal retVal; - PyObject* destinationDict = NULL; - PyObject* value = NULL; + PyObject* destinationDict = nullptr; + PyObject* value = nullptr; bool released = false; if (names.size() != values.size()) @@ -5961,7 +5961,7 @@ ito::RetVal PythonEngine::putParamsToWorkspace(bool globalNotLocal, const QStrin destinationDict = getLocalDictionary(); } - if (destinationDict == NULL) + if (destinationDict == nullptr) { retVal += ito::RetVal(ito::retError, 0, tr("Values cannot be saved since workspace dictionary not available.").toLatin1().data()); } @@ -5969,13 +5969,13 @@ ito::RetVal PythonEngine::putParamsToWorkspace(bool globalNotLocal, const QStrin { PyGILState_STATE gstate = PyGILState_Ensure(); - PyObject *existingItem = NULL; - PyObject *varname = NULL; + PyObject *existingItem = nullptr; + PyObject *varname = nullptr; for (int i = 0; (i < names.size()) && (!retVal.containsError()); i++) { varname = getAndCheckIdentifier(names[i], retVal); //new ref - existingItem = varname ? PyDict_GetItem(destinationDict, varname) : NULL; //borrowed ref + existingItem = varname ? PyDict_GetItem(destinationDict, varname) : nullptr; //borrowed ref if (existingItem) { @@ -6008,7 +6008,7 @@ ito::RetVal PythonEngine::putParamsToWorkspace(bool globalNotLocal, const QStrin if (varname) { value = PythonParamConversion::ParamBaseToPyObject(*(values[i])); - if (value == NULL) + if (value == nullptr) { retVal += ito::RetVal::format(ito::retError, 0, tr("Error while transforming value '%s' to PyObject*.").toLatin1().data(), names[i].toLatin1().data()); } @@ -6022,7 +6022,7 @@ ito::RetVal PythonEngine::putParamsToWorkspace(bool globalNotLocal, const QStrin Py_XDECREF(varname); } - if (semaphore != NULL) + if (semaphore != nullptr) { semaphore->returnValue = retVal; semaphore->release(); @@ -6051,7 +6051,7 @@ ito::RetVal PythonEngine::putParamsToWorkspace(bool globalNotLocal, const QStrin }*/ } - if (semaphore != NULL && !released) + if (semaphore != nullptr && !released) { semaphore->returnValue = retVal; semaphore->release(); @@ -6066,7 +6066,7 @@ ito::RetVal PythonEngine::getParamsFromWorkspace(bool globalNotLocal, const QStr ItomSharedSemaphoreLocker locker(semaphore); tPythonState oldState = m_pythonState; ito::RetVal retVal; - PyObject* value = NULL; + PyObject* value = nullptr; bool released = false; QSharedPointer param; @@ -6092,7 +6092,7 @@ ito::RetVal PythonEngine::getParamsFromWorkspace(bool globalNotLocal, const QStr pythonStateTransition(pyTransDebugExecCmdBegin); } - if ((globalNotLocal && getGlobalDictionary() == NULL) || (!globalNotLocal && getLocalDictionary() == NULL)) + if ((globalNotLocal && getGlobalDictionary() == nullptr) || (!globalNotLocal && getLocalDictionary() == nullptr)) { retVal += ito::RetVal(ito::retError, 0, tr("Values cannot be obtained since workspace dictionary not available.").toLatin1().data()); } @@ -6104,7 +6104,7 @@ ito::RetVal PythonEngine::getParamsFromWorkspace(bool globalNotLocal, const QStr for (int i = 0; i < names.size(); i++) { value = getPyObjectByFullName(globalNotLocal, names[i], &validVariableName); //new reference - if (value == NULL) + if (value == nullptr) { retVal += ito::RetVal(ito::retError, 0, tr("Item '%1' does not exist in workspace.").arg(names[i]).toLatin1().data()); break; @@ -6131,7 +6131,7 @@ ito::RetVal PythonEngine::getParamsFromWorkspace(bool globalNotLocal, const QStr PyGILState_Release(gstate); - if (semaphore != NULL) + if (semaphore != nullptr) { semaphore->returnValue = retVal; semaphore->release(); @@ -6149,7 +6149,7 @@ ito::RetVal PythonEngine::getParamsFromWorkspace(bool globalNotLocal, const QStr } } - if (semaphore != NULL && !released) + if (semaphore != nullptr && !released) { semaphore->returnValue = retVal; semaphore->release(); @@ -6165,7 +6165,7 @@ This function detects all currently available variables and stores them in a glo ito::RetVal PythonEngine::pythonGetClearAllValues() { ito::RetVal retVal; - if (m_itomFunctions == NULL) + if (m_itomFunctions == nullptr) { retVal += RetVal(retError, 0, tr("The script itomFunctions.py is not available").toLatin1().data()); } @@ -6186,7 +6186,7 @@ Afterwards the workspace will be updated. ito::RetVal PythonEngine::pythonClearAll() { ito::RetVal retVal; - if (m_itomFunctions == NULL) + if (m_itomFunctions == nullptr) { retVal += RetVal(retError, 0, tr("The script itomFunctions.py is not available").toLatin1().data()); } @@ -6211,15 +6211,15 @@ ito::RetVal PythonEngine::registerAddInInstance(QString varname, ito::AddInBase RetVal retVal(retOk); tPythonState oldState = m_pythonState; - PyObject* dict = NULL; - PyObject* value = NULL; + PyObject* dict = nullptr; + PyObject* value = nullptr; bool globalNotLocal = true; //may also be accessed by parameter, if desired if ((m_pythonState & pyStateRunning) || (m_pythonState & pyStateDebugging) || (m_pythonState & pyStateDebuggingWaitingButBusy)) { retVal += RetVal(retError, 0, tr("It is not allowed to register an AddIn-instance in modes pyStateRunning, pyStateDebugging or pyStateDebuggingWaitingButBusy").toLatin1().data()); - if (semaphore != NULL) //release semaphore now, since the following emit command will be a blocking connection, too. + if (semaphore != nullptr) //release semaphore now, since the following emit command will be a blocking connection, too. { semaphore->returnValue = retVal; semaphore->release(); @@ -6245,7 +6245,7 @@ ito::RetVal PythonEngine::registerAddInInstance(QString varname, ito::AddInBase dict = getLocalDictionary(); } - if (dict == NULL) + if (dict == nullptr) { retVal += RetVal(retError, 0, tr("Dictionary is not available").toLatin1().data()); } @@ -6257,7 +6257,7 @@ ito::RetVal PythonEngine::registerAddInInstance(QString varname, ito::AddInBase if (pyVarname) { - if (PyDict_GetItem(dict, pyVarname) != NULL) + if (PyDict_GetItem(dict, pyVarname) != nullptr) { QString ErrStr = tr("Variable name '%1' already exists in dictionary").arg(varname); retVal += RetVal(retError, 0, ErrStr.toLatin1().data()); @@ -6266,8 +6266,8 @@ ito::RetVal PythonEngine::registerAddInInstance(QString varname, ito::AddInBase { if (instance->getBasePlugin()->getType() & ito::typeDataIO) { - PythonPlugins::PyDataIOPlugin *dataIOPlugin = (PythonPlugins::PyDataIOPlugin*)PythonPlugins::PyDataIOPluginType.tp_new(&PythonPlugins::PyDataIOPluginType,NULL,NULL); //new ref - if (dataIOPlugin == NULL) + PythonPlugins::PyDataIOPlugin *dataIOPlugin = (PythonPlugins::PyDataIOPlugin*)PythonPlugins::PyDataIOPluginType.tp_new(&PythonPlugins::PyDataIOPluginType,nullptr,nullptr); //new ref + if (dataIOPlugin == nullptr) { retVal += RetVal(retError, 0, tr("No instance of python class dataIO could be created").toLatin1().data()); } @@ -6280,8 +6280,8 @@ ito::RetVal PythonEngine::registerAddInInstance(QString varname, ito::AddInBase } else if (instance->getBasePlugin()->getType() & ito::typeActuator) { - PythonPlugins::PyActuatorPlugin *actuatorPlugin = (PythonPlugins::PyActuatorPlugin*)PythonPlugins::PyActuatorPluginType.tp_new(&PythonPlugins::PyActuatorPluginType,NULL,NULL); //new ref - if (actuatorPlugin == NULL) + PythonPlugins::PyActuatorPlugin *actuatorPlugin = (PythonPlugins::PyActuatorPlugin*)PythonPlugins::PyActuatorPluginType.tp_new(&PythonPlugins::PyActuatorPluginType,nullptr,nullptr); //new ref + if (actuatorPlugin == nullptr) { retVal += RetVal(retError, 0, tr("No instance of python class actuator could be created").toLatin1().data()); } @@ -6315,7 +6315,7 @@ ito::RetVal PythonEngine::registerAddInInstance(QString varname, ito::AddInBase PyGILState_Release(gstate); } - if (semaphore != NULL) //release semaphore now, since the following emit command will be a blocking connection, too. + if (semaphore != nullptr) //release semaphore now, since the following emit command will be a blocking connection, too. { semaphore->returnValue = retVal; semaphore->release(); @@ -6344,11 +6344,11 @@ ito::RetVal PythonEngine::registerAddInInstance(QString varname, ito::AddInBase } //---------------------------------------------------------------------------------------------------------------------------------- -//! get the unicode object from identifier and checks if it is a valid python identifier (variable name). This returns a new reference of the unicode object or NULL with a corresponding error message (python error flag is cleared) +//! get the unicode object from identifier and checks if it is a valid python identifier (variable name). This returns a new reference of the unicode object or nullptr with a corresponding error message (python error flag is cleared) PyObject* PythonEngine::getAndCheckIdentifier(const QString &identifier, ito::RetVal &retval) const { //QByteArray ba = identifier.toLatin1(); - //PyObject *obj = PyUnicode_DecodeLatin1(ba.data(), ba.size(), NULL); + //PyObject *obj = PyUnicode_DecodeLatin1(ba.data(), ba.size(), nullptr); PyObject *obj = PythonQtConversion::QStringToPyObject(identifier); @@ -6357,7 +6357,7 @@ PyObject* PythonEngine::getAndCheckIdentifier(const QString &identifier, ito::Re if (!PyUnicode_IsIdentifier(obj)) { Py_DECREF(obj); - obj = NULL; + obj = nullptr; retval += ito::RetVal::format(ito::retError, 0, "String '%s' is no valid python identifier", identifier.toLatin1().data()); } } @@ -6394,7 +6394,7 @@ ito::RetVal PythonEngine::getSysModules(QSharedPointer modNames, QS } //code - if (m_itomFunctions == NULL) + if (m_itomFunctions == nullptr) { retValue += RetVal(retError, 0, tr("The script itomFunctions.py is not available").toLatin1().data()); } @@ -6469,7 +6469,7 @@ ito::RetVal PythonEngine::reloadSysModules(QSharedPointer modNames, } //code - if (m_itomFunctions == NULL) + if (m_itomFunctions == nullptr) { retValue += RetVal(retError, 0, tr("The script itomFunctions.py is not available").toLatin1().data()); } @@ -6525,7 +6525,7 @@ ito::RetVal PythonEngine::pickleVariables(bool globalNotLocal, QString filename, tPythonState oldState = m_pythonState; RetVal retVal; - PyObject* dict = NULL; + PyObject* dict = nullptr; if ((m_pythonState & pyStateRunning) || (m_pythonState & pyStateDebugging) || (m_pythonState & pyStateDebuggingWaitingButBusy)) { @@ -6569,7 +6569,7 @@ ito::RetVal PythonEngine::pickleVariables(bool globalNotLocal, QString filename, { tempElem = getPyObjectByFullName(globalNotLocal, varNames[i], &validVariableName); //new reference - if (tempElem == NULL) + if (tempElem == nullptr) { std::cerr << "variable '" << validVariableName.toLatin1().data() << "' cannot be found in dictionary and will not be exported.\n" << std::endl; } @@ -6592,7 +6592,7 @@ ito::RetVal PythonEngine::pickleVariables(bool globalNotLocal, QString filename, PyDict_Clear(exportDict); Py_DECREF(exportDict); - exportDict = NULL; + exportDict = nullptr; } PyGILState_Release(gstate); @@ -6633,7 +6633,7 @@ ito::RetVal PythonEngine::pickleSingleParam(QString filename, QSharedPointerreturnValue = retVal; semaphore->release(); @@ -6769,14 +6769,14 @@ ito::RetVal PythonEngine::pickleDictionary(PyObject *dict, const QString &filena RetVal retval; - if (m_mainModule == NULL) + if (m_mainModule == nullptr) { return RetVal(retError, 0, tr("MainModule is empty or cannot be accessed").toLatin1().data()); } PyObject* pickleModule = PyImport_AddModule("pickle"); // borrowed reference - if (pickleModule == NULL) + if (pickleModule == nullptr) { retval += PythonCommon::checkForPyExceptions(true); return retval; @@ -6784,7 +6784,7 @@ ito::RetVal PythonEngine::pickleDictionary(PyObject *dict, const QString &filena PyObject *builtinsModule = PyObject_GetAttrString(m_mainModule, "__builtins__"); //new reference - if (builtinsModule == NULL) + if (builtinsModule == nullptr) { retval += PythonCommon::checkForPyExceptions(true); return retval; @@ -6793,34 +6793,34 @@ ito::RetVal PythonEngine::pickleDictionary(PyObject *dict, const QString &filena PyObject* openMethod = PyDict_GetItemString(PyModule_GetDict(builtinsModule), "open"); //both: borrowed Py_DECREF(builtinsModule); - builtinsModule = NULL; + builtinsModule = nullptr; PyObject* pyMode = PyUnicode_FromString("wb\0"); //new reference - PyObject* fileHandle = NULL; + PyObject* fileHandle = nullptr; - PyObject* pyFileName = PyUnicode_DecodeLatin1(filename.toLatin1().data(), filename.length(), NULL); + PyObject* pyFileName = PyUnicode_DecodeLatin1(filename.toLatin1().data(), filename.length(), nullptr); - if (pyFileName != NULL) + if (pyFileName != nullptr) { - fileHandle = PyObject_CallFunctionObjArgs(openMethod, pyFileName, pyMode, NULL); //new reference + fileHandle = PyObject_CallFunctionObjArgs(openMethod, pyFileName, pyMode, nullptr); //new reference Py_DECREF(pyFileName); } Py_XDECREF(pyMode); - if (fileHandle == NULL) + if (fileHandle == nullptr) { retval += PythonCommon::checkForPyExceptions(true); } else { - PyObject *result = NULL; + PyObject *result = nullptr; PyObject *version = PyLong_FromLong(3); //Use pickle protocol version 3 as default. This is readable by all itom version that have been published (default for Python 3). PyObject *dumpObj = PyUnicode_FromString("dump"); //new reference try { - result = PyObject_CallMethodObjArgs(pickleModule, dumpObj, dict, fileHandle, version, NULL); //new reference + result = PyObject_CallMethodObjArgs(pickleModule, dumpObj, dict, fileHandle, version, nullptr); //new reference } catch(std::bad_alloc &/*ba*/) { @@ -6845,7 +6845,7 @@ ito::RetVal PythonEngine::pickleDictionary(PyObject *dict, const QString &filena Py_DECREF(dumpObj); Py_DECREF(version); - if (result == NULL) + if (result == nullptr) { retval += PythonCommon::checkForPyExceptions(true); } @@ -6876,7 +6876,7 @@ ito::RetVal PythonEngine::unpickleVariables(bool globalNotLocal, QString filenam tPythonState oldState = m_pythonState; RetVal retVal; bool released = false; - PyObject* destinationDict = NULL; + PyObject* destinationDict = nullptr; if ((m_pythonState & pyStateRunning) || (m_pythonState & pyStateDebugging) || (m_pythonState & pyStateDebuggingWaitingButBusy)) { @@ -6902,7 +6902,7 @@ ito::RetVal PythonEngine::unpickleVariables(bool globalNotLocal, QString filenam destinationDict = getLocalDictionary(); } - if (destinationDict == NULL) + if (destinationDict == nullptr) { retVal += RetVal(retError, 0, tr("Variables cannot be unpickled since dictionary is not available").toLatin1().data()); } @@ -6979,14 +6979,14 @@ ito::RetVal PythonEngine::unpickleDictionary(PyObject *destinationDict, const QS RetVal retval; - if (m_mainModule == NULL) + if (m_mainModule == nullptr) { return RetVal(retError, 0, tr("MainModule is empty or cannot be accessed").toLatin1().data()); } PyObject* pickleModule = PyImport_AddModule("pickle"); // borrowed reference - if (pickleModule == NULL) + if (pickleModule == nullptr) { retval += PythonCommon::checkForPyExceptions(true); return retval; @@ -6994,7 +6994,7 @@ ito::RetVal PythonEngine::unpickleDictionary(PyObject *destinationDict, const QS PyObject *builtinsModule = PyObject_GetAttrString(m_mainModule, "__builtins__"); //new reference - if (builtinsModule == NULL) + if (builtinsModule == nullptr) { retval += PythonCommon::checkForPyExceptions(true); return retval; @@ -7003,32 +7003,32 @@ ito::RetVal PythonEngine::unpickleDictionary(PyObject *destinationDict, const QS PyObject* openMethod = PyDict_GetItemString(PyModule_GetDict(builtinsModule), "open"); //borrowed Py_DECREF(builtinsModule); - builtinsModule = NULL; + builtinsModule = nullptr; PyObject* pyMode = PyUnicode_FromString("rb\0"); - PyObject* fileHandle = NULL; + PyObject* fileHandle = nullptr; - PyObject* pyFileName = PyUnicode_DecodeLatin1(filename.toLatin1().data(), filename.length(), NULL); + PyObject* pyFileName = PyUnicode_DecodeLatin1(filename.toLatin1().data(), filename.length(), nullptr); - if (pyFileName != NULL) + if (pyFileName != nullptr) { - fileHandle = PyObject_CallFunctionObjArgs(openMethod, pyFileName, pyMode, NULL); //new reference + fileHandle = PyObject_CallFunctionObjArgs(openMethod, pyFileName, pyMode, nullptr); //new reference Py_DECREF(pyFileName); } if (pyMode) Py_DECREF(pyMode); - if (fileHandle == NULL) + if (fileHandle == nullptr) { retval += PythonCommon::checkForPyExceptions(true); } else { PyObject *loadObj = PyUnicode_FromString("load"); - PyObject *unpickledItem = NULL; + PyObject *unpickledItem = nullptr; try { - unpickledItem = PyObject_CallMethodObjArgs(pickleModule, loadObj, fileHandle, NULL); //new ref + unpickledItem = PyObject_CallMethodObjArgs(pickleModule, loadObj, fileHandle, nullptr); //new ref } catch(std::bad_alloc &/*ba*/) { @@ -7051,7 +7051,7 @@ ito::RetVal PythonEngine::unpickleDictionary(PyObject *destinationDict, const QS } Py_DECREF(loadObj); - if (unpickledItem == NULL) + if (unpickledItem == nullptr) { retval += PythonCommon::checkForPyExceptions(true); } @@ -7180,12 +7180,12 @@ PyMethodDef PythonEngine::PyMethodItomDbg[] = { // "Python name", C Ffunction Code, Argument Flags, __doc__ description {"pyDbgCommandLoop", PythonEngine::PyDbgCommandLoop, METH_VARARGS, "will be invoked if debugger stopped at the given filename and line"}, {"pyDbgClearBreakpoint", PythonEngine::PyDbgClearBreakpoint, METH_VARARGS, "will be invoked if debugger wants to remove a temporary breakpoint"}, - {NULL, NULL, 0, NULL} + {nullptr, nullptr, 0, nullptr} }; PyModuleDef PythonEngine::PyModuleItomDbg = { - PyModuleDef_HEAD_INIT, "itomDbgWrapper", NULL, -1, PythonEngine::PyMethodItomDbg, - NULL, NULL, NULL, NULL + PyModuleDef_HEAD_INIT, "itomDbgWrapper", nullptr, -1, PythonEngine::PyMethodItomDbg, + nullptr, nullptr, nullptr, nullptr }; //---------------------------------------------------------------------------------------------------------------------------------- diff --git a/Qitom/python/pythonPlugins.cpp b/Qitom/python/pythonPlugins.cpp index c3f2fa9ce..7df2e4b8a 100644 --- a/Qitom/python/pythonPlugins.cpp +++ b/Qitom/python/pythonPlugins.cpp @@ -3949,7 +3949,6 @@ PyObject* PythonPlugins::PyDataIOPlugin_stop(PyDataIOPlugin *self) Py_RETURN_NONE; } - //------------------------------------------------------------------------------------- PyDoc_STRVAR(PyDataIOPlugin_getVal_doc,"getVal(dataObj) -> None \\\n\ getVal(buffer, length = INT_MAX) -> int \n\ @@ -4040,6 +4039,61 @@ PyObject* PythonPlugins::PyDataIOPlugin_getVal(PyDataIOPlugin *self, PyObject *a invokeMethod = 1; } + else if (PyErr_Clear(), PyArg_ParseTuple(args, "O!", &PyDict_Type, &bufferObj)) + { + PyObject *key, *value, *repr, *str; + Py_ssize_t pos = 0; + ito::DataObject* channelDataObj; + QSharedPointer> channelMap(new QMap); + while (PyDict_Next(bufferObj, &pos, &key, &value)) + { + if (PyUnicode_Check(key)) + { + + if ((Py_TYPE(value) == &PythonDataObject::PyDataObjectType)) + { + repr = PyObject_Repr(key); + str = PyUnicode_AsEncodedString(repr, "utf-8", "strict"); + if (((PythonDataObject::PyDataObject*)value)->dataObject) + { + QString key = QString(PyBytes_AS_STRING(str)); + if (key[0] == '\'' && key[key.length() - 1] == '\'') + { + key = key.mid(1, key.length() - 2); + } + (*channelMap)[key] = + ((PythonDataObject::PyDataObject*)value)->dataObject; + } + else + { + Py_XDECREF(repr); + Py_XDECREF(str); + PyErr_SetString( + PyExc_RuntimeError, + "given data object of at least one data object is empty (internal dataObject-pointer is NULL)"); + return NULL; + } + } + else + { + PyErr_SetString( + PyExc_RuntimeError, "The value of at least one item isn't a data object"); + return NULL; + } + } + else + { + PyErr_SetString(PyExc_RuntimeError, "The key of at least one item isn't a string"); + return NULL; + } + } + locker = (new ItomSharedSemaphore()); + QMetaObject::invokeMethod( + self->dataIOObj, "getVal", + QArgument > >("QSharedPointer >",channelMap), + Q_ARG(ItomSharedSemaphore*, locker.getSemaphore())); + + } else if (PyErr_Clear(), PyArg_ParseTuple(args, "O|i", &bufferObj, &length)) { if (PyByteArray_Check(bufferObj)) @@ -4085,7 +4139,7 @@ PyObject* PythonPlugins::PyDataIOPlugin_getVal(PyDataIOPlugin *self, PyObject *a PyErr_Clear(); PyErr_SetString( PyExc_RuntimeError, - "arguments of method must be either one data object, byte array or " + "arguments of method must be either one data object, a dictionary containing data objects, a byte array or a " "byte object."); return NULL; } @@ -4167,6 +4221,7 @@ PyObject* PythonPlugins::PyDataIOPlugin_copyVal(PyDataIOPlugin *self, PyObject * { int length = PyTuple_Size(args); PyObject *tempObj = NULL; + PyObject* bufferObj = NULL; ito::RetVal ret = ito::retOk; if (self->dataIOObj->getBasePlugin()->getType() & ito::typeGrabber) @@ -4183,45 +4238,121 @@ PyObject* PythonPlugins::PyDataIOPlugin_copyVal(PyDataIOPlugin *self, PyObject * if ((Py_TYPE(tempObj) == &PythonDataObject::PyDataObjectType)) { dObj = ((PythonDataObject::PyDataObject *)tempObj)->dataObject; - } - else - { - PyErr_SetString(PyExc_TypeError, "argument must be of type itom.dataObject."); - return NULL; - } + if (dObj == NULL) + { + PyErr_SetString(PyExc_ValueError, "invalid dataObject"); + return NULL; + } - if (dObj == NULL) - { - PyErr_SetString(PyExc_ValueError, "invalid dataObject"); - return NULL; - } + ItomSharedSemaphoreLocker locker(new ItomSharedSemaphore()); - ItomSharedSemaphoreLocker locker(new ItomSharedSemaphore()); + if (QMetaObject::invokeMethod(self->dataIOObj, "copyVal", Q_ARG(void*, (void*)dObj), Q_ARG(ItomSharedSemaphore*, locker.getSemaphore()))) + { + bool timeout = false; - if (QMetaObject::invokeMethod(self->dataIOObj, "copyVal", Q_ARG(void*, (void *)dObj), Q_ARG(ItomSharedSemaphore*, locker.getSemaphore()))) - { - bool timeout = false; + while (!locker.getSemaphore()->wait(AppManagement::timeouts.pluginGeneral)) + { + if (!self->dataIOObj->isAlive()) + { + timeout = true; + ret += ito::RetVal(ito::retError, 0, QObject::tr("timeout while calling 'copyVal'").toLatin1().data()); + break; + } + } - while (!locker.getSemaphore()->wait(AppManagement::timeouts.pluginGeneral)) + if (!timeout) + { + ret += locker.getSemaphore()->returnValue; + } + } + else { - if (!self->dataIOObj->isAlive()) + ret += ito::RetVal(ito::retError, 0, QObject::tr("Member 'copyVal' of plugin could not be invoked (error in signal/slot connection).").toLatin1().data()); + } + } + else if (PyArg_ParseTuple(args, "O!", &PyDict_Type, &bufferObj)) + { + PyObject* key, * value, * repr, * str; + Py_ssize_t pos = 0; + ito::DataObject* channelDataObj; + QSharedPointer> channelMap(new QMap); + while (PyDict_Next(bufferObj, &pos, &key, &value)) + { + if (PyUnicode_Check(key)) { - timeout = true; - ret += ito::RetVal(ito::retError, 0, QObject::tr("timeout while calling 'copyVal'").toLatin1().data()); - break; + + if ((Py_TYPE(value) == &PythonDataObject::PyDataObjectType)) + { + repr = PyObject_Repr(key); + str = PyUnicode_AsEncodedString(repr, "utf-8", "strict"); + if (((PythonDataObject::PyDataObject*)value)->dataObject) + { + QString key = QString(PyBytes_AS_STRING(str)); + if (key[0] == '\'' && key[key.length() - 1] == '\'') + { + key = key.mid(1, key.length() - 2); + } + (*channelMap)[key] = + ((PythonDataObject::PyDataObject*)value)->dataObject; + } + else + { + Py_XDECREF(repr); + Py_XDECREF(str); + PyErr_SetString( + PyExc_RuntimeError, + "given data object of at least one data object is empty (internal dataObject-pointer is NULL)"); + return NULL; + } + } + else + { + PyErr_SetString( + PyExc_RuntimeError, "The value of at least one item isn't a data object"); + return NULL; + } + } + else + { + PyErr_SetString(PyExc_RuntimeError, "The key of at least one item isn't a string"); + return NULL; } } + ItomSharedSemaphoreLocker locker(new ItomSharedSemaphore()); - if (!timeout) + if (QMetaObject::invokeMethod( + self->dataIOObj, "copyVal", + QArgument > >("QSharedPointer >", channelMap), + Q_ARG(ItomSharedSemaphore*, locker.getSemaphore()))) { - ret += locker.getSemaphore()->returnValue; + bool timeout = false; + + while (!locker.getSemaphore()->wait(AppManagement::timeouts.pluginGeneral)) + { + if (!self->dataIOObj->isAlive()) + { + timeout = true; + ret += ito::RetVal(ito::retError, 0, QObject::tr("timeout while calling 'copyVal'").toLatin1().data()); + break; + } + } + + if (!timeout) + { + ret += locker.getSemaphore()->returnValue; + } + } + else + { + ret += ito::RetVal(ito::retError, 0, QObject::tr("Member 'copyVal' of plugin could not be invoked (error in signal/slot connection).").toLatin1().data()); } + } else { - ret += ito::RetVal(ito::retError, 0, QObject::tr("Member 'copyVal' of plugin could not be invoked (error in signal/slot connection).").toLatin1().data()); + PyErr_SetString(PyExc_TypeError, "argument must be of type itom.dataObject or dict."); + return NULL; } - } else if (self->dataIOObj->getBasePlugin()->getType() & ito::typeADDA) { diff --git a/Qitom/python/pythonQtConversion.cpp b/Qitom/python/pythonQtConversion.cpp index 64e34f87a..b0d6eaa43 100644 --- a/Qitom/python/pythonQtConversion.cpp +++ b/Qitom/python/pythonQtConversion.cpp @@ -3200,6 +3200,32 @@ PyObject* PythonQtConversion::QVariantListToPyObject(const QVariantList& l) return result; } +//------------------------------------------------------------------------------------- +//! conversion from given QMap to python-dictionary. +/*! + returns new reference to python-dict type. Each pair of a QString and a ito::DataObject is one pair in the dictionary. + The values are converted using \a DataObjectToPyObject and \a QStringToPyObject. + + \param m is reference to QMap + \return is the resulting PyObject* + \see DataObjectToPyObject, QStringToPyObject +*/ +PyObject* ito::PythonQtConversion::QMapToPyObject(const QMap& m) +{ + PyObject* result = PyDict_New(); + QMap::const_iterator it = m.constBegin(); + PyObject* key; + PyObject* val; + for (; it != m.constEnd(); it++) + { + key = PythonQtConversion::QStringToPyObject(it.key()); + val = PythonQtConversion::DataObjectToPyObject(it.value()); + PyDict_SetItem(result, key, val); + Py_DECREF(key); + Py_DECREF(val); + } + return result; +} //------------------------------------------------------------------------------------- //! method internally used for conversion from given type-id (QMetaType) and corresponding char*-pointer to PyObject* @@ -3435,6 +3461,20 @@ PyObject* PythonQtConversion::ConvertQtValueToPythonInternal(int type, const voi } return DataObjectToPyObject(*(sharedPtr->data())); } + else if (strcmp(name, "QSharedPointer >") == 0) + { + QSharedPointer >* sharedPtr = (QSharedPointer >*) data; + if (sharedPtr == NULL) + { + PyErr_SetString(PyExc_TypeError, "The given QSharedPointer is NULL"); + return NULL; + } + else + { + return QMapToPyObject(**sharedPtr); + } + + } else if (strcmp(name, "QPointer") == 0 || \ strcmp(name, "QPointer") == 0 || \ strcmp(name, "QPointer") == 0) diff --git a/Qitom/python/pythonQtConversion.h b/Qitom/python/pythonQtConversion.h index f80dc10ba..400991738 100644 --- a/Qitom/python/pythonQtConversion.h +++ b/Qitom/python/pythonQtConversion.h @@ -149,6 +149,8 @@ class PythonQtConversion static PyObject* QVariantMapToPyObject(const QVariantMap& m); static PyObject* QVariantListToPyObject(const QVariantList& l); + static PyObject* QMapToPyObject(const QMap & m); + #if ITOM_POINTCLOUDLIBRARY > 0 static PyObject* PCLPointCloudToPyObject(const ito::PCLPointCloud& c); static PyObject* PCLPointToPyObject(const ito::PCLPoint& c); diff --git a/Qitom/widgets/AIManagerWidget.cpp b/Qitom/widgets/AIManagerWidget.cpp index f7998bac4..a5ba4828d 100644 --- a/Qitom/widgets/AIManagerWidget.cpp +++ b/Qitom/widgets/AIManagerWidget.cpp @@ -57,7 +57,7 @@ AIManagerWidget::AIManagerWidget( m_pMainToolbar(nullptr), m_pViewList(nullptr), m_pViewDetails(nullptr), m_pPlugInModel(nullptr) { int size = 0; - ito::AddInManager* aim = qobject_cast(AppManagement::getAddInManager()); + ito::AddInManager *aim = qobject_cast(AppManagement::getAddInManager()); m_pAIManagerView = new QTreeView(this); m_pAIManagerView->setContextMenuPolicy(Qt::CustomContextMenu); @@ -155,7 +155,7 @@ AIManagerWidget::AIManagerWidget( m_pAIManagerView->expand(index); } - QSettings* settings = new QSettings(AppManagement::getSettingsFile(), QSettings::IniFormat); + QSettings *settings = new QSettings(AppManagement::getSettingsFile(), QSettings::IniFormat); settings->beginGroup("itomPluginsDockWidget"); size = settings->beginReadArray("ColWidth"); for (int i = 0; i < size; ++i) @@ -204,18 +204,18 @@ AIManagerWidget::AIManagerWidget( //------------------------------------------------------------------------------------- AIManagerWidget::~AIManagerWidget() { - ito::AddInManager* aim = qobject_cast(AppManagement::getAddInManager()); + ito::AddInManager *aim = qobject_cast(AppManagement::getAddInManager()); if (aim) { - PlugInModel* plugInModel = (PlugInModel*)(aim->getPluginModel()); + PlugInModel *plugInModel = (PlugInModel*)(aim->getPluginModel()); QString setFile(AppManagement::getSettingsFile()); - QSettings* settings = new QSettings(setFile, QSettings::IniFormat); + QSettings *settings = new QSettings(setFile, QSettings::IniFormat); settings->beginGroup("itomPluginsDockWidget"); - // QByteArray state = m_pMainToolbar->saveGeometry(); - // settings->setValue("stateToolBar", state); + // QByteArray state = m_pMainToolbar->saveGeometry(); + // settings->setValue("stateToolBar", state); settings->beginWriteArray("ColWidth"); @@ -293,8 +293,8 @@ void AIManagerWidget::createMenus() //------------------------------------------------------------------------------------- void AIManagerWidget::createToolBars() { - QWidget* spacerWidget = new QWidget(); - QHBoxLayout* spacerLayout = new QHBoxLayout(); + QWidget *spacerWidget = new QWidget(); + QHBoxLayout *spacerLayout = new QHBoxLayout(); spacerLayout->addItem(new QSpacerItem(5, 5, QSizePolicy::Expanding, QSizePolicy::Minimum)); spacerLayout->setStretch(0, 2); spacerWidget->setLayout(spacerLayout); @@ -341,7 +341,7 @@ void AIManagerWidget::updateActions() { PlugInModel::tItemType itemType; size_t itemInternalData; - PlugInModel* plugInModel = (PlugInModel*)(index.model()); + PlugInModel *plugInModel = (PlugInModel*)(index.model()); if (plugInModel->flags(index) & Qt::ItemIsEnabled) { @@ -351,13 +351,13 @@ void AIManagerWidget::updateActions() // PlugInModel::itemCatActuator || itemType == PlugInModel::itemCatAlgo // || itemType == PlugInModel::itemCatDataIO || itemType == // PlugInModel::itemSubCategoryDataIO_Grabber; - bool isPlugInNode = (itemType == PlugInModel::itemPlugin); - bool isPlugInAlgoNode = plugInModel->getIsAlgoPlugIn(itemType, itemInternalData); - bool isInstanceNode = (itemType == PlugInModel::itemInstance); + bool isPlugInNode = (itemType == PlugInModel::itemPlugin); + bool isPlugInAlgoNode = plugInModel->getIsAlgoPlugIn(itemType, itemInternalData); + bool isInstanceNode = (itemType == PlugInModel::itemInstance); bool isPlugInGrabberNode = plugInModel->getIsGrabberInstance(itemType, itemInternalData); - bool isFilterNode = (itemType == PlugInModel::itemFilter); - bool isWidgetNode = (itemType == PlugInModel::itemWidget); + bool isFilterNode = (itemType == PlugInModel::itemFilter); + bool isWidgetNode = (itemType == PlugInModel::itemWidget); m_pActCloseAllInstances->setVisible(isPlugInNode && !isPlugInAlgoNode); m_pActCloseInstance->setVisible(isInstanceNode); @@ -374,11 +374,11 @@ void AIManagerWidget::updateActions() if (isInstanceNode) { - ito::AddInBase* ais = (ito::AddInBase*)index.internalPointer(); + ito::AddInBase *ais = (ito::AddInBase *)index.internalPointer(); m_pActCloseInstance->setEnabled(ais->createdByGUI() > 0); - QObject* engine = AppManagement::getPythonEngine(); + QObject *engine = AppManagement::getPythonEngine(); m_pActSendToPython->setEnabled(engine); m_pShowConfDialog->setEnabled( @@ -409,7 +409,7 @@ void AIManagerWidget::updateActions() if (m_pActAutoGrabbing->isVisible()) { - ito::AddInBase* ais = (ito::AddInBase*)index.internalPointer(); + ito::AddInBase *ais = (ito::AddInBase *)index.internalPointer(); if (ais) { m_pActAutoGrabbing->setChecked( @@ -466,7 +466,7 @@ QColor AIManagerWidget::backgroundColorInstancesWithPythonRef() const } //------------------------------------------------------------------------------------- -void AIManagerWidget::setBackgroundColorInstancesWithPythonRef(const QColor& bgColor) +void AIManagerWidget::setBackgroundColorInstancesWithPythonRef(const QColor &bgColor) { if (m_pPlugInModel) { @@ -512,7 +512,7 @@ void AIManagerWidget::selectionChanged( //------------------------------------------------------------------------------------- void AIManagerWidget::closeInstance(const QModelIndex index) { - ito::AddInBase* ais = (ito::AddInBase*)index.internalPointer(); + ito::AddInBase *ais = (ito::AddInBase *)index.internalPointer(); if (ais) { if (ais->createdByGUI() == 0) @@ -572,7 +572,7 @@ void AIManagerWidget::closeInstance(const QModelIndex index) } //------------------------------------------------------------------------------------- -void AIManagerWidget::treeViewContextMenuRequested(const QPoint& pos) +void AIManagerWidget::treeViewContextMenuRequested(const QPoint &pos) { updateActions(); m_pContextMenu->exec(pos + m_pAIManagerView->mapToGlobal(m_pAIManagerView->pos())); @@ -590,7 +590,7 @@ void AIManagerWidget::mnuShowConfdialog() if (index.isValid()) { - ito::AddInBase* ais = (ito::AddInBase*)index.internalPointer(); + ito::AddInBase *ais = (ito::AddInBase *)index.internalPointer(); if ((qobject_cast(QCoreApplication::instance())) && ais && ais->hasConfDialog()) { @@ -626,7 +626,7 @@ void AIManagerWidget::mnuToggleDockWidget() if (index.isValid()) { - ito::AddInBase* ais = (ito::AddInBase*)index.internalPointer(); + ito::AddInBase *ais = (ito::AddInBase *)index.internalPointer(); if (ais) { QDockWidget* dockWidget = ais->getDockWidget(); @@ -650,11 +650,11 @@ void AIManagerWidget::mnuCreateNewInstance() if (index.isValid()) { - ito::AddInManager* aim = qobject_cast(AppManagement::getAddInManager()); - ito::AddInInterfaceBase* aib = (ito::AddInInterfaceBase*)index.internalPointer(); + ito::AddInManager *aim = qobject_cast(AppManagement::getAddInManager()); + ito::AddInInterfaceBase *aib = (ito::AddInInterfaceBase*)index.internalPointer(); - DialogNewPluginInstance* dialog = new DialogNewPluginInstance(index, aib); - if (dialog->exec() == 1) // accepted + DialogNewPluginInstance *dialog = new DialogNewPluginInstance(index, aib); + if (dialog->exec() == 1) //accepted { QVector paramsMandNew, paramsOptNew; QString pythonVarName = dialog->getPythonVariable(); @@ -740,7 +740,7 @@ void AIManagerWidget::mnuCreateNewInstance() if (pythonVarName != "") { - QObject* engine = AppManagement::getPythonEngine(); + QObject *engine = AppManagement::getPythonEngine(); if (engine) { ItomSharedSemaphoreLocker locker(new ItomSharedSemaphore()); @@ -826,7 +826,7 @@ void AIManagerWidget::mnuCloseAllInstances() if (index.isValid()) { - const QAbstractItemModel* model = index.model(); + const QAbstractItemModel *model = index.model(); for (int i = model->rowCount(index) - 1; i > -1; --i) { @@ -847,10 +847,10 @@ void AIManagerWidget::mnuSendToPython() if (index.isValid()) { - ito::AddInBase* ais = (ito::AddInBase*)index.internalPointer(); + ito::AddInBase *ais = (ito::AddInBase *)index.internalPointer(); if (ais) { - QObject* engine = AppManagement::getPythonEngine(); + QObject *engine = AppManagement::getPythonEngine(); if (engine) { bool ok = false; @@ -945,11 +945,11 @@ void AIManagerWidget::mnuShowAlgoWidget(ito::AddInAlgo::AlgoWidgetDef* awd) { if (paramsMand.size() > 0 || paramsOpt.size() > 0) { - DialogOpenNewGui* dialog = new DialogOpenNewGui(awd->m_name, paramsMand, paramsOpt); + DialogOpenNewGui *dialog = new DialogOpenNewGui(awd->m_name, paramsMand, paramsOpt); - if (dialog->exec() == 1) // accepted + if (dialog->exec() == 1) //accepted { - // QString pythonVarName = dialog->getPythonVariable(); + //QString pythonVarName = dialog->getPythonVariable(); ito::RetVal retValue = ito::retOk; ito::AddInBase* basePlugin = nullptr; @@ -966,7 +966,7 @@ void AIManagerWidget::mnuShowAlgoWidget(ito::AddInAlgo::AlgoWidgetDef* awd) } } - UiOrganizer* uiOrganizer = qobject_cast(AppManagement::getUiOrganizer()); + UiOrganizer *uiOrganizer = qobject_cast(AppManagement::getUiOrganizer()); QSharedPointer dialogHandle(new unsigned int); QSharedPointer retCodeIfModal(new int); QSharedPointer objectID(new unsigned int); @@ -1065,15 +1065,14 @@ void AIManagerWidget::mnuShowLiveImage() if (index.isValid()) { - ito::AddInBase* ais = (ito::AddInBase*)index.internalPointer(); - - if (ais && ais->inherits("ito::AddInGrabber")) + ito::AddInBase *ais = (ito::AddInBase *)index.internalPointer(); + if (ais && ais->inherits("ito::AbstractAddInGrabber")) { - UiOrganizer* uiOrg = (UiOrganizer*)AppManagement::getUiOrganizer(); + UiOrganizer *uiOrg = (UiOrganizer*)AppManagement::getUiOrganizer(); QString defaultPlotClassName; QSharedPointer objectID(new unsigned int); QSharedPointer figHandle(new unsigned int); - *figHandle = 0; // new figure will be requested + *figHandle = 0; //new figure will be requested ito::RetVal retval = uiOrg->figureLiveImage( (ito::AddInDataIO*)ais, @@ -1123,13 +1122,12 @@ void AIManagerWidget::mnuSnapDialog() if (index.isValid()) { - ito::AddInBase* ais = (ito::AddInBase*)index.internalPointer(); - - if (ais && ais->inherits("ito::AddInGrabber")) + ito::AddInBase *ais = (ito::AddInBase *)index.internalPointer(); + if (ais && ais->inherits("ito::AbstractAddInGrabber")) { ito::RetVal retval = ito::retOk; QPointer aisPointer((ito::AddInDataIO*)ais); - DialogSnapshot* snapDialog = new DialogSnapshot(this, aisPointer, retval); + DialogSnapshot *snapDialog = new DialogSnapshot(this, aisPointer, retval); snapDialog->setAttribute(Qt::WA_DeleteOnClose, true); snapDialog->show(); @@ -1171,7 +1169,7 @@ void AIManagerWidget::mnuToggleAutoGrabbing() if (index.isValid()) { - ito::AddInBase* ais = (ito::AddInBase*)index.internalPointer(); + ito::AddInBase *ais = (ito::AddInBase *)index.internalPointer(); if (ais) { @@ -1187,14 +1185,14 @@ void AIManagerWidget::mnuToggleAutoGrabbing() QMetaObject::invokeMethod( ais, "disableAutoGrabbing", Q_ARG(ItomSharedSemaphore*, waitCond)); } - waitCond->deleteSemaphore(); + waitCond->deleteSemaphore(); waitCond = nullptr; } } } //------------------------------------------------------------------------------------- -void AIManagerWidget::setTreeViewHideColumns(const bool& hide, const int colCount) +void AIManagerWidget::setTreeViewHideColumns(const bool &hide, const int colCount) { for (int i = 1; i < colCount; ++i) { @@ -1205,8 +1203,8 @@ void AIManagerWidget::setTreeViewHideColumns(const bool& hide, const int colCoun //------------------------------------------------------------------------------------- void AIManagerWidget::showList() { - ito::AddInManager* aim = qobject_cast(AppManagement::getAddInManager()); - PlugInModel* plugInModel = (PlugInModel*)(aim->getPluginModel()); + ito::AddInManager *aim = qobject_cast(AppManagement::getAddInManager()); + PlugInModel *plugInModel = (PlugInModel*)(aim->getPluginModel()); bool isList = true; for (int i = 1; i < plugInModel->columnCount(); ++i) @@ -1241,8 +1239,8 @@ void AIManagerWidget::mnuToggleView() //------------------------------------------------------------------------------------- void AIManagerWidget::showDetails() { - ito::AddInManager* aim = qobject_cast(AppManagement::getAddInManager()); - PlugInModel* plugInModel = (PlugInModel*)(aim->getPluginModel()); + ito::AddInManager *aim = qobject_cast(AppManagement::getAddInManager()); + PlugInModel *plugInModel = (PlugInModel*)(aim->getPluginModel()); bool isList = true; for (int i = 1; i < plugInModel->columnCount(); ++i) @@ -1282,12 +1280,12 @@ void AIManagerWidget::mnuShowInfo() { if (itemType & PlugInModel::itemFilter) { // Filter - ito::AddInAlgo::FilterDef* awd = (ito::AddInAlgo::FilterDef*)itemInternalData; + ito::AddInAlgo::FilterDef *awd = (ito::AddInAlgo::FilterDef*)itemInternalData; emit showPluginInfo( "Algorithms." + awd->m_pBasePlugin->objectName() + "." + awd->m_name, HelpTreeDockWidget::typeFilter); } - else if (itemType & PlugInModel::itemWidget) + else if(itemType & PlugInModel::itemWidget) { // Widget ito::AddInAlgo::AlgoWidgetDef* awd = (ito::AddInAlgo::AlgoWidgetDef*)itemInternalData; @@ -1295,9 +1293,9 @@ void AIManagerWidget::mnuShowInfo() "Widgets." + awd->m_pBasePlugin->objectName() + "." + awd->m_name, HelpTreeDockWidget::typeWidget); } - else if (itemType & PlugInModel::itemPlugin) + else if(itemType & PlugInModel::itemPlugin) { // DataIO and Actuator and Plugins (eg BasicFilters) - ito::AddInInterfaceBase* aib = (ito::AddInInterfaceBase*)itemInternalData; + ito::AddInInterfaceBase *aib = (ito::AddInInterfaceBase*)itemInternalData; if (aib->getType() & ito::typeActuator) { emit showPluginInfo( @@ -1331,4 +1329,4 @@ void AIManagerWidget::mnuShowInfo() } } -} // end namespace ito +} //end namespace ito diff --git a/Qitom/widgets/figureWidget.cpp b/Qitom/widgets/figureWidget.cpp index 2acbfaf35..ff8aa4ead 100644 --- a/Qitom/widgets/figureWidget.cpp +++ b/Qitom/widgets/figureWidget.cpp @@ -29,11 +29,13 @@ #include "../helper/guiHelper.h" #include "plot/AbstractDObjFigure.h" #include "plot/AbstractDObjPCLFigure.h" +#include "../common/addInMultiChannelGrabber.h" #include #include + namespace ito { //---------------------------------------------------------------------------------------------------------------------------------- @@ -471,10 +473,9 @@ RetVal FigureWidget::liveImage( DesignerWidgetOrganizer *dwo = qobject_cast(AppManagement::getDesignerWidgetOrganizer()); RetVal retval; QString plotClassName; -// bool exists = false; int idx = areaCol + areaRow * m_cols; - *canvasWidget = NULL; + *canvasWidget = nullptr; if (!dwo) { @@ -487,34 +488,66 @@ RetVal FigureWidget::liveImage( else { //get grabDepth - bool setDepth = false; bool isLine = false; - ito::AutoInterval bitRange (0.0, 1.0); - QSharedPointer bpp = getParamByInvoke(cam.data(), "bpp", retval); + ito::AutoInterval bitRange(0.0, 1.0); - if (!retval.containsError()) - { - if (bpp->getVal() == 8) - { - setDepth = true; - bitRange.setMaximum(255.0); - } - else if (bpp->getVal() < 17) + if (qobject_cast(cam)) + { + auto paramDefaultChannel = getParamByInvoke(cam.data(), "defaultChannel", retval); + QString channel = ""; + + if (!retval.containsError()) { - setDepth = true; - bitRange.setMaximum((float)((1 << bpp->getVal())-1)); + channel = QString(":") + paramDefaultChannel->getVal(); } - else if (bpp->getVal() == 32) + + auto paramFormat = getParamByInvoke(cam.data(), QString("pixelFormat%1").arg(channel), retval); + + if (!retval.containsError() && !paramFormat.isNull()) { - // ToDo define float32 and int32 behavior! + const char* pixelFormat = paramFormat->getVal(); + int min, max = 0; + bool ok = false; + AbstractAddInGrabber::minMaxBoundariesFromIntegerPixelFormat(pixelFormat, min, max, ok); + + if (ok) + { + bitRange.setMaximum(max); + bitRange.setMinimum(min); + } + else + { + bitRange.setAuto(true); + } } - else if (bpp->getVal() == 64) + } + else // fall back for AddInGrabber + { + auto paramBpp = getParamByInvoke(cam.data(), "bpp", retval); + + if (!retval.containsError() && !paramBpp.isNull()) { - // ToDo define float64 behavior! - } + int bpp = paramBpp->getVal(); - } + if (bpp == 8) + { + bitRange.setMaximum(255.0); + } + else if (bpp < 17) + { + bitRange.setMaximum((float)((1 << bpp) - 1)); + } + else if (bpp == 32) + { + bitRange.setAuto(true); + } + else if (bpp == 64) + { + bitRange.setAuto(true); + } + } + } //get size of camera image QSharedPointer sizex = getParamByInvoke(cam.data(), "sizex", retval); QSharedPointer sizey = getParamByInvoke(cam.data(), "sizey", retval); @@ -590,10 +623,13 @@ RetVal FigureWidget::liveImage( dObjFigure->setProperty("yAxisFlipped", true); } - if (setDepth) + if (isLine) + { + dObjFigure->setYAxisInterval(bitRange); + } + else { - if (isLine) dObjFigure->setYAxisInterval(bitRange); - else dObjFigure->setZAxisInterval(bitRange); + dObjFigure->setZAxisInterval(bitRange); } dObjFigure->setCamera(cam); @@ -605,18 +641,21 @@ RetVal FigureWidget::liveImage( //check if dObjFigure has property "yAxisFlipped" and flip it, if so. QVariant yAxisFlipped = dObjPclFigure->property("yAxisFlipped"); + if (yAxisFlipped.isValid()) { dObjPclFigure->setProperty("yAxisFlipped", true); } - if (setDepth) + if (isLine) { - if (isLine) dObjPclFigure->setYAxisInterval(bitRange); - else dObjPclFigure->setZAxisInterval(bitRange); + dObjPclFigure->setYAxisInterval(bitRange); + } + else + { + dObjPclFigure->setZAxisInterval(bitRange); } -// dObjPclFigure->setCamera(cam); *canvasWidget = destWidget; } else @@ -815,30 +854,23 @@ QSharedPointer FigureWidget::getParamByInvoke(ito::AddInBase* addIn, { QSharedPointer result; - if (addIn == NULL) + if (addIn == nullptr) { retval += RetVal(retError, 0, tr("addInBase pointer is NULL").toLatin1().data()); } else { ItomSharedSemaphoreLocker locker(new ItomSharedSemaphore()); - ito::Param param = addIn->getParamRec(paramName); - if (param.getName() != NULL) // Parameter is defined + result = QSharedPointer(new ito::Param(ito::ByteArray(paramName.toLatin1().data()))); + QMetaObject::invokeMethod(addIn, "getParam", Q_ARG(QSharedPointer, result), Q_ARG(ItomSharedSemaphore*, locker.getSemaphore())); + + if (!locker.getSemaphore()->wait(PLUGINWAIT)) { - result = QSharedPointer(new ito::Param(param)); - QMetaObject::invokeMethod(addIn, "getParam", Q_ARG(QSharedPointer, result), Q_ARG(ItomSharedSemaphore*, locker.getSemaphore())); - if (!locker.getSemaphore()->wait(PLUGINWAIT)) - { - retval += RetVal::format(retError, 0, tr("timeout while getting parameter '%s' from plugin").toLatin1().data(), paramName.toLatin1().data()); - } - else - { - retval += locker.getSemaphore()->returnValue; - } + retval += RetVal::format(retError, 0, tr("timeout while getting parameter '%s' from plugin").toLatin1().data(), paramName.toLatin1().data()); } else { - retval += RetVal::format(retError, 0, tr("parameter '%s' is not defined in plugin").toLatin1().data(), paramName.toLatin1().data()); + retval += locker.getSemaphore()->returnValue; } } diff --git a/common/abstractAddInConfigDialog.h b/common/abstractAddInConfigDialog.h index c488e5cf1..efc6ab5fc 100644 --- a/common/abstractAddInConfigDialog.h +++ b/common/abstractAddInConfigDialog.h @@ -1,7 +1,7 @@ /* ******************************************************************** itom software URL: http://www.uni-stuttgart.de/ito - Copyright (C) 2020, Institut fuer Technische Optik (ITO), + Copyright (C) 2023, Institut fuer Technische Optik (ITO), Universitaet Stuttgart, Germany This file is part of itom and its software development toolkit (SDK). @@ -25,8 +25,7 @@ along with itom. If not, see . *********************************************************************** */ -#ifndef ABSTRACTADDINCONFIGDIALOG_H -#define ABSTRACTADDINCONFIGDIALOG_H +#pragma once #include "retVal.h" #include "typeDefs.h" @@ -41,8 +40,6 @@ - - //forward declarations namespace ito { @@ -156,10 +153,14 @@ namespace ito */ virtual ito::RetVal observeInvocation(ItomSharedSemaphore *waitCond, MessageLevel msgLevel) const; - QMap m_currentParameters; /*! use this map to save the current values of all parameters. For instance it is conventient to copy the map given in parametersChanged to this map */ + /*! use this map to save the current values of all parameters. + For instance it is conventient to copy the map given in parametersChanged to this map */ + QMap m_currentParameters; private: - AbstractAddInConfigDialogPrivate* d; /*! private data pointer of this class. */ + /*! private data pointer of this class. */ + QScopedPointer d_ptr; + Q_DECLARE_PRIVATE(AbstractAddInConfigDialog); public slots: //! slot invoked if any parameter of the plugin has been changed. @@ -174,5 +175,3 @@ namespace ito virtual void parametersChanged(QMap params) = 0; }; } //end namespace ito - -#endif //ABSTRACTADDINCONFIGDIALOG_H diff --git a/common/abstractAddInDockWidget.h b/common/abstractAddInDockWidget.h index 882083662..fcfc27c7c 100644 --- a/common/abstractAddInDockWidget.h +++ b/common/abstractAddInDockWidget.h @@ -1,7 +1,7 @@ /* ******************************************************************** itom software URL: http://www.uni-stuttgart.de/ito - Copyright (C) 2020, Institut fuer Technische Optik (ITO), + Copyright (C) 2023, Institut fuer Technische Optik (ITO), Universitaet Stuttgart, Germany This file is part of itom and its software development toolkit (SDK). @@ -25,8 +25,7 @@ along with itom. If not, see . *********************************************************************** */ -#ifndef ABSTRACTADDINDOCKWIDGET_H -#define ABSTRACTADDINDOCKWIDGET_H +#pragma once #include "retVal.h" #include "typeDefs.h" @@ -183,7 +182,9 @@ namespace ito ito::RetVal requestActuatorStatusAndPositions(bool sendCurrentPos, bool sendTargetPos, MessageLevel msgLevel = msgLevelWarningAndError) const; private: - AbstractAddInDockWidgetPrivate* d; /*! private data pointer of this class. */ + /*! private data pointer of this class. */ + QScopedPointer d_ptr; + Q_DECLARE_PRIVATE(AbstractAddInDockWidget); public slots: //! slot invoked if any parameter of the plugin has been changed. @@ -231,5 +232,3 @@ namespace ito virtual void targetChanged(QVector targetPositions); }; } //end namespace ito - -#endif //ABSTRACTADDINDOCKWIDGET_H diff --git a/common/abstractAddInGrabber.h b/common/abstractAddInGrabber.h new file mode 100644 index 000000000..a481f35a0 --- /dev/null +++ b/common/abstractAddInGrabber.h @@ -0,0 +1,125 @@ +/* ******************************************************************** + itom software + URL: http://www.uni-stuttgart.de/ito + Copyright (C) 2023, Institut fuer Technische Optik (ITO), + Universitaet Stuttgart, Germany + + This file is part of itom and its software development toolkit (SDK). + + itom is free software; you can redistribute it and/or modify it + under the terms of the GNU Library General Public Licence as published by + the Free Software Foundation; either version 2 of the Licence, or (at + your option) any later version. + + In addition, as a special exception, the Institut fuer Technische + Optik (ITO) gives you certain additional rights. + These rights are described in the ITO LGPL Exception version 1.0, + which can be found in the file LGPL_EXCEPTION.txt in this package. + + itom is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library + General Public Licence for more details. + + You should have received a copy of the GNU Library General Public License + along with itom. If not, see . +*********************************************************************** */ + +#pragma once + +#include "addInInterface.h" + +#include "../DataObject/dataobj.h" +#include "sharedStructuresQt.h" +#include "sharedStructures.h" + +#if !defined(Q_MOC_RUN) || defined(ITOMCOMMONQT_MOC) //only moc this file in itomCommonQtLib but not in other libraries or executables linking against this itomCommonQtLib + +namespace ito +{ + class AbstractAddInGrabberPrivate; + + class ITOMCOMMONQT_EXPORT AbstractAddInGrabber : public ito::AddInDataIO + { + Q_OBJECT + public: + + // all items must be lowercase! + enum PixelFormat + { + mono8 = ito::tUInt8, + mono8s = ito::tInt8, + mono10 = ito::tUInt16, + mono10Packed = ito::tUInt16, + mono12 = ito::tUInt16, + mono12Packed = ito::tUInt16, + mono14 = ito::tUInt16, + mono14Packed = ito::tUInt16, + mono16 = ito::tUInt16, + rgb8 = ito::tRGBA32, + rgba8 = ito::tRGBA32, + rgb8Planar = ito::tUInt8, + rgb10Planar = ito::tUInt16, + rgb12Planar = ito::tUInt16, + rgb16Planar = ito::tUInt16, + rg8 = ito::tRGBA32, + rg8Packed = ito::tRGBA32, + gb8 = ito::tRGBA32, + float32 = ito::tFloat32, + float64 = ito::tFloat64, + complex64 = ito::tComplex64, + complex128 = ito::tComplex128, + }; + + Q_ENUM(PixelFormat) + + private: + QScopedPointer d_ptr; + Q_DECLARE_PRIVATE(AbstractAddInGrabber); + + protected: + /*!< this method is called every time when the auto-grabbing-timer is fired. Usually you don't have to overwrite this method. */ + void timerEvent (QTimerEvent *event); + + //! implement this method in your camera plugin. In this method the image is grabbed and stored in the m_image variable. + /*! + Call this method in getVal(...) in order to get the image from the camera and deeply copy it the the m_image variable. + This method is equally called from timerEvent. + + \return retOk if copy operation was successfull, else retWarning or retError + \sa getVal, timerEvent + */ + virtual ito::RetVal retrieveData(ito::DataObject *externalDataObject = nullptr) = 0; + + virtual ito::RetVal sendDataToListeners(int waitMS) = 0; /*!< sends m_data to all registered listeners. */ + + /*!< returns the number of started devices \see m_started */ + int grabberStartedCount() const; + + /*!< increments the number of started devices \see m_started */ + void incGrabberStarted(); + + /*!< decrements the number of started devices \see m_started */ + void decGrabberStarted(); + + /*!< sets the number of started devices to a given value \see m_started */ + void setGrabberStarted(int value); + + public: + /*!< this method gives the value range pixel for a given integer pixelFormat */ + static void minMaxBoundariesFromIntegerPixelFormat( + const QByteArray &pixelFormat, + int& min, + int& max, + bool& ok); + + /*!< this method maps a string to a value of PixelFormat */ + static int itoDataTypeFromPixelFormat(const QByteArray &pixelFormat, bool *ok = nullptr); + + AbstractAddInGrabber(); + ~AbstractAddInGrabber(); + }; + +} //end namespace ito + +#endif //#if !defined(Q_MOC_RUN) || defined(ITOMCOMMONQT_MOC) diff --git a/common/addInGrabber.h b/common/addInGrabber.h index ad4bbdee8..f7fe9fe0b 100644 --- a/common/addInGrabber.h +++ b/common/addInGrabber.h @@ -1,7 +1,7 @@ /* ******************************************************************** itom software URL: http://www.uni-stuttgart.de/ito - Copyright (C) 2020, Institut fuer Technische Optik (ITO), + Copyright (C) 2023, Institut fuer Technische Optik (ITO), Universitaet Stuttgart, Germany This file is part of itom and its software development toolkit (SDK). @@ -25,10 +25,9 @@ along with itom. If not, see . *********************************************************************** */ -#ifndef ADDINGRABBER_H -#define ADDINGRABBER_H +#pragma once -#include "addInInterface.h" +#include "abstractAddInGrabber.h" #include "../DataObject/dataobj.h" #include "sharedStructuresQt.h" @@ -40,87 +39,35 @@ namespace ito { class AddInGrabberPrivate; - class ITOMCOMMONQT_EXPORT AddInGrabber : public ito::AddInDataIO + class ITOMCOMMONQT_EXPORT AddInGrabber : public AbstractAddInGrabber { Q_OBJECT - private: - //! counter indicating how many times startDevice has been called - /*! - increment this variable every time startDevice is called (by incGrabberStarted()) - decrement this variable every time stopDevice is called (by decGrabberStarted()) - - \sa grabberStartedCount, incGrabberStarted, decGrabberStarted, setGrabberStarted - */ - int m_started; - - AddInGrabberPrivate *dd; + QScopedPointer d_ptr; + Q_DECLARE_PRIVATE(AddInGrabber); protected: - void timerEvent (QTimerEvent *event); /*!< this method is called every time when the auto-grabbing-timer is fired. Usually you don't have to overwrite this method. */ + ito::DataObject m_data; /*!< variable for the recently grabbed image*/ //! implement this method in order to check if m_image should be (re)allocated with respect to the current sizex, sizey, bpp... /*! - Call this method if the size or bitdepth of your camera has changed (e.g. in your constructor, too). In this method, compare if the new size - is equal to the old one. If this is not the case, use the following example to set m_image to a newly allocated dataObject. The old dataObject - is deleted automatically with respect to its internal reference counter: + Call this method if the size or bitdepth of your camera has changed (e.g. in your constructor, too). In this method, compare if the new size + is equal to the old one. If this is not the case, use the following example to set m_image to a newly allocated dataObject. The old dataObject + is deleted automatically with respect to its internal reference counter: - m_image = ito::DataObject(futureHeight,futureWidth,futureType); + m_image = ito::DataObject(futureHeight,futureWidth,futureType); - \see m_image + \see m_image */ - virtual ito::RetVal checkData(ito::DataObject *externalDataObject = NULL); - - //! implement this method in your camera plugin. In this method the image is grabbed and stored in the m_image variable. - /*! - Call this method in getVal(...) in order to get the image from the camera and deeply copy it the the m_image variable. - This method is equally called from timerEvent. - - \return retOk if copy operation was successfull, else retWarning or retError - \sa getVal, timerEvent - */ - virtual ito::RetVal retrieveData(ito::DataObject *externalDataObject = NULL) = 0; - - ito::RetVal sendDataToListeners(int waitMS); /*!< sends m_data to all registered listeners. */ - - inline int grabberStartedCount() { return m_started; } /*!< returns the number of started devices \see m_started */ - - /*!< increments the number of started devices \see m_started */ - inline void incGrabberStarted() - { - m_started++; - if(m_started == 1) - { - runStatusChanged(true); //now, the device is started -> check if any listener is connected and if so start the auto grabbing timer (if flag is true, too) - } - } - - /*!< decrements the number of started devices \see m_started */ - inline void decGrabberStarted() - { - m_started--; - if(m_started == 0) - { - runStatusChanged(false); //now, the device is stopped -> stop any possibly started auto grabbing listener - } - } - - /*!< sets the number of started devices to a given value \see m_started */ - inline void setGrabberStarted(int value) - { - m_started = value; - runStatusChanged( value > 0 ); - } - - ito::DataObject m_data; /*!< variable for the recently grabbed image */ + virtual ito::RetVal checkData(ito::DataObject *externalDataObject = nullptr); + virtual ito::RetVal sendDataToListeners(int waitMS); /*!< sends m_data to all registered listeners. */ public: AddInGrabber(); ~AddInGrabber(); }; + } //end namespace ito #endif //#if !defined(Q_MOC_RUN) || defined(ITOMCOMMONQT_MOC) - -#endif diff --git a/common/addInInterface.h b/common/addInInterface.h old mode 100755 new mode 100644 index 442799d81..49d0de92a --- a/common/addInInterface.h +++ b/common/addInInterface.h @@ -1,7 +1,7 @@ /* ******************************************************************** itom software URL: http://www.uni-stuttgart.de/ito -Copyright (C) 2020, Institut fuer Technische Optik (ITO), +Copyright (C) 2023, Institut fuer Technische Optik (ITO), Universitaet Stuttgart, Germany This file is part of itom and its software development toolkit (SDK). @@ -25,34 +25,33 @@ You should have received a copy of the GNU Library General Public License along with itom. If not, see . *********************************************************************** */ -#ifndef ADDININTERFACE_H -#define ADDININTERFACE_H +#pragma once #include "commonGlobal.h" -#include "apiFunctionsInc.h" #include "apiFunctionsGraphInc.h" +#include "apiFunctionsInc.h" #include "addInInterfaceVersion.h" -#include "sharedStructuresQt.h" -#include "sharedStructures.h" #include "functionCancellationAndObserver.h" +#include "sharedStructures.h" +#include "sharedStructuresQt.h" +#include +#include #include #include +#include #include +#include #include -#include #include -#include -#include -#include -#include +#include -//plugins define VISUAL_LEAK_DETECTOR_CMAKE in their CMake configuration file -#if defined _DEBUG && defined(_MSC_VER) && defined(VISUAL_LEAK_DETECTOR_CMAKE) +// plugins define VISUAL_LEAK_DETECTOR_CMAKE in their CMake configuration file +#if defined _DEBUG && defined(_MSC_VER) && defined(VISUAL_LEAK_DETECTOR_CMAKE) #ifndef NOMINAX -#define NOMINMAX //instead min, max is defined as macro in winDef.h, included by vld.h +#define NOMINMAX // instead min, max is defined as macro in winDef.h, included by vld.h #include "vld.h" #undef NOMINMAX #else @@ -60,17 +59,18 @@ along with itom. If not, see . #endif #endif -#if !defined(Q_MOC_RUN) || defined(ITOMCOMMONQT_MOC) //only moc this file in itomCommonQtLib but not in other libraries or executables linking against this itomCommonQtLib +#if !defined(Q_MOC_RUN) || defined(ITOMCOMMONQT_MOC) // only moc this file in itomCommonQtLib but not in other libraries + // or executables linking against this itomCommonQtLib //! macro to create a new plugin instance in the method getAddInInst of any plugin /*! Insert this macro at the first line of the method getAddInInst of your plugin. Pass the name of the corresponding plugin class (not its interface class) */ -#define NEW_PLUGININSTANCE(PluginClass) \ - PluginClass* newInst = new PluginClass(); \ - newInst->setBasePlugin(this); \ - *addInInst = qobject_cast(newInst); \ +#define NEW_PLUGININSTANCE(PluginClass) \ + PluginClass *newInst = new PluginClass(); \ + newInst->setBasePlugin(this); \ + *addInInst = qobject_cast(newInst); \ m_InstList.append(*addInInst); //! macro to delete a plugin instance in the method closeThisInst of any plugin @@ -79,39 +79,46 @@ Insert this macro at the first line of the method closeThisInst of your plugin. Pass the name of the corresponding plugin class (not its interface class). This macro is the opposite of NEW_PLUGININSTANCE */ -#define REMOVE_PLUGININSTANCE(PluginClass) \ - if (*addInInst) \ - { \ - (*addInInst)->deleteLater(); \ - m_InstList.removeOne(*addInInst); \ - } +#define REMOVE_PLUGININSTANCE(PluginClass) \ + if (*addInInst) \ + { \ + (*addInInst)->deleteLater(); \ + m_InstList.removeOne(*addInInst); \ + } //! macro to set the pointer of the plugin to all its defined filters and widgets /*! Insert this macro right after NEW_PLUGININSTANCE in all plugins that are algo plugins. */ -#define REGISTER_FILTERS_AND_WIDGETS \ - foreach(ito::AddInAlgo::FilterDef *f, newInst->m_filterList) \ - { \ - f->m_pBasePlugin = this; \ - } \ - foreach(ito::AddInAlgo::AlgoWidgetDef *w, newInst->m_algoWidgetList) \ - { \ - w->m_pBasePlugin = this; \ - } - -//write this macro right after Q_INTERFACE(...) in your interface class definition -#define PLUGIN_ITOM_API \ - protected: \ - void importItomApi(void** apiPtr) \ - {ito::ITOM_API_FUNCS = apiPtr;} \ - void importItomApiGraph(void** apiPtr) \ - { ito::ITOM_API_FUNCS_GRAPH = apiPtr;} \ - public: \ - virtual int getAddInInterfaceVersion() const \ - { return ITOM_ADDININTERFACE_VERSION; } \ - //. +#define REGISTER_FILTERS_AND_WIDGETS \ + foreach (ito::AddInAlgo::FilterDef *f, newInst->m_filterList) \ + { \ + f->m_pBasePlugin = this; \ + } \ + foreach (ito::AddInAlgo::AlgoWidgetDef *w, newInst->m_algoWidgetList) \ + { \ + w->m_pBasePlugin = this; \ + } + +// write this macro right after Q_INTERFACE(...) in your interface class definition +#define PLUGIN_ITOM_API \ + protected: \ + void importItomApi(void **apiPtr) \ + { \ + ito::ITOM_API_FUNCS = apiPtr; \ + } \ + void importItomApiGraph(void **apiPtr) \ + { \ + ito::ITOM_API_FUNCS_GRAPH = apiPtr; \ + } \ + \ + public: \ + virtual int getAddInInterfaceVersion() const \ + { \ + return ITOM_ADDININTERFACE_VERSION; \ + } \ + //. QT_BEGIN_NAMESPACE class QPluginLoader; @@ -119,994 +126,1199 @@ QT_END_NAMESPACE namespace ito { - //---------------------------------------------------------------------------------------------------------------------------------- - //! tPluginType enumeration - /*! - used to describe the plugin type and subtype (in case of DataIO main type) - e.g. typeDataIO|typeGrabber for a frame grabber - */ - enum tPluginType +//---------------------------------------------------------------------------------------------------------------------------------- +//! tPluginType enumeration +/*! +used to describe the plugin type and subtype (in case of DataIO main type) +e.g. typeDataIO|typeGrabber for a frame grabber +*/ +enum tPluginType +{ + typeDataIO = 0x1, /*!< base type for data input and output (cameras, AD-converter, display windows...) */ + typeActuator = 0x2, /*!< base type for actuators and motors */ + typeAlgo = 0x4, /*!< base type for algorithm plugin */ + typeGrabber = 0x80, /*!< subtype of dataIO for cameras (grabbers), use this type in combination with typeDataIO + (OR-combination) */ + typeADDA = 0x100, /*!< subtype of dataIO for AD and DA-converters, use this type in combination with typeDataIO + (OR-combination) */ + typeRawIO = 0x200 /*!< subtype of dataIO for further input-output-devices (like display windows), use this type in + combination with typeDataIO (OR-combination) */ +}; + +//! tActuatorStatus enumeration +/*! +flags used for describing the status of one axis of an actuator plugin. + +These flags are intended to be combined in the status bitmask. +Usually the bitmask for each mask is saved in the vector ito::AddInActuator::m_currentStatus +of an actuator plugin. + +The bitmask is divided into different topical areas (moving flags, switches, general status). +*/ +enum tActuatorStatus +{ + // moving flags + actuatorUnknown = 0x0001, /*!< moving status of axis is unknown */ + actuatorInterrupted = 0x0002, /*!< movement has been interrupted by the user, axis is immediately stopped */ + actuatorMoving = 0x0004, /*!< axis is currently moving */ + actuatorAtTarget = 0x0008, /*!< axis reached target */ + actuatorTimeout = 0x0010, /*!< no signal from axis, timeout */ + // switches + actuatorEndSwitch = 0x0100, /*!< axis reached an undefined end switch */ + actuatorLeftEndSwitch = + 0x0200, /*!< axis reached the specified left end switch (if set, also set actuatorEndSwitch), deprecated */ + actuatorRightEndSwitch = + 0x0400, /*!< axis reached the specified right end switch (if set, also set actuatorEndSwitch), deprecated */ + actuatorEndSwitch1 = 0x0200, /*!< axis reached the specified left end switch (if set, also set actuatorEndSwitch) */ + actuatorEndSwitch2 = 0x0400, /*!< axis reached the specified left end switch (if set, also set actuatorEndSwitch) */ + actuatorRefSwitch = 0x0800, /*!< axis reached an undefined reference switch */ + actuatorLeftRefSwitch = 0x1000, /*!< axis reached the specified left reference switch (if set, also set + actuatorRefSwitch), deprecated */ + actuatorRightRefSwitch = 0x2000, /*!< axis reached the specified right reference switch (if set, also set + actuatorRefSwitch), deprecated */ + actuatorRefSwitch1 = + 0x1000, /*!< axis reached the specified right reference switch (if set, also set actuatorRefSwitch)*/ + actuatorRefSwitch2 = + 0x2000, /*!< axis reached the specified right reference switch (if set, also set actuatorRefSwitch)*/ + + // status flags + actuatorAvailable = 0x4000, /*!< axis is generally available */ + actuatorEnabled = 0x8000, /*!< axis is enabled for movements */ + actuatorError = 0x10000, /*axis has encountered error/reports error*/ + + actMovingMask = actuatorUnknown | actuatorInterrupted | actuatorMoving | actuatorAtTarget | + actuatorTimeout, /*!< bitmask that marks all bits related to the movement */ + + actEndSwitchMask = actuatorEndSwitch | actuatorEndSwitch1 | + actuatorEndSwitch2, /*!< bitmask that marks all bits related to end switches */ + + actRefSwitchMask = actuatorRefSwitch | actuatorRefSwitch1 | + actuatorRefSwitch2, /*!< bitmask that marks all bits related to reference switches */ + + actSwitchesMask = + actEndSwitchMask | actRefSwitchMask, /*!< bitmask that marks all bits related to reference and end switches */ + + actStatusMask = actuatorAvailable | actuatorEnabled | actuatorError /*!< bitmask that marks all status flags */ +}; + +enum tAutoLoadPolicy +{ + autoLoadAlways = 0x1, /*!< always loads xml file by addInManager */ + autoLoadNever = 0x2, /*!< never automatically loads parameters from xml-file (default) */ + autoLoadKeywordDefined = 0x4 /*!< only loads parameters if keyword autoLoadParams=1 exists in python-constructor */ +}; + +enum tAutoSavePolicy +{ + autoSaveAlways = 0x1, /*!< always saves parameters to xml-file at shutdown */ + autoSaveNever = 0x2 /*!< never saves parameters to xml-file at shutdown (default) */ +}; + +struct ExecFuncParams +{ + ExecFuncParams() : infoString("") { - typeDataIO = 0x1, /*!< base type for data input and output (cameras, AD-converter, display windows...) */ - typeActuator = 0x2, /*!< base type for actuators and motors */ - typeAlgo = 0x4, /*!< base type for algorithm plugin */ - typeGrabber = 0x80, /*!< subtype of dataIO for cameras (grabbers), use this type in combination with typeDataIO (OR-combination) */ - typeADDA = 0x100, /*!< subtype of dataIO for AD and DA-converters, use this type in combination with typeDataIO (OR-combination) */ - typeRawIO = 0x200 /*!< subtype of dataIO for further input-output-devices (like display windows), use this type in combination with typeDataIO (OR-combination) */ - }; + } + QVector paramsMand; /*!< mandatory parameters (default set), must have flag In or In|Out */ + QVector paramsOpt; /*!< optional parameters (default set), must have flag In or In|Out */ + QVector paramsOut; /*!< return parameters (default set), must have Out. Only types + Int,Char,Double,String,IntArray,CharArray or DoubleArray are allowed. */ + QString infoString; +}; + +struct FilterParams +{ + QVector paramsMand; + QVector paramsOpt; + QVector paramsOut; +}; + +class AddInBase; //!< forward declaration +class DataObject; +class AddInBasePrivate; //!< forward declaration to private container class of AddInBase +class AddInInterfaceBasePrivate; //!< forward declaration to private container class of AddInInterfaceBase +class AddInActuatorPrivate; //!< forward declaration to private container class of AddInActuator +class AddInDataIOPrivate; //!< forward declaration to private container class of AddInDataIO +class AddInAlgoPrivate; //!< forward declaration to private container class of AddInAlog + +//---------------------------------------------------------------------------------------------------------------------------------- +/** @class AddInInterfaceBase + * @brief class of the AddIn - Library (DLL) - Interface + * + * The measurement program can (and should) be expanded with additional functionality by "plugins". The aim of + * separating part of the program into plugins is to speed up developement and to reduce complexity for plugin + * developers. The main program holds the necessary functionality to load and use plugins with either the integrated + * python interpreter or within c/c++ functions. All plugins are divded into two parts: + * - the AddInInterfaceBase + * - the AddIn (derived from the specific addIn-type that should be created which is derived from AddInBase + * + * The Interface is a small light weight class which is used when loading the dll into the main program. It holds + * information about the plugin itself, e.g. name, version, parameters and so on. When loading the plugin is tested for + * compability with the current version of the main program based on the information in the interface class. The + * AddInXXX class provides the plugin functionality. Instances of this class are only created when the plugin "is used" + * either by python or within other functions. For a description about the loading, using and unloading process see \ref + * AddInBase, \ref AddInActuator, \ref AddInDataIO and \ref AddInAlgo. The instantiation of an AddIn class is a two step + * process. At first the necessary and optional parameter values as well as the plugin's reference number are retrieved + * from the AddInManager using the getInitParams \ref getInitParams method. Then a new instance is obtained using one of + * the initAddIn \ref initAddIn methods. Which first create a new instance, move the instance to a new thread and at + * last call the classes init method + */ +class ITOMCOMMONQT_EXPORT AddInInterfaceBase : public QObject +{ + Q_OBJECT + + private: + //!< internal function used within the closing process + virtual ito::RetVal closeThisInst(ito::AddInBase **addInInst) = 0; + + //!> self-managed pointer to the private class container (deletes itself if d_ptr is destroyed) + QScopedPointer d_ptr; + Q_DECLARE_PRIVATE(AddInInterfaceBase); + + protected: + int m_type; //!< plugin type + int m_version; //!< plugin version + QString m_filename; //!< plugin (library) filename on the disc + int m_maxItomVer; //!< minimum required version of the main program + int m_minItomVer; //!< maximum supported version of the main program + QString m_author; //!< the plugin author + QString m_description; //!< a brief descrition of the plugin + QString m_detaildescription; //!< a detail descrition of the plugin + QString m_license; //!< a short license string for the plugin, default value is "LGPL with ITO itom-exception" + QString m_aboutThis; + QList m_InstList; //!< vector holding a list of the actual instantiated classes of the plugin + QVector + m_initParamsMand; //!< vector with the mandatory initialisation parameters, please only read this vector within + //!< the init-method of AddInBase (afterwards it might have been changed) + QVector + m_initParamsOpt; //!< vector with the optional initialisation parameters, please only read this vector within + //!< the init-method of AddInBase (afterwards it might have been changed) + tAutoLoadPolicy m_autoLoadPolicy; /*!< defines the auto-load policy for automatic loading of parameters from + xml-file at startup of any instance */ + tAutoSavePolicy m_autoSavePolicy; /*!< defines the auto-save policy for automatic saving of parameters in xml-file + at shutdown of any instance */ + bool m_callInitInNewThread; /*!< true (default): the init-method of addIn will be called after that the + plugin-instance has been moved to new thread (my addInManager). false: the + init-method is called in main(gui)-thread, and will be moved to new thread afterwards + (this should only be chosen, if not otherwise feasible) */ + + virtual void importItomApi( + void **apiPtr) = 0; // this methods are implemented in the plugin itsself. Therefore place ITOM_API right after + // Q_INTERFACE in the header file and replace Q_EXPORT_PLUGIN2 by Q_EXPORT_PLUGIN2_ITOM in + // the source file. + virtual void importItomApiGraph(void **apiPtr) = 0; + + //!> check if we have gui support + inline bool hasGuiSupport() + { + if (qobject_cast(QCoreApplication::instance())) + { + return true; + } + else + { + return false; + } + } - //! tActuatorStatus enumeration - /*! - flags used for describing the status of one axis of an actuator plugin. + public: + void **m_apiFunctionsBasePtr; + void **m_apiFunctionsGraphBasePtr; + + //! destructor + virtual ~AddInInterfaceBase(); - These flags are intended to be combined in the status bitmask. - Usually the bitmask for each mask is saved in the vector ito::AddInActuator::m_currentStatus - of an actuator plugin. + //! default constructor + AddInInterfaceBase(); - The bitmask is divided into different topical areas (moving flags, switches, general status). + //! pure virtual function that returns the addin interface version of the plugin + /* This method is automatically implemented by the PLUGIN_ITOM_API macro. + The definition is 0xAABBCC where AA is the major, BB the minor and CC the patch. */ - enum tActuatorStatus + virtual int getAddInInterfaceVersion() const = 0; + + //! returns addIn type + inline int getType(void) const { - //moving flags - actuatorUnknown = 0x0001, /*!< moving status of axis is unknown */ - actuatorInterrupted = 0x0002, /*!< movement has been interrupted by the user, axis is immediately stopped */ - actuatorMoving = 0x0004, /*!< axis is currently moving */ - actuatorAtTarget = 0x0008, /*!< axis reached target */ - actuatorTimeout = 0x0010, /*!< no signal from axis, timeout */ - //switches - actuatorEndSwitch = 0x0100, /*!< axis reached an undefined end switch */ - actuatorLeftEndSwitch = 0x0200, /*!< axis reached the specified left end switch (if set, also set actuatorEndSwitch), deprecated */ - actuatorRightEndSwitch = 0x0400, /*!< axis reached the specified right end switch (if set, also set actuatorEndSwitch), deprecated */ - actuatorEndSwitch1 = 0x0200,/*!< axis reached the specified left end switch (if set, also set actuatorEndSwitch) */ - actuatorEndSwitch2 = 0x0400, /*!< axis reached the specified left end switch (if set, also set actuatorEndSwitch) */ - actuatorRefSwitch = 0x0800, /*!< axis reached an undefined reference switch */ - actuatorLeftRefSwitch = 0x1000, /*!< axis reached the specified left reference switch (if set, also set actuatorRefSwitch), deprecated */ - actuatorRightRefSwitch = 0x2000, /*!< axis reached the specified right reference switch (if set, also set actuatorRefSwitch), deprecated */ - actuatorRefSwitch1 = 0x1000,/*!< axis reached the specified right reference switch (if set, also set actuatorRefSwitch)*/ - actuatorRefSwitch2 = 0x2000,/*!< axis reached the specified right reference switch (if set, also set actuatorRefSwitch)*/ - - //status flags - actuatorAvailable = 0x4000, /*!< axis is generally available */ - actuatorEnabled = 0x8000, /*!< axis is enabled for movements */ - actuatorError = 0x10000,/*axis has encountered error/reports error*/ - - actMovingMask = actuatorUnknown | actuatorInterrupted | actuatorMoving | actuatorAtTarget | actuatorTimeout, /*!< bitmask that marks all bits related to the movement */ - - actEndSwitchMask = actuatorEndSwitch \ - | actuatorEndSwitch1 | actuatorEndSwitch2, /*!< bitmask that marks all bits related to end switches */ - - actRefSwitchMask = \ - actuatorRefSwitch \ - | actuatorRefSwitch1 | actuatorRefSwitch2, /*!< bitmask that marks all bits related to reference switches */ - - actSwitchesMask = actEndSwitchMask | actRefSwitchMask, /*!< bitmask that marks all bits related to reference and end switches */ - - actStatusMask = actuatorAvailable | actuatorEnabled | actuatorError /*!< bitmask that marks all status flags */ - }; + return m_type; + } + //! returns addIn version + inline int getVersion(void) const + { + return m_version; + } + //! returns minimum required version of main program + inline int getMinItomVer(void) const + { + return m_minItomVer; + } + //! returns maximum supported version of main program + inline int getMaxItomVer(void) const + { + return m_maxItomVer; + } - enum tAutoLoadPolicy + //! returns whether init-method should be called in new thread (default) or still in main thread + inline bool getCallInitInNewThread(void) const { - autoLoadAlways = 0x1, /*!< always loads xml file by addInManager */ - autoLoadNever = 0x2, /*!< never automatically loads parameters from xml-file (default) */ - autoLoadKeywordDefined = 0x4 /*!< only loads parameters if keyword autoLoadParams=1 exists in python-constructor */ - }; + return m_callInitInNewThread; + } - enum tAutoSavePolicy + //! returns true if the plugin allows his own parameter load to be autoloaded by addin manager + inline tAutoLoadPolicy getAutoLoadPolicy(void) const { - autoSaveAlways = 0x1, /*!< always saves parameters to xml-file at shutdown */ - autoSaveNever = 0x2 /*!< never saves parameters to xml-file at shutdown (default) */ - }; + return m_autoLoadPolicy; + } - struct ExecFuncParams + //! returns true if the plugin allows his own parameter save to be autoloaded by addin manager + inline tAutoSavePolicy getAutoSavePolicy(void) const { - ExecFuncParams() : infoString("") {} - QVector paramsMand; /*!< mandatory parameters (default set), must have flag In or In|Out */ - QVector paramsOpt; /*!< optional parameters (default set), must have flag In or In|Out */ - QVector paramsOut; /*!< return parameters (default set), must have Out. Only types Int,Char,Double,String,IntArray,CharArray or DoubleArray are allowed. */ - QString infoString; - }; + return m_autoSavePolicy; + } - struct FilterParams + //! returns plugin author + const QString getAuthor(void) const { - QVector paramsMand; - QVector paramsOpt; - QVector paramsOut; - }; + return m_author; + } + //! returns a brief description of the plugin + const QString getDescription(void) const + { + return m_description; + } + //! returns a detailed description of the plugin + const QString getDetailDescription(void) const + { + return m_detaildescription; + } + //! returns a detailed description of the plugin license + const QString getLicenseInfo(void) const + { + return m_license; + } + //! returns a detailed description of the plugin compile informations + const QString getAboutInfo(void) const + { + return m_aboutThis; + } + //! returns the plugin's filename + const QString getFilename(void) const + { + return m_filename; + } - class AddInBase; //!< forward declaration - class DataObject; - class AddInBasePrivate; //!< forward declaration to private container class of AddInBase - class AddInInterfaceBasePrivate; //!< forward declaration to private container class of AddInInterfaceBase - class AddInActuatorPrivate; //!< forward declaration to private container class of AddInActuator - class AddInDataIOPrivate; //!< forward declaration to private container class of AddInDataIO - class AddInAlgoPrivate; //!< forward declaration to private container class of AddInAlog - - //---------------------------------------------------------------------------------------------------------------------------------- - /** @class AddInInterfaceBase - * @brief class of the AddIn - Library (DLL) - Interface - * - * The measurement program can (and should) be expanded with additional functionality by "plugins". The aim of separating - * part of the program into plugins is to speed up developement and to reduce complexity for plugin developers. - * The main program holds the necessary functionality to load and use plugins with either the integrated python interpreter - * or within c/c++ functions. - * All plugins are divded into two parts: - * - the AddInInterfaceBase - * - the AddIn (derived from the specific addIn-type that should be created which is derived from AddInBase - * - * The Interface is a small light weight class which is used when loading the dll into the main program. It holds information - * about the plugin itself, e.g. name, version, parameters and so on. - * When loading the plugin is tested for compability with the current version of the main program based on the information in the - * interface class. - * The AddInXXX class provides the plugin functionality. Instances of this class are only created when the plugin "is used" either - * by python or within other functions. For a description about the loading, using and unloading process see \ref AddInBase, \ref AddInActuator, - * \ref AddInDataIO and \ref AddInAlgo. - * The instantiation of an AddIn class is a two step process. At first the necessary and optional parameter values as well as the - * plugin's reference number are retrieved from the AddInManager using the getInitParams \ref getInitParams method. Then a new instance - * is obtained using one of the initAddIn \ref initAddIn methods. Which first create a new instance, move the instance to a new thread - * and at last call the classes init method - */ - class ITOMCOMMONQT_EXPORT AddInInterfaceBase : public QObject + const ito::RetVal setFilename(const QString &name) + { + m_filename = name; + return ito::retOk; + } + //! returns a list of the actual intantiated classes from this plugin + inline QList getInstList(void) + { + return m_InstList; + } + inline const QList getInstList(void) const + { + return m_InstList; + } + //! method for closing an instance + ito::RetVal closeInst(ito::AddInBase **addInInst); + //! returns a vector with the mandatory initialisation parameters + virtual QVector *getInitParamsMand(void) + { + return &m_initParamsMand; + } + //! returns a vector with the optional initialisation parameters + virtual QVector *getInitParamsOpt(void) { - Q_OBJECT - - private: - //!< internal function used within the closing process - virtual ito::RetVal closeThisInst(ito::AddInBase **addInInst) = 0; - - QScopedPointer d_ptr; //!> self-managed pointer to the private class container (deletes itself if d_ptr is destroyed) - Q_DECLARE_PRIVATE(AddInInterfaceBase); - - protected: - int m_type; //!< plugin type - int m_version; //!< plugin version - QString m_filename; //!< plugin (library) filename on the disc - int m_maxItomVer; //!< minimum required version of the main program - int m_minItomVer; //!< maximum supported version of the main program - QString m_author; //!< the plugin author - QString m_description; //!< a brief descrition of the plugin - QString m_detaildescription; //!< a detail descrition of the plugin - QString m_license; //!< a short license string for the plugin, default value is "LGPL with ITO itom-exception" - QString m_aboutThis; - QList m_InstList; //!< vector holding a list of the actual instantiated classes of the plugin - QVector m_initParamsMand; //!< vector with the mandatory initialisation parameters, please only read this vector within the init-method of AddInBase (afterwards it might have been changed) - QVector m_initParamsOpt; //!< vector with the optional initialisation parameters, please only read this vector within the init-method of AddInBase (afterwards it might have been changed) - tAutoLoadPolicy m_autoLoadPolicy; /*!< defines the auto-load policy for automatic loading of parameters from xml-file at startup of any instance */ - tAutoSavePolicy m_autoSavePolicy; /*!< defines the auto-save policy for automatic saving of parameters in xml-file at shutdown of any instance */ - bool m_callInitInNewThread; /*!< true (default): the init-method of addIn will be called after that the plugin-instance has been moved to new thread (my addInManager). false: the init-method is called in main(gui)-thread, and will be moved to new thread afterwards (this should only be chosen, if not otherwise feasible) */ - - - virtual void importItomApi(void** apiPtr) = 0; //this methods are implemented in the plugin itsself. Therefore place ITOM_API right after Q_INTERFACE in the header file and replace Q_EXPORT_PLUGIN2 by Q_EXPORT_PLUGIN2_ITOM in the source file. - virtual void importItomApiGraph(void** apiPtr) = 0; - - //!> check if we have gui support - inline bool hasGuiSupport() + return &m_initParamsOpt; + } + //! method to instantiate a new class of the plugin + virtual ito::RetVal getAddInInst(ito::AddInBase **addInInst) = 0; + //! increment use reference + void incRef(ito::AddInBase *addIn); + //! decrement use reference + void decRef(ito::AddInBase *addIn); + //! get reference counter + int getRef(ito::AddInBase *addIn); + //! get number instantiated plugins + int getInstCount() + { + return m_InstList.length(); + } + //! set api function pointer + void setApiFunctions(void **apiFunctions); + void setApiFunctionsGraph(void **apiFunctionsGraph); + + void setLoader(QPluginLoader *loader); + QPluginLoader *getLoader(void) const; + + bool event(QEvent *e); +}; + +//---------------------------------------------------------------------------------------------------------------------------------- +/** @class AddInBase + * @brief Base class for all plugins. + * + * The common methods and members are defined here. The available plugin type (actuator \ref AddInActuator, + * dataIO \ref AddInDataIO and algo \ref AddInAlgo) are derived from this class. At the main program startup all + * available plugins located in the plugin directory are searched and matched against the current plugin interface + * version. Then all compatible plugins can be check with the AddInManager. Up to that stage for each plugin only a + * lightweight AddInInterface \ref AddInInterfaceBase class has been loaded. To use a plugin instances of the plugin + * class have to be instantiated. The AddInInterface is run in the calling thread whilst the plugin classes are run in + * separate threads. Therefore the plugin functions are implemented as slots which can be used e.g. with the + * invokeMethod function. The base functionality included in this base class is getting the plugin's parameter list, + * getting the classes uniqueID (which is used e.g. for saveing the parameter values) and optinally to bring up a + * configuration dialog. + */ +class ITOMCOMMONQT_EXPORT AddInBase : public QObject +{ + Q_OBJECT + + public: + struct AddInRef + { + AddInRef() : type(-1), ptr(0) { - if (qobject_cast(QCoreApplication::instance())) - { - return true; - } - else - { - return false; - } } - - public: - void **m_apiFunctionsBasePtr; - void **m_apiFunctionsGraphBasePtr; - - //! destructor - virtual ~AddInInterfaceBase(); - - //! default constructor - AddInInterfaceBase(); - - //! pure virtual function that returns the addin interface version of the plugin - /* This method is automatically implemented by the PLUGIN_ITOM_API macro. - The definition is 0xAABBCC where AA is the major, BB the minor and CC the patch. - */ - virtual int getAddInInterfaceVersion() const = 0; - - //! returns addIn type - inline int getType(void) const { return m_type; } - //! returns addIn version - inline int getVersion(void) const { return m_version; } - //! returns minimum required version of main program - inline int getMinItomVer(void) const { return m_minItomVer; } - //! returns maximum supported version of main program - inline int getMaxItomVer(void) const { return m_maxItomVer; } - - //! returns whether init-method should be called in new thread (default) or still in main thread - inline bool getCallInitInNewThread(void) const { return m_callInitInNewThread; } - - //! returns true if the plugin allows his own parameter load to be autoloaded by addin manager - inline tAutoLoadPolicy getAutoLoadPolicy(void) const { return m_autoLoadPolicy; } - - //! returns true if the plugin allows his own parameter save to be autoloaded by addin manager - inline tAutoSavePolicy getAutoSavePolicy(void) const { return m_autoSavePolicy; } - - //! returns plugin author - const QString getAuthor(void) const { return m_author; } - //! returns a brief description of the plugin - const QString getDescription(void) const { return m_description; } - //! returns a detailed description of the plugin - const QString getDetailDescription(void) const { return m_detaildescription; } - //! returns a detailed description of the plugin license - const QString getLicenseInfo(void) const { return m_license; } - //! returns a detailed description of the plugin compile informations - const QString getAboutInfo(void) const { return m_aboutThis; } - //! returns the plugin's filename - const QString getFilename(void) const { return m_filename; } - - const ito::RetVal setFilename(const QString &name) { m_filename = name; return ito::retOk; } - //! returns a list of the actual intantiated classes from this plugin - inline QList getInstList(void) { return m_InstList; } - inline const QList getInstList(void) const { return m_InstList; } - //! method for closing an instance - ito::RetVal closeInst(ito::AddInBase **addInInst); - //! returns a vector with the mandatory initialisation parameters - virtual QVector* getInitParamsMand(void) { return &m_initParamsMand; } - //! returns a vector with the optional initialisation parameters - virtual QVector* getInitParamsOpt(void) { return &m_initParamsOpt; } - //! method to instantiate a new class of the plugin - virtual ito::RetVal getAddInInst(ito::AddInBase **addInInst) = 0; - //! increment use reference - void incRef(ito::AddInBase *addIn); - //! decrement use reference - void decRef(ito::AddInBase *addIn); - //! get reference counter - int getRef(ito::AddInBase *addIn); - //! get number instantiated plugins - int getInstCount() { return m_InstList.length(); } - //! set api function pointer - void setApiFunctions(void **apiFunctions); - void setApiFunctionsGraph(void ** apiFunctionsGraph); - - void setLoader(QPluginLoader *loader); - QPluginLoader * getLoader(void) const; - - bool event(QEvent *e); + AddInRef(void *p, int t) : type(t), ptr(p) + { + } + int type; + void *ptr; }; - //---------------------------------------------------------------------------------------------------------------------------------- - /** @class AddInBase - * @brief Base class for all plugins. - * - * The common methods and members are defined here. The available plugin type (actuator \ref AddInActuator, - * dataIO \ref AddInDataIO and algo \ref AddInAlgo) are derived from this class. At the main program startup all available plugins - * located in the plugin directory are searched and matched against the current plugin interface version. Then all compatible - * plugins can be check with the AddInManager. Up to that stage for each plugin only a lightweight AddInInterface \ref AddInInterfaceBase - * class has been loaded. To use a plugin instances of the plugin class have to be instantiated. The AddInInterface is run in the - * calling thread whilst the plugin classes are run in separate threads. Therefore the plugin functions are implemented as slots which can be - * used e.g. with the invokeMethod function. - * The base functionality included in this base class is getting the plugin's parameter list, getting the classes uniqueID (which is - * used e.g. for saveing the parameter values) and optinally to bring up a configuration dialog. + //! method to retrieve a parameter from the parameter map (m_params) + const Param getParamRec(const QString name, bool *nameCheckOk = NULL) const; + + //! returns the interface of this instance. \sa AddInInterfaceBase + AddInInterfaceBase *getBasePlugin(void) const; + + //! creates new thread for the class instance and moves this instance to the new thread + ito::RetVal MoveToThread(void); + + //! returns a map with the parameters of this plugin. + /* + Use the method setParam in order to change any parameter. + + \param paramNames [out]. The pointer contains a pointer to the map after the call of this function + \return RetVal returns retOk. */ - class ITOMCOMMONQT_EXPORT AddInBase : public QObject + inline const ito::RetVal getParamList(QMap **paramNames) { - Q_OBJECT - - public: - - struct AddInRef { - AddInRef() : type(-1), ptr(0) {} - AddInRef(void *p, int t) : type(t), ptr(p) {} - int type; - void *ptr; - }; - - //! method to retrieve a parameter from the parameter map (m_params) - const Param getParamRec(const QString name, bool *nameCheckOk = NULL) const; - - //! returns the interface of this instance. \sa AddInInterfaceBase - AddInInterfaceBase* getBasePlugin(void) const; - - //! creates new thread for the class instance and moves this instance to the new thread - ito::RetVal MoveToThread(void); - - //! returns a map with the parameters of this plugin. - /* - Use the method setParam in order to change any parameter. - - \param paramNames [out]. The pointer contains a pointer to the map after the call of this function - \return RetVal returns retOk. - */ - inline const ito::RetVal getParamList(QMap **paramNames) { *paramNames = &m_params; return ito::retOk; } - - //! returns list of registered additional functions - /* - \param [out] funcs is the pointer to a map, that points to the internal map of additional functions after the method-call. - \return retOk - \sa registerExecFunc - */ - inline const ito::RetVal getExecFuncList(QMap **funcs) { *funcs = &m_execFuncList; return ito::retOk; } - - //! retrieve the uniqueID of this instance - int getID() const; - - //! retrieve the unique identifier of this instance - inline QString getIdentifier() const { return m_identifier; } - - //! determine if a configuration dialog is available - virtual int hasConfDialog(void); - - //! open configuration dialog - virtual const ito::RetVal showConfDialog(void); - - //! returns true if this instance has firstly been created by the GUI - int createdByGUI() const; - - //! method to set whether this instance has been firstly created by the GUI (true) or by any other component (Python, C++, other plugin,..) (false) - void setCreatedByGUI(int value); + *paramNames = &m_params; + return ito::retOk; + } + + //! returns list of registered additional functions + /* + \param [out] funcs is the pointer to a map, that points to the internal map of additional functions after the + method-call. \return retOk \sa registerExecFunc + */ + inline const ito::RetVal getExecFuncList(QMap **funcs) + { + *funcs = &m_execFuncList; + return ito::retOk; + } - //! Returns the reference counter of this instance. - /* - The reference counter is zero-based, hence, the value zero means that one reference is pointing to this instance - */ - int getRefCount(void) const; + //! retrieve the uniqueID of this instance + int getID() const; - //! Returns true if this plugin provides a dock widget, that can be shown in the main window. - /* - \sa getDockWidget - */ - bool hasDockWidget(void) const; + //! retrieve the unique identifier of this instance + inline QString getIdentifier() const + { + return m_identifier; + } - //! Returns the reference to the dock widget of this plugin or NULL, if no dock widget is provided or if it is already deleted. - /* - \sa hasDockWidget - */ - QDockWidget* getDockWidget(void) const; + //! determine if a configuration dialog is available + virtual int hasConfDialog(void); - // doc in source - virtual void dockWidgetDefaultStyle(bool &floating, bool &visible, Qt::DockWidgetArea &defaultArea) const; + //! open configuration dialog + virtual const ito::RetVal showConfDialog(void); - //! returns the alive-flag of this plugin - /* - Any time-consuming operation of the plugin should regularly set the alive-flag to true - by calling setAlive. The state of this flag is returned by this method and afterwards - reset to 0. This method is thread-safe. + //! returns true if this instance has firstly been created by the GUI + int createdByGUI() const; - \return current status of alive-flag (1 if "still alive", else 0) - \sa setAlive - */ - int isAlive(void); + //! method to set whether this instance has been firstly created by the GUI (true) or by any other component + //! (Python, C++, other plugin,..) (false) + void setCreatedByGUI(int value); - //! sets the alive-flag to 1 ("still alive") - /* - This method is thread-safe. + //! Returns the reference counter of this instance. + /* + The reference counter is zero-based, hence, the value zero means that one reference is pointing to this instance + */ + int getRefCount(void) const; - \sa isAlive - */ - void setAlive(void); + //! Returns true if this plugin provides a dock widget, that can be shown in the main window. + /* + \sa getDockWidget + */ + bool hasDockWidget(void) const; - //! returns in a thread-safe way the status of the m_initialized-member variable. This variable should be set to true at the end of the init-method. - bool isInitialized(void) const; + //! Returns the reference to the dock widget of this plugin or NULL, if no dock widget is provided or if it is + //! already deleted. + /* + \sa hasDockWidget + */ + QDockWidget *getDockWidget(void) const; - //! sets in a thread-safe way the status of the m_initialized-member - /* - \param [in] initialized is the value to set - */ - void setInitialized(bool initialized); + // doc in source + virtual void dockWidgetDefaultStyle(bool &floating, bool &visible, Qt::DockWidgetArea &defaultArea) const; - //! returns vector of AddInRef instances. - /* - This vector contains all plugin-instances, that have been passed to the init - method of this plugin. The reference counter of these plugin is incremented at - initialization of this plugin and decremented if this plugin will be destroyed. + //! returns the alive-flag of this plugin + /* + Any time-consuming operation of the plugin should regularly set the alive-flag to true + by calling setAlive. The state of this flag is returned by this method and afterwards + reset to 0. This method is thread-safe. - \sa AddInRef, init - */ - QVector * getArgAddIns(void) { return &m_hwDecList; } + \return current status of alive-flag (1 if "still alive", else 0) + \sa setAlive + */ + int isAlive(void); - //! returns the user mutex of this plugin, that can be used for user-defined purposes. - /* This mutex has no designed task in the plugin, however it can be used by - the user to for instance protect a sequence of different calls to this plugin. - - This can be important, if the plugin is for instance a communication object, - that is used by different other hardware instances (e.g. a SerialIO to - an arduino, that controls different motors, sensors etc.). Then, it might - be important, that every hardware plugin object, that uses the serialIO - plugin, can protect a setVal / getVal sequence without that any other - plugin instance interrupts its. However, it is the task of the user to - implement that protection. This mutex can only help for this. - */ - QMutex& getUserMutex(); + //! sets the alive-flag to 1 ("still alive") + /* + This method is thread-safe. - static int getMaximumThreadCount(); - - static RetVal setMaximumThreadCount(int threadCount); + \sa isAlive + */ + void setAlive(void); - protected: - // constructor (doc in source) - AddInBase(); + //! returns in a thread-safe way the status of the m_initialized-member variable. This variable should be set to + //! true at the end of the init-method. + bool isInitialized(void) const; - // destructor (doc in source) - virtual ~AddInBase(); + //! sets in a thread-safe way the status of the m_initialized-member + /* + \param [in] initialized is the value to set + */ + void setInitialized(bool initialized); - //! sets the identifier of the plugin. The slot AbstractAddInDockWidget::identifierChanged is invoked if a corresponding dock widget is available. - void setIdentifier(const QString &identifier); + //! returns vector of AddInRef instances. + /* + This vector contains all plugin-instances, that have been passed to the init + method of this plugin. The reference counter of these plugin is incremented at + initialization of this plugin and decremented if this plugin will be destroyed. - //doc in source - void createDockWidget(QString title, QDockWidget::DockWidgetFeatures features, Qt::DockWidgetAreas allowedAreas = Qt::AllDockWidgetAreas, QWidget *content = NULL); + \sa AddInRef, init + */ + QVector *getArgAddIns(void) + { + return &m_hwDecList; + } + + //! returns the user mutex of this plugin, that can be used for user-defined purposes. + /* This mutex has no designed task in the plugin, however it can be used by + the user to for instance protect a sequence of different calls to this plugin. + + This can be important, if the plugin is for instance a communication object, + that is used by different other hardware instances (e.g. a SerialIO to + an arduino, that controls different motors, sensors etc.). Then, it might + be important, that every hardware plugin object, that uses the serialIO + plugin, can protect a setVal / getVal sequence without that any other + plugin instance interrupts its. However, it is the task of the user to + implement that protection. This mutex can only help for this. + */ + QMutex &getUserMutex(); - // doc in source - ito::RetVal registerExecFunc(const QString funcName, const QVector ¶msMand, const QVector ¶msOpt, const QVector ¶msOut, const QString infoString); + static int getMaximumThreadCount(); - //! sets the interface of this instance to base. \sa AddInInterfaceBase - void setBasePlugin(AddInInterfaceBase *base); + static RetVal setMaximumThreadCount(int threadCount); - QMap m_params; //!< map of the available parameters - - QString m_identifier; //!< unique identifier (serial number, com-port...) + protected: + // constructor (doc in source) + AddInBase(); - //! check if we have gui support - inline bool hasGuiSupport() - { - if (qobject_cast(QCoreApplication::instance())) - { - return true; - } - else - { - return false; - } - } + // destructor (doc in source) + virtual ~AddInBase(); - private: - Q_DISABLE_COPY(AddInBase) + //! sets the identifier of the plugin. The slot AbstractAddInDockWidget::identifierChanged is invoked if a + //! corresponding dock widget is available. + void setIdentifier(const QString &identifier); - //! increments reference counter of this plugin (thread-safe) - void incRefCount(void); + // doc in source + void createDockWidget(QString title, QDockWidget::DockWidgetFeatures features, + Qt::DockWidgetAreas allowedAreas = Qt::AllDockWidgetAreas, QWidget *content = NULL); - //! decrements reference counter of this plugin (thread-safe) - void decRefCount(void); + // doc in source + ito::RetVal registerExecFunc(const QString funcName, const QVector ¶msMand, + const QVector ¶msOpt, const QVector ¶msOut, + const QString infoString); - QVector m_hwDecList; //!< list of hardware that was passed to the plugin on initialisation and whose refcounter was incremented - QMap m_execFuncList; //!< map with registered additional functions. funcExec-name -> (default mandParams, default optParams, default outParams, infoString) + //! sets the interface of this instance to base. \sa AddInInterfaceBase + void setBasePlugin(AddInInterfaceBase *base); - QScopedPointer d_ptr; //!> self-managed pointer to the private class container (deletes itself if d_ptr is destroyed). pointer to private class of AddInBase defined in AddInInterface.cpp. This container is used to allow flexible changes in the interface without destroying the binary compatibility - Q_DECLARE_PRIVATE(AddInBase); + //! inserts the given param to the m_params map. + /* + equivalent to: m_params.insert(param.getName(), param); + */ + void insertParam(const Param& param); - friend class AddInInterfaceBase; //!< AddInBase is friend with AddInInterfaceBase, such that the interface can access methods like the protected constructor or destructor of this plugin class. + QMap m_params; //!< map of the available parameters - static int m_instCounter; - static int maxThreadCount; //!< maximum number of threads algorithms can use e.g. with OpenMP parallelization. This is a number between 1 and QThread::idealThreadCount() + QString m_identifier; //!< unique identifier (serial number, com-port...) - Q_SIGNALS: - //! This signal usually is emitted if the vector m_params is changed. - /*! - Emit this signal for instance in setParam if the parameter has been changed in order - to inform connected dock-widgets... about the change. This signal is also emitted - if you invoke the slot sendParameterRequest. + //! check if we have gui support + inline bool hasGuiSupport() + { + if (qobject_cast(QCoreApplication::instance())) + { + return true; + } + else + { + return false; + } + } - \param params is the parameter-vector to send (usually m_params) - \sa m_params, sendParameterRequest - */ - void parametersChanged(QMap params); + private: + Q_DISABLE_COPY(AddInBase) - public Q_SLOTS: - //! method for the initialisation of a new instance of the class (must be overwritten) - virtual ito::RetVal init(QVector *paramsMand, QVector *paramsOpt, ItomSharedSemaphore *waitCond = NULL) = 0; - //! method for closing an instance (must be overwritten) - virtual ito::RetVal close(ItomSharedSemaphore *waitCond) = 0; + //! increments reference counter of this plugin (thread-safe) + void incRefCount(void); - //! method for the retrieval of a parameter. The actual value is always passed as ito::Param (must be overwritten). See also \ref setParam - virtual ito::RetVal getParam(QSharedPointer val, ItomSharedSemaphore *waitCond = NULL) = 0; - //! method to set a parameter. The actual value is always passed as ito::ParamBase (must be overwritten). See also \ref getParam - virtual ito::RetVal setParam(QSharedPointer val, ItomSharedSemaphore *waitCond = NULL) = 0; + //! decrements reference counter of this plugin (thread-safe) + void decRefCount(void); - //! method for setting various parameters (can be used instead of multiple calls to setParam, this can safe multiple invocations) - ito::RetVal setParamVector(const QVector > values, ItomSharedSemaphore *waitCond = NULL); + //!< list of hardware that was passed to the plugin on + //!< initialisation and whose refcounter was incremented + QVector m_hwDecList; - //! method for getting various parameters (can be used instead of multiple calls to getParam, this can safe multiple invocations) - ito::RetVal getParamVector(const QVector > values, ItomSharedSemaphore *waitCond = NULL); + //!< map with registered additional functions. funcExec-name -> (default mandParams, default + //!< optParams, default outParams, infoString) + QMap + m_execFuncList; - //! overwrite this function if you registered exec funcs. Once the exec function is called, this method is executed. - virtual ito::RetVal execFunc(const QString funcName, QSharedPointer > paramsMand, QSharedPointer > paramsOpt, QSharedPointer > paramsOut, ItomSharedSemaphore *waitCond = NULL); + //!> self-managed pointer to the private class container (deletes itself if d_ptr is destroyed). pointer + //!to private class of AddInBase defined in AddInInterface.cpp. This container is used to allow flexible + //!changes in the interface without destroying the binary compatibility + QScopedPointer d_ptr; + Q_DECLARE_PRIVATE(AddInBase); - //! method invoked by AddInManager if the plugin should be pulled back to the main thread of itom. (not for direct use in plugins) - ito::RetVal moveBackToApplicationThread(ItomSharedSemaphore *waitCond = NULL); + //!< AddInBase is friend with AddInInterfaceBase, such that the interface can + //!< access methods like the protected constructor or destructor of this plugin + //!< class. + friend class AddInInterfaceBase; - //! immediately emits the signal parametersChanged - /*! - call or invoke this method for instance after creating a configuration dialog for the plugin. - Then the dialog gets the current parameter map m_params, if it has been connected to the signal - parametersChanged (must be done before). + static int m_instCounter; - \sa parametersChanged, m_params - */ - void sendParameterRequest(){ emit parametersChanged(m_params); }; + //!< maximum number of threads algorithms can use e.g. with OpenMP parallelization. This + //!< is a number between 1 and QThread::idealThreadCount() + static int maxThreadCount; - private Q_SLOTS: + Q_SIGNALS: + //! This signal usually is emitted if the vector m_params is changed. + /*! + Emit this signal for instance in setParam if the parameter has been changed in order + to inform connected dock-widgets... about the change. This signal is also emitted + if you invoke the slot sendParameterRequest. - //! overwrite this slot if you want to get informed when the dock-widget of the plugin becomes (in)visible - /*! - It is recommended to use this method, in order to connect the widget to signals like parametersChanged, - actuatorStatusChanged or targetChanged (both actuator only) if the dock-widget becomes visible and disconnect - them if it is hidden. This is useful in order to avoid intense function calls if the dock-widget is not - visible. + \param params is the parameter-vector to send (usually m_params) + \sa m_params, sendParameterRequest + */ + void parametersChanged(QMap params); + + public Q_SLOTS: + //! method for the initialisation of a new instance of the class (must be overwritten) + virtual ito::RetVal init(QVector *paramsMand, QVector *paramsOpt, + ItomSharedSemaphore *waitCond = NULL) = 0; + //! method for closing an instance (must be overwritten) + virtual ito::RetVal close(ItomSharedSemaphore *waitCond) = 0; + + //! method for the retrieval of a parameter. The actual value is always passed as ito::Param (must be overwritten). + //! See also \ref setParam + virtual ito::RetVal getParam(QSharedPointer val, ItomSharedSemaphore *waitCond = NULL) = 0; + //! method to set a parameter. The actual value is always passed as ito::ParamBase (must be overwritten). See also + //! \ref getParam + virtual ito::RetVal setParam(QSharedPointer val, ItomSharedSemaphore *waitCond = NULL) = 0; + + //! method for setting various parameters (can be used instead of multiple calls to setParam, this can safe multiple + //! invocations) + ito::RetVal setParamVector(const QVector> values, + ItomSharedSemaphore *waitCond = NULL); + + //! method for getting various parameters (can be used instead of multiple calls to getParam, this can safe multiple + //! invocations) + ito::RetVal getParamVector(const QVector> values, ItomSharedSemaphore *waitCond = NULL); + + //! overwrite this function if you registered exec funcs. Once the exec function is called, this method is executed. + virtual ito::RetVal execFunc(const QString funcName, QSharedPointer> paramsMand, + QSharedPointer> paramsOpt, + QSharedPointer> paramsOut, + ItomSharedSemaphore *waitCond = NULL); + + //! method invoked by AddInManager if the plugin should be pulled back to the main thread of itom. (not for direct + //! use in plugins) + ito::RetVal moveBackToApplicationThread(ItomSharedSemaphore *waitCond = NULL); + + //! immediately emits the signal parametersChanged + /*! + call or invoke this method for instance after creating a configuration dialog for the plugin. + Then the dialog gets the current parameter map m_params, if it has been connected to the signal + parametersChanged (must be done before). - \sa parametersChanged - */ - virtual void dockWidgetVisibilityChanged(bool /*visible*/) {}; + \sa parametersChanged, m_params + */ + void sendParameterRequest() + { + emit parametersChanged(m_params); }; - //---------------------------------------------------------------------------------------------------------------------------------- - /** @class AddInDataIO - * @brief base class for all dataIO plugin classes - * - * This class is one step further down the line from \ref AddInBase. DataIO plugins must be derived from this class which - * is derived from AddInBase. In this class only the methods specific to dataIO plugins are declared. A dataIO - * device (e.g. a framegrabber / camera) should use this sequence to operate: - * 1. startDevice - device is now ready to acquire data - * 2. acquire - now a data set is freezed and prepared for retrieval - * 3. getVal - method to retrieve the previously freezed data (shallow copy, if you want to work with this data, make a deep copy) - * 4. stopDevice - acquisition is stopped, device is no longer ready to record data - * - * the steps 2. and 3. can be repeated until the desired number of "frames" has been read. The device - * should be only started once before the first acquisition of a sequence and stop only at their end. - * The device itself MUST NOT allocate memory for the data to be stored. This HAS TO BE DONE in the main programm - * or in the calling method! - * - * If a live image is listening this device, its source node calls startDeviceAndRegisterListener. If the autoGrabbing-flag is enabled, - * a timer will be started, which triggers the method 'timerEvent' (should be implemented by any camera). If this flag is disabled, the - * live image is registered, but no images will be regularily aquired. In this case, only manually taken images will be passed to any registered - * source node. If the flag is enabled again, the timer is restarted and every live image will automatically get new images. This is done by - * invoking the slot 'setSource' of every registered source node. - * - * Every camera will only return shallow copies of its internal image both to the live image and to the user. This image can be read by everybody. - * If the user wants to change values in this image, he should make a deep copy first. - * + private Q_SLOTS: + + //! overwrite this slot if you want to get informed when the dock-widget of the plugin becomes (in)visible + /*! + It is recommended to use this method, in order to connect the widget to signals like parametersChanged, + actuatorStatusChanged or targetChanged (both actuator only) if the dock-widget becomes visible and disconnect + them if it is hidden. This is useful in order to avoid intense function calls if the dock-widget is not + visible. + + \sa parametersChanged */ - class ITOMCOMMONQT_EXPORT AddInDataIO : public AddInBase + virtual void dockWidgetVisibilityChanged(bool /*visible*/){}; +}; + +//---------------------------------------------------------------------------------------------------------------------------------- +/** @class AddInDataIO + * @brief base class for all dataIO plugin classes + * + * This class is one step further down the line from \ref AddInBase. DataIO plugins must be derived from this class + * which is derived from AddInBase. In this class only the methods specific to dataIO plugins are declared. A dataIO + * device (e.g. a framegrabber / camera) should use this sequence to operate: + * 1. startDevice - device is now ready to acquire data + * 2. acquire - now a data set is freezed and prepared for retrieval + * 3. getVal - method to retrieve the previously freezed data (shallow copy, if you want to work with this data, make + * a deep copy) + * 4. stopDevice - acquisition is stopped, device is no longer ready to record data + * + * the steps 2. and 3. can be repeated until the desired number of "frames" has been read. The device + * should be only started once before the first acquisition of a sequence and stop only at their end. + * The device itself MUST NOT allocate memory for the data to be stored. This HAS TO BE DONE in the main programm + * or in the calling method! + * + * If a live image is listening this device, its source node calls startDeviceAndRegisterListener. If the + * autoGrabbing-flag is enabled, a timer will be started, which triggers the method 'timerEvent' (should be implemented + * by any camera). If this flag is disabled, the live image is registered, but no images will be regularily aquired. In + * this case, only manually taken images will be passed to any registered source node. If the flag is enabled again, the + * timer is restarted and every live image will automatically get new images. This is done by invoking the slot + * 'setSource' of every registered source node. + * + * Every camera will only return shallow copies of its internal image both to the live image and to the user. This + * image can be read by everybody. If the user wants to change values in this image, he should make a deep copy first. + * + */ +class ITOMCOMMONQT_EXPORT AddInDataIO : public AddInBase +{ + Q_OBJECT + + private: + Q_DISABLE_COPY(AddInDataIO) + + QScopedPointer + d_ptr; //!> self-managed pointer to the private class container (deletes itself if d_ptr is destroyed) + Q_DECLARE_PRIVATE(AddInDataIO); + + protected: + virtual ~AddInDataIO(); + AddInDataIO(); + + void runStatusChanged(bool deviceStarted); + + // void timerEvent (QTimerEvent *event) = 0; //implement this event in your plugin, if you are a device, which is + // accessible by any liveImage!!! + + /*!< MultiMap of listeners (live image source nodes), which want to have updates from + this camera. The String indicates the channel (for multigrabber sources), else the channel is an empty string. */ + QMultiMap m_autoGrabbingListeners; + int m_timerID; /*!< internal ID of the timer, which acquires images for any live view (if allowed) */ + int m_timerIntervalMS; /*!< timer interval (in ms)*/ + bool m_autoGrabbingEnabled; /*!< defines, whether the auto-grabbing timer for any live image can be activated. If + this variable becomes false and any timer is activated, this timer is killed.*/ + + public: + + /*!< returns the state of m_autoGrabbingEnabled; consider this method as final */ + inline int getAutoGrabbing() { - Q_OBJECT + return m_autoGrabbingEnabled; + } + + Q_SIGNALS: + + public Q_SLOTS: + //! method to start the device - i.e. get ready to record data + virtual ito::RetVal startDevice(ItomSharedSemaphore *waitCond); + + //! method to stop the device, it is no longer possible to acquire data + virtual ito::RetVal stopDevice(ItomSharedSemaphore *waitCond); + + //! freeze the current data and prepare it for retrieval + virtual ito::RetVal acquire(const int trigger, ItomSharedSemaphore *waitCond = nullptr); + + //! stops a continuous acquisition (usually only required by AD/DA converters). This method has not to be + //! implemented in every plugin. New from itom.AddIn.Interface/4.0.0 on + virtual ito::RetVal stop(ItomSharedSemaphore *waitCond = nullptr); + + //! read data from the device into a dataObject (which is passed as void pointer actually). Output is a shallow-copy + //! to the grabber internal buffer-object. + virtual ito::RetVal getVal(void *data, ItomSharedSemaphore *waitCond = nullptr); + + //! read data from the device into a "raw data pointer" (in this case a char * is passed, pointing to the start of + //! the preallocated memory) + virtual ito::RetVal getVal(QSharedPointer data, QSharedPointer length, + ItomSharedSemaphore *waitCond = nullptr); + + //! read data from the device into a dataObject (which is passed as void pointer actually). The map contains + //! dataObjects for different channels. Output is a shallow-copy to the grabber internal buffer-object. + virtual ito::RetVal getVal(QSharedPointer> dataObjMap, + ItomSharedSemaphore *waitCond = nullptr); + + virtual ito::RetVal getVal(ItomSharedSemaphore* waitCond = nullptr); + //! read data from the device into a dataObject (which is passed as void pointer actually). Output is a deep-copy to + //! the grabber internal object. + virtual ito::RetVal copyVal(void *dObj, ItomSharedSemaphore *waitCond); + + //! write data, e.g. to the DA part of an ADDA card + virtual ito::RetVal setVal(const char *data, const int length, ItomSharedSemaphore *waitCond = nullptr); + + //! enables the timer for auto grabbing (live image), if any live image has signed on (usually this method must not + //! be overwritten) + ito::RetVal enableAutoGrabbing(ItomSharedSemaphore *waitCond = nullptr); // consider this method as final + + //! disables the timer for auto grabbing (live image) (usually this method must not be overwritten) + ito::RetVal disableAutoGrabbing(ItomSharedSemaphore *waitCond = nullptr); // consider this method as final + + //! sets a new interval for the auto-grabbing timer (in ms). If interval <= 0 is passed, nothing is changed, but the + //! current interval is returned. This method does not enable or disable the timer. + ito::RetVal setAutoGrabbingInterval(QSharedPointer interval, + ItomSharedSemaphore *waitCond = nullptr); // consider this method as final + + //! starts device and registers obj as listener (live image). This listener must have a slot void + //! setSource(QSharedPointer, ItomSharedSemaphore). + ito::RetVal startDeviceAndRegisterListener(QObject *listener, + ItomSharedSemaphore *waitCond = nullptr); // consider this method as final + + //! stops device and unregisters obj (live image). + ito::RetVal stopDeviceAndUnregisterListener(QObject * listener, + ItomSharedSemaphore *waitCond = nullptr); // consider this method as final +}; + +//---------------------------------------------------------------------------------------------------------------------------------- + +/** @class AddInActuator + * @brief base class for all actuator plugin classes + * + * This class is one step further down the line from \ref AddInBase. Actuator plugins must be derived from this class + * which is derived from AddInBase. In this class only the methods specific to actuator plugins are declared. + */ +class ITOMCOMMONQT_EXPORT AddInActuator : public AddInBase +{ + Q_OBJECT + + private: + Q_DISABLE_COPY(AddInActuator) + + QScopedPointer + d_ptr; //!> self-managed pointer to the private class container (deletes itself if d_ptr is destroyed) + Q_DECLARE_PRIVATE(AddInActuator); + + protected: + virtual ~AddInActuator(); + AddInActuator(); + + QVector m_currentStatus; /*!< vector (same length than number of axes) containing the status of every axis. The + status is a combination of enumeration ito::tActuatorStatus. */ + QVector m_currentPos; /*!< vector (same length than number of axes) containing the current position (mm or + degree) of every axis. The current position should be updated with a reasonable + frequency (depending on the actuator and situation)*/ + QVector m_targetPos; /*!< vector (same length than number of axes) containing the target position (mm or + degree) of every axis */ + + //! checks whether any axis is still moving (moving flag is set) + bool isMotorMoving() const; + + void sendStatusUpdate( + const bool statusOnly = + false); /* emits actuatorStatusChanged signal with the vector of currentStatus (and currentPos if statusOnly + = false) to notify connected listeners about the current status (and position)*/ + void sendTargetUpdate(); /* emits targetChanged with the vector of targetPositions to notify connected listeners + about the change of the target position(s) */ + + //! this method must be overwritten. + /*! + WaitForDone should wait for a moving motor until the indicated axes (or all axes of nothing is indicated) have + stopped or a timeout or user interruption occurred. The timeout can be given in milliseconds, or -1 if no timeout + should be considered. The flag-parameter can be used for your own purpose. + */ + virtual ito::RetVal waitForDone(const int timeoutMS = -1, + const QVector axis = QVector() /*if empty -> all axis*/, + const int flags = 0 /*for your use*/) = 0; - private: - Q_DISABLE_COPY(AddInDataIO) + //! sets status flags of given status variable + /*! + Use this small inline method in order to set the status of given status variable. The status is an OR-combination of + the enumeration ito::tActuatorStatus. You can assign a mask (keepMask). Bits whithin this mask will be unchanged. - QScopedPointer d_ptr; //!> self-managed pointer to the private class container (deletes itself if d_ptr is destroyed) - Q_DECLARE_PRIVATE(AddInDataIO); + \param [in,out] status is the status variable which is changed. + \param [in] newFlags is an OR-combination of ito::tActuatorStatus which is assigned to status. + \param [in] keepMask is a mask whose bits are not deleted if they are not contained in newFlags. - protected: - virtual ~AddInDataIO(); - AddInDataIO(); + \sa tActuatorStatus + */ + void setStatus(int &status, const int newFlags, const int keepMask = 0); - void runStatusChanged(bool deviceStarted); + //! sets status flags of the status of the given axes + /*! + This method calls setStatus for the status of every given axis-number. The status is directly changed in the member + variable m_currentStatus. For further information see the description of method setStatus (for one single status + variable) - //void timerEvent (QTimerEvent *event) = 0; //implement this event in your plugin, if you are a device, which is accessible by any liveImage!!! + \param [in] axis is the vector with axis-numbers. + \param [in] newFlags is an OR-combination of ito::tActuatorStatus which is assigned to status. + \param [in] keepMask is a mask whose bits are not deleted if they are not contained in newFlags. - QSet m_autoGrabbingListeners; /*!< list of listeners (live image source nodes), which want to have updates from this camera */ - int m_timerID; /*!< internal ID of the timer, which acquires images for any live view (if allowed) */ - int m_timerIntervalMS; /*!< timer interval (in ms)*/ - bool m_autoGrabbingEnabled; /*!< defines, whether the auto-grabbing timer for any live image can be activated. If this variable becomes false and any timer is activated, this timer is killed.*/ + \sa setStatus + */ + void setStatus(const QVector &axis, const int newFlags, const int keepMask = 0); - public: - inline int getAutoGrabbing() { return m_autoGrabbingEnabled; } /*!< returns the state of m_autoGrabbingEnabled; consider this method as final */ + //! changes the status bit of the given status value from one existing to a new value. + /*! + If the given existingFlag bitmask of the status-value is set, it is completely replaced by the flags set by + replaceFlag. - Q_SIGNALS: + \param [in,out] status is the status variable which is changed. + \param [in] existingFlag is the bitmask which must be set and is replace by replaceFlag + \param [in] replaceFlag is the bitmask which is used for the replacement. - public Q_SLOTS: - //! method to start the device - i.e. get ready to record data - virtual ito::RetVal startDevice(ItomSharedSemaphore *waitCond); + \sa tActuatorStatus + */ + void replaceStatus(int &status, const int existingFlag, const int replaceFlag); - //! method to stop the device, it is no longer possible to acquire data - virtual ito::RetVal stopDevice(ItomSharedSemaphore *waitCond); + //! changes the status flags of the status of the given axes from one existing to a new value + /*! + This method calls replaceStatus for the status of every given axis-number. The status is directly changed in the + member variable m_currentStatus. For further information see the description of method replaceStatus (for one single + status variable) - //! freeze the current data and prepare it for retrieval - virtual ito::RetVal acquire(const int trigger, ItomSharedSemaphore *waitCond = NULL); + \param [in] axis is the vector with axis-numbers. + \param [in] existingFlag is the bitmask which must be set and is replace by replaceFlag + \param [in] replaceFlag is the bitmask which is used for the replacement. - //! stops a continuous acquisition (usually only required by AD/DA converters). This method has not to be implemented in every plugin. New from itom.AddIn.Interface/4.0.0 on - virtual ito::RetVal stop(ItomSharedSemaphore *waitCond = NULL); + \sa replaceStatus + */ + void replaceStatus(const QVector &axis, const int existingFlag, const int replaceFlag); + + //! initializes the current status, current position and target position vectors to the same size and the given + //! start values + /*! + If sendUpdateSignals is true, the signals targetChanged and actuatorStatusChanged are emitted with the new size and + content. In any case, the last signalled states are set to these initial values, too. + */ + void initStatusAndPositions(int numAxes, int status, double currentPosition = 0.0, double targetPosition = 0.0, + bool sendUpdateSignals = true); - //! read data from the device into a dataObject (which is passed as void pointer actually). Output is a shallow-copy to the grabber internal buffer-object. - virtual ito::RetVal getVal(void* data, ItomSharedSemaphore *waitCond = NULL); + //! returns interrupt flag (thread-safe) + /*! + This methods returns true if the interrupt flag has been set using setInterrupt. Once this method is called, the + interrupt flag is reset. - //! read data from the device into a "raw data pointer" (in this case a char * is passed, pointing to the start of the preallocated memory) - virtual ito::RetVal getVal(QSharedPointer data, QSharedPointer length, ItomSharedSemaphore *waitCond = NULL); + \return true if interrupt flag has been set, else false. + \sa setInterrupt + */ + bool isInterrupted(); - //! read data from the device into a dataObject (which is passed as void pointer actually). Output is a deep-copy to the grabber internal object. - virtual ito::RetVal copyVal(void *dObj, ItomSharedSemaphore *waitCond); + public: + //! set interrupt flag (thread-safe) + /*! + call this method (even direct call from different thread is possible) if you want to set the interrupt flag in order + to stop a moving actuator. This flag has to be continously be checked in waitForDone using the method isInterrupted, + since this method only sets the flag without initiating further actions. - //! write data, e.g. to the DA part of an ADDA card - virtual ito::RetVal setVal(const char *data, const int length, ItomSharedSemaphore *waitCond = NULL); + \sa waitForDone, isInterrupted + */ + void setInterrupt(); - //! enables the timer for auto grabbing (live image), if any live image has signed on (usually this method must not be overwritten) - ito::RetVal enableAutoGrabbing(ItomSharedSemaphore *waitCond = NULL); //consider this method as final + //! resets the interrupt flag (thread-safe) + /*! + call this method (even direct call from different thread is possible) if you want to reset the interrupt flag. + This method is called if setOrigin, setPosAbs or setPosRel is called from Python since the interrupt flag can be set + if a Python script is interrupted (depending on itom property). + */ + void resetInterrupt(); - //! disables the timer for auto grabbing (live image) (usually this method must not be overwritten) - ito::RetVal disableAutoGrabbing(ItomSharedSemaphore *waitCond = NULL); //consider this method as final + //! put the latest signalled states (current status, position and target position) to the given arguments. + /*! + "last signalled" signifies that whenever the signal targetChanged or actuatorStatusChanged is emitted, + the current value of these states is stored and can be obtained by this method. - //! sets a new interval for the auto-grabbing timer (in ms). If interval <= 0 is passed, nothing is changed, but the current interval is returned. This method does not enable or disable the timer. - ito::RetVal setAutoGrabbingInterval(QSharedPointer interval, ItomSharedSemaphore *waitCond = NULL); //consider this method as final + The call to this method is thread-safe. - //! starts device and registers obj as listener (live image). This listener must have a slot void setSource(QSharedPointer, ItomSaredSemaphore). - ito::RetVal startDeviceAndRegisterListener(QObject* obj, ItomSharedSemaphore *waitCond = NULL); //consider this method as final + \return ito::retOk if all states could be read, ito::retError if no status or position value has been reported up to + now. + */ + ito::RetVal getLastSignalledStates(QVector &status, QVector ¤tPos, QVector &targetPos); - //! stops device and unregisters obj (live image). - ito::RetVal stopDeviceAndUnregisterListener(QObject* obj, ItomSharedSemaphore *waitCond = NULL); //consider this method as final - }; + Q_SIGNALS: + //! signal emitted if status or actual position of any axis has been changed. + /*! + Usually this signal can be sent using the method sendStatusUpdate(...). This method firstly checks if any slot has + been connected to this signal and only fires the signal of at least one slot is connected (e.g. any docking-widget). - //---------------------------------------------------------------------------------------------------------------------------------- + Usually the status and positions are taken from the member variables m_currentStatus and m_currentPos. - /** @class AddInActuator - * @brief base class for all actuator plugin classes - * - * This class is one step further down the line from \ref AddInBase. Actuator plugins must be derived from this class which - * is derived from AddInBase. In this class only the methods specific to actuator plugins are declared. + \params status is a vector with the length of the number of axis and each value contains a OR-combination of + ito::tActuatorStatus \params actPosition is a vector with the length of the number of axis containing the actual + axis positions, or length 0, if no actual positions are sended. */ - class ITOMCOMMONQT_EXPORT AddInActuator : public AddInBase + void actuatorStatusChanged(QVector status, QVector actPosition); + + //! signal emitted if target position of any axis has changed. + /*! + Usually this signal can be sent using the method sendTargetUpdate(). This method firstly checks if any slot has been + connected to this signal and only fires the signal of at least one slot is connected (e.g. any docking-widget). + + Usually the target is taken from the member variable m_targetPos. + + \params targetPositions is a vector with the length of the number of axis containing the desired target positions + for ALL axis. + */ + void targetChanged(QVector targetPositions); + + public Q_SLOTS: + //! method to calibrate a single axis + virtual ito::RetVal calib(const int axis, ItomSharedSemaphore *waitCond = NULL) = 0; + //! method to calibrate a number of axis. The axis' numbers are given in the axis vector + virtual ito::RetVal calib(const QVector axis, ItomSharedSemaphore *waitCond = NULL) = 0; + //! method to set the origin of one axis to the current position + virtual ito::RetVal setOrigin(const int axis, ItomSharedSemaphore *waitCond = NULL) = 0; + //! method to set the origin of a number of axis to their current positions. The axis' numbers are given in the axis + //! vector + virtual ito::RetVal setOrigin(const QVector axis, ItomSharedSemaphore *waitCond = NULL) = 0; + //! retrieve the status of the actuator + virtual ito::RetVal getStatus(QSharedPointer> status, ItomSharedSemaphore *waitCond) = 0; + //! retrieve the status of one axis of the actuator. By default, this method uses the general implementation of + //! getStatus and returns the requested axis only. + virtual ito::RetVal getStatus(const int axis, QSharedPointer status, ItomSharedSemaphore *waitCond); + //! read the position of one axis + virtual ito::RetVal getPos(const int axis, QSharedPointer pos, ItomSharedSemaphore *waitCond) = 0; + //! read the position of a number of axis. The axis' numbers are given in the axis vector + virtual ito::RetVal getPos(const QVector axis, QSharedPointer> pos, + ItomSharedSemaphore *waitCond) = 0; + //! move a single axis to a new absolute position + virtual ito::RetVal setPosAbs(const int axis, const double pos, ItomSharedSemaphore *waitCond = NULL) = 0; + //! move a number of axis to a new absolute position. The axis' numbers are given in the axis vector + virtual ito::RetVal setPosAbs(const QVector axis, QVector pos, + ItomSharedSemaphore *waitCond = NULL) = 0; + //! increment/decrement a single axis by position value + virtual ito::RetVal setPosRel(const int axis, const double pos, ItomSharedSemaphore *waitCond = NULL) = 0; + //! increment/decrement a number of axis by position values. The axis' numbers are given in the axis vector + virtual ito::RetVal setPosRel(const QVector axis, QVector pos, + ItomSharedSemaphore *waitCond = NULL) = 0; + + //! overload this function to update the current status and position values, followed by calling sendStatusUpdate + //! and/or sendTargetUpdate + virtual ito::RetVal requestStatusAndPosition(bool sendCurrentPos, bool sendTargetPos); +}; + +//---------------------------------------------------------------------------------------------------------------------------------- +/** @class AddInAlgo + * @brief base class for all "algorithm" plugin classes + * + * This class is one step further down the line from \ref AddInBase. "Algorithm" plugins must be derived from this + * class which is derived from AddInBase. Compared to \ref AddInDataIO and \ref AddInActuator the AddInAlgo class is + * fairly simple. It does not have an init function or a close function. In the algo base class at the moment no further + * methods or variables are declared - it serves more as an organisation class, putting all actual plugins to the same + * level of inheritance. + */ +class ITOMCOMMONQT_EXPORT AddInAlgo : public AddInBase +{ + Q_OBJECT + + private: + Q_DISABLE_COPY(AddInAlgo) + + QScopedPointer + d_ptr; //!> self-managed pointer to the private class container (deletes itself if d_ptr is destroyed) + Q_DECLARE_PRIVATE(AddInAlgo); + + public: + typedef ito::RetVal (*t_filter)(QVector *paramsMand, QVector *paramsOpt, + QVector *paramsOut); + typedef ito::RetVal (*t_filterExt)(QVector *paramsMand, QVector *paramsOpt, + QVector *paramsOut, + QSharedPointer observer); + typedef QWidget *(*t_algoWidget)(QVector *paramsMand, QVector *paramsOpt, + ito::RetVal &retValue); + typedef ito::RetVal (*t_filterParam)(QVector *paramsMand, QVector *paramsOpt, + QVector *paramsOut); + + //!< possible categories for filter or widget-methods + enum tAlgoCategory { - Q_OBJECT - - private: - Q_DISABLE_COPY(AddInActuator) - - QScopedPointer d_ptr; //!> self-managed pointer to the private class container (deletes itself if d_ptr is destroyed) - Q_DECLARE_PRIVATE(AddInActuator); - - protected: - virtual ~AddInActuator(); - AddInActuator(); - - QVector m_currentStatus; /*!< vector (same length than number of axes) containing the status of every axis. The status is a combination of enumeration ito::tActuatorStatus. */ - QVector m_currentPos; /*!< vector (same length than number of axes) containing the current position (mm or degree) of every axis. The current position should be updated with a reasonable frequency (depending on the actuator and situation)*/ - QVector m_targetPos; /*!< vector (same length than number of axes) containing the target position (mm or degree) of every axis */ - - //! checks whether any axis is still moving (moving flag is set) - bool isMotorMoving() const; - - void sendStatusUpdate(const bool statusOnly = false); /* emits actuatorStatusChanged signal with the vector of currentStatus (and currentPos if statusOnly = false) to notify connected listeners about the current status (and position)*/ - void sendTargetUpdate(); /* emits targetChanged with the vector of targetPositions to notify connected listeners about the change of the target position(s) */ - - //! this method must be overwritten. - /*! - WaitForDone should wait for a moving motor until the indicated axes (or all axes of nothing is indicated) have stopped or a timeout or user interruption - occurred. The timeout can be given in milliseconds, or -1 if no timeout should be considered. The flag-parameter can be used for your own purpose. - */ - virtual ito::RetVal waitForDone(const int timeoutMS = -1, const QVector axis = QVector() /*if empty -> all axis*/, const int flags = 0 /*for your use*/) = 0; - - //! sets status flags of given status variable - /*! - Use this small inline method in order to set the status of given status variable. The status is an OR-combination of the enumeration ito::tActuatorStatus. - You can assign a mask (keepMask). Bits whithin this mask will be unchanged. - - \param [in,out] status is the status variable which is changed. - \param [in] newFlags is an OR-combination of ito::tActuatorStatus which is assigned to status. - \param [in] keepMask is a mask whose bits are not deleted if they are not contained in newFlags. - - \sa tActuatorStatus - */ - void setStatus(int &status, const int newFlags, const int keepMask = 0); - - //! sets status flags of the status of the given axes - /*! - This method calls setStatus for the status of every given axis-number. The status is directly changed in the member variable m_currentStatus. - For further information see the description of method setStatus (for one single status variable) - - \param [in] axis is the vector with axis-numbers. - \param [in] newFlags is an OR-combination of ito::tActuatorStatus which is assigned to status. - \param [in] keepMask is a mask whose bits are not deleted if they are not contained in newFlags. - - \sa setStatus - */ - void setStatus(const QVector &axis, const int newFlags, const int keepMask = 0); - - //! changes the status bit of the given status value from one existing to a new value. - /*! - If the given existingFlag bitmask of the status-value is set, it is completely replaced by the flags set by replaceFlag. - - \param [in,out] status is the status variable which is changed. - \param [in] existingFlag is the bitmask which must be set and is replace by replaceFlag - \param [in] replaceFlag is the bitmask which is used for the replacement. - - \sa tActuatorStatus - */ - void replaceStatus(int &status, const int existingFlag, const int replaceFlag); - - //! changes the status flags of the status of the given axes from one existing to a new value - /*! - This method calls replaceStatus for the status of every given axis-number. The status is directly changed in the member variable m_currentStatus. - For further information see the description of method replaceStatus (for one single status variable) - - \param [in] axis is the vector with axis-numbers. - \param [in] existingFlag is the bitmask which must be set and is replace by replaceFlag - \param [in] replaceFlag is the bitmask which is used for the replacement. - - \sa replaceStatus - */ - void replaceStatus(const QVector &axis, const int existingFlag, const int replaceFlag); - - //! initializes the current status, current position and target position vectors to the same size and the given start values - /*! - If sendUpdateSignals is true, the signals targetChanged and actuatorStatusChanged are emitted with the new size and content. - In any case, the last signalled states are set to these initial values, too. - */ - void initStatusAndPositions(int numAxes, int status, double currentPosition = 0.0, double targetPosition = 0.0, bool sendUpdateSignals = true); - - //! returns interrupt flag (thread-safe) - /*! - This methods returns true if the interrupt flag has been set using setInterrupt. Once this method is called, the interrupt flag is reset. - - \return true if interrupt flag has been set, else false. - \sa setInterrupt - */ - bool isInterrupted(); - - public: - //! set interrupt flag (thread-safe) - /*! - call this method (even direct call from different thread is possible) if you want to set the interrupt flag in order to stop a moving actuator. - This flag has to be continously be checked in waitForDone using the method isInterrupted, since this method only sets the flag without initiating - further actions. - - \sa waitForDone, isInterrupted - */ - void setInterrupt(); - - //! resets the interrupt flag (thread-safe) - /*! - call this method (even direct call from different thread is possible) if you want to reset the interrupt flag. - This method is called if setOrigin, setPosAbs or setPosRel is called from Python since the interrupt flag can be set if a Python - script is interrupted (depending on itom property). - */ - void resetInterrupt(); - - //! put the latest signalled states (current status, position and target position) to the given arguments. - /*! - "last signalled" signifies that whenever the signal targetChanged or actuatorStatusChanged is emitted, - the current value of these states is stored and can be obtained by this method. - - The call to this method is thread-safe. - - \return ito::retOk if all states could be read, ito::retError if no status or position value has been reported up to now. - */ - ito::RetVal getLastSignalledStates(QVector &status, QVector ¤tPos, QVector &targetPos); - - Q_SIGNALS: - //! signal emitted if status or actual position of any axis has been changed. - /*! - Usually this signal can be sent using the method sendStatusUpdate(...). This method firstly checks if any slot has been connected to this signal - and only fires the signal of at least one slot is connected (e.g. any docking-widget). - - Usually the status and positions are taken from the member variables m_currentStatus and m_currentPos. - - \params status is a vector with the length of the number of axis and each value contains a OR-combination of ito::tActuatorStatus - \params actPosition is a vector with the length of the number of axis containing the actual axis positions, or length 0, if no actual positions are sended. - */ - void actuatorStatusChanged(QVector status, QVector actPosition); - - //! signal emitted if target position of any axis has changed. - /*! - Usually this signal can be sent using the method sendTargetUpdate(). This method firstly checks if any slot has been connected to this signal - and only fires the signal of at least one slot is connected (e.g. any docking-widget). - - Usually the target is taken from the member variable m_targetPos. - - \params targetPositions is a vector with the length of the number of axis containing the desired target positions for ALL axis. - */ - void targetChanged(QVector targetPositions); - - public Q_SLOTS: - //! method to calibrate a single axis - virtual ito::RetVal calib(const int axis, ItomSharedSemaphore *waitCond = NULL) = 0; - //! method to calibrate a number of axis. The axis' numbers are given in the axis vector - virtual ito::RetVal calib(const QVector axis, ItomSharedSemaphore *waitCond = NULL) = 0; - //! method to set the origin of one axis to the current position - virtual ito::RetVal setOrigin(const int axis, ItomSharedSemaphore *waitCond = NULL) = 0; - //! method to set the origin of a number of axis to their current positions. The axis' numbers are given in the axis vector - virtual ito::RetVal setOrigin(const QVector axis, ItomSharedSemaphore *waitCond = NULL) = 0; - //! retrieve the status of the actuator - virtual ito::RetVal getStatus(QSharedPointer > status, ItomSharedSemaphore *waitCond) = 0; - //! retrieve the status of one axis of the actuator. By default, this method uses the general implementation of getStatus and returns the requested axis only. - virtual ito::RetVal getStatus(const int axis, QSharedPointer status, ItomSharedSemaphore *waitCond); - //! read the position of one axis - virtual ito::RetVal getPos(const int axis, QSharedPointer pos, ItomSharedSemaphore *waitCond) = 0; - //! read the position of a number of axis. The axis' numbers are given in the axis vector - virtual ito::RetVal getPos(const QVector axis, QSharedPointer > pos, ItomSharedSemaphore *waitCond) = 0; - //! move a single axis to a new absolute position - virtual ito::RetVal setPosAbs(const int axis, const double pos, ItomSharedSemaphore *waitCond = NULL) = 0; - //! move a number of axis to a new absolute position. The axis' numbers are given in the axis vector - virtual ito::RetVal setPosAbs(const QVector axis, QVector pos, ItomSharedSemaphore *waitCond = NULL) = 0; - //! increment/decrement a single axis by position value - virtual ito::RetVal setPosRel(const int axis, const double pos, ItomSharedSemaphore *waitCond = NULL) = 0; - //! increment/decrement a number of axis by position values. The axis' numbers are given in the axis vector - virtual ito::RetVal setPosRel(const QVector axis, QVector pos, ItomSharedSemaphore *waitCond = NULL) = 0; - - //! overload this function to update the current status and position values, followed by calling sendStatusUpdate and/or sendTargetUpdate - virtual ito::RetVal requestStatusAndPosition(bool sendCurrentPos, bool sendTargetPos); + catNone = 0x0000, //!< default: no category + catDiskIO = 0x0001, //!< category for saving or loading data from hard drive + catAnalyseDataObject = 0x0002, //!< category for methods analysing data objects + catPlotDataObject = 0x0004 //!< category for methods plotting data objects }; - //---------------------------------------------------------------------------------------------------------------------------------- - /** @class AddInAlgo - * @brief base class for all "algorithm" plugin classes - * - * This class is one step further down the line from \ref AddInBase. "Algorithm" plugins must be derived from this class which - * is derived from AddInBase. Compared to \ref AddInDataIO and \ref AddInActuator the AddInAlgo class is fairly simple. It does - * not have an init function or a close function. In the algo base class at the moment no further methods or variables are declared - - * it serves more as an organisation class, putting all actual plugins to the same level of inheritance. - */ - class ITOMCOMMONQT_EXPORT AddInAlgo : public AddInBase + //!< possible algorithm interfaces + enum tAlgoInterface + { + iNotSpecified = 0x0000, //!< default: filter or widget does not fit to any interface + iReadDataObject = 0x0001, //!< interface for loading content of files into a data object + iWriteDataObject = 0x0002, //!< interface for saving data object to file + iReadPointCloud = 0x0004, //!< interface for loading content of files into a point cloud + iWritePointCloud = 0x0008, //!< interface for saving point cloud to file + iReadPolygonMesh = 0x0010, //!< interface for loading content of files into a polygon mesh + iWritePolygonMesh = 0x0020, //!< interface for saving polygon mesh to file + iPlotSingleObject = 0x0040 //!< interface for ploting dataObjects via the GUI + }; + + // Q_ENUM exposes a meta object to the enumeration types, such that the key names for the enumeration + // values are always accessible. + Q_ENUM(tAlgoCategory) + Q_ENUM(tAlgoInterface) + + //! container for publishing filters provided by any plugin + class FilterDef { - Q_OBJECT + public: + //!< empty, default constructor + FilterDef() + : m_filterFunc(NULL), m_paramFunc(NULL), m_pBasePlugin(NULL), m_category(ito::AddInAlgo::catNone), + m_interface(ito::AddInAlgo::iNotSpecified) + { + } - private: - Q_DISABLE_COPY(AddInAlgo) + //!< constructor with all necessary arguments. + FilterDef(AddInAlgo::t_filter filterFunc, AddInAlgo::t_filterParam filterParamFunc, + QString description = QString(), ito::AddInAlgo::tAlgoCategory category = ito::AddInAlgo::catNone, + ito::AddInAlgo::tAlgoInterface interf = ito::AddInAlgo::iNotSpecified, + QString interfaceMeta = QString()) + : m_filterFunc(filterFunc), m_paramFunc(filterParamFunc), m_pBasePlugin(NULL), m_description(description), + m_category(category), m_interface(interf), m_interfaceMeta(interfaceMeta) + { + } - QScopedPointer d_ptr; //!> self-managed pointer to the private class container (deletes itself if d_ptr is destroyed) - Q_DECLARE_PRIVATE(AddInAlgo); + virtual ~FilterDef() + { + } - public: - typedef ito::RetVal (*t_filter) (QVector *paramsMand, QVector *paramsOpt, QVector *paramsOut); - typedef ito::RetVal (*t_filterExt) (QVector *paramsMand, QVector *paramsOpt, QVector *paramsOut, QSharedPointer observer); - typedef QWidget* (*t_algoWidget) (QVector *paramsMand, QVector *paramsOpt, ito::RetVal &retValue); - typedef ito::RetVal (*t_filterParam)(QVector *paramsMand, QVector *paramsOpt, QVector *paramsOut); + t_filter m_filterFunc; //!< function pointer (unbounded, static) for filter-method + t_filterParam m_paramFunc; //!< function pointer (unbounded, static) for filter's default parameter method + ito::AddInInterfaceBase + *m_pBasePlugin; //!< interface (factory) instance of this plugin (will be automatically filled) + QString m_name; //!< name of filter + QString m_description; //!< description of filter + ito::AddInAlgo::tAlgoCategory m_category; //!< category, filter belongs to (default: catNone) + ito::AddInAlgo::tAlgoInterface m_interface; //!< algorithm interface, filter fits to (default: iNotSpecified) + QString m_interfaceMeta; //!< meta information if required by algorithm interface + private: + FilterDef(const FilterDef & /*p*/); // disable copy constructor + }; + + //! extended FilterDef (derived from FilterDef) with a filterFunc of type f_filterExt instead of t_filter. This + //! method has an additional argument of type FunctionCancellationAndObserver + class FilterDefExt : public FilterDef + { + public: + //!< empty, default constructor + FilterDefExt() : FilterDef(), m_filterFuncExt(NULL) + { + } - //!< possible categories for filter or widget-methods - enum tAlgoCategory + //!< constructor with all necessary arguments. + FilterDefExt(AddInAlgo::t_filterExt filterFuncExt, AddInAlgo::t_filterParam filterParamFunc, + QString description = QString(), ito::AddInAlgo::tAlgoCategory category = ito::AddInAlgo::catNone, + ito::AddInAlgo::tAlgoInterface interf = ito::AddInAlgo::iNotSpecified, + QString interfaceMeta = QString(), bool hasStatusInfo = true, bool isCancellable = true) + : FilterDef(NULL, filterParamFunc, description, category, interf, interfaceMeta), + m_filterFuncExt(filterFuncExt), m_hasStatusInformation(hasStatusInfo), m_isCancellable(isCancellable) { - catNone = 0x0000, //!< default: no category - catDiskIO = 0x0001, //!< category for saving or loading data from hard drive - catAnalyseDataObject = 0x0002, //!< category for methods analysing data objects - catPlotDataObject = 0x0004 //!< category for methods plotting data objects - }; - - //!< possible algorithm interfaces - enum tAlgoInterface + } + + virtual ~FilterDefExt() { - iNotSpecified = 0x0000, //!< default: filter or widget does not fit to any interface - iReadDataObject = 0x0001, //!< interface for loading content of files into a data object - iWriteDataObject = 0x0002, //!< interface for saving data object to file - iReadPointCloud = 0x0004, //!< interface for loading content of files into a point cloud - iWritePointCloud = 0x0008, //!< interface for saving point cloud to file - iReadPolygonMesh = 0x0010, //!< interface for loading content of files into a polygon mesh - iWritePolygonMesh = 0x0020, //!< interface for saving polygon mesh to file - iPlotSingleObject = 0x0040 //!< interface for ploting dataObjects via the GUI - }; - - //Q_ENUM exposes a meta object to the enumeration types, such that the key names for the enumeration - //values are always accessible. - Q_ENUM(tAlgoCategory) - Q_ENUM(tAlgoInterface) - - //! container for publishing filters provided by any plugin - class FilterDef + } + + t_filterExt m_filterFuncExt; //!< extended function pointer (unbounded, static) for filter-method + bool m_hasStatusInformation; //!< true, if filter updates status information to the optional observer + bool m_isCancellable; //!< true, if filter listens to a possible interrupt flag in the optional observer and + //!< cancels the execution if set + + private: + FilterDefExt(const FilterDefExt & /*p*/); // disable copy constructor + }; + + //! container for publishing widgets provided by any plugin + class AlgoWidgetDef + { + public: + //!< empty, default constructor + AlgoWidgetDef() + : m_widgetFunc(NULL), m_paramFunc(NULL), m_pBasePlugin(NULL), m_category(ito::AddInAlgo::catNone), + m_interface(ito::AddInAlgo::iNotSpecified) { - public: - //!< empty, default constructor - FilterDef() : - m_filterFunc(NULL), - m_paramFunc(NULL), - m_pBasePlugin(NULL), - m_category(ito::AddInAlgo::catNone), - m_interface(ito::AddInAlgo::iNotSpecified) - {} - - //!< constructor with all necessary arguments. - FilterDef(AddInAlgo::t_filter filterFunc, AddInAlgo::t_filterParam filterParamFunc, - QString description = QString(), ito::AddInAlgo::tAlgoCategory category = ito::AddInAlgo::catNone, - ito::AddInAlgo::tAlgoInterface interf = ito::AddInAlgo::iNotSpecified, - QString interfaceMeta = QString()) : - m_filterFunc(filterFunc), - m_paramFunc(filterParamFunc), - m_pBasePlugin(NULL), - m_description(description), - m_category(category), - m_interface(interf), - m_interfaceMeta(interfaceMeta) - {} - - virtual ~FilterDef() {} - - t_filter m_filterFunc; //!< function pointer (unbounded, static) for filter-method - t_filterParam m_paramFunc; //!< function pointer (unbounded, static) for filter's default parameter method - ito::AddInInterfaceBase *m_pBasePlugin; //!< interface (factory) instance of this plugin (will be automatically filled) - QString m_name; //!< name of filter - QString m_description; //!< description of filter - ito::AddInAlgo::tAlgoCategory m_category; //!< category, filter belongs to (default: catNone) - ito::AddInAlgo::tAlgoInterface m_interface; //!< algorithm interface, filter fits to (default: iNotSpecified) - QString m_interfaceMeta; //!< meta information if required by algorithm interface - private: - FilterDef(const FilterDef & /*p*/); //disable copy constructor - }; - - //! extended FilterDef (derived from FilterDef) with a filterFunc of type f_filterExt instead of t_filter. This method has an additional argument of type FunctionCancellationAndObserver - class FilterDefExt : public FilterDef + } + + //!< constructor with all necessary arguments. + AlgoWidgetDef(AddInAlgo::t_algoWidget algoWidgetFunc, AddInAlgo::t_filterParam algoWidgetParamFunc, + QString description = QString(), ito::AddInAlgo::tAlgoCategory category = ito::AddInAlgo::catNone, + ito::AddInAlgo::tAlgoInterface interf = ito::AddInAlgo::iNotSpecified, + QString interfaceMeta = QString()) + : m_widgetFunc(algoWidgetFunc), m_paramFunc(algoWidgetParamFunc), m_pBasePlugin(NULL), + m_description(description), m_category(category), m_interface(interf), m_interfaceMeta(interfaceMeta) { - public: - //!< empty, default constructor - FilterDefExt() : - FilterDef(), - m_filterFuncExt(NULL) - {} - - //!< constructor with all necessary arguments. - FilterDefExt(AddInAlgo::t_filterExt filterFuncExt, AddInAlgo::t_filterParam filterParamFunc, - QString description = QString(), ito::AddInAlgo::tAlgoCategory category = ito::AddInAlgo::catNone, - ito::AddInAlgo::tAlgoInterface interf = ito::AddInAlgo::iNotSpecified, - QString interfaceMeta = QString(), bool hasStatusInfo = true, bool isCancellable = true) : - FilterDef(NULL, filterParamFunc, description, category, interf, interfaceMeta), - m_filterFuncExt(filterFuncExt), - m_hasStatusInformation(hasStatusInfo), - m_isCancellable(isCancellable) - {} - - virtual ~FilterDefExt() {} - - t_filterExt m_filterFuncExt; //!< extended function pointer (unbounded, static) for filter-method - bool m_hasStatusInformation; //!< true, if filter updates status information to the optional observer - bool m_isCancellable; //!< true, if filter listens to a possible interrupt flag in the optional observer and cancels the execution if set - - private: - FilterDefExt(const FilterDefExt & /*p*/); //disable copy constructor - }; - - //! container for publishing widgets provided by any plugin - class AlgoWidgetDef + } + + virtual ~AlgoWidgetDef() { - public: - //!< empty, default constructor - AlgoWidgetDef() : - m_widgetFunc(NULL), - m_paramFunc(NULL), - m_pBasePlugin(NULL), - m_category(ito::AddInAlgo::catNone), - m_interface(ito::AddInAlgo::iNotSpecified) - {} - - //!< constructor with all necessary arguments. - AlgoWidgetDef(AddInAlgo::t_algoWidget algoWidgetFunc, AddInAlgo::t_filterParam algoWidgetParamFunc, QString description = QString(), ito::AddInAlgo::tAlgoCategory category = ito::AddInAlgo::catNone, ito::AddInAlgo::tAlgoInterface interf = ito::AddInAlgo::iNotSpecified, QString interfaceMeta = QString()) : - m_widgetFunc(algoWidgetFunc), - m_paramFunc(algoWidgetParamFunc), - m_pBasePlugin(NULL), - m_description(description), - m_category(category), - m_interface(interf), - m_interfaceMeta(interfaceMeta) - {} - - virtual ~AlgoWidgetDef() {} //!< destructor - - t_algoWidget m_widgetFunc; //!< function pointer (unbounded, static) for widget-method - t_filterParam m_paramFunc; //!< function pointer (unbounded, static) for widget's default parameter method - ito::AddInInterfaceBase *m_pBasePlugin; //!< interface (factory) instance of this plugin (will be automatically filled) - QString m_name; //!< name of widget - QString m_description; //!< description of widget - ito::AddInAlgo::tAlgoCategory m_category; //!< category, widget belongs to (default: catNone) - ito::AddInAlgo::tAlgoInterface m_interface; //!< algorithm interface, widget fits to (default: iNotSpecified) - QString m_interfaceMeta; //!< meta information if required by algorithm interface - - private: - AlgoWidgetDef(const AlgoWidgetDef & /*p*/); //disable copy constructor - }; - - ito::RetVal getFilterList(QHash &fList) const; - ito::RetVal getAlgoWidgetList(QHash &awList) const; - ito::RetVal rejectFilter(const QString &name); - ito::RetVal rejectAlgoWidget(const QString &name); - - protected: - virtual ~AddInAlgo(); - AddInAlgo(); - QHash m_filterList; - QHash m_algoWidgetList; - - //! small check and cleaning of all parameter vectors (can be used in filterParam methods) - static ito::RetVal prepareParamVectors(QVector *paramsMand, QVector *paramsOpt, QVector *paramsOut); - - public Q_SLOTS: - virtual ito::RetVal getParam(QSharedPointer /*val*/, ItomSharedSemaphore * /*waitCond*/ = NULL) { return ito::retOk; } - virtual ito::RetVal setParam(QSharedPointer /*val*/, ItomSharedSemaphore * /*waitCond*/ = NULL) { return ito::retOk; } + } //!< destructor + + t_algoWidget m_widgetFunc; //!< function pointer (unbounded, static) for widget-method + t_filterParam m_paramFunc; //!< function pointer (unbounded, static) for widget's default parameter method + ito::AddInInterfaceBase + *m_pBasePlugin; //!< interface (factory) instance of this plugin (will be automatically filled) + QString m_name; //!< name of widget + QString m_description; //!< description of widget + ito::AddInAlgo::tAlgoCategory m_category; //!< category, widget belongs to (default: catNone) + ito::AddInAlgo::tAlgoInterface m_interface; //!< algorithm interface, widget fits to (default: iNotSpecified) + QString m_interfaceMeta; //!< meta information if required by algorithm interface + + private: + AlgoWidgetDef(const AlgoWidgetDef & /*p*/); // disable copy constructor }; - //---------------------------------------------------------------------------------------------------------------------------------- -} // namespace ito + ito::RetVal getFilterList(QHash &fList) const; + ito::RetVal getAlgoWidgetList(QHash &awList) const; + ito::RetVal rejectFilter(const QString &name); + ito::RetVal rejectAlgoWidget(const QString &name); -#endif //#if !defined(Q_MOC_RUN) || defined(ITOMCOMMONQT_MOC) + protected: + virtual ~AddInAlgo(); + AddInAlgo(); + QHash m_filterList; + QHash m_algoWidgetList; -//! must be out of namespace ito, otherwise it results in a strange compiler error (template ...) -Q_DECLARE_INTERFACE(ito::AddInInterfaceBase, ito_AddInInterface_CurrentVersion /*"ito.AddIn.InterfaceBase/4"*/) + //! small check and cleaning of all parameter vectors (can be used in filterParam methods) + static ito::RetVal prepareParamVectors(QVector *paramsMand, QVector *paramsOpt, + QVector *paramsOut); + public Q_SLOTS: + virtual ito::RetVal getParam(QSharedPointer /*val*/, ItomSharedSemaphore * /*waitCond*/ = NULL) + { + return ito::retOk; + } + virtual ito::RetVal setParam(QSharedPointer /*val*/, ItomSharedSemaphore * /*waitCond*/ = NULL) + { + return ito::retOk; + } +}; +//---------------------------------------------------------------------------------------------------------------------------------- +} // namespace ito -#endif +#endif // #if !defined(Q_MOC_RUN) || defined(ITOMCOMMONQT_MOC) + +//! must be out of namespace ito, otherwise it results in a strange compiler error (template ...) +Q_DECLARE_INTERFACE(ito::AddInInterfaceBase, ito_AddInInterface_CurrentVersion /*"ito.AddIn.InterfaceBase/4"*/) diff --git a/common/addInMultiChannelGrabber.h b/common/addInMultiChannelGrabber.h new file mode 100644 index 000000000..2b857047a --- /dev/null +++ b/common/addInMultiChannelGrabber.h @@ -0,0 +1,268 @@ +/* ******************************************************************** + itom software + URL: http://www.uni-stuttgart.de/ito + Copyright (C) 2023, Institut fuer Technische Optik (ITO), + Universitaet Stuttgart, Germany + + This file is part of itom and its software development toolkit (SDK). + + itom is free software; you can redistribute it and/or modify it + under the terms of the GNU Library General Public Licence as published by + the Free Software Foundation; either version 2 of the Licence, or (at + your option) any later version. + + In addition, as a special exception, the Institut fuer Technische + Optik (ITO) gives you certain additional rights. + These rights are described in the ITO LGPL Exception version 1.0, + which can be found in the file LGPL_EXCEPTION.txt in this package. + + itom is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library + General Public Licence for more details. + + You should have received a copy of the GNU Library General Public License + along with itom. If not, see . +*********************************************************************** */ + +#pragma once + +#include "addInInterface.h" +#include "abstractAddInGrabber.h" + +#include "../DataObject/dataobj.h" +#include "sharedStructuresQt.h" +#include "sharedStructures.h" + +// only moc this file in itomCommonQtLib but not in other libraries or executables linking against this itomCommonQtLib +#if !defined(Q_MOC_RUN) || defined(ITOMCOMMONQT_MOC) + +namespace ito +{ + class AddInMultiChannelGrabberPrivate; + + class ITOMCOMMONQT_EXPORT AddInMultiChannelGrabber : public AbstractAddInGrabber + { + Q_OBJECT + + protected: + + //! enumeration values, that can be combined + enum class DataStatus + { + //! idle = no new data in object + Idle = 0, + + //! newData = new data in object, not emitted via newData + //! yet, not fetched via getVal/copyVal yet + NewData = 1, + + //! same than newData, however data is already emitted, + //! but not fetched via getVal/copyVal yet + NewDataAndEmitted = 2 + }; + + class ITOMCOMMONQT_EXPORT ChannelContainer + { + public: + ChannelContainer(); + ~ChannelContainer() = default; + ChannelContainer(const ChannelContainer&) = default; + ChannelContainer( + const ito::Param& roi, + const ito::Param& pixelFormat, + const ito::Param& sizex, + const ito::Param& sizey, + const ito::Param& axisOffsets, + const ito::Param& axisScales, + const ito::Param& axisDescriptions, + const ito::Param& axisUnits, + const ito::Param& valueDescription, + const ito::Param& valueUnit); + ChannelContainer( + const ito::Param& roi, + const ito::Param& pixelFormat, + const ito::Param& sizex, + const ito::Param& sizey); + + void addChannelParam(const ito::Param& param); + + //!< dataObject container with currently acquired data for this channel + ito::DataObject m_data; + + //!< state of the dataObject container + DataStatus m_dataStatus; + + //!< map of individual parameters for this channel. Every channel has a set + //! of default parameters, namely: pixelFormat, roi, sizex, sizey, axisOffset, axisScale. + //! axisDescription, axisUnit, valueDescription, valueUnit. Further parameters + //! can be added. It is recommended to have the same parameter types and names + //! in every channel, since they are mirrored to the m_params map of the main + //! plugin class. + ParamMap m_channelParams; + + protected: + void addDefaultMetaParams(); + }; + + typedef QMap ChannelContainerMap; + typedef ChannelContainerMap::iterator ChannelContainerMapIterator; + typedef ChannelContainerMap::const_iterator ChannelContainerMapConstIterator; + + ChannelContainerMap m_channels; /*!< Map for recently grabbed images of various channels */ + + virtual ito::RetVal checkData(ito::DataObject* externalDataObject = nullptr); + virtual ito::RetVal checkData(const QString& channelName, ito::DataObject* externalDataObject = nullptr); + + //!< calls checkData for the internal data caches for all channels + virtual ito::RetVal checkDataFromAllChannels(); + + virtual ito::RetVal sendDataToListeners(int waitMS); /*!< sends m_data to all registered listeners. */ + ito::RetVal adaptDefaultChannelParams(); /*!< adaptes the params after changing the defaultChannel param*/ + + void addChannel(QString name); + + virtual ito::RetVal switchChannelSelector();/*!< synchronizes m_params with the params of default channel container */ + virtual ito::RetVal applyParamsToChannelParams(const QStringList& keyList = QStringList()); + + //! registers all channel containers, initializes their parameters as well as all common, global parameters + ito::RetVal initChannelsAndGlobalParameters( + const ChannelContainerMap& channelContainerMap, + const QString& defaultChannelName, + const QList& globalParameters = QList()); + + ito::RetVal setParamMeta(const QByteArray& paramName, ito::ParamMeta* meta, bool takeOwnerShip, const QList& channelList = QList()); + ito::RetVal setParamFlags(const QByteArray& paramName, const unsigned int& flags, const QList& channelList = QList()); + + //! This method fetches the latest acquired images or datasets from the grabber and store it into the channel. + /* + This method has to be overloaded by the specific plugin instance. It should + fetch the latest acquired images or datasets for all given channels and store + it into the internal buffers (m_data) of all corresponding channels. + + The new data is not emitted yet. Its state has to be set to DataStatus::NewData. + + \param channels are the desired channels. If empty, all registered channels should + be fetched. + \return ito::retError if at least one dataset of at least one desired channel + is not available. + + */ + virtual ito::RetVal retrieveData(const QStringList& channels = QStringList()) = 0; + + //! This method fetches the latest acquired image of the current default channel. + /* + This method gets the name of the current default channel and calls the overloaded + method ``retrieveData(channels)`` to fetch the latest acquired image of the default + channel. + + If the ``externalDataObject`` is given, it must either be empty or have the same + size and dtype than the latest image of the default channel. If given, the latest + image is copied into the given externalDataObject. + + Usually, this method has not to be overloaded, since it is implemented in a useable + way. Nevertheless, it can be overloaded. + */ + virtual ito::RetVal retrieveData(ito::DataObject* externalDataObject = nullptr); + + //! Specific function to set the parameters in the respective plugin class + /*! + This function is a specific implementation of setParam. Overload this function to + process parameters individually in the plugin class. This function is called + by setParam after the parameter has been parsed and checked . + + \param [in] val parameter to be processed + \param [in] it ParamMapIterator iterator to the parameter in m_params + \param [in] suffix possible suffix of the parameter + \param [in] key of the parameter + \param [in] index of the parameter + \param [in] hasIndex is set to true if parameter has an index + \param [in] set ok to true if parameter was processed + \param [in] add key of changed channel specific parameters to pendingUpdate. + \return retOk if everything was ok, else retError + */ + virtual ito::RetVal setParameter( + QSharedPointer& val, + const ParamMapIterator& it, + const QString& suffix, + const QString& key, + int index, + bool hasIndex, + bool& ok, + QStringList& pendingUpdate) = 0; + + //! Specific function to get a parameter in the respective plugin class. + /* + This method has to be overwritten in every plugin class and is called within + the ``getParam`` method, which is final in this base class. Overload this method + instead of the ``getParam`` method to deliver the value of the requested parameter. + It is either possible, that this method delivers the content of the requested parameter, + or that the ``ok`` argument is set to true, the return value is retOk. In this case, + the calling ``getParam`` method will deliver the corresponding value in m_params as + it is. + */ + virtual ito::RetVal getParameter( + QSharedPointer val, + const ParamMapIterator& it, + const QString& key, + const QString& suffix, + int index, + bool hasIndex, + bool& ok) = 0; + + void updateSizeXY(); /*!< updates sizex und sizey*/ + + ChannelContainerMapConstIterator getCurrentDefaultChannel() const; + ChannelContainerMapIterator getCurrentDefaultChannel(); + + public: + AddInMultiChannelGrabber(const QByteArray& grabberName); + ~AddInMultiChannelGrabber(); + + private: + QScopedPointer d_ptr; + Q_DECLARE_PRIVATE(AddInMultiChannelGrabber); + + public slots: + ito::RetVal setParam(QSharedPointer val, ItomSharedSemaphore* waitCond = nullptr) final; + + //! returns the current value of a selected parameter + /* + Approach: This method calls the abstract method ``getParameter`` that has to be overloaded + by the plugin in order to obtain the parameter. If this method sets its argument ``ok`` to false, + the current value of the parameter is returned per default by this base implementation. + + This method can either be invoked as ansychronous call, while the argument ``waitCond`` can + be used to handle a notification about end of the call or a timeout, or as a direct call. Then, + ``waitCond`` can also be set to a nullptr. + + getParam will always return the values of the parameters on the top level. If a parameter + is individual per channel, the value of the current channel is returned. This current channel + can be set via the parameter ``channelSelector``. + + \params val is the parameter, whose value is requested. It is a shared pointer of an ito::Param + object, whose name is the only thing that has to be given when calling this method. If this + method succeeds, this value is filled with the full parameter information including its current + value. + \params waitCond is the wait condition, that is used to observe the call state of an asychronous call. + \returns a RetVal object, that indicates the success of this call. The same return value is also + contained in the argument ``waitCond`` if given. + */ + ito::RetVal getParam(QSharedPointer val, ItomSharedSemaphore* waitCond) final; + + virtual ito::RetVal getVal(void* vpdObj, ItomSharedSemaphore* waitCond); + virtual ito::RetVal copyVal(void* vpdObj, ItomSharedSemaphore* waitCond); + + virtual ito::RetVal getVal(QSharedPointer > channelDatasets, ItomSharedSemaphore* waitCond); + virtual ito::RetVal copyVal(QSharedPointer > channelDatasets, ItomSharedSemaphore* waitCond); + + ito::RetVal changeChannelForListener(QObject* listener, const QString& newChannel); + + signals: + /*!< Signals that a new image or set of images is available. Connect to this signal to obtain a shallow copy of the new images */ + void newData(QSharedPointer > channelDatasets); + }; + +} + +#endif diff --git a/common/sharedStructuresQt.h b/common/sharedStructuresQt.h index 399290a4f..d75d3b404 100644 --- a/common/sharedStructuresQt.h +++ b/common/sharedStructuresQt.h @@ -50,6 +50,7 @@ typedef QMap ParamMap; typedef ParamMap::iterator ParamMapIterator; +typedef ParamMap::const_iterator ParamMapConstIterator; //namespace ito //{ diff --git a/common/sources/abstractAddInConfigDialog.cpp b/common/sources/abstractAddInConfigDialog.cpp index 703df59ca..6b3a0499e 100644 --- a/common/sources/abstractAddInConfigDialog.cpp +++ b/common/sources/abstractAddInConfigDialog.cpp @@ -1,7 +1,7 @@ /* ******************************************************************** itom software URL: http://www.uni-stuttgart.de/ito - Copyright (C) 2020, Institut fuer Technische Optik (ITO), + Copyright (C) 2023, Institut fuer Technische Optik (ITO), Universitaet Stuttgart, Germany This file is part of itom and its software development toolkit (SDK). @@ -42,29 +42,30 @@ namespace ito class AbstractAddInConfigDialogPrivate { public: - AbstractAddInConfigDialogPrivate() : m_pPlugin(NULL) + AbstractAddInConfigDialogPrivate() : m_pPlugin(nullptr) {} ito::AddInBase *m_pPlugin; }; //------------------------------------------------------------------------------------------------------------------------------------------------- -AbstractAddInConfigDialog::AbstractAddInConfigDialog(ito::AddInBase *plugin) : QDialog(), d(NULL) +AbstractAddInConfigDialog::AbstractAddInConfigDialog(ito::AddInBase *plugin) : QDialog(), d_ptr(new AbstractAddInConfigDialogPrivate()) { - d = new AbstractAddInConfigDialogPrivate(); + Q_D(AbstractAddInConfigDialog); + d->m_pPlugin = plugin; } //------------------------------------------------------------------------------------------------------------------------------------------------- AbstractAddInConfigDialog::~AbstractAddInConfigDialog() { - delete d; } //------------------------------------------------------------------------------------------------------------------------------------------------- ito::RetVal AbstractAddInConfigDialog::setPluginParameter(QSharedPointer param, MessageLevel msgLevel /*= msgLevelWarningAndError*/) { ito::RetVal retval; + Q_D(AbstractAddInConfigDialog); if (d->m_pPlugin) { @@ -133,6 +134,7 @@ ito::RetVal AbstractAddInConfigDialog::setPluginParameter(QSharedPointer > params, MessageLevel msgLevel /*= msgLevelWarningAndError*/) { ito::RetVal retval; + Q_D(AbstractAddInConfigDialog); if (d->m_pPlugin) { @@ -186,6 +188,7 @@ ito::RetVal AbstractAddInConfigDialog::setPluginParameters(const QVectorm_pPlugin) { diff --git a/common/sources/abstractAddInDockWidget.cpp b/common/sources/abstractAddInDockWidget.cpp index 02a071c63..753f0c3ec 100644 --- a/common/sources/abstractAddInDockWidget.cpp +++ b/common/sources/abstractAddInDockWidget.cpp @@ -1,7 +1,7 @@ /* ******************************************************************** itom software URL: http://www.uni-stuttgart.de/ito - Copyright (C) 2020, Institut fuer Technische Optik (ITO), + Copyright (C) 2023, Institut fuer Technische Optik (ITO), Universitaet Stuttgart, Germany This file is part of itom and its software development toolkit (SDK). @@ -41,29 +41,30 @@ namespace ito class AbstractAddInDockWidgetPrivate { public: - AbstractAddInDockWidgetPrivate() : m_pPlugin(NULL) + AbstractAddInDockWidgetPrivate() : m_pPlugin(nullptr) {} ito::AddInBase *m_pPlugin; }; //------------------------------------------------------------------------------------------------------------------------------------------------- -AbstractAddInDockWidget::AbstractAddInDockWidget(ito::AddInBase *plugin) : d(NULL) +AbstractAddInDockWidget::AbstractAddInDockWidget(ito::AddInBase *plugin) : d_ptr(new AbstractAddInDockWidgetPrivate()) { - d = new AbstractAddInDockWidgetPrivate(); + Q_D(AbstractAddInDockWidget); + d->m_pPlugin = plugin; } //------------------------------------------------------------------------------------------------------------------------------------------------- AbstractAddInDockWidget::~AbstractAddInDockWidget() { - delete d; } //------------------------------------------------------------------------------------------------------------------------------------------------- ito::RetVal AbstractAddInDockWidget::setPluginParameter(QSharedPointer param, MessageLevel msgLevel /*= msgLevelWarningAndError*/) const { ito::RetVal retval; + Q_D(const AbstractAddInDockWidget); if (d->m_pPlugin) { @@ -112,6 +113,7 @@ ito::RetVal AbstractAddInDockWidget::setPluginParameter(QSharedPointer > params, MessageLevel msgLevel /*= msgLevelWarningAndError*/) const { ito::RetVal retval; + Q_D(const AbstractAddInDockWidget); if (d->m_pPlugin) { @@ -160,6 +162,7 @@ ito::RetVal AbstractAddInDockWidget::setPluginParameters(const QVectorm_pPlugin) { @@ -210,6 +213,7 @@ ito::RetVal AbstractAddInDockWidget::observeInvocation(ItomSharedSemaphore *wait ito::RetVal AbstractAddInDockWidget::setActuatorPosition(QVector axes, QVector positions, bool relNotAbs, MessageLevel msgLevel) const { ito::RetVal retval; + Q_D(const AbstractAddInDockWidget); QByteArray funcName = relNotAbs ? "setPosRel" : "setPosAbs"; @@ -268,6 +272,7 @@ ito::RetVal AbstractAddInDockWidget::setActuatorPosition(QVector axes, QVec ito::RetVal AbstractAddInDockWidget::setActuatorPosition(int axis, double position, bool relNotAbs, MessageLevel msgLevel) const { ito::RetVal retval; + Q_D(const AbstractAddInDockWidget); QByteArray funcName = relNotAbs ? "setPosRel" : "setPosAbs"; @@ -326,6 +331,7 @@ ito::RetVal AbstractAddInDockWidget::setActuatorPosition(int axis, double positi ito::RetVal AbstractAddInDockWidget::requestActuatorStatusAndPositions(bool sendCurrentPos, bool sendTargetPos, MessageLevel msgLevel) const { ito::RetVal retval; + Q_D(const AbstractAddInDockWidget); if (d->m_pPlugin) { @@ -376,6 +382,7 @@ ito::RetVal AbstractAddInDockWidget::requestActuatorStatusAndPositions(bool send ito::RetVal AbstractAddInDockWidget::setActuatorInterrupt() const { ito::RetVal retval; + Q_D(const AbstractAddInDockWidget); if (d->m_pPlugin) { diff --git a/common/sources/abstractAddInGrabber.cpp b/common/sources/abstractAddInGrabber.cpp new file mode 100644 index 000000000..50f55a70c --- /dev/null +++ b/common/sources/abstractAddInGrabber.cpp @@ -0,0 +1,270 @@ +/* ******************************************************************** + itom software + URL: http://www.uni-stuttgart.de/ito + Copyright (C) 2023, Institut fuer Technische Optik (ITO), + Universitaet Stuttgart, Germany + + This file is part of itom and its software development toolkit (SDK). + + itom is free software; you can redistribute it and/or modify it + under the terms of the GNU Library General Public Licence as published by + the Free Software Foundation; either version 2 of the Licence, or (at + your option) any later version. + + In addition, as a special exception, the Institut fuer Technische + Optik (ITO) gives you certain additional rights. + These rights are described in the ITO LGPL Exception version 1.0, + which can be found in the file LGPL_EXCEPTION.txt in this package. + + itom is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library + General Public Licence for more details. + + You should have received a copy of the GNU Library General Public License + along with itom. If not, see . +*********************************************************************** */ + +#include "abstractAddInGrabber.h" + +#include "common/helperCommon.h" +#include +#include +#include +#include + +namespace ito +{ +class AbstractAddInGrabberPrivate +{ + public: + AbstractAddInGrabberPrivate() : m_nrLiveImageErrors(0), m_started(0) + { + + } + + // number of consecutive errors when automatically grabbing the next image. If this number + // becomes bigger than a threshold, auto grabbing will be disabled. + int m_nrLiveImageErrors; + + //! counter indicating how many times startDevice has been called + /*! + increment this variable every time startDevice is called (by incGrabberStarted()) + decrement this variable every time stopDevice is called (by decGrabberStarted()) + + \sa grabberStartedCount, incGrabberStarted, decGrabberStarted, setGrabberStarted + */ + int m_started; +}; + + +/*! +\class AbstractAddInGrabber +\brief Inherit from AbstractAddInGrabber if you write a camera/grabber plugin. Please call the constructor of +AbstractAddInGrabber within your plugin constructor. + +This class contains important variables and helper methods which simplify the creation of a camera plugin. Please +consider that you should implement the methods checkImage() and retriveImage() (pure virtual in this class) in your own +class. + +\see checkImage(), retrieveImage() +*/ + +//------------------------------------------------------------------------------------- +//! constructor +AbstractAddInGrabber::AbstractAddInGrabber() : AddInDataIO(), d_ptr(new AbstractAddInGrabberPrivate()) +{ +} + +//------------------------------------------------------------------------------------- +//! destructor +AbstractAddInGrabber::~AbstractAddInGrabber() +{ +} + +//------------------------------------------------------------------------------------- +//! this method gives the value range pixel for a given integer pixelFormat. +void AbstractAddInGrabber::minMaxBoundariesFromIntegerPixelFormat(const QByteArray& pixelFormat, int &min, int &max, bool &ok) +{ + ok = false; + QByteArray pixelFormatLower = pixelFormat.toLower(); + + if (pixelFormatLower == "mono8" || pixelFormatLower == "rgb8" || pixelFormatLower == "rgba8" || + pixelFormatLower == "rgb8planar" || pixelFormatLower == "rg8" || pixelFormatLower == "rg8packed" || + pixelFormatLower == "gb8") + { + min = 0.0; + max = 255.0; + ok = true; + } + else if (pixelFormatLower == "mono8s") + { + min = -128.0; + max = 127.0; + ok = true; + } + else if (pixelFormatLower == "mono10" || pixelFormatLower == "mono10packed" || pixelFormatLower == "rgb10planar") + { + min = 0.0; + max = 1023.0; + ok = true; + } + else if (pixelFormatLower == "mono12" || pixelFormatLower == "mono12packed" || pixelFormatLower == "rgb12planar") + { + min = 0.0; + max = 4095.0; + ok = true; + } + else if (pixelFormatLower == "mono14" || pixelFormatLower == "mono14packed") + { + min = 0.0; + max = 16383.0; + ok = true; + } + else if (pixelFormatLower == "mono16" || pixelFormatLower == "rgb16planar") + { + min = 0.0; + max = 65535.0; + ok = true; + } +} +//------------------------------------------------------------------------------------- +/*! +\class AbstractAddInGrabber +\brief This method maps a string to a value of pixelFormat. + +This function maps a string to a pixel format by using QMetaType. +*/ + +int AbstractAddInGrabber::itoDataTypeFromPixelFormat(const QByteArray &pixelFormat, bool *ok) +{ +#if QT_VERSION >= 0x050500 + const QMetaObject mo = staticMetaObject; +#else + const QMetaObject mo = StaticQtMetaObject::get(); +#endif + const QByteArray pixelFormatLower = pixelFormat.toLower(); + const char *val_ = pixelFormatLower.data(); + QMetaEnum me = mo.enumerator(mo.indexOfEnumerator("PixelFormat")); + int dataType = me.keyToValue(val_, ok); + + return dataType; +} +//------------------------------------------------------------------------------------- +//! if any live image has been connected to this camera, this event will be regularly fired. +/*! + This event is continoulsy fired if auto grabbing is enabled. At first, the image is acquired (method acquire). Then + the image is retrieved (retrieveImage) and finally the newly grabbed image is send to all registered listeners + (sendImagetoListeners) +*/ +void AbstractAddInGrabber::timerEvent(QTimerEvent * /*event*/) +{ + Q_D(AbstractAddInGrabber); + + QCoreApplication::sendPostedEvents(this, 0); + ito::RetVal retValue = ito::retOk; + + if (m_autoGrabbingListeners.size() > 0) // verify that any liveImage is listening + { + retValue += acquire(0, nullptr); + + if (!retValue.containsError()) + { + retValue += retrieveData(); + } + + if (!retValue.containsError()) + { + retValue += sendDataToListeners(200); + } + + if (retValue.containsWarning()) + { + if (retValue.hasErrorMessage()) + { + std::cout << "warning while sending live image: " << retValue.errorMessage() << "\n" << std::endl; + } + else + { + std::cout << "warning while sending live image." + << "\n" + << std::endl; + } + + d->m_nrLiveImageErrors = 0; + } + else if (retValue.containsError()) + { + if (retValue.hasErrorMessage()) + { + std::cout << "error while sending live image: " << retValue.errorMessage() << "\n" << std::endl; + } + else + { + std::cout << "error while sending live image." + << "\n" + << std::endl; + } + + d->m_nrLiveImageErrors++; + + if (d->m_nrLiveImageErrors > 10) + { + disableAutoGrabbing(); + d->m_nrLiveImageErrors = 0; + std::cout << "Auto grabbing of grabber " << this->getIdentifier().toLatin1().data() + << " was stopped due to consecutive errors in the previous tries\n" + << std::endl; + } + } + else + { + d->m_nrLiveImageErrors = 0; + } + } +} + +//------------------------------------------------------------------------------------- +/*!< returns the number of started devices \see m_started */ +int AbstractAddInGrabber::grabberStartedCount() const +{ + Q_D(const AbstractAddInGrabber); + return d->m_started; +} + +//------------------------------------------------------------------------------------- +/*!< increments the number of started devices \see m_started */ +void AbstractAddInGrabber::incGrabberStarted() +{ + Q_D(AbstractAddInGrabber); + d->m_started++; + + if (d->m_started == 1) + { + runStatusChanged(true); //now, the device is started -> check if any listener is connected and if so start the auto grabbing timer (if flag is true, too) + } +} + +//------------------------------------------------------------------------------------- +/*!< decrements the number of started devices \see m_started */ +void AbstractAddInGrabber::decGrabberStarted() +{ + Q_D(AbstractAddInGrabber); + d->m_started--; + + if (d->m_started == 0) + { + runStatusChanged(false); //now, the device is stopped -> stop any possibly started auto grabbing listener + } +} + +//------------------------------------------------------------------------------------- +/*!< sets the number of started devices to a given value \see m_started */ +void AbstractAddInGrabber::setGrabberStarted(int value) +{ + Q_D(AbstractAddInGrabber); + d->m_started = value; + runStatusChanged(value > 0); +} + +} // end namespace ito diff --git a/common/sources/addInGrabber.cpp b/common/sources/addInGrabber.cpp index 09aec05a5..255fd4562 100644 --- a/common/sources/addInGrabber.cpp +++ b/common/sources/addInGrabber.cpp @@ -1,7 +1,7 @@ /* ******************************************************************** itom software URL: http://www.uni-stuttgart.de/ito - Copyright (C) 2020, Institut fuer Technische Optik (ITO), + Copyright (C) 2023, Institut fuer Technische Optik (ITO), Universitaet Stuttgart, Germany This file is part of itom and its software development toolkit (SDK). @@ -27,246 +27,288 @@ #include "addInGrabber.h" -#include +#include "common/helperCommon.h" #include +#include +#include +#include + namespace ito { - class AddInGrabberPrivate +//------------------------------------------------------------------------------------- +class AddInGrabberPrivate +{ +}; + +//------------------------------------------------------------------------------------- +//! constructor +AddInGrabber::AddInGrabber() : AbstractAddInGrabber(), d_ptr(new AddInGrabberPrivate()) +{ +} + +//------------------------------------------------------------------------------------- +//! destructor +AddInGrabber::~AddInGrabber() +{ + +} +//------------------------------------------------------------------------------------- +ito::RetVal AddInGrabber::checkData(ito::DataObject *externalDataObject) +{ + const int futureHeight = m_params["sizey"].getVal(); + const int futureWidth = m_params["sizex"].getVal(); + int futureType; + + const int bpp = m_params["bpp"].getVal(); + + ito::float64 axisOffset[] = {0.0, 0.0}; + ito::float64 axisScale[] = {1.0, 1.0}; + ito::ByteArray axisUnit[] = {"", ""}; + ito::ByteArray axisDescription[] = {"", ""}; + ito::ByteArray valueDescription = ""; + ito::ByteArray valueUnit = ""; + + // only if exists in plugin + if (m_params.contains("axisOffset")) { - public: - int m_nrLiveImageErrors; //number of consecutive errors when automatically grabbing the next image. If this number becomes bigger than a threshold, auto grabbing will be disabled. - }; + axisOffset[0] = m_params["axisOffset"].getVal()[0]; + axisOffset[1] = m_params["axisOffset"].getVal()[1]; + } - /*! - \class AddInGrabber - \brief Inherit from AddInGrabber if you write a camera/grabber plugin. Please call the constructor of AddInGrabber within your plugin constructor. + // only if exists in plugin + if (m_params.contains("axisScale")) + { + axisScale[0] = m_params["axisScale"].getVal()[0]; + axisScale[1] = m_params["axisScale"].getVal()[1]; + } - This class contains important variables and helper methods which simplify the creation of a camera plugin. Please consider that you should implement - the methods checkImage() and retriveImage() (pure virtual in this class) in your own class. + // only if exists in plugin + if (m_params.contains("axisDescription")) + { + axisDescription[0] = + m_params["axisDescription"].getVal()[0]; + axisDescription[1] = + m_params["axisDescription"].getVal()[1]; + } - \see checkImage(), retrieveImage() - */ + // only if exists in plugin + if (m_params.contains("axisUnit")) + { + axisUnit[0] = m_params["axisUnit"].getVal()[0]; + axisUnit[1] = m_params["axisUnit"].getVal()[1]; + } - //---------------------------------------------------------------------------------------------------------------------------------- - //! constructor - AddInGrabber::AddInGrabber() : - AddInDataIO(), - m_started(0) + // only if exists in plugin + if (m_params.contains("valueDescription")) { - dd = new AddInGrabberPrivate(); - dd->m_nrLiveImageErrors = 0; + valueDescription = m_params["valueDescription"].getVal(); } - //---------------------------------------------------------------------------------------------------------------------------------- - //! destructor - AddInGrabber::~AddInGrabber() + // only if exists in plugin + if (m_params.contains("valueUnit")) { - DELETE_AND_SET_NULL(dd); + valueUnit = m_params["valueUnit"].getVal(); } - //---------------------------------------------------------------------------------------------------------------------------------- - //! sends m_image to all registered listeners. - /*! - This method is continuously called from timerEvent. Also call this method from your getVal-Method (usually with 0-timeout) + if (bpp <= 8) + { + futureType = ito::tUInt8; + } + else if (bpp <= 16) + { + futureType = ito::tUInt16; + } + else if (bpp <= 32) + { + futureType = ito::tInt32; + } + else + { + futureType = ito::tFloat64; + } - \param [in] waitMS indicates the time (in ms) that should be waiting until every registered live image source node received m_image. 0: no wait, -1: infinit waiting time, else time in milliseconds - \return retOk if everything was ok, retWarning if live image could not be invoked - */ - ito::RetVal AddInGrabber::sendDataToListeners(int waitMS) + if (!m_params.contains("sizez")) { - QObject *obj; - ito::RetVal retValue = ito::retOk; -// int i=0; - int size = m_autoGrabbingListeners.size(); - if (waitMS == 0) + if (externalDataObject == nullptr) { - foreach(obj, m_autoGrabbingListeners) + if (m_data.getDims() < 2 || m_data.getSize(0) != futureHeight || + m_data.getSize(1) != futureWidth || m_data.getType() != futureType) { - if (!QMetaObject::invokeMethod( obj, "setSource", Q_ARG(QSharedPointer, QSharedPointer(new ito::DataObject(m_data))), Q_ARG(ItomSharedSemaphore*, NULL))) - { - retValue += ito::RetVal(ito::retWarning, 1001, tr("slot 'setSource' of live source node could not be invoked").toLatin1().data()); - } + m_data = ito::DataObject(futureHeight, futureWidth, futureType); } + + m_data.setAxisScale(0, axisScale[0]); + m_data.setAxisScale(1, axisScale[1]); + m_data.setAxisOffset(0, axisOffset[0]); + m_data.setAxisOffset(1, axisOffset[1]); + m_data.setAxisDescription(0, axisDescription[0].data()); + m_data.setAxisDescription(1, axisDescription[1].data()); + m_data.setAxisUnit(0, axisUnit[0].data()); + m_data.setAxisUnit(1, axisUnit[1].data()); + m_data.setValueDescription(valueDescription.data()); + m_data.setValueUnit(valueUnit.data()); } - else if (m_autoGrabbingListeners.size() > 0) + else { - ItomSharedSemaphore** waitConds = new ItomSharedSemaphore*[size]; - int i=0; + int dims = externalDataObject->getDims(); - foreach(obj, m_autoGrabbingListeners) + if (externalDataObject->getDims() == 0) { - waitConds[i] = new ItomSharedSemaphore(); - // \todo On Linux a crash occurs here when closing the liveImage ... maybe the same reason why we get an error message on windows? - if (!QMetaObject::invokeMethod( obj, "setSource", Q_ARG(QSharedPointer, QSharedPointer(new ito::DataObject(m_data))), Q_ARG(ItomSharedSemaphore*, waitConds[i]))) - { - retValue += ito::RetVal(ito::retWarning, 1001, tr("slot 'setSource' of live source node could not be invoked").toLatin1().data()); - } - - i++; + *externalDataObject = ito::DataObject(futureHeight, futureWidth, futureType); + externalDataObject->setAxisScale(0, axisScale[0]); + externalDataObject->setAxisScale(1, axisScale[1]); + externalDataObject->setAxisOffset(0, axisOffset[0]); + externalDataObject->setAxisOffset(1, axisOffset[1]); + externalDataObject->setAxisDescription(0, axisDescription[0].data()); + externalDataObject->setAxisDescription(1, axisDescription[1].data()); + externalDataObject->setAxisUnit(0, axisUnit[0].data()); + externalDataObject->setAxisUnit(1, axisUnit[1].data()); + externalDataObject->setValueDescription(valueDescription.data()); + externalDataObject->setValueUnit(valueUnit.data()); } - - for (i = 0; i < size; i++) + else if (externalDataObject->calcNumMats() != 1) { - if (!waitConds[i]->wait(waitMS)) - { - qDebug() << "timeout in number: " << i << "number of items: " << size; - } - waitConds[i]->deleteSemaphore(); - waitConds[i] = NULL; + return ito::RetVal( + ito::retError, 0, + tr("Error during check data, external dataObject invalid. Object has more or less " + "than 1 plane. It must be of right size and type or an uninitilized image.") + .toLatin1() + .data()); + } + else if (externalDataObject->getSize(dims - 2) != (unsigned int)futureHeight || + externalDataObject->getSize(dims - 1) != (unsigned int)futureWidth || + externalDataObject->getType() != futureType) + { + return ito::RetVal( + ito::retError, 0, + tr("Error during check data, external dataObject invalid. Object must be of right " + "size and type or an uninitilized image.") + .toLatin1() + .data()); } - - delete[] waitConds; - waitConds = NULL; } - - return retValue; } - - //---------------------------------------------------------------------------------------------------------------------------------- - //! if any live image has been connected to this camera, this event will be regularly fired. - /*! - This event is continoulsy fired if auto grabbing is enabled. At first, the image is acquired (method acquire). Then - the image is retrieved (retrieveImage) and finally the newly grabbed image is send to all registered listeners (sendImagetoListeners) - */ - void AddInGrabber::timerEvent (QTimerEvent * /*event*/) + else { - QCoreApplication::sendPostedEvents(this,0); - ito::RetVal retValue = ito::retOk; + int numChannel = m_params["sizez"].getVal(); - if (m_autoGrabbingListeners.size() > 0) //verify that any liveImage is listening + if (externalDataObject == nullptr) { - retValue += acquire(0,NULL); - - if (!retValue.containsError()) + if (m_data.getDims() < 3 || m_data.getSize(0) != numChannel || + m_data.getSize(1) != futureHeight || m_data.getSize(2) != futureWidth || + m_data.getType() != futureType) { - retValue += retrieveData(); + m_data = ito::DataObject(numChannel, futureHeight, futureWidth, futureType); } - if (!retValue.containsError()) - { - retValue += sendDataToListeners(200); - } + m_data.setAxisScale(0, axisScale[0]); + m_data.setAxisScale(1, axisScale[1]); + m_data.setAxisOffset(0, axisOffset[0]); + m_data.setAxisOffset(1, axisOffset[1]); + m_data.setAxisDescription(0, axisDescription[0].data()); + m_data.setAxisDescription(1, axisDescription[1].data()); + m_data.setAxisUnit(0, axisUnit[0].data()); + m_data.setAxisUnit(1, axisUnit[1].data()); + m_data.setValueDescription(valueDescription.data()); + m_data.setValueUnit(valueUnit.data()); + } + else + { + int dims = externalDataObject->getDims(); - if (retValue.containsWarning()) + if (externalDataObject->getDims() == 0) { - if (retValue.hasErrorMessage()) - { - std::cout << "warning while sending live image: " << retValue.errorMessage() << "\n" << std::endl; - } - else - { - std::cout << "warning while sending live image." << "\n" << std::endl; - } - - dd->m_nrLiveImageErrors = 0; + *externalDataObject = ito::DataObject(numChannel, futureHeight, futureWidth, futureType); } - else if (retValue.containsError()) + else if (externalDataObject->getSize(dims - 3) != numChannel || + externalDataObject->getSize(dims - 2) != futureHeight || + externalDataObject->getSize(dims - 1) != futureWidth || + externalDataObject->getType() != futureType) { - if (retValue.hasErrorMessage()) - { - std::cout << "error while sending live image: " << retValue.errorMessage() << "\n" << std::endl; - } - else - { - std::cout << "error while sending live image." << "\n" << std::endl; - } - - dd->m_nrLiveImageErrors++; - - if (dd->m_nrLiveImageErrors > 10) - { - disableAutoGrabbing(); - dd->m_nrLiveImageErrors = 0; - std::cout << "Auto grabbing of grabber " << this->getIdentifier().toLatin1().data() << " was stopped due to consecutive errors in the previous tries\n" << std::endl; - } - } - else - { - dd->m_nrLiveImageErrors = 0; + return ito::RetVal( + ito::retError, 0, + tr("Error during check data, external dataObject invalid. Object must be of right " + "size and type or an uninitilized image.") + .toLatin1() + .data()); } } } - //---------------------------------------------------------------------------------------------------------------------------------- - // Now functions for multiliveimages - ito::RetVal AddInGrabber::checkData(ito::DataObject *externalDataObject) - { - int futureHeight = m_params["sizey"].getVal(); - int futureWidth = m_params["sizex"].getVal(); - int futureType; + return ito::retOk; +} +//------------------------------------------------------------------------------------- +//! sends m_image to all registered listeners. +/*! +This method is continuously called from timerEvent. Also call this method from your getVal-Method (usually with +0-timeout) + +\param [in] waitMS indicates the time (in ms) that should be waiting until every registered live image source node +received m_image. 0: no wait, -1: infinit waiting time, else time in milliseconds \return retOk if everything was ok, +retWarning if live image could not be invoked +*/ +ito::RetVal AddInGrabber::sendDataToListeners(int waitMS) +{ + QObject *obj; + ito::RetVal retValue = ito::retOk; + // int i=0; + int size = m_autoGrabbingListeners.size(); - int bpp = m_params["bpp"].getVal(); - if (bpp <= 8) - { - futureType = ito::tUInt8; - } - else if (bpp <= 16) - { - futureType = ito::tUInt16; - } - else if (bpp <= 32) - { - futureType = ito::tInt32; - } - else - { - futureType = ito::tFloat64; - } - if (!m_params.contains("sizez")) + if (waitMS == 0) + { + foreach (obj, m_autoGrabbingListeners) { - - if (externalDataObject == NULL) - { - if (m_data.getDims() < 2 || m_data.getSize(0) != (unsigned int)futureHeight || m_data.getSize(1) != (unsigned int)futureWidth || m_data.getType() != futureType) - { - m_data = ito::DataObject(futureHeight, futureWidth, futureType); - } - } - else + if (!QMetaObject::invokeMethod(obj, "setSource", + Q_ARG(QSharedPointer, + QSharedPointer(new ito::DataObject(m_data))), + Q_ARG(ItomSharedSemaphore *, nullptr))) { - int dims = externalDataObject->getDims(); - if (externalDataObject->getDims() == 0) - { - *externalDataObject = ito::DataObject(futureHeight, futureWidth, futureType); - } - else if (externalDataObject->calcNumMats() != 1) - { - return ito::RetVal(ito::retError, 0, tr("Error during check data, external dataObject invalid. Object has more or less than 1 plane. It must be of right size and type or an uninitilized image.").toLatin1().data()); - } - else if (externalDataObject->getSize(dims - 2) != (unsigned int)futureHeight || externalDataObject->getSize(dims - 1) != (unsigned int)futureWidth || externalDataObject->getType() != futureType) - { - return ito::RetVal(ito::retError, 0, tr("Error during check data, external dataObject invalid. Object must be of right size and type or an uninitilized image.").toLatin1().data()); - } + retValue += + ito::RetVal(ito::retWarning, 1001, + tr("slot 'setSource' of live source node could not be invoked").toLatin1().data()); } } - else + } + else if (m_autoGrabbingListeners.size() > 0) + { + ItomSharedSemaphore **waitConds = new ItomSharedSemaphore *[size]; + int i = 0; + + foreach (obj, m_autoGrabbingListeners) { - int numChannel = m_params["sizez"].getVal(); - if (externalDataObject == NULL) + waitConds[i] = new ItomSharedSemaphore(); + // \todo On Linux a crash occurs here when closing the liveImage ... maybe the same reason why we get an + // error message on windows? + if (!QMetaObject::invokeMethod(obj, "setSource", + Q_ARG(QSharedPointer, + QSharedPointer(new ito::DataObject(m_data))), + Q_ARG(ItomSharedSemaphore *, waitConds[i]))) { - if (m_data.getDims() < 3 || m_data.getSize(0) != (unsigned int)numChannel || m_data.getSize(1) != (unsigned int)futureHeight || m_data.getSize(2) != (unsigned int)futureWidth || m_data.getType() != futureType) - { - m_data = ito::DataObject(numChannel ,futureHeight, futureWidth, futureType); - } + retValue += + ito::RetVal(ito::retWarning, 1001, + tr("slot 'setSource' of live source node could not be invoked").toLatin1().data()); } - else + + i++; + } + + for (i = 0; i < size; i++) + { + if (!waitConds[i]->wait(waitMS)) { - int dims = externalDataObject->getDims(); - if (externalDataObject->getDims() == 0) - { - *externalDataObject = ito::DataObject(numChannel, futureHeight, futureWidth, futureType); - } - else if (externalDataObject->getSize(dims - 3) != (unsigned int)numChannel || externalDataObject->getSize(dims - 2) != (unsigned int)futureHeight || externalDataObject->getSize(dims - 1) != (unsigned int)futureWidth || externalDataObject->getType() != futureType) - { - return ito::RetVal(ito::retError, 0, tr("Error during check data, external dataObject invalid. Object must be of right size and type or an uninitilized image.").toLatin1().data()); - } + qDebug() << "timeout in number: " << i << "number of items: " << size; } + waitConds[i]->deleteSemaphore(); + waitConds[i] = nullptr; } - return ito::retOk; + delete[] waitConds; + waitConds = nullptr; } - //---------------------------------------------------------------------------------------------------------------------------------- -} //end namespace ito + return retValue; +} + +} // end namespace ito diff --git a/common/sources/addInInterface.cpp b/common/sources/addInInterface.cpp index e054a1194..81289a7b4 100644 --- a/common/sources/addInInterface.cpp +++ b/common/sources/addInInterface.cpp @@ -1,7 +1,7 @@ /* ******************************************************************** itom software URL: http://www.uni-stuttgart.de/ito - Copyright (C) 2020, Institut fuer Technische Optik (ITO), + Copyright (C) 2023, Institut fuer Technische Optik (ITO), Universitaet Stuttgart, Germany This file is part of itom and its software development toolkit (SDK). @@ -34,6 +34,7 @@ #include #include #include +#include "addInGrabber.h" #include "abstractAddInDockWidget.h" #include "helperCommon.h" @@ -47,7 +48,7 @@ namespace ito { - //---------------------------------------------------------------------------------------------------------------------------------- + //--------------------------------------------------------------------------------- class AddInInterfaceBasePrivate { public: @@ -62,7 +63,7 @@ namespace ito int AddInBase::m_instCounter = 0; int AddInBase::maxThreadCount = QThread::idealThreadCount(); - //---------------------------------------------------------------------------------------------------------------------------------- + //--------------------------------------------------------------------------------- AddInInterfaceBase::AddInInterfaceBase() : m_type(0), m_version(CREATEVERSION(0, 0, 0)), @@ -83,39 +84,39 @@ namespace ito d_ptr(new AddInInterfaceBasePrivate()) { } - //---------------------------------------------------------------------------------------------------------------------------------- + //--------------------------------------------------------------------------------- AddInInterfaceBase::~AddInInterfaceBase() { m_initParamsMand.clear(); m_initParamsOpt.clear(); } - //---------------------------------------------------------------------------------------------------------------------------------- + //--------------------------------------------------------------------------------- ito::RetVal AddInInterfaceBase::closeInst(ito::AddInBase **addInInst) { ito::RetVal ret = closeThisInst(addInInst); return ret; } - //---------------------------------------------------------------------------------------------------------------------------------- + //--------------------------------------------------------------------------------- void AddInInterfaceBase::incRef(ito::AddInBase *addIn) { addIn->incRefCount(); } - //---------------------------------------------------------------------------------------------------------------------------------- + //--------------------------------------------------------------------------------- void AddInInterfaceBase::decRef(ito::AddInBase *addIn) { addIn->decRefCount(); } - //---------------------------------------------------------------------------------------------------------------------------------- + //--------------------------------------------------------------------------------- int AddInInterfaceBase::getRef(ito::AddInBase *addIn) { return addIn->getRefCount(); } - //---------------------------------------------------------------------------------------------------------------------------------- + //--------------------------------------------------------------------------------- //! set api function pointer void AddInInterfaceBase::setApiFunctions(void **apiFunctions) { @@ -124,7 +125,7 @@ namespace ito ito::ITOM_API_FUNCS = apiFunctions; //this propagates the api pointer to the itomCommonQt dll where this source file has been compiled } - //---------------------------------------------------------------------------------------------------------------------------------- + //--------------------------------------------------------------------------------- void AddInInterfaceBase::setApiFunctionsGraph(void ** apiFunctionsGraph) { m_apiFunctionsGraphBasePtr = apiFunctionsGraph; @@ -132,7 +133,7 @@ namespace ito ito::ITOM_API_FUNCS_GRAPH = apiFunctionsGraph; //this propagates the api pointer to the itomCommonQt dll where this source file has been compiled } - //---------------------------------------------------------------------------------------------------------------------------------- + //--------------------------------------------------------------------------------- bool AddInInterfaceBase::event(QEvent *e) { //the event User+123 is emitted by AddInManager, if the API has been prepared and can @@ -150,21 +151,21 @@ namespace ito return QObject::event(e); } - //---------------------------------------------------------------------------------------------------------------------------------- + //--------------------------------------------------------------------------------- void AddInInterfaceBase::setLoader(QPluginLoader *loader) { Q_D(AddInInterfaceBase); d_ptr->m_pLoader = loader; } - //---------------------------------------------------------------------------------------------------------------------------------- + //--------------------------------------------------------------------------------- QPluginLoader * AddInInterfaceBase::getLoader(void) const { Q_D(const AddInInterfaceBase); return d->m_pLoader; } - //---------------------------------------------------------------------------------------------------------------------------------- + //--------------------------------------------------------------------------------- class AddInBasePrivate { public: @@ -202,7 +203,7 @@ namespace ito QMutex m_userMutex; }; - //---------------------------------------------------------------------------------------------------------------------------------- + //--------------------------------------------------------------------------------- //! Constructor. /*! This constructor is called by any constructor of classes AddInActuator, AddInDataIO or AddInAlgo. @@ -221,7 +222,7 @@ namespace ito d->m_uniqueID = (++m_instCounter); } - //---------------------------------------------------------------------------------------------------------------------------------- + //--------------------------------------------------------------------------------- //! Destructor. /*! This destructor is automatically called if any plugin instance is destroyed. It does the following steps: @@ -250,7 +251,13 @@ namespace ito } } - //---------------------------------------------------------------------------------------------------------------------------------- + //--------------------------------------------------------------------------------- + void AddInBase::insertParam(const Param& param) + { + m_params.insert(param.getName(), param); + } + + //--------------------------------------------------------------------------------- //! retrieve the uniqueID of this instance int AddInBase::getID() const { @@ -258,7 +265,7 @@ namespace ito return d->m_uniqueID; } - //---------------------------------------------------------------------------------------------------------------------------------- + //--------------------------------------------------------------------------------- //! increments reference counter of this plugin (thread-safe) void AddInBase::incRefCount(void) { @@ -267,7 +274,7 @@ namespace ito d->m_refCount++; } - //---------------------------------------------------------------------------------------------------------------------------------- + //--------------------------------------------------------------------------------- //! decrements reference counter of this plugin (thread-safe) void AddInBase::decRefCount(void) { @@ -282,7 +289,7 @@ namespace ito return d->m_refCount; } - //---------------------------------------------------------------------------------------------------------------------------------- + //--------------------------------------------------------------------------------- //! returns true if this instance has firstly been created by the GUI int AddInBase::createdByGUI() const { @@ -290,7 +297,7 @@ namespace ito return d->m_createdByGUI; } - //---------------------------------------------------------------------------------------------------------------------------------- + //--------------------------------------------------------------------------------- //! method to set whether this instance has been firstly created by the GUI (true) or by any other component (Python, C++, other plugin,..) (false) void AddInBase::setCreatedByGUI(int value) { @@ -298,7 +305,7 @@ namespace ito d->m_createdByGUI = value; } - //---------------------------------------------------------------------------------------------------------------------------------- + //--------------------------------------------------------------------------------- //! returns in a thread-safe way the status of the m_initialized-member variable. This variable should be set to true at the end of the init-method. bool AddInBase::isInitialized(void) const { @@ -306,7 +313,7 @@ namespace ito return d->m_initialized; } - //---------------------------------------------------------------------------------------------------------------------------------- + //--------------------------------------------------------------------------------- //! sets in a thread-safe way the status of the m_initialized-member /* \param [in] initialized is the value to set @@ -317,7 +324,7 @@ namespace ito d->m_initialized = initialized; } - //---------------------------------------------------------------------------------------------------------------------------------- + //--------------------------------------------------------------------------------- //! returns the alive-flag of this plugin /* Any time-consuming operation of the plugin should regularly set the alive-flag to true @@ -335,7 +342,7 @@ namespace ito return wasalive; } - //---------------------------------------------------------------------------------------------------------------------------------- + //--------------------------------------------------------------------------------- //! sets the alive-flag to 1 ("still alive") /* This method is thread-safe. @@ -348,14 +355,14 @@ namespace ito d->m_alive = 1; } - //---------------------------------------------------------------------------------------------------------------------------------- + //--------------------------------------------------------------------------------- QMutex& AddInBase::getUserMutex() { Q_D(AddInBase); return d->m_userMutex; } - //---------------------------------------------------------------------------------------------------------------------------------- + //--------------------------------------------------------------------------------- //! method for setting various parameters in a sequence /*! Using this method, only one over-thread call needs to be executed in order to set various parameters @@ -386,7 +393,7 @@ namespace ito return retValue; } - //---------------------------------------------------------------------------------------------------------------------------------- + //--------------------------------------------------------------------------------- //! method for setting various parameters in a sequence /*! Using this method, only one over-thread call needs to be executed in order to set various parameters @@ -417,7 +424,7 @@ namespace ito return retValue; } - //---------------------------------------------------------------------------------------------------------------------------------- + //--------------------------------------------------------------------------------- //! creates new thread for the class instance and moves this instance to the new thread ito::RetVal AddInBase::MoveToThread(void) { @@ -426,17 +433,17 @@ namespace ito moveToThread(d->m_pThread); d->m_pThread->start(); - /*set new seed for random generator of OpenCV. - This is required to have real random values for any randn or randu command. - The seed must be set in every thread. This is for the main thread. - */ - cv::theRNG().state = (uint64)cv::getCPUTickCount(); - /*seed is set*/ + /*set new seed for random generator of OpenCV. + This is required to have real random values for any randn or randu command. + The seed must be set in every thread. This is for the main thread. + */ + cv::theRNG().state = (uint64)cv::getCPUTickCount(); + /*seed is set*/ return retOk; } - //---------------------------------------------------------------------------------------------------------------------------------- + //--------------------------------------------------------------------------------- //! method to retrieve a parameter from the parameter map (m_params) /*! returns parameter from m_params vector. If the parameter could not be found or if the given name is invalid an invalid Param is returned. @@ -489,7 +496,7 @@ namespace ito return Param(); } - //---------------------------------------------------------------------------------------------------------------------------------- + //--------------------------------------------------------------------------------- //! this method can handle additional functions of your plugin. /*! Use registerExecFunc to register a specific function name and a set of mandatory and optional default parameters. @@ -520,14 +527,14 @@ namespace ito return retValue; } - //---------------------------------------------------------------------------------------------------------------------------------- + //--------------------------------------------------------------------------------- bool AddInBase::hasDockWidget(void) const { Q_D(const AddInBase); return !d->m_dockWidget.isNull(); } - //---------------------------------------------------------------------------------------------------------------------------------- + //--------------------------------------------------------------------------------- //! Returns the reference to the dock widget of this plugin or NULL, if no dock widget is provided. /* \sa hasDockWidget @@ -538,7 +545,7 @@ namespace ito return d->m_dockWidget; } - //---------------------------------------------------------------------------------------------------------------------------------- + //--------------------------------------------------------------------------------- //! Creates the dock-widget for this plugin /* Call this method ONLY in the constructor of your plugin, since it must be executed in the main thread. @@ -579,7 +586,7 @@ namespace ito } } - //---------------------------------------------------------------------------------------------------------------------------------- + //--------------------------------------------------------------------------------- void AddInBase::setIdentifier(const QString &identifier) { Q_D(AddInBase); @@ -595,7 +602,7 @@ namespace ito } } - //---------------------------------------------------------------------------------------------------------------------------------- + //--------------------------------------------------------------------------------- //! sets the interface of this instance to base. \sa AddInInterfaceBase void AddInBase::setBasePlugin(AddInInterfaceBase *base) { @@ -603,13 +610,13 @@ namespace ito d->m_pBasePlugin = base; } - //---------------------------------------------------------------------------------------------------------------------------------- + //--------------------------------------------------------------------------------- /*static*/ int AddInBase::getMaximumThreadCount() { return maxThreadCount; } - //---------------------------------------------------------------------------------------------------------------------------------- + //--------------------------------------------------------------------------------- /*static*/ RetVal AddInBase::setMaximumThreadCount(int threadCount) { if (QThread::idealThreadCount() > 0) @@ -632,14 +639,14 @@ namespace ito return ito::retOk; } - //---------------------------------------------------------------------------------------------------------------------------------- + //--------------------------------------------------------------------------------- AddInInterfaceBase* AddInBase::getBasePlugin(void) const { Q_D(const AddInBase); return d->m_pBasePlugin; } - //---------------------------------------------------------------------------------------------------------------------------------- + //--------------------------------------------------------------------------------- //! Registers an additional function with specific name and default parameters /* After having registered the function, the method execFunc can be called with the specific function name @@ -726,7 +733,7 @@ namespace ito return retValue; } - //---------------------------------------------------------------------------------------------------------------------------------- + //--------------------------------------------------------------------------------- //! returns default style properties for dock-widget of plugin /* This method is called by the AddInManager at initialization of a plugin instance. Then, @@ -755,7 +762,7 @@ namespace ito } } - //---------------------------------------------------------------------------------------------------------------------------------- + //--------------------------------------------------------------------------------- //! method indicates whether this plugin instance has a configuration dialog. /*! Overwrite this method if your plugin provides such a configuration dialog by simply returning 1 instead of 0. @@ -768,7 +775,7 @@ namespace ito return 0; } - //---------------------------------------------------------------------------------------------------------------------------------- + //--------------------------------------------------------------------------------- //! method called if the configuration dialog of the plugin should be shown. /*! Overwrite this method if your plugin provides a configuration dialog. This method is directly called by the main (GUI) thread. @@ -782,7 +789,7 @@ namespace ito return ito::RetVal(ito::retWarning,0, tr("Your plugin is supposed to have a configuration dialog, but you did not implement the showConfDialog-method").toLatin1().data()); } - //---------------------------------------------------------------------------------------------------------------------------------- + //--------------------------------------------------------------------------------- //! method invoked by AddInManager if the plugin should be pulled back to the main thread of itom. /*! Do not invoke this method in any other case. It should only be invoked by AddInManager of the itom core. @@ -812,7 +819,7 @@ namespace ito return retOk; } - //---------------------------------------------------------------------------------------------------------------------------------- + //--------------------------------------------------------------------------------- class AddInDataIOPrivate { public: @@ -822,7 +829,7 @@ namespace ito }; - //---------------------------------------------------------------------------------------------------------------------------------- + //--------------------------------------------------------------------------------- AddInDataIO::AddInDataIO() : AddInBase(), m_timerID(0), @@ -833,7 +840,7 @@ namespace ito qDebug() << "AddInDataIO constructor. ThreadID: " << QThread::currentThreadId(); } - //---------------------------------------------------------------------------------------------------------------------------------- + //--------------------------------------------------------------------------------- AddInDataIO::~AddInDataIO() { if (m_timerID > 0) @@ -843,39 +850,60 @@ namespace ito } } - //---------------------------------------------------------------------------------------------------------------------------------- - ito::RetVal AddInDataIO::startDeviceAndRegisterListener(QObject* obj, ItomSharedSemaphore *waitCond) + //--------------------------------------------------------------------------------- + ito::RetVal AddInDataIO::startDeviceAndRegisterListener(QObject* listener, ItomSharedSemaphore *waitCond) { qDebug("begin: startDeviceAndRegisterListener"); ItomSharedSemaphoreLocker locker(waitCond); ito::RetVal retValue(ito::retOk); + QString defaultChannel; + bool isMultiChannel = inherits("ito::AddInMultiChannelGrabber"); + QByteArray setSourceSignature = + QMetaObject::normalizedSignature( + "setSource(QSharedPointer,ItomSharedSemaphore*)" + ); - if (obj->metaObject()->indexOfSlot(QMetaObject::normalizedSignature("setSource(QSharedPointer,ItomSharedSemaphore*)")) == -1) + if (isMultiChannel) { - retValue += ito::RetVal(ito::retError, 2002, tr("listener does not have a slot ").toLatin1().data()); + defaultChannel = QLatin1String(m_params["defaultChannel"].getVal()); } - else if (m_autoGrabbingListeners.contains(obj)) + + if (listener->metaObject()->indexOfSlot(setSourceSignature) == -1) + { + retValue += ito::RetVal(ito::retError, 2002, tr("listener does not have the mandatory slot ``setSource``.").toLatin1().data()); + } + else if ( + (!isMultiChannel && m_autoGrabbingListeners.contains("",listener)) || + (isMultiChannel && m_autoGrabbingListeners.contains(defaultChannel, listener)) + ) { - retValue += ito::RetVal(ito::retWarning, 1011, tr("this object already has been registered as listener").toLatin1().data()); + retValue += ito::RetVal(ito::retWarning, 1011, tr("this object has already been registered as listener").toLatin1().data()); } else { - retValue += startDevice(NULL); + retValue += startDevice(nullptr); - if (!retValue.containsError()) - { - if (m_autoGrabbingEnabled == true && m_autoGrabbingListeners.size() >= 0 && m_timerID == 0) - { - m_timerID = startTimer(m_timerIntervalMS); + if (!retValue.containsError()) + { + if (m_autoGrabbingEnabled && m_autoGrabbingListeners.size() >= 0 && m_timerID == 0) + { + m_timerID = startTimer(m_timerIntervalMS); - if (m_timerID == 0) - { - retValue += ito::RetVal(ito::retError, 2001, tr("timer could not be set").toLatin1().data()); - } - } + if (m_timerID == 0) + { + retValue += ito::RetVal(ito::retError, 2001, tr("timer could not be set").toLatin1().data()); + } + } - m_autoGrabbingListeners.insert(obj); - } + if (!isMultiChannel) + { + m_autoGrabbingListeners.insert("", listener); + } + else + { + m_autoGrabbingListeners.insert(defaultChannel, listener); + } + } } if (waitCond) @@ -883,57 +911,73 @@ namespace ito waitCond->returnValue = retValue; waitCond->release(); } - else if (retValue.containsError()) - { - std::cout << "Error binding / starting camera: " << retValue.errorMessage() << "\n" << std::endl; - } + else if (retValue.containsError()) + { + std::cout << "Error binding / starting camera: " << retValue.errorMessage() << "\n" << std::endl; + } qDebug("end: startDeviceAndRegisterListener"); return retValue; } - //---------------------------------------------------------------------------------------------------------------------------------- - ito::RetVal AddInDataIO::stopDeviceAndUnregisterListener(QObject* obj, ItomSharedSemaphore *waitCond) - { - qDebug("start: stopDeviceAndUnregisterListener"); - ItomSharedSemaphoreLocker locker(waitCond); - ito::RetVal retValue(ito::retOk); - - if (!m_autoGrabbingListeners.remove(obj)) - { - retValue += ito::RetVal(ito::retWarning, 1012, tr("the object could not been removed from the listener list").toLatin1().data()); - } - else - { - qDebug("live image has been removed from listener list"); - - if (m_autoGrabbingListeners.size() <= 0) - { - if (m_timerID) //stop timer if no other listeners are registered - { - killTimer(m_timerID); - m_timerID = 0; - } - } - - retValue += stopDevice(NULL); - } + //--------------------------------------------------------------------------------- + ito::RetVal AddInDataIO::stopDeviceAndUnregisterListener(QObject* listener, ItomSharedSemaphore *waitCond) + { + qDebug("start: stopDeviceAndUnregisterListener"); + ItomSharedSemaphoreLocker locker(waitCond); + ito::RetVal retValue(ito::retOk); + + if (listener) + { + bool found = false; + auto it = m_autoGrabbingListeners.begin(); + + while (it != m_autoGrabbingListeners.end()) + { + if (*it == listener) + { + found = true; + m_autoGrabbingListeners.erase(it); + break; + } + } + + if (!found) + { + retValue += ito::RetVal(ito::retWarning, 1012, tr("The given listener (e.g. plot) is not among the list of currently registered listeners.").toLatin1().data()); + } + } + else + { + qDebug("live image has been removed from listener list"); + + if (m_autoGrabbingListeners.size() <= 0) + { + if (m_timerID) //stop timer if no other listeners are registered + { + killTimer(m_timerID); + m_timerID = 0; + } + } + + retValue += stopDevice(nullptr); + } if (waitCond) { waitCond->returnValue = retValue; waitCond->release(); } - else if (retValue.containsError()) - { - std::cout << "Error unbinding / stopping camera: " << retValue.errorMessage() << "\n" << std::endl; - } + else if (retValue.containsError()) + { + std::cout << "Error unbinding / stopping camera: " << retValue.errorMessage() << "\n" << std::endl; + } qDebug("end: stopDeviceAndUnregisterListener"); return retValue; } - //---------------------------------------------------------------------------------------------------------------------------------- + //--------------------------------------------------------------------------------- ito::RetVal AddInDataIO::disableAutoGrabbing(ItomSharedSemaphore *waitCond) { m_autoGrabbingEnabled = false; @@ -954,7 +998,7 @@ namespace ito return ito::retOk; } - //---------------------------------------------------------------------------------------------------------------------------------- + //--------------------------------------------------------------------------------- ito::RetVal AddInDataIO::enableAutoGrabbing(ItomSharedSemaphore *waitCond) { m_autoGrabbingEnabled = true; @@ -974,7 +1018,7 @@ namespace ito return ito::retOk; } - //---------------------------------------------------------------------------------------------------------------------------------- + //--------------------------------------------------------------------------------- ito::RetVal AddInDataIO::setAutoGrabbingInterval(QSharedPointer interval, ItomSharedSemaphore *waitCond /*= NULL*/) { ito::RetVal retval; @@ -1012,7 +1056,7 @@ namespace ito return retval; } - //---------------------------------------------------------------------------------------------------------------------------------- + //--------------------------------------------------------------------------------- void AddInDataIO::runStatusChanged(bool deviceStarted) { if (deviceStarted && m_autoGrabbingEnabled) @@ -1034,7 +1078,7 @@ namespace ito } } - //---------------------------------------------------------------------------------------------------------------------------------- + //--------------------------------------------------------------------------------- ito::RetVal AddInDataIO::startDevice(ItomSharedSemaphore *waitCond) { Q_ASSERT_X(1, "AddInDataIO::startDevice", tr("not implemented").toLatin1().data()); @@ -1054,7 +1098,7 @@ namespace ito } } - //---------------------------------------------------------------------------------------------------------------------------------- + //--------------------------------------------------------------------------------- ito::RetVal AddInDataIO::stopDevice(ItomSharedSemaphore *waitCond) { Q_ASSERT_X(1, "AddInDataIO::stopDevice", tr("not implemented").toLatin1().data()); @@ -1072,7 +1116,7 @@ namespace ito } } - //---------------------------------------------------------------------------------------------------------------------------------- + //--------------------------------------------------------------------------------- ito::RetVal AddInDataIO::acquire(const int /*trigger*/, ItomSharedSemaphore *waitCond) { Q_ASSERT_X(1, "AddInDataIO::acquire", tr("not implemented").toLatin1().data()); @@ -1090,7 +1134,7 @@ namespace ito } } - //---------------------------------------------------------------------------------------------------------------------------------- + //--------------------------------------------------------------------------------- ito::RetVal AddInDataIO::stop(ItomSharedSemaphore *waitCond) { Q_ASSERT_X(1, "AddInDataIO::stop", tr("not implemented").toLatin1().data()); @@ -1108,7 +1152,7 @@ namespace ito } } - //---------------------------------------------------------------------------------------------------------------------------------- + //--------------------------------------------------------------------------------- ito::RetVal AddInDataIO::getVal(void * /*data*/, ItomSharedSemaphore *waitCond) { Q_ASSERT_X(1, "AddInDataIO::getVal(ito::RetVal, void *data, ItomSharedSemaphore *waitCond)", tr("not implemented").toLatin1().data()); @@ -1125,8 +1169,32 @@ namespace ito return ito::retError; } } + //--------------------------------------------------------------------------------- + ito::RetVal AddInDataIO::getVal(QSharedPointer> dataObjMap, ItomSharedSemaphore* waitCond) + { + if (waitCond) + { + waitCond->returnValue += ito::RetVal( + ito::retError, + 0, + tr("method getVal(QSharedPointer>, ItomSharedSemaphore*) " + "is not implemented in this plugin") + .toLatin1() + .data()); + waitCond->release(); - //---------------------------------------------------------------------------------------------------------------------------------- + return waitCond->returnValue; + } + else + { + return ito::retError; + } + } + ito::RetVal AddInDataIO::getVal(ItomSharedSemaphore* waitCond) + { + return ito::retError; + } + //--------------------------------------------------------------------------------- ito::RetVal AddInDataIO::getVal(QSharedPointer /*data*/, QSharedPointer /*length*/, ItomSharedSemaphore *waitCond) { Q_ASSERT_X(1, "AddInDataIO::getVal(ito::RetVal, QSharedPointer data, QSharedPointer length, ItomSharedSemaphore *waitCond)", tr("not implemented").toLatin1().data()); @@ -1144,7 +1212,7 @@ namespace ito } } - //---------------------------------------------------------------------------------------------------------------------------------- + //--------------------------------------------------------------------------------- ito::RetVal AddInDataIO::copyVal(void * /*data*/, ItomSharedSemaphore *waitCond) { Q_ASSERT_X(1, "AddInDataIO::copyVal(void *data, ItomSharedSemaphore *waitCond)", tr("not implemented").toLatin1().data()); @@ -1162,7 +1230,7 @@ namespace ito } } - //---------------------------------------------------------------------------------------------------------------------------------- + //--------------------------------------------------------------------------------- ito::RetVal AddInDataIO::setVal(const char * /*data*/, const int /*length*/, ItomSharedSemaphore *waitCond) { Q_ASSERT_X(1, "AddInDataIO::setVal(const char *data, const int length, ItomSharedSemaphore *waitCond)", tr("not implemented").toLatin1().data()); @@ -1181,7 +1249,7 @@ namespace ito } - //---------------------------------------------------------------------------------------------------------------------------------- + //--------------------------------------------------------------------------------- class AddInActuatorPrivate { public: @@ -1199,19 +1267,19 @@ namespace ito }; - //---------------------------------------------------------------------------------------------------------------------------------- + //--------------------------------------------------------------------------------- AddInActuator::AddInActuator() : AddInBase(), d_ptr(new AddInActuatorPrivate()) { } - //---------------------------------------------------------------------------------------------------------------------------------- + //--------------------------------------------------------------------------------- AddInActuator::~AddInActuator() { } - //---------------------------------------------------------------------------------------------------------------------------------- + //--------------------------------------------------------------------------------- //! method emits the actuatorStatusChanged signal if any slot is connected to this signal. /*! The emitted values are the member variables m_currentStatus and m_currentPos (optional). @@ -1240,7 +1308,7 @@ namespace ito } } - //---------------------------------------------------------------------------------------------------------------------------------- + //--------------------------------------------------------------------------------- //! method emits the targetChanged signal if any slot is connected to this signal. /*! The emitted values is the member variable m_targetPos @@ -1259,7 +1327,7 @@ namespace ito emit targetChanged(m_targetPos); } - //---------------------------------------------------------------------------------------------------------------------------------- + //--------------------------------------------------------------------------------- //! method invoked in order to force a re-emitation of the current status, the current positions (if desired) and the target positions (if desired) /*! This method is mainly invoked by a dock widget of the actuator such that the plugin re-emits the current values, that are then @@ -1284,7 +1352,7 @@ namespace ito return retval; } - //---------------------------------------------------------------------------------------------------------------------------------- + //--------------------------------------------------------------------------------- ito::RetVal AddInActuator::getLastSignalledStates(QVector &status, QVector ¤tPos, QVector &targetPos) { Q_D(AddInActuator); @@ -1304,13 +1372,13 @@ namespace ito } } - //---------------------------------------------------------------------------------------------------------------------------------- + //--------------------------------------------------------------------------------- void AddInActuator::setStatus(int &status, const int newFlags, const int keepMask /*= 0*/) { status = (status & keepMask) | newFlags; } - //---------------------------------------------------------------------------------------------------------------------------------- + //--------------------------------------------------------------------------------- void AddInActuator::setStatus(const QVector &axis, const int newFlags, const int keepMask /*= 0*/) { foreach(const int &i, axis) @@ -1319,7 +1387,7 @@ namespace ito } } - //---------------------------------------------------------------------------------------------------------------------------------- + //--------------------------------------------------------------------------------- void AddInActuator::replaceStatus(const QVector &axis, const int existingFlag, const int replaceFlag) { foreach(const int &i, axis) @@ -1328,7 +1396,7 @@ namespace ito } } - //---------------------------------------------------------------------------------------------------------------------------------- + //--------------------------------------------------------------------------------- void AddInActuator::replaceStatus(int &status, const int existingFlag, const int replaceFlag) { if (status & existingFlag) @@ -1363,7 +1431,7 @@ namespace ito } } - //---------------------------------------------------------------------------------------------------------------------------------- + //--------------------------------------------------------------------------------- //! checks whether any axis is still moving (moving flag is set) bool AddInActuator::isMotorMoving() const { @@ -1377,7 +1445,7 @@ namespace ito return false; } - //---------------------------------------------------------------------------------------------------------------------------------- + //--------------------------------------------------------------------------------- bool AddInActuator::isInterrupted() { Q_D(AddInActuator); @@ -1387,7 +1455,7 @@ namespace ito return res; } - //---------------------------------------------------------------------------------------------------------------------------------- + //--------------------------------------------------------------------------------- void AddInActuator::setInterrupt() { Q_D(AddInActuator); @@ -1395,7 +1463,7 @@ namespace ito d->m_interruptFlag = true; } - //---------------------------------------------------------------------------------------------------------------------------------- + //--------------------------------------------------------------------------------- void AddInActuator::resetInterrupt() { Q_D(AddInActuator); @@ -1403,7 +1471,7 @@ namespace ito d->m_interruptFlag = false; } - //---------------------------------------------------------------------------------------------------------------------------------- + //--------------------------------------------------------------------------------- ito::RetVal AddInActuator::getStatus(const int axis, QSharedPointer status, ItomSharedSemaphore *waitCond) { ito::RetVal retval; @@ -1438,14 +1506,14 @@ namespace ito return retval; } - //---------------------------------------------------------------------------------------------------------------------------------- + //--------------------------------------------------------------------------------- class AddInAlgoPrivate { public: AddInAlgoPrivate() {} }; - //---------------------------------------------------------------------------------------------------------------------------------- + //--------------------------------------------------------------------------------- AddInAlgo::AddInAlgo() : AddInBase(), d_ptr(new AddInAlgoPrivate()) { @@ -1453,7 +1521,7 @@ namespace ito return; } - //---------------------------------------------------------------------------------------------------------------------------------- + //--------------------------------------------------------------------------------- AddInAlgo::~AddInAlgo() { FilterDef *filter; @@ -1471,21 +1539,21 @@ namespace ito m_algoWidgetList.clear(); } - //---------------------------------------------------------------------------------------------------------------------------------- + //--------------------------------------------------------------------------------- ito::RetVal AddInAlgo::getFilterList(QHash &fList) const { fList = m_filterList; return ito::retOk; } - //---------------------------------------------------------------------------------------------------------------------------------- + //--------------------------------------------------------------------------------- ito::RetVal AddInAlgo::getAlgoWidgetList(QHash &awList) const { awList = m_algoWidgetList; return ito::retOk; } - //---------------------------------------------------------------------------------------------------------------------------------- + //--------------------------------------------------------------------------------- ito::RetVal AddInAlgo::rejectFilter(const QString &name) { QHash::iterator it = m_filterList.find(name); @@ -1499,7 +1567,7 @@ namespace ito return ito::retError; } - //---------------------------------------------------------------------------------------------------------------------------------- + //--------------------------------------------------------------------------------- ito::RetVal AddInAlgo::rejectAlgoWidget(const QString &name) { QHash::iterator it = m_algoWidgetList.find(name); @@ -1513,7 +1581,7 @@ namespace ito return ito::retError; } - //---------------------------------------------------------------------------------------------------------------------------------- + //--------------------------------------------------------------------------------- /*static*/ ito::RetVal AddInAlgo::prepareParamVectors(QVector *paramsMand, QVector *paramsOpt, QVector *paramsOut) { if (!paramsMand) @@ -1534,5 +1602,5 @@ namespace ito return ito::retOk; } - //---------------------------------------------------------------------------------------------------------------------------------- + //--------------------------------------------------------------------------------- } // namespace ito diff --git a/common/sources/addInMultiChannelGrabber.cpp b/common/sources/addInMultiChannelGrabber.cpp new file mode 100644 index 000000000..9f3ba61c4 --- /dev/null +++ b/common/sources/addInMultiChannelGrabber.cpp @@ -0,0 +1,1309 @@ +/* ******************************************************************** + itom software + URL: http://www.uni-stuttgart.de/ito + Copyright (C) 2023, Institut fuer Technische Optik (ITO), + Universitaet Stuttgart, Germany + + This file is part of itom and its software development toolkit (SDK). + + itom is free software; you can redistribute it and/or modify it + under the terms of the GNU Library General Public Licence as published by + the Free Software Foundation; either version 2 of the Licence, or (at + your option) any later version. + + In addition, as a special exception, the Institut fuer Technische + Optik (ITO) gives you certain additional rights. + These rights are described in the ITO LGPL Exception version 1.0, + which can be found in the file LGPL_EXCEPTION.txt in this package. + + itom is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library + General Public Licence for more details. + + You should have received a copy of the GNU Library General Public License + along with itom. If not, see . +*********************************************************************** */ + +#include "AddInMultiChannelGrabber.h" + +#include +#include +#include +#include +#include +#include "common/helperCommon.h" +#include "common/interval.h" + + +namespace ito +{ + +//------------------------------------------------------------------------------------- +class AddInMultiChannelGrabberPrivate +{ +public: + AddInMultiChannelGrabberPrivate() : m_channelParamsProxyInitialized(false) + { + + } + + //!< true if an appropriate parameter is created in the m_params map of the + //! plugin for every parameter of the channels. The m_params value is a + //! proxy for the currently selected channel. + bool m_channelParamsProxyInitialized; + + //!< this map contains all parameter names in m_param, that belong to a + //! channel parameter. The value string list contains all channel names, + //! where this parameter is explicitely contained. Global parameters, + //! that are independent on channels, are not listed here. + QMap m_paramChannelAvailabilityMap; +}; + +//------------------------------------------------------------------------------------- +AddInMultiChannelGrabber::ChannelContainer::ChannelContainer() : + m_dataStatus(DataStatus::Idle) +{ + ito::Param paramVal; + int roi[] = { 0, 0, 1, 1 }; + paramVal = ito::Param("roi", ito::ParamBase::IntArray, 4, roi, "roi"); + m_channelParams.insert(paramVal.getName(), paramVal); + + paramVal = ito::Param("sizex", ito::ParamBase::Int | ito::ParamBase::Readonly, 1, 1, 1, "sizex"); + m_channelParams.insert(paramVal.getName(), paramVal); + + paramVal = ito::Param("sizey", ito::ParamBase::Int | ito::ParamBase::Readonly, 1, 1, 1, "sizey"); + m_channelParams.insert(paramVal.getName(), paramVal); + + paramVal = ito::Param("pixelFormat", ito::ParamBase::String, "mono8", "pixelFormat"); + m_channelParams.insert(paramVal.getName(), paramVal); + + addDefaultMetaParams(); +}; + +//------------------------------------------------------------------------------------- +AddInMultiChannelGrabber::ChannelContainer::ChannelContainer( + const ito::Param& roi, + const ito::Param& pixelFormat, + const ito::Param& sizex, + const ito::Param& sizey) : + m_dataStatus(DataStatus::Idle) +{ + Q_ASSERT(QByteArray(roi.getName()) == "roi"); + Q_ASSERT(QByteArray(pixelFormat.getName()) == "pixelFormat"); + Q_ASSERT(QByteArray(sizex.getName()) == "sizex"); + Q_ASSERT(QByteArray(sizey.getName()) == "sizey"); + + addChannelParam(roi); + addChannelParam(pixelFormat); + addChannelParam(sizex); + addChannelParam(sizey); + addDefaultMetaParams(); +} + +//------------------------------------------------------------------------------------- +AddInMultiChannelGrabber::ChannelContainer::ChannelContainer( + const ito::Param& roi, + const ito::Param& pixelFormat, + const ito::Param& sizex, + const ito::Param& sizey, + const ito::Param& axisOffsets, + const ito::Param& axisScales, + const ito::Param& axisDescriptions, + const ito::Param& axisUnits, + const ito::Param& valueDescription, + const ito::Param& valueUnit) : + m_dataStatus(DataStatus::Idle) +{ + Q_ASSERT(QByteArray(roi.getName()) == "roi"); + Q_ASSERT(QByteArray(pixelFormat.getName()) == "pixelFormat"); + Q_ASSERT(QByteArray(sizex.getName()) == "sizex"); + Q_ASSERT(QByteArray(sizey.getName()) == "sizey"); + Q_ASSERT(QByteArray(axisOffsets.getName()) == "axisOffsets"); + Q_ASSERT(QByteArray(axisScales.getName()) == "axisScales"); + Q_ASSERT(QByteArray(axisDescriptions.getName()) == "axisDescriptions"); + Q_ASSERT(QByteArray(axisUnits.getName()) == "axisUnits"); + Q_ASSERT(QByteArray(valueDescription.getName()) == "valueDescription"); + Q_ASSERT(QByteArray(valueUnit.getName()) == "valueUnit"); + + addChannelParam(roi); + addChannelParam(pixelFormat); + addChannelParam(sizex); + addChannelParam(sizey); + addChannelParam(axisOffsets); + addChannelParam(axisScales); + addChannelParam(axisDescriptions); + addChannelParam(axisUnits); + addChannelParam(axisDescriptions); + addChannelParam(axisUnits); + addChannelParam(valueDescription); + addChannelParam(valueUnit); +} + +//------------------------------------------------------------------------------------- +void AddInMultiChannelGrabber::ChannelContainer::addDefaultMetaParams() +{ + ito::Param paramVal; + + double axisOffsets[] = { 0.0, 0.0 }; + paramVal = ito::Param("axisOffsets", ito::ParamBase::DoubleArray, 2, axisOffsets, "the offset values of the y- and x-axis of this channel image."); + paramVal.setMeta(new ito::DoubleArrayMeta(-DBL_MAX, DBL_MAX, 0.0, 2, 2, 1, "MetaInformation"), true); + addChannelParam(paramVal); + + double axisScales[] = { 1.0, 1.0 }; + paramVal = ito::Param("axisScales", ito::ParamBase::DoubleArray, 2, axisScales, "the scale values of the y- and x-axis of this channel image."); + paramVal.setMeta(new ito::DoubleArrayMeta(-DBL_MAX, DBL_MAX, 0.0, 2, 2, 1, "MetaInformation"), true); + addChannelParam(paramVal); + + ito::ByteArray axisUnits[] = { "", "" }; + paramVal = ito::Param( + "axisUnits", + ito::ParamBase::StringList, 2, + axisUnits, "The unit strings for the y- and x-axis of the grabber image"); + paramVal.setMeta(new ito::StringListMeta(ito::StringMeta::Wildcard, "*", 2, 2, 1, "MetaInformation"), true); + addChannelParam(paramVal); + + ito::ByteArray axisDescriptions[] = { "", "" }; + paramVal = ito::Param( + "axisDescriptions", + ito::ParamBase::StringList, 2, + axisDescriptions, + "axis description"); + paramVal.setMeta(new ito::StringListMeta(ito::StringMeta::Wildcard, "*", 2, 2, 1, "MetaInformation"), true); + addChannelParam(paramVal); + + paramVal = ito::Param( + "valueDescription", + ito::ParamBase::String, + "", + "value description"); + addChannelParam(paramVal); + + paramVal = ito::Param( + "valueUnit", ito::ParamBase::String, "", "The unit string of the values of this channel image"); + addChannelParam(paramVal); +} + +//------------------------------------------------------------------------------------- +void AddInMultiChannelGrabber::ChannelContainer::addChannelParam(const ito::Param& param) +{ + m_channelParams.insert(param.getName(), param); +} + +//------------------------------------------------------------------------------------- +//! constructor +AddInMultiChannelGrabber::AddInMultiChannelGrabber(const QByteArray& grabberName) : + AbstractAddInGrabber(), + d_ptr(new AddInMultiChannelGrabberPrivate()) +{ + ito::Param paramVal("name", ito::ParamBase::String | ito::ParamBase::Readonly, grabberName.data(), "GrabberName"); + paramVal.setMeta(new ito::StringMeta(ito::StringMeta::String, "General"), true); + insertParam(paramVal); + + paramVal = ito::Param("defaultChannel", ito::ParamBase::String, "", tr("indicates the default channel name, that is for instance used in plots if not otherwise stated.").toLatin1().data()); + insertParam(paramVal); + + paramVal = ito::Param("channelSelector", ito::ParamBase::String, "", tr("The channel dependent parameters (like sizex, sizey, roi, pixelFormat...) are related to this channel.").toLatin1().data()); + insertParam(paramVal); + + paramVal = ito::Param("availableChannels", ito::ParamBase::StringList | ito::ParamBase::Readonly, {}, tr("names of the channels provided by the plugin").toLatin1().data()); + insertParam(paramVal); +} + +//------------------------------------------------------------------------------------- +//! destructor +AddInMultiChannelGrabber::~AddInMultiChannelGrabber() +{ +} + +//------------------------------------------------------------------------------------- +ito::RetVal AddInMultiChannelGrabber::initChannelsAndGlobalParameters( + const ChannelContainerMap& channelContainerMap, + const QString& defaultChannelName, + const QList& globalParameters /*= QList()*/) +{ + Q_D(AddInMultiChannelGrabber); + + ito::RetVal retValue(ito::retOk); + + Q_ASSERT_X( + channelContainerMap.contains(defaultChannelName), + "initChannelsAndGlobalParameters", + "a channel with the defaultChannelName must exist"); + + Q_ASSERT_X(!d->m_channelParamsProxyInitialized, + "initChannelsAndGlobalParameters", + "channels and global parameters must not be initialized yet"); + + Q_ASSERT_X(channelContainerMap.size() > 0, + "initChannelsAndGlobalParameters", + "at least one channel container must be given"); + + // initialize default global parameters + m_params["defaultChannel"].setVal(defaultChannelName.toLatin1().constData()); + m_params["channelSelector"].setVal(defaultChannelName.toLatin1().constData()); + + QVector channelNames; + + foreach(const QString & channelName, channelContainerMap.keys()) + { + channelNames << ito::ByteArray(channelName.toLatin1().constData()); + } + + m_params["availableChannels"].setVal(channelNames.constData(), channelNames.size()); + + m_channels = channelContainerMap; + + // iterate over all channels and register their parameters as global parameter, + // however store a flag, that this is a channel parameter. + + QString paramName; + ChannelContainerMapConstIterator channelIter = channelContainerMap.constBegin(); + + while (channelIter != channelContainerMap.constEnd()) + { + ParamMapConstIterator channelParamIter = channelIter->m_channelParams.constBegin(); + + while (channelParamIter != channelIter->m_channelParams.constEnd()) + { + //iterate through channel params + + paramName = channelParamIter.key(); + + if (m_params.contains(paramName)) + { + // if another channel already registered this key, it must have the same type + Q_ASSERT_X(m_params[paramName].getType() == channelParamIter->getType(), + "initChannelsAndGlobalParameters", + "The type of channel parameters of the same name must be equal."); + } + else + { + // add a deep copy of the channel parameter to m_params + m_params.insert(paramName, Param(channelParamIter.value())); + } + + if (!d->m_paramChannelAvailabilityMap.contains(paramName)) + { + d->m_paramChannelAvailabilityMap[paramName] = QStringList(channelIter.key()); + } + else + { + d->m_paramChannelAvailabilityMap[paramName].append(channelIter.key()); + } + + channelParamIter++; + } + + channelIter++; + } + + // add all global parameters to m_params, unless they exist already: error + + foreach(const ito::Param& p, globalParameters) + { + paramName = QLatin1String(p.getName()); + Q_ASSERT_X(!m_params.contains(paramName), + "initChannelsAndGlobalParameters", + "the globalParameters must not contain a parameter whose name is already contained in at least one channel."); + m_params[paramName] = p; + } + + d->m_channelParamsProxyInitialized = true; + + // call switchChannelSelector to synchronize the values in the channel specific parameters with + // to these of the current channel (channelSelector). + retValue += switchChannelSelector(); + + return retValue; +} + +//------------------------------------------------------------------------------- +//! sends m_image to all registered listeners. +/* +This method is continuously called from timerEvent. Also call this method from +your getVal-Method (usually with 0-timeout). The function adds axis scale and +axis unit to the dataObject. + +\param [in] waitMS indicates the time (in ms) that should be waiting until every + registered live image source node received m_image. 0: no wait, -1: + infinit waiting time, else time in milliseconds +\return retOk if everything was ok, retWarning if live image could not be invoked +*/ +ito::RetVal AddInMultiChannelGrabber::sendDataToListeners(int waitMS) +{ + Q_D(AddInMultiChannelGrabber); + + assert(d->m_channelParamsProxyInitialized); + ito::RetVal retValue = ito::retOk; + int size = m_autoGrabbingListeners.size(); + + if (waitMS == 0) + { + auto it = m_autoGrabbingListeners.constBegin(); + + while (it != m_autoGrabbingListeners.constEnd()) + { + const ChannelContainer& container = m_channels[it.key().toLatin1().data()]; + QSharedPointer pDObj(new ito::DataObject(container.m_data)); + + if (!QMetaObject::invokeMethod(it.value(), "setSource", Q_ARG(QSharedPointer, pDObj), Q_ARG(ItomSharedSemaphore*, nullptr))) + { + retValue += ito::RetVal(ito::retWarning, 1001, tr("slot 'setSource' of live source node could not be invoked").toLatin1().data()); + } + + it++; + } + } + else if (m_autoGrabbingListeners.size() > 0) + { + ItomSharedSemaphore** waitConds = new ItomSharedSemaphore*[size]; + int i = 0; + auto it = m_autoGrabbingListeners.constBegin(); + + while (it != m_autoGrabbingListeners.constEnd()) + { + waitConds[i] = new ItomSharedSemaphore(); + // \todo On Linux a crash occurs here when closing the liveImage ... maybe the same reason why we get an error message on windows? + if (it.value()) + { + if (!QMetaObject::invokeMethod(it.value(), "setSource", Q_ARG(QSharedPointer, QSharedPointer(new ito::DataObject(m_channels[it.key().toLatin1().data()].m_data))), Q_ARG(ItomSharedSemaphore*, waitConds[i]))) + { + retValue += ito::RetVal(ito::retWarning, 1001, tr("slot 'setSource' of live source node could not be invoked").toLatin1().data()); + } + } + + it++; + i++; + } + + for (i = 0; i < size; i++) + { + if (!waitConds[i]->wait(waitMS)) + { + qDebug() << "timeout in number: " << i << "number of items: " << size; + } + + waitConds[i]->deleteSemaphore(); + waitConds[i] = nullptr; + } + + DELETE_AND_SET_NULL_ARRAY(waitConds); + } + + return retValue; +} + +//------------------------------------------------------------------------------------- +ito::RetVal AddInMultiChannelGrabber::checkData(ito::DataObject* externalDataObject /*= nullptr*/) +{ + QString defaultChannel = QLatin1String(m_params["defaultChannel"].getVal()); + return checkData(defaultChannel, externalDataObject); +} + +//------------------------------------------------------------------------------------- +ito::RetVal AddInMultiChannelGrabber::checkDataFromAllChannels() +{ + auto it = m_channels.constBegin(); + ito::RetVal retval; + + while (it != m_channels.constEnd()) + { + retval += checkData(it.key()); + ++it; + } + + return retval; +} + +//------------------------------------------------------------------------------------- +ito::RetVal AddInMultiChannelGrabber::checkData(const QString& channelName, ito::DataObject* externalDataObject /*= nullptr*/) +{ + Q_D(AddInMultiChannelGrabber); + + assert(d->m_channelParamsProxyInitialized); + ito::RetVal retVal(ito::retOk); + + auto channel = m_channels.find(channelName); + + if (channel == m_channels.end()) + { + return ito::RetVal(ito::retError, 0, tr("channel name does not exist").toLatin1().data()); + } + + const int futureHeight = channel->m_channelParams["sizey"].getVal(); + const int futureWidth = channel->m_channelParams["sizex"].getVal(); + bool futureTypeOk; + int futureType = itoDataTypeFromPixelFormat(channel->m_channelParams["pixelFormat"].getVal(), &futureTypeOk); + + if (!futureTypeOk) + { + return ito::RetVal(ito::retError, 0, tr("unsupported or invalid pixelFormat").toLatin1().data()); + } + + ito::float64 axisOffset[] = { + channel->m_channelParams["axisOffsets"].getVal()[0], + channel->m_channelParams["axisOffsets"].getVal()[1] + }; + + ito::float64 axisScale[] = { + channel->m_channelParams["axisScales"].getVal()[0], + channel->m_channelParams["axisScales"].getVal()[1] + }; + + ito::ByteArray axisUnit[] = { + channel->m_channelParams["axisUnits"].getVal()[0], + channel->m_channelParams["axisUnits"].getVal()[1] + }; + + ito::ByteArray axisDescription[] = { + channel->m_channelParams["axisDescriptions"].getVal()[0], + channel->m_channelParams["axisDescriptions"].getVal()[1] + }; + + ito::ByteArray valueDescription = channel->m_channelParams["valueDescription"].getVal(); + ito::ByteArray valueUnit = channel->m_channelParams["valueUnit"].getVal(); + + if (!externalDataObject) + { + if (channel->m_data.getDims() < 2 || channel->m_data.getSize(0) != futureHeight || + channel->m_data.getSize(1) != futureWidth || channel->m_data.getType() != futureType) + { + channel->m_data = ito::DataObject(futureHeight, futureWidth, futureType); + } + + channel->m_data.setAxisScale(0, axisScale[0]); + channel->m_data.setAxisScale(1, axisScale[1]); + channel->m_data.setAxisOffset(0, axisOffset[0]); + channel->m_data.setAxisOffset(1, axisOffset[1]); + channel->m_data.setAxisDescription(0, axisDescription[0].data()); + channel->m_data.setAxisDescription(1, axisDescription[1].data()); + channel->m_data.setAxisUnit(0, axisUnit[0].data()); + channel->m_data.setAxisUnit(1, axisUnit[1].data()); + channel->m_data.setValueDescription(valueDescription.data()); + channel->m_data.setValueUnit(valueUnit.data()); + } + else + { + int dims = externalDataObject->getDims(); + + if (dims == 0) + { + *externalDataObject = ito::DataObject(futureHeight, futureWidth, futureType); + externalDataObject->setAxisScale(0, axisScale[0]); + externalDataObject->setAxisScale(1, axisScale[1]); + externalDataObject->setAxisOffset(0, axisOffset[0]); + externalDataObject->setAxisOffset(1, axisOffset[1]); + externalDataObject->setAxisDescription(0, axisDescription[0].data()); + externalDataObject->setAxisDescription(1, axisDescription[1].data()); + externalDataObject->setAxisUnit(0, axisUnit[0].data()); + externalDataObject->setAxisUnit(1, axisUnit[1].data()); + externalDataObject->setValueDescription(valueDescription.data()); + externalDataObject->setValueUnit(valueUnit.data()); + } + else if (externalDataObject->calcNumMats() != 1) + { + return ito::RetVal( + ito::retError, 0, + tr("Error during check data, external dataObject invalid. Object has more or less " + "than 1 plane. It must be of right size and type or an uninitilized image.") + .toLatin1() + .data()); + } + else if (externalDataObject->getSize(dims - 2) != (unsigned int)futureHeight || + externalDataObject->getSize(dims - 1) != (unsigned int)futureWidth || + externalDataObject->getType() != futureType) + { + return ito::RetVal( + ito::retError, 0, + tr("Error during check data, external dataObject invalid. Object must be of right " + "size and type or an uninitilized image.") + .toLatin1() + .data()); + } + } + + return ito::retOk; +} + +//------------------------------------------------------------------------------------- +void AddInMultiChannelGrabber::addChannel(QString name) +{ + ChannelContainer container( + m_params["roi"], + m_params["pixelFormat"], + m_params["sizex"], + m_params["sizey"], + m_params["axisOffset"], + m_params["axisScale"], + m_params["axisDescription"], + m_params["axisUnit"], + m_params["valueDescription"], + m_params["valueUnit"]); + m_channels[name] = container; + const ByteArray* channelList = m_params["availableChannels"].getVal(); + int len = 0; + m_params["availableChannels"].getVal(len); + + QVector qVectorList(len, *channelList); + qVectorList.append(ByteArray(name.toLatin1().data())); + m_params["availableChannels"].setVal(qVectorList.data(), qVectorList.length()); +} + +//--------------------------------------------------------------------------------- +ito::RetVal AddInMultiChannelGrabber::adaptDefaultChannelParams() +{ + ito::RetVal retVal(ito::retOk); + char* channel = m_params["defaultChannel"].getVal(); + return retVal; +} + +//--------------------------------------------------------------------------------- +ito::RetVal AddInMultiChannelGrabber::getParam(QSharedPointer val, ItomSharedSemaphore* waitCond) +{ + Q_D(AddInMultiChannelGrabber); + assert(d->m_channelParamsProxyInitialized); + + ItomSharedSemaphoreLocker locker(waitCond); + ito::RetVal retValue; + QString key; + bool hasIndex = false; + int index; + QString suffix; + ParamMapIterator it; + bool ok = false; + + //parse the given parameter-name (if you support indexed or suffix-based parameters) + retValue += apiParseParamName(val->getName(), key, hasIndex, index, suffix); + + if (!retValue.containsError()) + { + retValue += apiGetParamFromMapByKey(m_params, key, it, false); + } + + if (!retValue.containsError()) + { + retValue += getParameter(val, it, key, suffix, index, hasIndex, ok); + } + + if (!retValue.containsError() && !ok) + { + //the parameter was not processed by the plugin, so it is done here + + // if a suffix is available, check if it is a channel name and if yes, + // check if the key is contained in this channel. If this is also true, + // return this parameter instead of the global one. + if (suffix != "") + { + auto channel = m_channels.find(suffix); + + if (channel != m_channels.end()) + { + // ok, there is a channel with the suffix name + auto channelParam = channel->m_channelParams.find(key); + + // check if this channel also has the desired param, and if yes, return this one. + if (channelParam != channel->m_channelParams.end()) + { + it = channelParam; + } + } + else + { + retValue += ito::RetVal::format( + ito::retWarning, + 0, + "Suffix '%s' is no valid channel and unsupported. It is ignored.", + suffix.toLatin1().data() + ); + } + } + + // check if an index is available and if yes, try to return this index. + // In this case, the parameter must be an array-type parameter. If this is not + // the case an error is returned. + if (hasIndex) + { + retValue += apiGetItemFromParamArray(it.value(), index, *val); + } + else + { + *val = it.value(); + } + } + + if (waitCond) + { + waitCond->returnValue = retValue; + waitCond->release(); + } + + return retValue; +} + +//--------------------------------------------------------------------------------- +ito::RetVal AddInMultiChannelGrabber::changeChannelForListener(QObject* listener, const QString& newChannel) +{ + Q_D(AddInMultiChannelGrabber); + + assert(d->m_channelParamsProxyInitialized); + ito::RetVal retValue(ito::retOk); + bool found = false; + + if (listener) + { + auto it = m_autoGrabbingListeners.begin(); + + while (it != m_autoGrabbingListeners.end()) + { + if (it.value() == listener) + { + found = true; + + if (it.key() != newChannel) + { + // temporarily remove the source from the plot + /*QMetaObject::invokeMethod(listener, "setSource", Qt::DirectConnection, + Q_ARG(QSharedPointer, + QSharedPointer(nullptr)), + Q_ARG(ItomSharedSemaphore*, nullptr));*/ + + // the channel has changed + m_autoGrabbingListeners.erase(it); + m_autoGrabbingListeners.insert(newChannel, listener); + + // Problem: here, the itomCLommonPlotLib library cannot be used, due to a ring + // include. Therefore, all properties etc. have to be read and written using the + // generic Qt methods of the MOC system. + if (listener->inherits("ito::AbstractDObjFigure")) + { + // here the property must be requested by its name, since the itomPlot library + // cannot be linked here, due to a ring include issue. + Qt::Axis plotValueAxis = listener->property("valueAxis").value(); + + // request the pixel format for the desired channel (independent if this channel is the default channel + // or the selected channel). + ito::ByteArray paramName = ito::ByteArray("pixelFormat:").append(newChannel.toLatin1().data()); + QSharedPointer pixelFormatParam(new ito::Param(paramName, ito::ParamBase::String)); + ito::RetVal retval2 = getParam(pixelFormatParam, nullptr); + + if (retval2 == ito::retOk) + { + ito::AutoInterval bitRange(0.0, 1.0); + const char* pixelFormat = pixelFormatParam->getVal(); + int min, max = 0; + bool ok = false; + AbstractAddInGrabber::minMaxBoundariesFromIntegerPixelFormat(pixelFormat, min, max, ok); + + if (ok) + { + bitRange.setMaximum(max); + bitRange.setMinimum(min); + } + else + { + bitRange.setAuto(true); + } + + switch (plotValueAxis) + { + case Qt::YAxis: + listener->setProperty("yAxisInterval", QVariant::fromValue(bitRange)); + break; + default: + listener->setProperty("zAxisInterval", QVariant::fromValue(bitRange)); + break; + } + } + } + } + + break; + } + + it++; + } + + if (!found) + { + retValue += ito::RetVal(ito::retError, 0, tr("The given listener (e.g. plot) must be registered first.").toLatin1().data()); + } + } + else + { + retValue += ito::RetVal(ito::retError, 0, "QObject not callable."); + } + + return retValue; +} + +//------------------------------------------------------------------------------- +//! Sets a new value to a parameter. +/*! + This function parses the given parameter and calls setParameter. If the bool + parameter ok in the setParameter (to be implemented in the individual plugins) + function returns false, it gets assumed that the plugin didn't process the + parameter. In this case the value of the parameter gets copied here. + If the parameter name is "roi" sizex and sizey gets updated by setParam. If the + key of the parameter is "defaultChannel" the function "switchDefaultChannel" gets called. + Both happens also if the "ok" value of setParameter is true. + "applyParamsToChannelParams" is called to synchronize the parameters of the + channel container follwed by a call of checkData. + +\param [in] val is a QSharedPOinter of type ParamBase containing the paremeter to be set. +\param [in] waitCond +\return retOk if everything was ok, else retError +*/ +ito::RetVal AddInMultiChannelGrabber::setParam(QSharedPointer val, ItomSharedSemaphore* waitCond/* = nullptr*/) +{ + // todo: consider the cases if suffixes or index is given + Q_D(AddInMultiChannelGrabber); + assert(d->m_channelParamsProxyInitialized); + + ItomSharedSemaphoreLocker locker(waitCond); + ito::RetVal retValue; + bool hasIndex; + bool ok = false; + int index; + QString suffix; + QString key; + QStringList paramUpdateList; + ParamMapIterator it; + + int cntStartedDevices = grabberStartedCount(); + + retValue += apiParseParamName(val->getName(), key, hasIndex, index, suffix); + retValue += apiGetParamFromMapByKey(m_params, key, it, true); + retValue += apiValidateParam(*it, *val, false, true); + + if (!retValue.containsError()) + { + retValue += setParameter(val, it, suffix, key, index, hasIndex, ok, paramUpdateList); + + if (ok && !paramUpdateList.contains(val->getName())) + { + paramUpdateList << val->getName(); + } + + if (!retValue.containsError() && !ok) + { + if (!retValue.containsError()) + { + if (key != "defaultChannel") + { + retValue += it->copyValueFrom(&(*val)); + paramUpdateList << val->getName(); + } + else + { + if (m_channels.find(val->getVal()) != m_channels.end()) + { + retValue += it->copyValueFrom(&(*val)); + paramUpdateList << val->getName(); + } + else + { + QStringList availableChannels = m_channels.keys(); + + retValue += ito::RetVal( + ito::retError, + 0, + tr("Cannot switch to channel \"%1\" since it does not exist. Available channels are \"%2\".") + .arg(val->getVal()) + .arg(availableChannels.join("\", \"")).toLatin1().data() + ); + } + } + } + } + + if (!retValue.containsError()) + { + if (key == "roi" || paramUpdateList.contains("roi")) + { + updateSizeXY(); + paramUpdateList << "sizex" << "sizey"; + } + else if (key == "channelSelector") + { + retValue += switchChannelSelector(); + } + + retValue += applyParamsToChannelParams(paramUpdateList); + retValue += checkData(); + } + + if (!retValue.containsError()) + { + emit parametersChanged(m_params); + } + } + + if (cntStartedDevices < grabberStartedCount()) + { + if (cntStartedDevices != 0) + { + retValue += startDevice(nullptr); + setGrabberStarted(cntStartedDevices); + } + } + + if (waitCond) + { + waitCond->returnValue = retValue; + waitCond->release(); + } + return retValue; +} + +//------------------------------------------------------------------------------- +//! synchronizes m_params with the params of default channel container +/*! +This method synchronizes the parameters from the current selected channel container +with m_params. Call this function after changing the defaultChannel parameter. +Parameters which are not available for the current default channel are set to readonly + +\return retOk if everything was ok, else retError +*/ +ito::RetVal AddInMultiChannelGrabber::switchChannelSelector() +{ + Q_D(AddInMultiChannelGrabber); + + assert(d->m_channelParamsProxyInitialized); + ito::RetVal retValue(ito::retOk); + ito::uint32 flag = 0; + QString selectedChannel = QLatin1String(m_params["channelSelector"].getVal()); + + if (m_channels.contains(selectedChannel)) + { + const auto& selChannel = m_channels[selectedChannel]; + auto paramsInChannelIter = d->m_paramChannelAvailabilityMap.constBegin(); + + while (paramsInChannelIter != d->m_paramChannelAvailabilityMap.constEnd()) + { + if (paramsInChannelIter->contains(selectedChannel)) + { + // this parameters is contained in the selected channel. Copy its value and flags + // from the channel to m_params + const ito::Param p = selChannel.m_channelParams[paramsInChannelIter.key()]; + m_params[paramsInChannelIter.key()].copyValueFrom(&p); + m_params[paramsInChannelIter.key()].setFlags(selChannel.m_channelParams[paramsInChannelIter.key()].getFlags()); + } + + paramsInChannelIter++; + } + } + else + { + retValue += ito::RetVal( + ito::retError, + 0, + tr("Cannot switch to channel %1. The channel is not registered.").arg(selectedChannel).toLatin1().data() + ); + } + + emit parametersChanged(m_params); + + return retValue; +} + +//------------------------------------------------------------------------------- +//! copies value m_params to the channel params of the current default channel +/*! +This method copies params of m_params to the params of the channel container if the param is contained in the channel container . This function is usally called after setParam to apply the changed entries of m_params to the corresponding channel container. +If a parameter is not found in the channel container nothing happens. + +\param [in] keyList indicates which params are copied. If the List is empty all Parameters of the current channel are updated. +\return retOk if everything was ok, else retError +*/ +ito::RetVal AddInMultiChannelGrabber::applyParamsToChannelParams(const QStringList& keyList) +{ + Q_D(AddInMultiChannelGrabber); + + assert(d->m_channelParamsProxyInitialized); + ito::RetVal retVal(ito::retOk); + QString channelSelector = QLatin1String(m_params["channelSelector"].getVal()); + + if (!keyList.isEmpty()) + { + if (m_channels.contains(channelSelector)) + { + QString tmp; + foreach(tmp, keyList) + { + if (m_channels[channelSelector].m_channelParams.contains(tmp)) + { + if (m_params.contains(tmp)) + { + m_channels[channelSelector].m_channelParams[tmp] = m_params[tmp]; + } + else + { + retVal = ito::RetVal(ito::retError, 0, tr("unknown parameter %1 in m_params").arg(tmp).toLatin1().data()); + } + } + } + } + + else + { + retVal = ito::RetVal(ito::retError, 0, tr("Unknown channel \"%1\". Available channels are: %2").arg(channelSelector).arg(m_channels.keys().join(", ")).toLatin1().data()); + } + } + else + { + QMapIterator it(m_channels[m_params["channelSelector"].getVal()].m_channelParams); + + while (it.hasNext()) + { + it.next(); + const_cast(it.value()) = m_params[it.key()]; + } + } + + return retVal; +} + +//------------------------------------------------------------------------------- +//! updates sizex and sizey +/*! +Call this function to update sizex and sizey. If the roi is changed via setParam this function will be called automatically. +Note: Do not forget to apply the changes to the channel parameters by calling applyParamsToChannelParams after calling this function. + +\return retOk if everything was ok, else retError +*/ +void AddInMultiChannelGrabber::updateSizeXY() +{ + Q_D(AddInMultiChannelGrabber); + + assert(d->m_channelParamsProxyInitialized); + const int* roi = m_params["roi"].getVal(); + int height = roi[3]; + int width = roi[2]; + m_params["sizex"].setVal(width); + m_params["sizey"].setVal(height); +} + +//--------------------------------------------------------------------------------- +ito::RetVal AddInMultiChannelGrabber::setParamMeta(const QByteArray& paramName, ito::ParamMeta* meta, bool takeOwnerShip, const QList& channelList/* = QList()*/) +{ + Q_D(AddInMultiChannelGrabber); + + assert(d->m_channelParamsProxyInitialized); + ito::RetVal retValue(ito::retOk); + if (d->m_paramChannelAvailabilityMap.contains(paramName) && m_params.contains(paramName)) + { + if (channelList.isEmpty()) //we want to update the param for all channels even if it is a global one + { + m_params[paramName].setMeta(meta, takeOwnerShip); + QStringListIterator it(d->m_paramChannelAvailabilityMap[paramName]); + while (it.hasNext()) // update param for all channels + { + m_channels[it.next()].m_channelParams[paramName].setMeta(meta, takeOwnerShip); + } + } + else // we only want to update the param for a list of channels + { + for (int i = 0; i < channelList.length(); i++) + { + if (m_channels.contains(channelList[i])) + { + if (d->m_paramChannelAvailabilityMap[paramName].contains(channelList[i])) + { + m_channels[channelList[i]].m_channelParams[paramName].setMeta(meta, takeOwnerShip); + } + } + else + { + retValue += ito::RetVal(ito::retError, 0, QString("unknown channel %1").arg(QString(paramName)).toLatin1().data()); + } + + } + if (!retValue.containsError()) + { + //update m_params if the current default channel is listed in channelList or if the current default channel does not support the param (the param in m_params then is set to readonly) + if (channelList.contains(m_params["defaultChannel"].getVal()) || !d->m_paramChannelAvailabilityMap[paramName].contains(m_params["defaultChannel"].getVal())) + { + m_params[paramName].setMeta(meta, takeOwnerShip); + } + } + } + + } + else + { + retValue += ito::RetVal(ito::retError, 0, QString("could not find parameter %1. Maybe the parameter is not registered").arg(QString(paramName)).toLatin1().data()); + } + + return retValue; +} + +//--------------------------------------------------------------------------------- +ito::RetVal AddInMultiChannelGrabber::setParamFlags(const QByteArray& paramName, const unsigned int& flags, const QList& channelList/* = QList()*/) +{ + Q_D(AddInMultiChannelGrabber); + + assert(d->m_channelParamsProxyInitialized); + ito::RetVal retValue(ito::retOk); + if (d->m_paramChannelAvailabilityMap.contains(paramName) && m_params.contains(paramName)) + { + if (channelList.isEmpty()) //we want to update the param for all channels even if it is a global one + { + m_params[paramName].setFlags(flags); + QStringListIterator it(d->m_paramChannelAvailabilityMap[paramName]); + while (it.hasNext()) // update param for all channels + { + m_channels[it.next()].m_channelParams[paramName].setFlags(flags); + } + } + else // we only want to update the param for a list of channels + { + for (int i = 0; i < channelList.length(); i++) + { + if (m_channels.contains(channelList[i])) + { + if (d->m_paramChannelAvailabilityMap[paramName].contains(channelList[i])) + { + m_channels[channelList[i]].m_channelParams[paramName].setFlags(flags); + } + } + else + { + retValue += ito::RetVal(ito::retError, 0, QString("unknown channel %1").arg(QString(paramName)).toLatin1().data()); + } + + } + if (!retValue.containsError()) + { + //update m_params if the current default channel is listed in channelList or if the current default channel does not support the param (the param in m_params then is set to readonly) + if (channelList.contains(m_params["defaultChannel"].getVal()) || !d->m_paramChannelAvailabilityMap[paramName].contains(m_params["defaultChannel"].getVal())) + { + m_params[paramName].setFlags(flags); + } + } + } + + } + else + { + retValue += ito::RetVal(ito::retError, 0, QString("could not find parameter %1. Maybe the parameter is not registered").arg(QString(paramName)).toLatin1().data()); + } + + return retValue; +} + +//------------------------------------------------------------------------------------- +ito::RetVal AddInMultiChannelGrabber::getVal(void* vpdObj, ItomSharedSemaphore* waitCond) +{ + ItomSharedSemaphoreLocker locker(waitCond); + ito::RetVal retValue(ito::retOk); + ito::DataObject* dObj = reinterpret_cast(vpdObj); + QString defaultChannel = QLatin1String(m_params["defaultChannel"].getVal()); + + if (!dObj) + { + retValue += ito::RetVal( + ito::retError, 0, tr("Empty dataObject handle retrieved from caller").toLatin1().data()); + } + + if (!retValue.containsError()) + { + retValue += retrieveData(QStringList(defaultChannel)); + } + + if (!retValue.containsError()) + { + // don't wait for live image, since user should get the image as fast as possible. + sendDataToListeners(0); + + (*dObj) = m_channels[defaultChannel].m_data; + + auto channelDatasets = QSharedPointer>::create(); + channelDatasets->insert(defaultChannel, m_channels[defaultChannel].m_data); + + emit newData(channelDatasets); + m_channels[defaultChannel].m_dataStatus = DataStatus::NewDataAndEmitted; + } + + if (waitCond) + { + waitCond->returnValue = retValue; + waitCond->release(); + } + + return retValue; +} + +//------------------------------------------------------------------------------------- +ito::RetVal AddInMultiChannelGrabber::copyVal(void* vpdObj, ItomSharedSemaphore* waitCond) +{ + ItomSharedSemaphoreLocker locker(waitCond); + ito::RetVal retValue; + ito::DataObject* dObj = reinterpret_cast(vpdObj); + + if (!dObj) + { + retValue += ito::RetVal( + ito::retError, 0, tr("Empty dataObject handle retrieved from caller").toLatin1().data()); + } + else + { + retValue += checkData(dObj); + } + + if (!retValue.containsError()) + { + retValue += getVal(vpdObj, nullptr); + } + + if (!retValue.containsError()) + { + QString defaultChannel = QLatin1String(m_params["defaultChannel"].getVal()); + m_channels[defaultChannel].m_data.deepCopyPartial(*dObj); + } + + if (waitCond) + { + waitCond->returnValue = retValue; + waitCond->release(); + } + + return retValue; +} + +//------------------------------------------------------------------------------------- +ito::RetVal AddInMultiChannelGrabber::getVal(QSharedPointer > channelDatasets, ItomSharedSemaphore* waitCond) +{ + ItomSharedSemaphoreLocker locker(waitCond); + ito::RetVal retValue; + QStringList channels; + + auto it = channelDatasets->constBegin(); + + while (it != channelDatasets->constEnd()) + { + retValue += checkData(it.key(), nullptr); + channels << it.key(); + it++; + } + + if (!retValue.containsError()) + { + retValue += retrieveData(channels); + } + + if (!retValue.containsError()) + { + // don't wait for live image, since user should get the image as fast as possible. + sendDataToListeners(0); + + auto it2 = channelDatasets->begin(); + + while (it2 != channelDatasets->end()) + { + it2->operator=(m_channels[it2.key()].m_data); + m_channels[it.key()].m_dataStatus = DataStatus::NewDataAndEmitted; + it2++; + } + + emit newData(channelDatasets); + } + + if (waitCond) + { + waitCond->returnValue = retValue; + waitCond->release(); + } + + return retValue; +} + +//------------------------------------------------------------------------------------- +ito::RetVal AddInMultiChannelGrabber::copyVal(QSharedPointer > channelDatasets, ItomSharedSemaphore* waitCond) +{ + ItomSharedSemaphoreLocker locker(waitCond); + ito::RetVal retValue; + QStringList channels; + + auto it = channelDatasets->begin(); + + while (it != channelDatasets->end()) + { + retValue += checkData(it.key(), &(*it)); + channels << it.key(); + it++; + } + + if (!retValue.containsError()) + { + retValue += retrieveData(channels); + } + + if (!retValue.containsError()) + { + // don't wait for live image, since user should get the image as fast as possible. + sendDataToListeners(0); + + it = channelDatasets->begin(); + + while (it != channelDatasets->end()) + { + m_channels[it.key()].m_dataStatus = DataStatus::NewDataAndEmitted; + retValue += m_channels[it.key()].m_data.deepCopyPartial(*it); + it++; + } + + emit newData(channelDatasets); + } + + if (waitCond) + { + waitCond->returnValue = retValue; + waitCond->release(); + } + + return retValue; +} + +//------------------------------------------------------------------------------------- +ito::RetVal AddInMultiChannelGrabber::retrieveData(ito::DataObject* externalDataObject /*= nullptr*/) +{ + QString defaultChannel = QLatin1String(m_params["defaultChannel"].getVal()); + ito::RetVal retval; + + if (externalDataObject) + { + retval += checkData(defaultChannel, externalDataObject); + } + + if (!retval.containsError()) + { + // fetch all channels. This is necessary for the auto + // grabbing using the timerEvent in abstractAddInGrabber. + retval += retrieveData(QStringList()); + } + + if (externalDataObject && !retval.containsError()) + { + retval += m_channels[defaultChannel].m_data.deepCopyPartial(*externalDataObject); + } + + return retval; +} + + +//------------------------------------------------------------------------------------- +AddInMultiChannelGrabber::ChannelContainerMapConstIterator AddInMultiChannelGrabber::getCurrentDefaultChannel() const +{ + QString defaultChannel = QLatin1String(m_params["defaultChannel"].getVal()); + return m_channels.constFind(defaultChannel); +} + +//------------------------------------------------------------------------------------- +AddInMultiChannelGrabber::ChannelContainerMapIterator AddInMultiChannelGrabber::getCurrentDefaultChannel() +{ + QString defaultChannel = QLatin1String(m_params["defaultChannel"].getVal()); + return m_channels.find(defaultChannel); +} + +} //end namespace ito diff --git a/commonQt/CMakeLists.txt b/commonQt/CMakeLists.txt index f229e3058..f6b476b4f 100644 --- a/commonQt/CMakeLists.txt +++ b/commonQt/CMakeLists.txt @@ -1,6 +1,6 @@ # - itom software # URL: http://www.uni-stuttgart.de/ito -# Copyright (C) 2020, Institut fuer Technische Optik (ITO), +# Copyright (C) 2023, Institut fuer Technische Optik (ITO), # Universitaet Stuttgart, Germany # # This file is part of itom and its software development toolkit (SDK). @@ -69,7 +69,9 @@ link_directories( set(ITOMCOMMONQT_HEADERS ${CMAKE_CURRENT_SOURCE_DIR}/commonQtVersion.h + ${CMAKE_CURRENT_SOURCE_DIR}/../common/abstractAddInGrabber.h ${CMAKE_CURRENT_SOURCE_DIR}/../common/addInGrabber.h + ${CMAKE_CURRENT_SOURCE_DIR}/../common/addInMultiChannelGrabber.h ${CMAKE_CURRENT_SOURCE_DIR}/../common/addInInterface.h ${CMAKE_CURRENT_SOURCE_DIR}/../common/addInInterfaceVersion.h ${CMAKE_CURRENT_SOURCE_DIR}/../common/abstractAddInDockWidget.h @@ -90,7 +92,9 @@ set(ITOMCOMMONQT_HEADERS ) set(ITOMCOMMONQT_SOURCES + ${CMAKE_CURRENT_SOURCE_DIR}/../common/sources/abstractAddInGrabber.cpp ${CMAKE_CURRENT_SOURCE_DIR}/../common/sources/addInGrabber.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/../common/sources/addInMultiChannelGrabber.cpp ${CMAKE_CURRENT_SOURCE_DIR}/../common/sources/addInInterface.cpp ${CMAKE_CURRENT_SOURCE_DIR}/../common/sources/abstractAddInDockWidget.cpp ${CMAKE_CURRENT_SOURCE_DIR}/../common/sources/abstractAddInConfigDialog.cpp diff --git a/demo/itom/plugins/demo_DummyGrabber.py b/demo/itom/plugins/demo_DummyGrabber.py index 25d88243b..62ab957ab 100644 --- a/demo/itom/plugins/demo_DummyGrabber.py +++ b/demo/itom/plugins/demo_DummyGrabber.py @@ -2,7 +2,12 @@ ================ This demo shows with the example of the ``DummyGrabber`` -how grabber and cameras are used in ``itom``.""" +how grabbers and cameras are used in ``itom``. +The ``camera`` shows how to set parameter like ``region of interest`` +or ``bits per pixel``. + +First a ``liveImage`` is opened. In addition, 100 frames are grabbed +from the ``camera`` and stored in the ``imageStack``.""" from itom import dataIO from itom import dataObject @@ -12,19 +17,21 @@ ############################################################################### -# Start camera (e.g.: ``DummyGrabber``) -camera = dataIO("DummyGrabber") # noise camera -cameraGaussian = dataIO("DummyGrabber", imageType="gaussianSpot") # moving Gaussian spot -cameraGaussianArray = dataIO("DummyGrabber", imageType="gaussianSpotArray") # moving 4 Gaussian spots +# Start camera (e.g.: ``DummyGrabber``) with a ``noise image`` (default). +camera = dataIO("DummyGrabber") ############################################################################### -# Set region of interest (ROI). +# Set region of interest (ROI) by a tuple. +# # x: [100,499] -> width: 400 (borders are included!) +# # y: [40, 349] -> height: 310 camera.setParam("roi", [100, 40, 400, 300]) -# or: -# camera.setParam("roi[0]", 100) -# camera.setParam("roi[2]", 400) #... + +############################################################################### +# or by explicite roi values. +camera.setParam("roi[0]", 100) +camera.setParam("roi[2]", 400) print("width:", camera.getParam("sizex")) print("height:", camera.getParam("sizey")) @@ -35,15 +42,16 @@ # print available parameters of that device print("DummyGrabber has the following parameters:") -print(camera.getParamList()) +camera.getParamList() # print detailed information about parameters: -print(camera.getParamListInfo()) +camera.getParamListInfo() ############################################################################### # Read parameters from device. sizex = camera.getParam("sizex") sizey = camera.getParam("sizey") + ############################################################################### # Start camera. camera.startDevice() @@ -83,21 +91,10 @@ ############################################################################### # Start a live image. -liveImage(camera) - -############################################################################### +# # .. image:: ../../_static/demoDummyGrabber_1.png # :width: 100% -liveImage(cameraGaussian) - -############################################################################### -# .. image:: ../../_static/demoDummyGrabber_2.png -# :width: 100% -liveImage(cameraGaussianArray) - -############################################################################### -# .. image:: ../../_static/demoDummyGrabber_3.png -# :width: 100% +liveImage(camera) ############################################################################### # Acquire an image stack of 10 measurements. diff --git a/demo/itom/plugins/demo_GaussianDummyGrabber.py b/demo/itom/plugins/demo_GaussianDummyGrabber.py new file mode 100644 index 000000000..47bc3b776 --- /dev/null +++ b/demo/itom/plugins/demo_GaussianDummyGrabber.py @@ -0,0 +1,56 @@ +"""Gaussian DummyGrabber +===================== + +This demo shows with the example of the ``DummyGrabber`` +how grabber and cameras are used in ``itom``. +The ``DummyGrabber`` can optionally show a Gaussian spot or +an array of Gaussian spots. In addition, it is shown here how +fruther meta information (*axis description, axis unit, axis scale, axis offset, +value description, value unit*) of the frames are set, which are adopted +for the ``liveImage`` and the returned ``dataObject`` frames..""" + +from itom import dataIO +from itom import liveImage + +# sphinx_gallery_thumbnail_path = '11_demos/_static/_thumb/demoGaussianDummyGrabber.png' + +############################################################################### +# Start camera (e.g.: ``DummyGrabber``) with moving ``Gaussian spot``. +cameraGaussian = dataIO("DummyGrabber", imageType="gaussianSpot") + +############################################################################### +# Start camera (e.g.: ``DummyGrabber``) with moving ``4 Gaussian spots``. +cameraGaussianArray = dataIO("DummyGrabber", imageType="gaussianSpotArray") + + +############################################################################### +# Set meta information for the gaussianSpot of image for liveImage and return image. +# The axis properties are set assuming a pixel pitch of 10µm. +# The offset is set such that origin is in the center. +cameraGaussian.setParam("axisScale", (10e-6, 10e-6)) # scale 10µm +cameraGaussian.setParam( + "axisOffset", ((480 - 1) / 2, (640 - 1) / 2) +) # origin on center +cameraGaussian.setParam("axisDescription", ("y axis", "x axis")) +cameraGaussian.setParam("axisUnit", ("µm", "µm")) +cameraGaussian.setParam("valueDescription", "counts") +cameraGaussian.setParam("valueUnit", "a.u.") + +############################################################################### +# Start a live image with aspect ratio of 1 and visible colorBar. +# +# .. image:: ../../_static/demoGaussianDummyGrabber_1.png +# :width: 100% +liveImage( + cameraGaussian, + properties={ + "colorMap": "falseColorIR", + "keepAspectRatio": True, + "colorBarVisible": True, + }, +) + +############################################################################### +# .. image:: ../../_static/demoGaussianDummyGrabber_2.png +# :width: 100% +liveImage(cameraGaussianArray) diff --git a/demo/itom/plugins/demo_MultiChannelDummyGrabber.py b/demo/itom/plugins/demo_MultiChannelDummyGrabber.py new file mode 100644 index 000000000..d740b5016 --- /dev/null +++ b/demo/itom/plugins/demo_MultiChannelDummyGrabber.py @@ -0,0 +1,114 @@ +"""MultiChannelDummyGrabber +================ + +This demo shows with the example of the ``MultiChannelDummyGrabber`` +how grabber and cameras are used in ``itom``.""" + +from itom import dataIO +from itom import dataObject +from itom import plot +from itom import liveImage +# sphinx_gallery_thumbnail_path = '11_demos/_static/_thumb/demoDummyGrabber.png' + +############################################################################### +# Start camera (e.g.: ``DummyMultiChannelGrabber``) with a ``noise image`` (default). +camera = dataIO("DummyMultiChannelGrabber") + +############################################################################### +# Start camera (e.g.: ``DummyMultiChannelGrabber``) with moving ``Gaussian spot``. +cameraGaussian = dataIO("DummyMultiChannelGrabber", imageType="gaussianSpot") + +############################################################################### +# Start camera (e.g.: ``DummyMultiChannelGrabber``) with moving ``4 Gaussian spots``. +cameraGaussianArray = dataIO("DummyMultiChannelGrabber", imageType="gaussianSpotArray") + +print("width:", camera.getParam("sizex")) +print("height:", camera.getParam("sizey")) + +############################################################################### +# Set pixel format to ``mono8`` +camera.setParam("pixelFormat", "mono8") + +# print available parameters of that device +print("DummyMultiChannelGrabber has the following parameters:") +camera.getParamList() + +# print detailed information about parameters: +camera.getParamListInfo() + +############################################################################### +# Read parameters from device. +roi = camera.getParam("roi") +############################################################################### +# Start camera. +camera.startDevice() + +############################################################################### +# Acquire single image. +camera.acquire() + +# Create empty dataObject for getting the image +data = dataObject() + +# get a reference to the acquired image +# the reference is then available by the recently created dataObject +camera.getVal(data) + +############################################################################### +# .. warning:: +# +# The method **getVal** returns only a shallow copy of the plugin internal memory. +# Therefore, the content of data will change when the next image is acquired. +# In order to create a deep copy of data, type: +# +# .. code-block:: python +# +# camera.copyVal(data) +# + +# You can also convert the data afterwards to a deep copy by typing: +dataCopy = data.copy() + +# plot the acquired image +plot(data) + +############################################################################### +# Stop camera. +camera.stopDevice() + +############################################################################### +# Start a live image. +liveImage(camera) + +############################################################################### +# +# .. image:: ../../_static/demoMultiChannelDummyGrabber_1.png +# :width: 100% + +liveImage(cameraGaussian) +liveImage(cameraGaussianArray) + +############################################################################### +# Acquire an image stack of 10 measurements. +num = 100 +camera.startDevice() +image = dataObject() +imageStack = dataObject([num, roi[2], roi[3]], "uint8") + +# stop the auto grabbing of the live image +camera.disableAutoGrabbing() + +for idx in range(num): + camera.acquire() + camera.getVal(image) + imageStack[idx, :, :] = image + print(idx) + +camera.stopDevice() +# acquire stack finished + +# plot stack (use arrows in widget to switch between planes) +plot(imageStack) + +# enable the auto grabbing of the live image +camera.enableAutoGrabbing() diff --git a/docs/userDoc/source/07_plugins/development/plugin-dataIO.rst b/docs/userDoc/source/07_plugins/development/plugin-dataIO.rst index 98e0452c3..843b75698 100644 --- a/docs/userDoc/source/07_plugins/development/plugin-dataIO.rst +++ b/docs/userDoc/source/07_plugins/development/plugin-dataIO.rst @@ -23,7 +23,7 @@ Base idea behind any DataIO Grabber plugin ------------------------------ -This is a subtype of DataIO for camera / framegrabber communication. Plugins of this type are inherited from **ito::AddInGrabber**. The data acquisition is managed as follows: +This is a subtype of DataIO for camera / framegrabber communication. Plugins of this type are inherited from **ito::AddInGrabber** or the **ito::AddInMultiChannelGrabber** section. For more information about the **ito::AddInMultiChannelGrabber** interface please read the :ref:`addInMultiChannelGrabber` The data acquisition is managed as follows: * The methods **startDevice** and **stopDevice** open and close the capture logic of the devices to reduce CPU-load. For serial ports these functions are unnecessary. * The method **acquire** starts the DataIO grabbing a frame with the current parameters. The function returns after sending the trigger. The function should be callable several times without calling get-/copyVal(). @@ -37,7 +37,8 @@ A typical sequence in python is .. code-block:: python :linenos: - + + dObj = dataObject() device.startDevice() device.acquire() device.getVal(dObj) @@ -154,7 +155,81 @@ If desired implement the following optional parameters in the map **m_params**: parameter **roi** which expects an array [left, top, width, height]. This parameter can easily be parametrized using the meta information ito::RectMeta and allows the direct configuration of the entire ROI or a single access to one of the four components, by passing the parametername *roi[0]*, *roi[1]*.... +.. _AddInMultiChannelGrabber: + +AddInMultiChannelGrabber +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +This section describes the AddInMultiChannelGrabber-Interface which replaces the previous AddInGrabber-Interface. The interface allows the implementation +of grabbers with multiple channels like hyperspectral imagers or stereo-vision systems. To use the interface a grabber plugin must be derived +from the class **ito::AddInMultiChannelGrabber**. + +By inheriting **ito::AddInMultiChannelGrabber** the plugin inherits a **QMap** called **m_channels**. Each element contained in **m_channels** represents +an individual channel. The **ChannelContainer** is a struct which looks as followed: + +.. code-block:: c++ + :linenos: + + struct ChannelContainer + { + ito::DataObject data; + QMap m_channelParam; + ChannelContainer() {}; + ChannelContainer(ito::Param roi, + ito::Param pixelFormat, + ito::Param sizex, + ito::Param sizey, + ito::Param axisOffset, + ito::Param axisScale) + { + m_channelParam.insert("pixelFormat", pixelFormat); + m_channelParam.insert("roi", roi); + m_channelParam.insert("sizex", sizex); + m_channelParam.insert("sizey", sizey); + m_channelParam.insert("axisOffset", axisOffset); + m_channelParam.insert("axisScale", axisScale); + } + }; +As it can be seen each container has its own **ito::DataObject** called **data** for storing the captured data. Furthermore a **QMap** called **m_channelParam** for the storage +of channel specific parameters is included. By default the parameters **pixelFormat**, **roi**, **sizex**, **sizey**, **axisOffset** and **axisScale** are added to this map. + +Like all plugins **ito::AddInMultiChannelGrabber** inherits from **ito::AddInBase** and therefore also contains a **m_params** member (**QMap**). This map contains all +parameters of all channels and also further global parameters. A mandatory global parameter is the **defaultChannel** which is used to indicate the current selected channel which +will be addressed if **getParam** or **setParam** is called. If a parameter is addressed which is not provided by the current default channel the parameter in the **m_params** map will +be set to read only. + +In the following it is described how to initialize a plugin derived from the **AddInMultiChannelGrabber** interface. The initialization is done by the same functions like with the former **ito::AddInGrabber** interface. +During the initialization the function **AddInMultiChannelGrabber::initializeDefaultConfiguration** must be called. The function takes as a first argument a **QMap** +containing a **ChannelContainer** for each channel of the plugin. The **QString** defines the name of the channel. Channel specific parameters must be added to the to the parameter map of +the corresponding **ChannelContainer**. If a value (or its meta information) of a parameter varies for the individual channels the parameter must be added to each parameter map. Keep in mind that the +**m_channelParam** by default already contains some mandatory parameters, which have to be adapted to the plugin. For convenience a constructor of the **ChannelContainer** is available which takes +the mandatory parameters and adds them to the map. +Non channel specific parameters (parameters affecting all channels) must be passed to **AddInMultiChannelGrabber::initializeDefaultConfiguration** as a second argument. +**AddInMultiChannelGrabber::initializeDefaultConfiguration** iterates through all parameters and adds all of them to **m_params**. Parameters with the same name in multiple channels +are only added ones to the **m_params** list containing the value of the channel selected by the **defaultChannel** parameter which is automatically added to **m_params**. Furthermore the +**AddInMultiChannelGrabber::initializeDefaultConfiguration** adds all channels to the **channelList** parameter of type **ito::ParamBase::StringList**. + +When using the grabber interface, a function called **setParameter** must be implemented. This function gets called by **AddInMultiChannelGrabber::setParam**. **AddInMultiChannelGrabber::setParam** +parses and checks the parameter followed by a call to **setParameter**. If the plugin consumes and updates the corresponding parameter the **bool** parameter **ok** should be set to true. If not +**AddInMultiChannelGrabber** will copy the value to parameter stored in m_param. Regardless if the parameter was processed or not **AddInMultiChannelGrabber::setParam** will synchronize the corresponding +parameter stored in **m_params** with the corresponding parameter stored in the channel parameter map. If a change of a parameter affects the value of other parameters the plugin has the possibility to trigger +an update of the additional changed parameters. For this, add the name of the additional changed parameter to the **QStringList** called **pendingUpdate** passed to the **setParameter** function by an argument. +If an update of a parameter affects a channel specific parameter of channel which is not the current default channel, the plugin can change the value of the parameter directly in the parameter map +of the corresponding channel container. If setParam is called on the mandatory parameter **roi** **sizex** and **sizey** will be updated automatically. A change of the **defaultChannel** must be +followed by a subsequent call of **AddInMultiChannelGrabber::switchDefaultChannel** to synchronize **m_param** with the channel parameter. If the channel switch is triggered by a call to +**AddInMultiChannelGrabber::setParam** **AddInMultiChannelGrabber::switchDefaultChannel** is called automatically. If for any reason the parameters stored in the **ChannelContainer** of the current default channel, +needs to be synchronized with the parameters stored in **m_params** this can be done by calling **AddInMultiChannelGrabber::applyParamsToChannelParams(const QStringList& keyList)**. + +The plugin needs to provide a function **getParameter**. This is called by **AddInMultiChannelGrabber::getParam**. If the boolean parameter **ok** is set to true inside of **getParameter** the value of the requested +parameter needs to be copied to the provided **ito::param** by the plugin. If **ok** stays false, the value copy procedure is carried out by **AddInMultiChannelGrabber**. + +With the AddInMultiChannelGrabber interface new versions of getVal and copyVal are introduced. The functions offer the possibility to copy data captured by multiple channels by +a single function call. The functions expect a **QSharedPointer>** where the **QString** indicates the requested channels. The functions **getVal** and **copyVal** +with a single pointer to an **ito::DataObject** remains. + +**AddInMultichannelGrabber** introduces a new signal called **newData**. If this signal is emitted with a **QSharedPointer >** containing a map of new data. The **QString** should +contain the name of the channel which recorded the data stored in the **ito::DataObject**. The signal can used to trigger a python function. The signature of the Signal is **newData(QSharedPointer>)**. AD-Converters ------------------------------------- diff --git a/docs/userDoc/source/11_demos/_static/_thumb/demoGaussianDummyGrabber.png b/docs/userDoc/source/11_demos/_static/_thumb/demoGaussianDummyGrabber.png new file mode 100644 index 000000000..b57cb8756 Binary files /dev/null and b/docs/userDoc/source/11_demos/_static/_thumb/demoGaussianDummyGrabber.png differ diff --git a/docs/userDoc/source/11_demos/_static/demoDummyGrabber_1.png b/docs/userDoc/source/11_demos/_static/demoDummyGrabber_1.png index e675c03b4..2a9d51c85 100644 Binary files a/docs/userDoc/source/11_demos/_static/demoDummyGrabber_1.png and b/docs/userDoc/source/11_demos/_static/demoDummyGrabber_1.png differ diff --git a/docs/userDoc/source/11_demos/_static/demoDummyGrabber_2.png b/docs/userDoc/source/11_demos/_static/demoDummyGrabber_2.png deleted file mode 100644 index 1982ffedf..000000000 Binary files a/docs/userDoc/source/11_demos/_static/demoDummyGrabber_2.png and /dev/null differ diff --git a/docs/userDoc/source/11_demos/_static/demoDummyGrabber_3.png b/docs/userDoc/source/11_demos/_static/demoDummyGrabber_3.png deleted file mode 100644 index ff28798b2..000000000 Binary files a/docs/userDoc/source/11_demos/_static/demoDummyGrabber_3.png and /dev/null differ diff --git a/docs/userDoc/source/11_demos/_static/demoGaussianDummyGrabber_1.png b/docs/userDoc/source/11_demos/_static/demoGaussianDummyGrabber_1.png new file mode 100644 index 000000000..88ae3c5dc Binary files /dev/null and b/docs/userDoc/source/11_demos/_static/demoGaussianDummyGrabber_1.png differ diff --git a/docs/userDoc/source/11_demos/_static/demoGaussianDummyGrabber_2.png b/docs/userDoc/source/11_demos/_static/demoGaussianDummyGrabber_2.png new file mode 100644 index 000000000..ed01320fb Binary files /dev/null and b/docs/userDoc/source/11_demos/_static/demoGaussianDummyGrabber_2.png differ diff --git a/docs/userDoc/source/11_demos/_static/demoMultiChannelDummyGrabber_1.png b/docs/userDoc/source/11_demos/_static/demoMultiChannelDummyGrabber_1.png new file mode 100644 index 000000000..b15ed38be Binary files /dev/null and b/docs/userDoc/source/11_demos/_static/demoMultiChannelDummyGrabber_1.png differ diff --git a/itomWidgets/plotInfoDObject.cpp b/itomWidgets/plotInfoDObject.cpp index dcb8bf487..6a826a1d1 100644 --- a/itomWidgets/plotInfoDObject.cpp +++ b/itomWidgets/plotInfoDObject.cpp @@ -37,10 +37,11 @@ PlotInfoDObject::PlotInfoDObject(QWidget* parent /*= NULL*/) : QPlainTextEdit(pa //--------------------------------------------------------------------------------------------------------- void PlotInfoDObject::updateInfoHeader(const QString newString) { - m_infoHeader = newString; - QString baseText = m_infoHeader; - baseText.append(m_infoDetail); - setPlainText(baseText); + if (newString != m_infoHeader) + { + m_infoHeader = newString; + setPlainText(m_infoHeader + m_infoDetail); + } } //--------------------------------------------------------------------------------------------------------- void PlotInfoDObject::updateInfoHeader(const QString typeString, const int dType, const int dims, const int sizes[]) @@ -107,15 +108,17 @@ void PlotInfoDObject::updateInfoHeader(const QString typeString, const int dType //--------------------------------------------------------------------------------------------------------- void PlotInfoDObject::updateInfoDetail(const QString newString) { - m_infoDetail = newString; - QString baseText = m_infoHeader; - baseText.append(m_infoDetail); - setPlainText(baseText); + if (newString != m_infoDetail) + { + m_infoDetail = newString; + setPlainText(m_infoHeader + m_infoDetail); + } } //--------------------------------------------------------------------------------------------------------- void PlotInfoDObject::updateInfoDetail(const double minVal, const double maxVal, const double meanVal, const double devVal) { QString baseText = ""; + if (m_valid) { baseText.append(QString("Maximum: %1\n").arg(QString::number(maxVal))); @@ -123,6 +126,7 @@ void PlotInfoDObject::updateInfoDetail(const double minVal, const double maxVal, baseText.append(QString("Mean Value: %1\n").arg(QString::number(meanVal))); baseText.append(QString("Dev Value: %1\n").arg(QString::number(devVal))); } + updateInfoDetail(baseText); } //--------------------------------------------------------------------------------------------------------- @@ -138,10 +142,12 @@ void PlotInfoDObject::clearObjectInfo() void PlotInfoDObject::setUseDetailInfo(const bool state) { m_addDetailInfo = state; + if (!state) { updateInfoDetail(""); } + return; } //--------------------------------------------------------------------------------------------------------- @@ -153,4 +159,3 @@ QPainterPath PlotInfoDObject::renderToPainterPath(const int xsize, const int ysi return destinationPath; } -//--------------------------------------------------------------------------------------------------------- diff --git a/plot/AbstractDObjFigure.h b/plot/AbstractDObjFigure.h index 2535f862d..37d868d60 100644 --- a/plot/AbstractDObjFigure.h +++ b/plot/AbstractDObjFigure.h @@ -1,7 +1,7 @@ /* ******************************************************************** itom software URL: http://www.uni-stuttgart.de/ito - Copyright (C) 2020, Institut fuer Technische Optik (ITO), + Copyright (C) 2023, Institut fuer Technische Optik (ITO), Universitaet Stuttgart, Germany This file is part of itom and its software development toolkit (SDK). @@ -25,8 +25,7 @@ along with itom. If not, see . *********************************************************************** */ -#ifndef ABSTRACTDOBJFIGURE_H -#define ABSTRACTDOBJFIGURE_H +#pragma once #include "AbstractFigure.h" #include "../DataObject/dataobj.h" @@ -54,6 +53,10 @@ class ITOMCOMMONPLOT_EXPORT AbstractDObjFigure : public AbstractFigure Q_PROPERTY(ito::AutoInterval yAxisInterval READ getYAxisInterval WRITE setYAxisInterval DESIGNABLE true USER true) Q_PROPERTY(ito::AutoInterval zAxisInterval READ getZAxisInterval WRITE setZAxisInterval DESIGNABLE true USER true) Q_PROPERTY(QString colorMap READ getColorMap WRITE setColorMap DESIGNABLE true USER true) + Q_PROPERTY(QString cameraChannel READ getDisplayedCameraChannel WRITE setDisplayedCameraChannel DESIGNABLE false USER true); + + // the property valueAxis is requested as dynamic property by AddInMultiChannelGrabber::changeChannelForListener. Do not change the name! + Q_PROPERTY(Qt::Axis valueAxis READ getValueAxis DESIGNABLE false USER false); Q_CLASSINFO("prop://source", "Sets the input data object for this plot.") Q_CLASSINFO("prop://displayed", "This returns the currently displayed data object [read only].") @@ -62,10 +65,13 @@ class ITOMCOMMONPLOT_EXPORT AbstractDObjFigure : public AbstractFigure Q_CLASSINFO("prop://yAxisInterval", "Sets the visible range of the displayed y-axis (in coordinates of the data object). Set it to 'auto' if range should be automatically set [default].") Q_CLASSINFO("prop://zAxisInterval", "Sets the visible range of the displayed z-axis (in coordinates of the data object). Set it to 'auto' if range should be automatically set [default].") Q_CLASSINFO("prop://colorMap", "Color map (string) that should be used to colorize a non-color data object.") + Q_CLASSINFO("prop://cameraChannel", "If a multi channel device (MultiChannelGrabber) is connected to this plot, the currently displayed channel of the device can be set. To obtain a list of the available channels see the parameter channelList of the device") + Q_CLASSINFO("prop://valueaxis", "Returns the axis that is used in this plot for displaying the values. Usually this is the z-axis for a 2D plot and the y-axis for a 1D plot.") Q_CLASSINFO("slot://setSource", "This slot can be implemented by any plot plugin to send a dataObject to the plot. Here it is not required and therefore not implemented.") Q_CLASSINFO("slot://setLinePlot", "This slot can be implemented by any plot plugin to force the plot to open a line plot. Here it is not required and therefore not implemented.") - +private: + QString m_currentDisplayedCameraChannel; public: AbstractDObjFigure(const QString &itomSettingsFile, AbstractFigure::WindowMode windowMode = AbstractFigure::ModeStandaloneInUi, QWidget *parent = 0); @@ -97,16 +103,19 @@ class ITOMCOMMONPLOT_EXPORT AbstractDObjFigure : public AbstractFigure virtual QString getColorMap(void) const; virtual void setColorMap(QString); + virtual Qt::Axis getValueAxis() const; + //! plot-specific render function to enable more complex printing in subfigures ... virtual QPixmap renderToPixMap(const int xsize, const int ysize, const int resolution); + //!< returns the currently displayed channel of the connected grabber + QString getDisplayedCameraChannel() const; + protected: QHash > m_dataPointer; bool m_cameraConnected; - RetVal removeLiveSource(); - -signals: + virtual RetVal removeLiveSource(); public slots: //this source is invoked by any connected camera @@ -114,10 +123,13 @@ public slots: //this can be invoked by python to trigger a lineplot virtual ito::RetVal setLinePlot(const double x0, const double y0, const double x1, const double y1, const int destID = -1); + + virtual ito::RetVal setDisplayedCameraChannel(const QString& channel); + +signals: + void cameraChannelChanged(QObject* listener, const QString& channel); }; } // namespace ito #endif //#if !defined(Q_MOC_RUN) || defined(ITOMCOMMONQT_MOC) - -#endif //ABSTRACTDOBJFIGURE_H diff --git a/plot/CMakeLists.txt b/plot/CMakeLists.txt index 4c7642c48..5b803f6a3 100644 --- a/plot/CMakeLists.txt +++ b/plot/CMakeLists.txt @@ -1,6 +1,6 @@ # - itom software # URL: http://www.uni-stuttgart.de/ito -# Copyright (C) 2020, Institut fuer Technische Optik (ITO), +# Copyright (C) 2023, Institut fuer Technische Optik (ITO), # Universitaet Stuttgart, Germany # # This file is part of itom and its software development toolkit (SDK). diff --git a/plot/sources/AbstractDObjFigure.cpp b/plot/sources/AbstractDObjFigure.cpp index 5c5531c77..13e147bbf 100644 --- a/plot/sources/AbstractDObjFigure.cpp +++ b/plot/sources/AbstractDObjFigure.cpp @@ -1,7 +1,7 @@ /* ******************************************************************** itom software URL: http://www.uni-stuttgart.de/ito - Copyright (C) 2020, Institut fuer Technische Optik (ITO), + Copyright (C) 2023, Institut fuer Technische Optik (ITO), Universitaet Stuttgart, Germany This file is part of itom and its software development toolkit (SDK). @@ -37,7 +37,8 @@ namespace ito //---------------------------------------------------------------------------------------------------------------------------------- AbstractDObjFigure::AbstractDObjFigure(const QString &itomSettingsFile, AbstractFigure::WindowMode windowMode /*= AbstractFigure::ModeStandaloneInUi*/, QWidget *parent /*= 0*/) : AbstractFigure(itomSettingsFile, windowMode, parent), - m_cameraConnected(false) + m_cameraConnected(false), + m_currentDisplayedCameraChannel("") { addInputParam(new ito::Param("source", ito::ParamBase::DObjPtr, NULL, QObject::tr("Source data for plot").toLatin1().data())); addInputParam(new ito::Param("liveSource", ito::ParamBase::HWRef, NULL, QObject::tr("Live data source for plot").toLatin1().data())); @@ -107,6 +108,14 @@ QSharedPointer AbstractDObjFigure::getSource(void) const } return QSharedPointer(); } + +//------------------------------------------------------------------------------------- +Qt::Axis AbstractDObjFigure::getValueAxis() const +{ + // default, only the 1D plot will overwrite this to correct it + return Qt::ZAxis; +} + //---------------------------------------------------------------------------------------------------------------------------------- ito::RetVal AbstractDObjFigure::setAxisData(QSharedPointer data, Qt::Axis axis) { @@ -299,15 +308,18 @@ void AbstractDObjFigure::setSource(QSharedPointer source, ItomS { QSharedPointer oldSource = m_dataPointer["source"]; m_dataPointer["source"] = source; + ito::ParamBase thisParam("source", ito::ParamBase::DObjPtr, (const char*)source.data()); + retval += inputParamChanged(&thisParam); } } else { m_dataPointer["source"] = source; + ito::ParamBase thisParam("source", ito::ParamBase::DObjPtr, (const char*)source.data()); + retval += inputParamChanged(&thisParam); } - ito::ParamBase thisParam("source", ito::ParamBase::DObjPtr, (const char*)source.data()); - retval += inputParamChanged(&thisParam); + } if (waitCond) @@ -320,7 +332,7 @@ void AbstractDObjFigure::setSource(QSharedPointer source, ItomS } //---------------------------------------------------------------------------------------------------------------------------------- -RetVal AbstractDObjFigure::removeLiveSource() +/*virtual*/ RetVal AbstractDObjFigure::removeLiveSource() { RetVal retval; ito::Param *liveSource = getInputParam("liveSource"); @@ -402,4 +414,71 @@ QPixmap AbstractDObjFigure::renderToPixMap(const int xsize, const int ysize, con return emptyMap; } +//------------------------------------------------------------------------------------- +ito::RetVal AbstractDObjFigure::setDisplayedCameraChannel(const QString& channel) +{ + ito::RetVal retValue(ito::retOk); + QPointer liveSource = getCamera(); + + if (liveSource) + { + bool isMultiChannel = false; + isMultiChannel = liveSource->inherits("ito::AddInMultiChannelGrabber"); + + if (isMultiChannel) + { + ItomSharedSemaphoreLocker locker(new ItomSharedSemaphore()); + QSharedPointer channelListParam(new ito::Param("availableChannels", ito::ParamBase::StringList)); + + if (QMetaObject::invokeMethod(liveSource, "getParam", Q_ARG(QSharedPointer, channelListParam), Q_ARG(ItomSharedSemaphore*, locker.getSemaphore()))) + { + bool timeout = false; + + while (!locker.getSemaphore()->wait(500)) + { + retValue += ito::RetVal(ito::retError, 0, tr("timeout while getting channelList parameter").toLatin1().data()); + break; + } + + if (!retValue.containsError()) + { + int len = 0; + const ito::ByteArray* channelList = channelListParam->getVal(len); + bool found = false; + + for (int i = 0; i < len; i++) + { + if (QString::fromLatin1(channelList[i].data()).compare(channel) == 0) + { + found = true; + m_currentDisplayedCameraChannel = channel; + emit cameraChannelChanged(this, channel); + break; + } + } + + if (!found) + { + retValue += ito::RetVal(ito::retError, 0, tr("the connected camera does not provide the channel '%1'.").arg(channel).toLatin1().data()); + } + } + } + } + else + { + retValue +=ito::RetVal(ito::retWarning, 0, tr("could not set a camera channel, since the connected camera is not of type \"AddInMultiChannelGrabber\".").toLatin1().data()); + m_currentDisplayedCameraChannel = ""; + } + + + } + + return retValue; +} +//------------------------------------------------------------------------------------- +QString AbstractDObjFigure::getDisplayedCameraChannel() const +{ + return m_currentDisplayedCameraChannel; +} + } //end namespace ito diff --git a/pluginTemplates/actuator/myActuator.cpp b/pluginTemplates/actuator/myActuator.cpp index c4a9ef051..45722ffa4 100644 --- a/pluginTemplates/actuator/myActuator.cpp +++ b/pluginTemplates/actuator/myActuator.cpp @@ -690,7 +690,6 @@ ito::RetVal MyActuator::waitForDone(const int timeoutMS, const QVector axis else if (1 /*axis i is at target*/) { setStatus(m_currentStatus[i], ito::actuatorAtTarget, ito::actSwitchesMask | ito::actStatusMask); - done = false; //not done yet } } diff --git a/python_unittests/multichannel_test.py b/python_unittests/multichannel_test.py new file mode 100644 index 000000000..b90791e61 --- /dev/null +++ b/python_unittests/multichannel_test.py @@ -0,0 +1,95 @@ +import unittest +from itom import dataIO, dataObject + +def channelSpecificFunc1(): + cam = dataIO("DummyMultiChannelGrabber") + cam.setParam('defaultChannel','channel_1') + cam.setParam('channelSpecificParameter',200) + +def test_invalidDefaultChannelErrorFunc(): + cam = dataIO("DummyMultiChannelGrabber") + cam.setParam('defaultChannel', 'xyz') + +class MultiChannelDummyGrabberTest(unittest.TestCase): + @classmethod + def setUpClass(cls): + pass + + def channelSpecificFunc1(): + cam = dataIO("DummyMultiChannelGrabber") + cam.setParam('defaultChannel','Channel_1') + cam.setParam('channelSpecificParameter',200) + + def test_setAndGetParamViaDefaultChannel(self): + cam = dataIO("DummyMultiChannelGrabber") + cam.setParam('defaultChannel', 'channel_0') + originalRoi = cam.getParam('roi') + cam.setParam('defaultChannel', 'channel_1') + cam.setParam('roi', [0,0,40,40]) + cam.setParam('defaultChannel', 'channel_0') + channel0Roi = cam.getParam('roi') + cam.setParam('defaultChannel', 'channel_1') + channel1Roi = cam.getParam('roi') + + self.assertEqual(originalRoi, channel0Roi) + self.assertNotEqual(originalRoi, channel1Roi) + + def test_invalidDefaultChannelErrorTest(self): + self.assertRaises(RuntimeError, test_invalidDefaultChannelErrorFunc) + + def test_invalidDefaultChannelTest(self): + cam = dataIO("DummyMultiChannelGrabber") + paramList = cam.getParamList() + originalParamDict = {} + for elem in paramList: + originalParamDict[elem] = cam.getParam(elem) + try: + cam.setParam('defaultChannel', 'xyz') + except RuntimeError: + pass + testParamDict = {} + for elem in paramList: + testParamDict[elem] = cam.getParam(elem) + self.assertEqual(originalParamDict, testParamDict) + + + def test_getValByDict(self): + cam=dataIO("DummyMultiChannelGrabber") + cam.startDevice() + cam.acquire() + channelList=cam.getParam('channelList') + roi={} + getValDict={} + for elem in channelList: + cam.setParam("defaultChannel", elem) + roi[elem] = cam.getParam('roi') + getValDict[elem]=dataObject() + cam.getVal(getValDict) + for key in roi: + self.assertEqual(roi[key][-2], getValDict[key].shape[-1]) + self.assertEqual(roi[key][-1], getValDict[key].shape[-2]) + + def test_copyValByDict(self): + cam=dataIO("DummyMultiChannelGrabber") + cam.startDevice() + cam.acquire() + channelList=cam.getParam('channelList') + roi={} + getValDict={} + for elem in channelList: + cam.setParam('defaultChannel',elem) + roi[elem] = cam.getParam('roi') + getValDict[elem]=dataObject() + cam.copyVal(getValDict) + for key in roi: + self.assertEqual(roi[key][-2], getValDict[key].shape[-1]) + self.assertEqual(roi[key][-1], getValDict[key].shape[-2]) + + + def test_channelSpecific(self): + self.assertRaises(RuntimeError, channelSpecificFunc1) + + + + if __name__ == '__main__': + unittest.main(module='multichannel_test', exit=False) diff --git a/python_unittests/run_suite.py b/python_unittests/run_suite.py index 4aee30718..e5f557f7b 100644 --- a/python_unittests/run_suite.py +++ b/python_unittests/run_suite.py @@ -19,7 +19,7 @@ import idc_test import plot_test import shape_test - +import multichannel_test if pyversion >= (3, 6): import itom_stubs_generator import itom_algorithm_stubs_generator @@ -43,6 +43,7 @@ def suite(): suite.addTest(unittest.makeSuite(datatype_conversion_test.DatatypeConversionTest)) suite.addTest(unittest.makeSuite(pointcloud_pickle.PointCloudPickle)) suite.addTest(unittest.makeSuite(idc_test.IdcTest)) + suite.addTest(unittest.makeSuite(multichannel_test.MultiChannelDummyGrabberTest)) if pyversion >= (3, 6): suite.addTest(unittest.makeSuite(itom_stubs_generator.ItomStubsGenTest))