diff --git a/src/application/xqchildmodel.cpp b/src/application/xqchildmodel.cpp index eae879f..9c351e4 100644 --- a/src/application/xqchildmodel.cpp +++ b/src/application/xqchildmodel.cpp @@ -35,23 +35,57 @@ XQChildModel::XQChildModel( QObject *parent ) void XQChildModel::initModel(const QString& modelName) { + + auto extendItemType = [=](const XQNodePtr& entry) + { + const QString& typeName = entry->attribute("ItemType"); + XQItemType* itemType = _itemFactory.findItemTypeTemplate( typeName); // throws + // über alle attribute + for (const auto& attr : entry->attributes()) + { + // prüfen, ob der itemType des attribute schon hat + int role = itemType->hasAttribute( attr.first); + // wenn ja, überschreiben + if( role != XQItem::NoRole ) + { + QVariant newValue = _itemFactory.makeVariant(role,attr.second); + itemType->replaceAttribute( newValue, role ); + } + + } + + }; + // #0: Wir suchen die Model-Beschreibung XQNodePtr modelSheet = _itemFactory.findModelSheet( modelName ); // throws - // #1: Wie erzeugen die Model-Struktur: Jedes Kind beschreibt einen + // #1: Wir erzeugen die Model-Struktur: Jedes Kind beschreibt einen // XML-Datentyp, z.B. , // Jeder XML-Knoten entspricht einer Zeile im späteren Model, jedes // Attribut wird einem eigenen Feld (XQItem) abgebildet. - for( auto& sheetNode : modelSheet->children() ) + for( const auto& sheetNode : modelSheet->children() ) { + + XQItemList list = _itemFactory.makeHeaderRow( sheetNode ); // für jeden XML-Knotentyp in der Modelbeschreibung erzeugen wir eine section addSection(list, sheetNode ); + // jedes kind kann enthält einen itemType und einen headerItemType. Für + // diese sind eventuell weitere attribute vorhanden, die die im type + // enthaltenen defualt-werte überschreiben. + + for( const auto& sheetChild : sheetNode->children() ) + { + //qDebug() << "---- kloppo: " << sheetChild->tag_name() << ": " << sheetChild->to_string(); + extendItemType( sheetChild ); + } + + /* - // empty row + // empty row: XQNodePtr contentNode = XQNode::make_node( sheetNode->tag_name() ); XQItemList emptyRow = _itemFactory.makeEmptyRow( contentNode, sheetNode ); appendRow( emptyRow ); diff --git a/src/items/xqitem.cpp b/src/items/xqitem.cpp index aae05b6..702bef8 100644 --- a/src/items/xqitem.cpp +++ b/src/items/xqitem.cpp @@ -451,6 +451,7 @@ QVariant XQItem::data(int role ) const case IconRole: // aka Qt::DecorationRole, case RenderStyleRole: case EditorTypeRole: + case UnitTypeRole: case ContentFormatRole: case FixedChoicesRole: { @@ -504,12 +505,11 @@ QVariant XQItem::data(int role ) const return firstItem.data( XQItem::ContentNodeRole ); } - case UnitTypeRole: - case Qt::StatusTipRole: case Qt::WhatsThisRole: case Qt::SizeHintRole: + case Qt::FontRole: case Qt::TextAlignmentRole: case Qt::BackgroundRole: @@ -554,13 +554,18 @@ void XQItem::setData(const QVariant& value, int role ) case RenderStyleRole : case EditorTypeRole : + case UnitTypeRole: case ContentFormatRole: case FlagsRole: // Stimmt das? case IconRole: case FixedChoicesRole: { //qDebug() << " ---call type set Data: " << role << ": " << XQItem::fetchItemDataRoleName(role) << ":" << value.toString(); - itemType().replaceAttribute( this, value, role ); + XQItemType* oldType = &itemType(); + XQItemType* newType = oldType->replaceAttribute(value, role ); + if( oldType != newType ) + setItemType( newType ); + emitDataChanged(); // no break, return! return; @@ -593,8 +598,6 @@ void XQItem::setData(const QVariant& value, int role ) } // alles andere wie gehabt - case UnitTypeRole: - case ContentNodeRole: case SheetNodeRole: diff --git a/src/items/xqitem.h b/src/items/xqitem.h index dafc095..38fa77d 100644 --- a/src/items/xqitem.h +++ b/src/items/xqitem.h @@ -159,8 +159,8 @@ public: // shortcuts für die itemFlags // __fix! das können die selber !? - void addFlag( Qt::ItemFlag newFlag ); - void clearFlag( Qt::ItemFlag newFlag ); + void addFlag( Qt::ItemFlag newFlag ); + void clearFlag( Qt::ItemFlag newFlag ); //das ist ein Sonderfall: Ein ist ein dereferenzierter Zeiger auf 'unser' Atrribut in // XQNodePtr, also unserem contentNode(). Das wird hier direkt aufgelöst und nicht auf @@ -192,7 +192,7 @@ public: void setContentFormat(const QString& contentFormat); QStandardItemModel* fixedChoices() const; - QString fixedChoicesToString() const; + QString fixedChoicesToString() const; //! setzt das auswahl-model für read-only comboboxes void setfixedChoices( QStandardItemModel* newModel ); @@ -201,7 +201,7 @@ public: //shortCuts // - bool isHeaderStyle(); + bool isHeaderStyle(); QString dataRoleName(int role) const; QVariant data(int role = Qt::DisplayRole ) const override; diff --git a/src/items/xqitemfactory.cpp b/src/items/xqitemfactory.cpp index d4529e7..a11b191 100644 --- a/src/items/xqitemfactory.cpp +++ b/src/items/xqitemfactory.cpp @@ -28,7 +28,7 @@ void XQItemFactory::initItemFactory( const QString& modelSheetFileName ) // über alle attribute for( const auto& [key,value] : sheetNode->attributes() ) { - qDebug() << " --- conf: " << key << " : " << value; + qDebug() << " --- conf item Type: " << key << " : " << value; setItemDataFromString( *itemType, key, value ); } }; @@ -45,7 +45,7 @@ void XQItemFactory::initItemFactory( const QString& modelSheetFileName ) _typesSheet = _modelSheet->find_child_by_tag_name( "ItemTypes" ); // ... und testen if( !_typesSheet ) - throw XQException( "initItemFactory typeSheetRoot is null" ); + throw XQException( "initItemFactory is null" ); // alle itemtype vorlagen erzeugen for( const XQNodePtr& typeSheetNode : _typesSheet->children()) @@ -56,8 +56,9 @@ void XQItemFactory::initItemFactory( const QString& modelSheetFileName ) configureItemType(itemType, typeSheetNode); itemType->setText( typeName); - s_ItemTypeCache[typeName] = itemType; + s_ItemTypeTemplates[typeName] = itemType; } + } @@ -67,11 +68,32 @@ bool XQItemFactory::isValid() } -XQItemType* XQItemFactory::findItemType(const QString& key ) const +//! es reicht nicht, einen itemType aus den itemType-templates zu +//! holen: möglicherweise muss der noch mit zusätzlichen attributen +//! ergänzt werden, (hier 'UnitType' ). Al +//! +//! \param sheetEntry +//! \return +//! + +XQItemType* XQItemFactory::makeItemType(const XQNodePtr& sheetEntry ) { - if( !key.isEmpty() && s_ItemTypeCache.contains(key)) - return s_ItemTypeCache[key]; - throw XQException( "itemfactory: findItemType: not found:", key ); + QString typeKey = sheetEntry->attribute("ItemType"); + XQItemType* itemType = findItemTypeTemplate(typeKey); + + // wir prüfen, ob im sheetEntry noch zusätzliche attribute vorhanden + // sind, die wir in dem itemType müssen + + + + return itemType; +} + +XQItemType* XQItemFactory::findItemTypeTemplate(const QString& key ) const +{ + if( !key.isEmpty() && s_ItemTypeTemplates.contains(key)) + return s_ItemTypeTemplates[key]; + throw XQException( "itemfactory: findItemTypeTemplate: not found:", key ); } @@ -85,11 +107,13 @@ XQNodePtr XQItemFactory::findModelSheet( const QString& modelName ) const } -XQItem* XQItemFactory::makeContentItem( const XQNodePtr& contentNode, const XQNodePtr& sheetEntry ) const +XQItem* XQItemFactory::makeContentItem( const XQNodePtr& contentNode, const XQNodePtr& sheetEntry ) { // den itemtype des neuen items rausfinden QString typeKey = sheetEntry->attribute("ItemType"); - XQItemType* itemType = findItemType(typeKey); // throws + //XQItemType* itemType = findItemTypeTemplate(typeKey); // throws + XQItemType* itemType = makeItemType(sheetEntry); // throws + const QString* contentPtr = contentNode->attribute_ptr( sheetEntry->tag_name() ); XQItem* newItem = new XQItem( itemType, contentPtr ); @@ -98,7 +122,7 @@ XQItem* XQItemFactory::makeContentItem( const XQNodePtr& contentNode, const XQNo } -XQItem* XQItemFactory::makeHeaderItem( const XQNodePtr& sheetEntry ) const +XQItem* XQItemFactory::makeHeaderItem( const XQNodePtr& sheetEntry ) { // header items are all non-data items: // - section header row items @@ -108,7 +132,7 @@ XQItem* XQItemFactory::makeHeaderItem( const XQNodePtr& sheetEntry ) const // den itemtype des neuen items rausfinden QString typeKey = sheetEntry->attribute("HeaderItemType"); - XQItemType* itemType = findItemType(typeKey); // throws + XQItemType* itemType = findItemTypeTemplate(typeKey); // throws // das ist Unterschied zum normalen Item: Der Titel kommt aus der Modelbeschreibung const QString* contentPtr = sheetEntry->attribute_ptr("HeaderCaption"); @@ -148,7 +172,7 @@ QVariant XQItemFactory::makeVariant( int dataRole, const QString& source ) const case XQItem::ItemTypeRole: { // itemType() -> XQItemType* - XQItemType* itemType = findItemType( source ); + XQItemType* itemType = findItemTypeTemplate( source ); value = QVariant::fromValue(itemType); break; } diff --git a/src/items/xqitemfactory.h b/src/items/xqitemfactory.h index f76dfdf..8934e70 100644 --- a/src/items/xqitemfactory.h +++ b/src/items/xqitemfactory.h @@ -32,9 +32,8 @@ public: XQNodePtr findModelSheet( const QString& modelName ) const; - - XQItem* makeHeaderItem(const XQNodePtr& typeSheetNode ) const; - XQItem* makeContentItem( const XQNodePtr& contentNode, const XQNodePtr& sheetEntry ) const; + XQItem* makeHeaderItem(const XQNodePtr& typeSheetNode ); + XQItem* makeContentItem( const XQNodePtr& contentNode, const XQNodePtr& sheetEntry ); virtual XQItemList makeHeaderRow( const XQNodePtr& sheetNode ); virtual XQItemList makeContentRow( const XQNodePtr& contentNode, const XQNodePtr& sheetNode ); @@ -44,8 +43,8 @@ public: void setItemDataFromString( XQItem& item, const QString& roleKey, const QString& source ) const; - // __fix! unsinn! - XQItemType* findItemType(const QString& key ) const; + XQItemType* makeItemType(const XQNodePtr& sheetEntry ); + XQItemType* findItemTypeTemplate(const QString& key ) const; QVariant makeVariant(int dataRole, const QString &value ) const; protected: @@ -56,7 +55,7 @@ protected: using ItemConfigFunc = std::function; using ItemConfigMap = QMap; - XQItemTypeMap s_ItemTypeCache; + XQItemTypeMap s_ItemTypeTemplates; // Beschreibung des XQModels XQNodePtr _modelSheet{}; diff --git a/src/items/xqitemtype.cpp b/src/items/xqitemtype.cpp index 7231769..f02098d 100644 --- a/src/items/xqitemtype.cpp +++ b/src/items/xqitemtype.cpp @@ -69,38 +69,60 @@ void XQItemType::setData(const QVariant& value, int role ) return QStandardItem::setData(value,role); } +//! tested, ob ein attribute (z.B. unitType) hier vorhanden ist +int XQItemType::hasAttribute( const QString& attrKey ) +{ + int role = XQItem::fetchItemDataRole(attrKey); + // gibbed überhaupt eine rolle für unser attribut? + if( role == XQItem::NoRole) + return XQItem::NoRole; + + // wenn ja, ist die role hier besetzt? + QVariant value = data(role); + if( !value.isValid() || value.isNull() ) + return XQItem::NoRole; + + return role; +} + //! setzt einen attributwert neu. Ggf. wird ein neuer ItemType erzeugt. -void XQItemType::replaceAttribute( XQItem* item, const QVariant& newValue, int role ) +XQItemType* XQItemType::replaceAttribute( const QVariant& newValue, int role ) { + // hat sich überhaupt was geändert? QVariant oldValue = data(role); - // ja, es hat - if( oldValue != newValue ) - { - XQItemType* myClone = new XQItemType(*this); - // Änderungen übernehmen - myClone->setData( newValue, role ); - // Gibt es den geänderten ItemType schon? - QString newKey = myClone->makeItemTypeKey(); - // jawoll - if( s_ItemTypeMap.contains( newKey ) ) - { - // nur abräumen, sonst nix - delete myClone; - } - else - { - // speichern - s_ItemTypeMap.insert( newKey, myClone ); - // und ins item übernehmen - item->setItemType( myClone ); - /// Obacht! Der alte, geänderte itemType bleibt erhalten - /// und verrottet ggf. ohne Daseinszweck - } + // nein, es hat nicht + if( oldValue == newValue ) + return this; + + // kopie von mir + XQItemType* myClone = new XQItemType(*this); + // Änderungen übernehmen + myClone->setData( newValue, role ); + // Gibt es den geänderten ItemType schon? + QString newKey = myClone->makeItemTypeKey(); + // jawoll + if( s_ItemTypeMap.contains( newKey ) ) + { + // abräumen ... + delete myClone; + // und die alte version zurückgegen + return s_ItemTypeMap[newKey]; } + + // speichern + s_ItemTypeMap.insert( newKey, myClone ); + // und ins item übernehmen + //item.setItemType( myClone ); + + /// Obacht! Der alte, geänderte itemType bleibt erhalten + /// und verrottet ggf. ohne Daseinszweck + + return myClone; + } QVariant XQItemType::formatText( const XQItem& item ) const diff --git a/src/items/xqitemtype.h b/src/items/xqitemtype.h index ba37502..af4559a 100644 --- a/src/items/xqitemtype.h +++ b/src/items/xqitemtype.h @@ -42,12 +42,13 @@ public: virtual QVariant formatText( const XQItem& item ) const; - QString formatToSI(const QString& rawText, XQItem::UnitType unitType ) const; - QString unFormatFromSI(const QString& valueText ) const; + QString formatToSI(const QString& rawText, XQItem::UnitType unitType ) const; + QString unFormatFromSI(const QString& valueText ) const; - void replaceAttribute( XQItem* item, const QVariant& newValue, int role ); + int hasAttribute( const QString& attrKey ); + XQItemType* replaceAttribute(const QVariant& newValue, int role ); - QString makeItemTypeKey(); + QString makeItemTypeKey(); static XQItemType* staticItemType(); diff --git a/src/model/xqviewmodel.cpp b/src/model/xqviewmodel.cpp index 9220aae..a1808eb 100644 --- a/src/model/xqviewmodel.cpp +++ b/src/model/xqviewmodel.cpp @@ -430,14 +430,14 @@ void XQViewModel::cmdToggleSection( const QModelIndex& index ) } -//! firz +//! git die treetable zurück XQTreeTable* XQViewModel::treeTable() { return _treeTable; } -//! firz +//! setzt die treetable als member. void XQViewModel::setTreeTable(XQTreeTable* mainView ) { diff --git a/src/nodes/znode_payload.h b/src/nodes/znode_payload.h index 3b5fd96..2cbd940 100644 --- a/src/nodes/znode_payload.h +++ b/src/nodes/znode_payload.h @@ -232,13 +232,13 @@ namespace znode if( !_attributes.empty() ) { result += " ["; - bool first = true; + bool beg = true; for (const auto& entry : _attributes) { - if(first) + if(beg) { result += entry.first + "=" + entry.second; - first = false; + beg = false; continue; } result += ", " + entry.first + "=" + entry.second; diff --git a/xml/modelsheets.xml b/xml/modelsheets.xml index 73a0d0d..6ecea64 100644 --- a/xml/modelsheets.xml +++ b/xml/modelsheets.xml @@ -11,7 +11,7 @@ - +