From a13a1de8febf8974c7eb55ac2053bbeae25f30bc Mon Sep 17 00:00:00 2001 From: "PANIK\\chris" Date: Sat, 16 Aug 2025 22:03:41 +0200 Subject: [PATCH] reworked section handling (a bit) --- src/application/xqchildmodel.cpp | 6 ++- src/application/xqmainmodel.cpp | 39 +++++++++++++++++++ src/application/xqmainmodel.h | 2 +- src/application/xqmainwindow.cpp | 43 +++++++++----------- src/application/xqmainwindow.h | 5 ++- src/model/xqmodelsectionlist.cpp | 67 +++++++++++++++++++++++++++----- src/model/xqmodelsectionlist.h | 24 +++++++++--- src/model/xqviewmodel.cpp | 43 ++++++++++---------- src/model/xqviewmodel.h | 4 +- xml/modelsheets.xml | 12 +++--- 10 files changed, 170 insertions(+), 75 deletions(-) diff --git a/src/application/xqchildmodel.cpp b/src/application/xqchildmodel.cpp index 9e16dfc..9f74391 100644 --- a/src/application/xqchildmodel.cpp +++ b/src/application/xqchildmodel.cpp @@ -59,10 +59,12 @@ void XQChildModel::setContent( const XQNodePtr& contentRoot ) // wir speichern das parent des datenknoten auch in der // section. // contentEntry->parent == _contentRoot, aber halt nur weil das model flach ist - section.contentRootNode = contentEntry->parent(); + section.setContentRootNode( contentEntry->parent() ); int newRow = _sections.lastRow(section); - XQItemList list = _itemFactory.makeContentRow( section.sheetRootNode, contentEntry ); + XQNodePtr node = section.sheetRootNode(); + XQItemList list = _itemFactory.makeContentRow( node, contentEntry ); + //XQItemList list = _itemFactory.makeContentRow( section.sheetRootNode, contentEntry ); // als Baum? //section.headerItem().appendRow( list ); diff --git a/src/application/xqmainmodel.cpp b/src/application/xqmainmodel.cpp index bcb106a..25dcf65 100644 --- a/src/application/xqmainmodel.cpp +++ b/src/application/xqmainmodel.cpp @@ -41,3 +41,42 @@ void XQMainModel::initContextMenu() } +//! erzeugt einen eintrag in der baum-übersicht. + +XQItem* XQMainModel::createTreeEntry( XQNodePtr contentNode ) +{ + + for(const auto& section : _sections ) + { + qDebug() << " --- wtf1: " << contentNode->to_string(); + qDebug() << " --- wtf2: " << section.sheetRootNode()->to_string(); + /* + if( contentNode->attribute("State") == section.sheetRootNode->attribute("State") ) + { + //XQItem* newTreeentry = _itemFactory.makeTreeChildItem( contentNode, section.sheetRootNode ); + + makeTreeChildItem: + // den itemtype des neuen items rausfinden + QString typeKey = sheetEntry->attribute("ItemType"); + XQItemType* itemType = findItemTypeTemplate(typeKey); // throws + //XQItemType* itemType = makeItemType(sheetEntry); // throws + + const QString* contentPtr = contentNode->attribute_ptr( "ProjectName" ); + + XQItem* newItem = new XQItem( itemType, contentPtr ); + + return newItem; + + section.headerItem().appendRow( newTreeentry ); + _treeTable->expand( section.modelIndex ); + // ?? + _treeTable->setCurrentIndex( section.modelIndex ); + newTreeentry->setContentNode(contentNode); + emit xqItemCreated( newTreeentry ); + return newTreeentry; + } + */ + } + + throw XQException( "createTreeEntry: main model should not be empty!" ); +} diff --git a/src/application/xqmainmodel.h b/src/application/xqmainmodel.h index a3c83ec..443b7dd 100644 --- a/src/application/xqmainmodel.h +++ b/src/application/xqmainmodel.h @@ -32,7 +32,7 @@ public: explicit XQMainModel(QObject *parent = nullptr); virtual ~XQMainModel() = default; - + XQItem* createTreeEntry( XQNodePtr contentNode ); public slots: diff --git a/src/application/xqmainwindow.cpp b/src/application/xqmainwindow.cpp index 713b418..2a6c85b 100644 --- a/src/application/xqmainwindow.cpp +++ b/src/application/xqmainwindow.cpp @@ -271,39 +271,38 @@ void XQMainWindow::onTabClicked( int index ) _mainTreeView->setCurrentIndex( _documentStore[index].treeItem->index() ); } -void XQMainWindow::onSectionCreated( const XQModelSection* section ) +void XQMainWindow::onSectionCreated( const XQModelSection& section ) { - qDebug() << " --- XXX section created: " << section->row(); + qDebug() << " --- XXX section created: " << section.contentType() << ":" << section.contentType(); } -void XQMainWindow::onSectionToggled( const XQModelSection* section ) +void XQMainWindow::onSectionToggled( const XQModelSection& section ) { - qDebug() << " --- XXX section toggled: " << section->row(); + qDebug() << " --- XXX section toggled: " << section.contentType() << ":" << section.sheetRootNode()->to_string(); } //! liest eine XML datei namens 'fileName' void XQMainWindow::loadDocument( const QString& fileName ) { - // gibts die Datei? + + // gibts die Datei? if( !QFile::exists( fileName) ) throw XQException( "no such file", fileName ); - // load data tree from xml file XQNodeFactory treeLoader; + // xml daten laden XQNodePtr rawTree = treeLoader.load_tree( qPrintable(fileName) ); - // versteckten root node ignorieren XQNodePtr contentRoot = rawTree->first_child(); - // Project-ID behandeln const QString& pID = contentRoot->attribute(c_ProjectID); int idx = _documentStore.indexOf( pID ); if( idx > -1 ) { - const XQDocument& doc = _documentStore.at(idx); + const XQDocument& document = _documentStore.at(idx); QMessageBox::warning( this, "Load Document", QString("File: %1 already loaded.").arg( fileName ) ); - _mainTreeView->setCurrentIndex( doc.treeItem->index() ); + _mainTreeView->setCurrentIndex( document.treeItem->index() ); _tabWidget->setCurrentIndex( idx ); return; } @@ -322,8 +321,9 @@ void XQMainWindow::loadDocument( const QString& fileName ) // Ein neues Child-Model erzeugen XQChildModel* childModel = new XQChildModel(this); - // die Modelstruktur anlegen - childModel->initModel( c_ChildModelName ); + connect( childModel, SIGNAL(sectionCreated(XQModelSection)), this, SLOT(onSectionCreated(XQModelSection)) ); + connect( childModel, SIGNAL(sectionToggled(XQModelSection)), this, SLOT(onSectionToggled(XQModelSection)) ); + // Den globalen undo-stack ... childModel->setUndoStack(&_undoStack); @@ -331,24 +331,17 @@ void XQMainWindow::loadDocument( const QString& fileName ) // und die TreeView übergeben childModel->setTreeTable(childTreeView); - bool c1 = connect( childModel, SIGNAL(sectionCreated(const XQModelSection*)), this, SLOT(onSectionCreated(const XQModelSection*)) ); - bool c2 = connect( childModel, SIGNAL(sectionToggled(const XQModelSection*)), this, SLOT(onSectionToggled(const XQModelSection*)) ); + // create new entry in the left side main tree view + //XQItem* newEntry = _mainModelView.createTreeEntry( contentRoot ); + //_mainTreeView->setCurrentIndex( newEntry->index() ); + //_documentStore.addDocument( fileName, pTitle, newEntry, childModel ); - qDebug() << " --- EWTF: " << c1 << ":" << c2; + // die Modelstruktur anlegen + childModel->initModel( c_ChildModelName ); // model inhalte laden childModel->setContent( contentRoot->first_child() ); - /* - // create new entry in the left side main tree view - XQItem* newEntry = _mainModelView.createTreeEntry( contentRoot ); - _mainTreeView->setCurrentIndex( newEntry->index() ); - _documentStore.addDocument( fileName, pTitle, newEntry, childModel ); - */ - - - - } diff --git a/src/application/xqmainwindow.h b/src/application/xqmainwindow.h index 74d9d23..08013ff 100644 --- a/src/application/xqmainwindow.h +++ b/src/application/xqmainwindow.h @@ -49,8 +49,8 @@ public slots: void onTreeItemClicked(const QModelIndex& index ); void onTabClicked( int index ); //void onItemCreated( XQItem* item ); - void onSectionCreated( const XQModelSection* section); - void onSectionToggled( const XQModelSection* section ); + void onSectionCreated( const XQModelSection& section); + void onSectionToggled( const XQModelSection& section ); protected: @@ -62,6 +62,7 @@ protected: void loadDocument( const QString& fileName ); void saveDocument( const QString& fileName ); + QUndoStack _undoStack; XQDocumentStore _documentStore; diff --git a/src/model/xqmodelsectionlist.cpp b/src/model/xqmodelsectionlist.cpp index 49f5a06..c645e41 100644 --- a/src/model/xqmodelsectionlist.cpp +++ b/src/model/xqmodelsectionlist.cpp @@ -15,12 +15,11 @@ #include - //! kontstruktor. übergibt den start-index und einen model-knoten mit der beschreibung //! der datenknoten. -XQModelSection::XQModelSection(const QModelIndex& aModelIndex, XQNodePtr aSheetNode) - : modelIndex{ aModelIndex }, sheetRootNode{ aSheetNode } +XQModelSection::XQModelSection(const QModelIndex& modelIndex, XQNodePtr sheetNode) + : _modelIndex{ modelIndex }, _sectionRootNode{ sheetNode } { } @@ -30,7 +29,7 @@ XQModelSection::XQModelSection(const QModelIndex& aModelIndex, XQNodePtr aSheetN bool XQModelSection::operator==(const XQModelSection& other) const { - return modelIndex == other.modelIndex && sheetRootNode == other.sheetRootNode; + return _modelIndex == other._modelIndex && _sectionRootNode == other._sectionRootNode; } @@ -38,7 +37,44 @@ bool XQModelSection::operator==(const XQModelSection& other) const bool XQModelSection::isValid() const { - return modelIndex.isValid() && sheetRootNode; + return _modelIndex.isValid() && _sectionRootNode; +} + +const QModelIndex& XQModelSection::modelIndex() const +{ + return _modelIndex; +} + +XQNodePtr XQModelSection::sectionRootNode() const +{ + return _sectionRootNode; +} + +//! Gibt den sheet-node zurück, das ist die model-beschreibung, +//! siehe modelsheet.xml: +//!
+//!
+//! <- dort + +//! __fix! das versteht doch kein mensch! + +XQNodePtr XQModelSection::sheetRootNode() const +{ + return _sectionRootNode->find_child_by_tag_name( c_Data ); +} + + +//! Gibt den content root node zurück, das ist der +//! zeiger auf die realen inhalte. + +XQNodePtr XQModelSection::contentRootNode() const +{ + return _contentRootNode; +} + +void XQModelSection::setContentRootNode( const XQNodePtr contentRootNode ) +{ + _contentRootNode = contentRootNode; } @@ -46,7 +82,15 @@ bool XQModelSection::isValid() const int XQModelSection::XQModelSection::row() const { - return modelIndex.row(); + return _modelIndex.row(); +} + + +//! gibt den 'content type' zurück. + +const QString& XQModelSection::contentType() const +{ + return _sectionRootNode->attribute( c_ContentType ); } @@ -54,9 +98,10 @@ int XQModelSection::XQModelSection::row() const XQItem& XQModelSection::XQModelSection::headerItem() const { - return XQItem::xqItemFromIndex( modelIndex ); + return XQItem::xqItemFromIndex( _modelIndex ); } + //! testet, ob die unter 'sectionKey' eine gültige section vorhanden ist. bool XQModelSectionList::hasValidSection(const QString& sectionKey) const @@ -66,6 +111,7 @@ bool XQModelSectionList::hasValidSection(const QString& sectionKey) const return at(sectionKey).isValid(); } + //! gibt für einen model index die 'zuständige' section zurück. const XQModelSection& XQModelSectionList::sectionFromIndex( const QModelIndex& index ) const @@ -83,11 +129,12 @@ const XQModelSection& XQModelSectionList::sectionFromRow(int itemRow ) const int i = size() - 1; for (; i >= 0; --i) { - if ( at(i).modelIndex.row() < itemRow ) + if ( at(i).modelIndex().row() < itemRow ) return at(i); } static XQModelSection s_DummySection; + return s_DummySection; } @@ -123,7 +170,7 @@ int XQModelSectionList::lastRow(const XQModelSection& section ) const { // last section? return last row of model if (index == size() - 1) - return section.modelIndex.model()->rowCount();// - 1; + return section.modelIndex().model()->rowCount();// - 1; // return row above the row of the next section -> last row of given section return at(index+1).row(); } @@ -138,7 +185,7 @@ void XQModelSectionList::dump() const qDebug() << " --- sections dump(): " <children() ) + for( auto& sectionNode : modelSheet->children() ) { // #2: (optionalen?) header erzeugen - const XQNodePtr header = section->find_child_by_tag_name( "Header"); + const XQNodePtr header = sectionNode->find_child_by_tag_name( c_Header ); if( header ) { XQItemList list = _itemFactory.makeContentRow( header, nullptr ); - addSection(list, section ); + addSection(list, sectionNode ); } } } -//! hilfsfunktion: fügt die liste unserem model hinzu und erzeugt eine 'section'. +//! Hilfsfunktion: fügt die item-liste unserem model hinzu und erzeugt eine 'section'. //! die section kann erst gültig sein, wenn die items im model gelandet sind, //! deswegen ist das hier zusammengefasst. -//! erzeugt dann eine section aus einer frisch erzeugten itemlist. der erste modelindex -//! der liste und der unterknoten 'Data' werden gespeichert. +//! Wrzeugt dann eine section aus einer frisch erzeugten itemlist. Der erste modelindex +//! der liste und der root knoten der model-beschreibung werden gespeichert. -void XQViewModel::addSection(const XQItemList& list, const XQNodePtr& sheetNode ) +void XQViewModel::addSection(const XQItemList& list, const XQNodePtr& sectionNode ) { // 1. die liste darf nicht leer sein Q_ASSERT(!list.isEmpty()); - // 2. sheetNode muss da sein - Q_ASSERT(sheetNode); + // 2. sectionNode muss da sein + Q_ASSERT(sectionNode); // 3. 'ContenType' muss vorhanden sein - if( !sheetNode->has_attribute( c_ContentType) ) + if( !sectionNode->has_attribute( c_ContentType) ) throw XQException( "section list: Section node needs attribute 'ContentType'!"); - // 4. Data child muss auch da sein - XQNodePtr dataNode = sheetNode->find_child_by_tag_name( c_Data ); - if( !dataNode ) - throw XQException( "section list: 'Data' child is missing!"); // 5. das erzeugt dann auch valide indices appendRow(list); + // 6. die beschreibung der daten liegt im unterknoten 'Data' + + // 6. jetzt können wir auch die sction erzeugen - XQModelSection section(list[0]->index(), dataNode ); - _sections.addAtKey(sheetNode->attribute( c_ContentType), section); + XQModelSection section(list[0]->index(), sectionNode ); + _sections.addAtKey(sectionNode->attribute( c_ContentType), section); // ... und es der welt mitteilen. - emit sectionCreated( §ion ); + emit sectionCreated( section ); } @@ -354,7 +353,7 @@ void XQViewModel::cmdCutUndo( XQCommand& command ) const XQNodePtr& savedNode = entry.contentNode; // __fix! should not be _contentRoot! savedNode->add_me_at( entry.nodePos, _contentRoot ); - XQItemList list = _itemFactory.makeContentRow( section.sheetRootNode, savedNode ); + XQItemList list = _itemFactory.makeContentRow( section.sheetRootNode(), savedNode ); XQItem& firstItem = *((XQItem*)list[0]); qDebug() << " --- Cut Undo: " << firstItem.text() << " " << firstItem.row() << " id#" << entry.contentNode->_id << " count: " << entry.contentNode.use_count(); @@ -386,10 +385,10 @@ void XQViewModel::cmdPaste( XQCommand& command ) for (auto& entry : _clipBoard ) { // noch ein clone vom clone erzeugen ... - XQNodePtr newNode = entry.contentNode->clone(section.contentRootNode ); - newNode->clone(section.contentRootNode )->add_me_at( nodePos ); + XQNodePtr newNode = entry.contentNode->clone(section.contentRootNode() ); + newNode->clone(section.contentRootNode() )->add_me_at( nodePos ); // ... und damit eine frische item-row erzeugen - XQItemList list = _itemFactory.makeContentRow( section.sheetRootNode, newNode ); + XQItemList list = _itemFactory.makeContentRow( section.sheetRootNode(), newNode ); insertRow( insRow, list ); // die neue item-row selektieren const QModelIndex& selIdx = list[0]->index(); @@ -508,7 +507,7 @@ void XQViewModel::cmdToggleSection( XQCommand& command ) for (int row = fstRow; row < lstRow; ++row ) _treeTable->setRowHidden( row, _treeTable->rootIndex(), !hidden ); - emit sectionToggled( &_sections.sectionFromIndex(index) ); + emit sectionToggled( _sections.sectionFromIndex(index) ); } diff --git a/src/model/xqviewmodel.h b/src/model/xqviewmodel.h index c8fc558..b1ca62e 100644 --- a/src/model/xqviewmodel.h +++ b/src/model/xqviewmodel.h @@ -100,8 +100,8 @@ public slots: signals: void itemCreated( XQItem* newItem ); - void sectionCreated( const XQModelSection* section ); - void sectionToggled( const XQModelSection* section ); + void sectionCreated( const XQModelSection& section ); + void sectionToggled( const XQModelSection& section ); protected: diff --git a/xml/modelsheets.xml b/xml/modelsheets.xml index a55d630..d8aea64 100644 --- a/xml/modelsheets.xml +++ b/xml/modelsheets.xml @@ -53,7 +53,7 @@ -
+
@@ -65,7 +65,7 @@
- + @@ -80,7 +80,7 @@
-
+
@@ -90,7 +90,7 @@
- + @@ -101,7 +101,7 @@
-
+
@@ -111,7 +111,7 @@
- +