reworked model sections.

This commit is contained in:
2025-08-14 21:36:39 +02:00
parent a6fb7e82bd
commit 0d7ab33c74
13 changed files with 79 additions and 70 deletions

View File

@@ -28,6 +28,7 @@ const QString c_ItemType = "ItemType";
const QString c_Caption = "Caption";
const QString c_Header = "Header";
const QString c_ContentType = "ContentType";
const QString c_Data = "Data";
const QString c_MainModelName = "DocumentTreeModel";
const QString c_ChildModelName = "DocumentDetailsModel";

View File

@@ -47,20 +47,14 @@ void XQChildModel::setContent( const XQNodePtr& contentRoot )
// haben, hier: <Panel>. <Battery> ...
for (const auto& contentEntry : _contentRoot->children())
{
qDebug() << " --- GOGOGO: 00: " << contentEntry->to_string();
// Das ist hier der Typ des Eintrags: Panel, Battery ...
QString key = contentEntry->tag_name();
qDebug() << " --- GOGOGO: " << key;
// 'silent failure' hier der Datenbaum kann auch Knoten enthalten
// die nicht für uns gedacht sind.
if (!_sections.hasValidSection(key))
continue;
qDebug() << " --- GOGOGO: FOUND!" << key;
XQModelSection& section = _sections.at( key );
// wir speichern das parent des datenknoten auch in der
// section.
@@ -70,8 +64,6 @@ void XQChildModel::setContent( const XQNodePtr& contentRoot )
XQItemList list = _itemFactory.makeContentRow( section.sheetRootNode, contentEntry );
qDebug() << " --- AHJA: " << key << " -- last Row dazu: " << newRow;
// als Baum?
//section.headerItem().appendRow( list );
insertRow( newRow, list);

View File

@@ -40,6 +40,7 @@ XQMainModel::XQMainModel(QObject *parent )
XQItem* XQMainModel::createTreeEntry( XQNodePtr contentNode )
{
/*
for(const auto& section : _sections )
{
qDebug() << " --- wtf1: " << contentNode->to_string();
@@ -47,7 +48,20 @@ XQItem* XQMainModel::createTreeEntry( XQNodePtr contentNode )
if( contentNode->attribute("State") == section.sheetRootNode->attribute("State") )
{
XQItem* newTreeentry = _itemFactory.makeTreeChildItem( contentNode, section.sheetRootNode );
//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 );
// ??
@@ -57,6 +71,7 @@ XQItem* XQMainModel::createTreeEntry( XQNodePtr contentNode )
return newTreeentry;
}
}
*/
throw XQException( "createTreeEntry: main model should not be empty!" );
}

View File

@@ -119,24 +119,7 @@ XQNodePtr XQItemFactory::findModelSheet( const QString& modelName ) const
}
//! firz!
XQItem* XQItemFactory::makeTreeChildItem( const XQNodePtr& contentNode, const XQNodePtr& sheetEntry )
{
// 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;
}
//! firz!
//! erzeugt eine QVariant aus dem gegebenen string und setzt diese dann via role im item.
void XQItemFactory::setItemDataFromString( XQItem& item, const QString& roleKey, const QString& source ) const
{
@@ -150,7 +133,7 @@ void XQItemFactory::setItemDataFromString( XQItem& item, const QString& roleKey,
}
//! firz!
//! erzeugt eine QVariant aus dem gegebenen string
QVariant XQItemFactory::makeVariant( int dataRole, const QString& source ) const
{

View File

@@ -32,9 +32,6 @@ public:
XQNodePtr findModelSheet( const QString& modelName ) const;
XQItem* makeTreeChildItem( const XQNodePtr& contentNode, const XQNodePtr& sheetEntry );
XQItem* makeItem( const XQNodePtr& sheetNode, const XQNodePtr& contentNode=nullptr);
XQItemList makeHeaderRow( const XQNodePtr& sheetNode );

View File

@@ -13,7 +13,7 @@
#include <xqmodelsectionlist.h>
#include <xqitem.h>
//! kontstruktor. übergibt den start-index und einen model-knoten mit der beschreibung
@@ -38,6 +38,7 @@ bool XQModelSection::operator==(const XQModelSection& other) const
bool XQModelSection::isValid() const
{
qDebug() << " mi: " << modelIndex.isValid() << " sheetNode: " << (bool)(sheetRootNode);
return modelIndex.isValid() && sheetRootNode;
}
@@ -57,32 +58,27 @@ XQItem& XQModelSection::XQModelSection::headerItem() const
return XQItem::xqItemFromIndex( modelIndex );
}
void XQModelSectionList::addSectionEntry(const QModelIndex& idx, XQNodePtr sheetNode)
{
if( !sheetNode->has_attribute( c_ContentType) )
throw XQException( "section list: Section node needs attribute 'ContentType'!");
XQModelSection section(idx, sheetNode->find_child_by_tag_name("Data"));
qDebug() << " ---- ADD section: " << sheetNode->attribute( c_ContentType);
addAtKey(sheetNode->attribute( c_ContentType), section);
}
//! testet, ob die unter 'sectionKey' eine gültige section vorhanden ist.
bool XQModelSectionList::hasValidSection(const QString& sectionKey) const
{
qDebug() << " ---- FIND section: " << sectionKey << ":" << contains(sectionKey) << ":" << at(sectionKey).isValid();
if (!contains(sectionKey) )
return false;
return at(sectionKey).isValid();
}
//! gibt für einen model index die 'zuständige' section zurück.
const XQModelSection& XQModelSectionList::sectionxqItemFromIndex( const QModelIndex& index ) const
const XQModelSection& XQModelSectionList::sectionFromIndex( const QModelIndex& index ) const
{
return sectionFromRow( index.row() );
}
//! gibt für eine zeile die 'zuständige' section zurück: der bestand an section wird
//! nach der passenden section durchsucht.
const XQModelSection& XQModelSectionList::sectionFromRow(int itemRow ) const
{
@@ -99,18 +95,26 @@ const XQModelSection& XQModelSectionList::sectionFromRow(int itemRow ) const
}
//! ermittelt die erste zeile einer section.
int XQModelSectionList::firstRow(const QModelIndex& idx) const
{
return sectionFromRow(idx.row() ).row();
}
//! ermittelt die zeile unterhalb des gegebenen modelindex,
//! zum einfügen neuer items ebendort.
int XQModelSectionList::lastRow(const QModelIndex& idx) const
{
return lastRow(sectionFromRow(idx.row()));
}
//! ermittelt die zeile unterhalb der gegebenen section,
//! zum einfügen neuer items ebendort.
int XQModelSectionList::lastRow(const XQModelSection& section ) const
{
//qDebug() << " -- last row in section: " << section.modelIndex.data().toString() << " --> " << section.modelIndex.row();
@@ -129,6 +133,8 @@ int XQModelSectionList::lastRow(const XQModelSection& section ) const
}
//! gibt alle sections aus, zum ankucken.
void XQModelSectionList::dump() const
{
qDebug() << " --- sections dump(): " <<size() << " entries.";

View File

@@ -16,10 +16,9 @@
#define XQMODELSECTIONLIST_H
#include <QPersistentModelIndex>
#include <xqnode.h>
#include <xqmaptor.h>
class XQItem;
#include <xqmaptor.h>
#include <xqitem.h>
/**
* @brief Struct containing data for a header section
@@ -54,11 +53,11 @@ public:
XQModelSectionList() = default;
virtual ~XQModelSectionList() = default;
void addSectionEntry(const QModelIndex& idx, XQNodePtr sheetNode );
void createSectionEntry(const XQItemList& list, const XQNodePtr& sheetNode );
bool hasValidSection(const QString& sectionKey) const;
const XQModelSection& sectionFromRow( int row ) const;
const XQModelSection& sectionxqItemFromIndex( const QModelIndex& index ) const;
const XQModelSection& sectionFromIndex( const QModelIndex& index ) const;
int firstRow(const QModelIndex& idx) const;
int lastRow(const QModelIndex& idx) const;

View File

@@ -104,12 +104,12 @@ void XQViewModel::initModel(const QString& modelName)
// #1: über alle sections
for( auto& section : modelSheet->children() )
{
// #2: (optionalen) header erzeugen
// #2: (optionalen?) header erzeugen
const XQNodePtr header = section->find_child_by_tag_name( "Header");
if( header )
{
XQItemList list = _itemFactory.makeHeaderRow( header );
Q_ASSERT(!list.isEmpty());
//XQItemList list = _itemFactory.makeHeaderRow( header );
XQItemList list = _itemFactory.makeContentRow( header, nullptr );
addSection(list, section );
}
@@ -117,6 +117,33 @@ void XQViewModel::initModel(const QString& modelName)
}
//! hilfsfunktion: fügt die 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.
void XQViewModel::addSection(const XQItemList& list, const XQNodePtr& sheetNode )
{
// 1. die liste darf nicht leer sein
Q_ASSERT(!list.isEmpty());
// 2. sheetNode muss da sein
Q_ASSERT(sheetNode);
// 3. 'ContenType' muss vorhanden sein
if( !sheetNode->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);
XQModelSection section(list[0]->index(), dataNode );
_sections.addAtKey(sheetNode->attribute( c_ContentType), section);
}
//! SLOT, der aufgerufen wird, wenn eine edit-action getriggert wurde.
void XQViewModel::onActionTriggered(QAction* action)
@@ -263,10 +290,13 @@ void XQViewModel::cmdCut( XQCommand& command )
{
// ... holen das erste item, das auch den content node enthält
//const XQNodeBackup& entry = *it;
//XQItem& firstItem = xqFirstItem( (*it).itemPos );
//qDebug() << " --- Cut: " << firstItem.text() << " " << firstItem.row() << " id#" << entry.contentNode->_id;
// jetzt löschen, dabei wird die parent-verbindung entfernt
const XQNodeBackup& entry = *it;
XQItem& firstItem = xqFirstItem( (*it).itemPos );
qDebug() << " --- Cut: " << firstItem.text() << " " << firstItem.row() << " id#" << entry.contentNode->_id;
entry.contentNode->unlink_self();
removeRow(entry.itemPos );
}
@@ -404,7 +434,7 @@ void XQViewModel::cmdNew( XQCommand& command )
// store node in node->parent()
//node->add_before_me( newNode );
// store node also in 'command' to enable undo
const XQModelSection& section = _sections.sectionxqItemFromIndex( origin );
const XQModelSection& section = _sections.sectionFromIndex( origin );
// create new item row
XQItemList list = _itemFactory.createGenericRow( newNode, section.sheetRootNode );
@@ -484,15 +514,6 @@ void XQViewModel::setupViewProperties()
}
//! füg eine section mit header hinzu.
void XQViewModel::addSection( const XQItemList& list, const XQNodePtr& sheetNode )
{
appendRow(list);
_sections.addSectionEntry( list[0]->index(), sheetNode );
}
//! gibt den undo-stack zurück.
QUndoStack* XQViewModel::undoStack()

View File

@@ -104,9 +104,6 @@ signals:
protected:
void addSection(const XQItemList& list, const XQNodePtr& sheetNode );
protected:
virtual void initContextMenu() = 0;
// __fixme: should be created from xml

View File

@@ -15,7 +15,6 @@ HEADERS += \
application/xqmainmodel.h \
application/xqmainwindow.h \
application/xqappdata.h \
items/xqgenericitem.h \
items/xqitem.h \
items/xqitemfactory.h \
items/xqitemtype.h \
@@ -52,7 +51,6 @@ SOURCES += \
application/xqmainmodel.cpp \
application/xqmainwindow.cpp \
application/xqappdata.cpp \
items/xqgenericitem.cpp \
items/xqitem.cpp \
items/xqitemfactory.cpp \
items/xqitemtype.cpp \

View File

@@ -8,7 +8,7 @@
<ItemTypes>
<TreeParentType RenderStyle="PlainStyle" ItemFlags="IsEnabled|IsDropEnabled" Icon="DirIcon" />
<TreeChildType RenderStyle="PlainStyle" ItemFlags="IsEnabled|IsDragEnabled|IsSelectable|IsDropEnabled"/>
<TreeChildType RenderStyle="PlainStyle" ItemFlags="IsCheckable|IsEnabled|IsDragEnabled|IsSelectable|IsDropEnabled"/>
<HeaderType RenderStyle="HeaderStyle" ItemFlags="IsEnabled" Icon="battery"/>
<HiddenType RenderStyle="HiddenStyle"/>
<StaticType RenderStyle="PlainStyle"/>