Compare commits

..

21 Commits

Author SHA1 Message Date
3887748c1a remorked sections. 2025-09-05 21:42:40 +02:00
b8f0893d59 Backup. 2025-09-05 17:12:38 +02:00
9c6f7688d7 Enable section toggle 2025-09-05 11:49:36 +02:00
8d26c32e51 cleanups, added const iterators to xqmaptor 2025-09-05 09:57:43 +02:00
c9b61c1c2b Fixed ::setData, part II 2025-09-04 20:09:21 +02:00
d6ccac1d85 Fixed ::setData, part I 2025-09-04 18:10:14 +02:00
5d2fb1b378 Added new-undo == delete 2025-09-04 17:01:01 +02:00
89c5fd21f1 Completed cmdNew implementation. 2025-09-04 14:56:18 +02:00
f8bd0886d3 Added cmdNew implementation. 2025-09-04 13:52:23 +02:00
Christoph Holzheuer
831daf898c --fy 2025-09-03 17:23:52 +02:00
Christoph Holzheuer
3e7b65dca5 add signal prototypes 2025-09-02 16:58:56 +02:00
147769bf60 added signal handler 'itemChanged' 2025-09-01 23:28:24 +02:00
Christoph Holzheuer
527de65074 -- fy 2025-09-01 17:40:08 +02:00
4d49a495fd -- fy 2025-08-31 23:18:14 +02:00
952409ab1a repaired it (a bit) 2025-08-31 14:38:11 +02:00
c6454f3106 cracket it. 2025-08-27 15:39:33 +02:00
04b0f650d6 -- pre-holiday 2025-08-27 14:06:31 +02:00
6ee677c595 looking better. 2025-08-26 19:41:28 +02:00
5057edb9ad Merge branch 'experimental/qml-widget' 2025-08-26 17:57:16 +02:00
39909ad543 Added scrollbars. 2025-08-26 17:55:39 +02:00
b217f2f9ad little breakthrought im QML Layouts 2025-08-26 17:45:06 +02:00
42 changed files with 1213 additions and 741 deletions

View File

@@ -0,0 +1,44 @@
// SPDX-FileCopyrightText: 2025 Martin Leutelt <martin.leutelt@basyskom.com>
// SPDX-FileCopyrightText: 2025 basysKom GmbH
//
// SPDX-License-Identifier: LGPL-3.0-or-later
import QtQuick
import QtQuick.Controls
Control {
id: container
required property int column
required property var model
property int sortOrder: Qt.AscendingOrder
signal clicked(int sortOrder)
padding: 8
background: Rectangle {
color: tapHandler.pressed ? "gray" : "lightgray"
TapHandler {
id: tapHandler
onTapped: {
if (container.sortOrder === Qt.AscendingOrder) {
container.sortOrder = Qt.DescendingOrder
} else {
container.sortOrder = Qt.AscendingOrder
}
container.clicked(container.sortOrder)
}
}
}
contentItem: Label {
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
elide: Text.ElideRight
text: container.model.display
}
}

View File

@@ -0,0 +1,26 @@
import QtQuick
import QtQuick.Controls
Control {
id: container
required property int row
required property var model
padding: 8
background: Rectangle {
color: tapHandler.pressed ? "gray" : "lightgray"
TapHandler {
id: tapHandler
}
}
contentItem: Label {
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
elide: Text.ElideRight
text: container.model.display
}
}

161
qml/XMain.qml Normal file
View File

@@ -0,0 +1,161 @@
// SPDX-FileCopyrightText: 2025 Martin Leutelt <martin.leutelt@basyskom.com>
// SPDX-FileCopyrightText: 2025 basysKom GmbH
//
// SPDX-License-Identifier: LGPL-3.0-or-later
pragma ComponentBehavior: Bound
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
ApplicationWindow {
width: 640
height: 480
visible: true
title: Application.displayName
header: ToolBar {
ColumnLayout {
RowLayout {
Label {
text: "Rows"
}
SpinBox {
id: rowSettings
from: 1
to: 20
}
ToolSeparator {}
Label {
text: "Columns"
}
SpinBox {
id: columnSettings
from: 1
to: 20
}
ToolSeparator {}
CheckBox {
id: movableColumnsSetting
text: "Movable columns"
}
ToolSeparator {}
CheckBox {
id: resizableColumnsSetting
text: "Resizable columns"
}
}
RowLayout {
Label {
text: "Selection"
}
ComboBox {
id: selectionSetting
textRole: "text"
valueRole: "value"
model: [
{ text: "disabled", value: TableView.SelectionDisabled },
{ text: "by cells", value: TableView.SelectCells },
{ text: "by rows", value: TableView.SelectRows },
{ text: "by columns", value: TableView.SelectColumns }
]
onCurrentIndexChanged: tableView.selectionModel.clear()
}
Label {
text: "Longpress to start selection, modify selection with CTRL/SHIFT of by mouse"
visible: selectionSetting.currentIndex > 0
}
}
}
}
Rectangle {
id: tableBackground
anchors.fill: parent
color: Application.styleHints.colorScheme === Qt.Light ? palette.mid : palette.midlight
HorizontalHeaderView {
id: horizontalHeader
anchors.left: tableView.left
anchors.top: parent.top
syncView: tableView
movableColumns: movableColumnsSetting.checked
resizableColumns: resizableColumnsSetting.checked
clip: true
boundsBehavior: tableView.boundsBehavior
delegate: HorizontalHeaderViewDelegate {
onClicked: (sortOrder) => tableView.model.sort(column, sortOrder)
}
}
VerticalHeaderView {
id: verticalHeader
anchors.top: tableView.top
anchors.left: parent.left
syncView: tableView
clip: true
boundsBehavior: tableView.boundsBehavior
delegate: VerticalHeaderViewDelegate {}
}
TableView {
id: tableView
anchors.left: verticalHeader.right
anchors.top: horizontalHeader.bottom
anchors.right: parent.right
anchors.bottom: parent.bottom
clip: true
columnSpacing: 1
rowSpacing: 1
rowHeightProvider: (row) => 40
boundsBehavior: TableView.StopAtBounds
selectionModel: ItemSelectionModel {}
selectionBehavior: selectionSetting.currentValue
model: SortFilterModel {
sourceModel: TableModel {
columns: columnSettings.value
rows: rowSettings.value
// when adding a new column its width isn't properly applied to the header, so we do that manually
onColumnsInserted: {
if (columns > 1) {
horizontalHeader.setColumnWidth(columns - 1, tableView.implicitColumnWidth(columns - 1))
}
}
}
}
delegate: TableViewDelegate {
implicitWidth: tableView.width / columnSettings.to
}
ScrollBar.horizontal: ScrollBar {}
ScrollBar.vertical: ScrollBar {}
}
SelectionRectangle {
target: tableView
}
}
}

56
qml/dummyview.qml Normal file
View File

@@ -0,0 +1,56 @@
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import QtQuick.Window
ApplicationWindow
{
visible: true
width: 600
height: 400
TreeView
{
anchors.fill: parent
clip: true
columnSpacing: 1
rowSpacing: 1
model: myChildModel
columnWidthProvider: function(column)
{
var z= 2*(width / columns);
console.log("Firz:", z);
console.log("Berechne Spaltenbreite für column:", column);
console.log("Aktuelle TreeView-Breite:", width);
return z;
}
delegate: Rectangle
{
required property int row
required property int column
required property var model
border.width: 0
implicitWidth: 30
implicitHeight: 30
border.color: "#cccccc"
//color: index % 2 === 0 ? "#f9f9f9" : "#e0e0e0"
color: TreeView.isSelected ? "#d0eaff" : (row % 2 === 0 ? "#f9f9f9" : "#ffffff")
Text
{
anchors.centerIn: parent
text: display
font.pixelSize: 14
}
}
ScrollBar.horizontal: ScrollBar {}
ScrollBar.vertical: ScrollBar {}
}
}

65
qml/xqtableview.qml Normal file
View File

@@ -0,0 +1,65 @@
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
Window
{
width: 640
height: 480
visible: true
title: qsTr("StringListModel")
TableView
{
id: childTableView
anchors.fill: parent
model: myChildModel // z.B. QStandardItemModel mit 9 Spalten
delegate: Rectangle
{
required property string display
//height: 5
//width: childTableView.width
color : "blue"
border.color: "#ccc"
width: childTableView.width;
RowLayout
{
anchors.fill: parent
anchors.margins: 2
TextField
{
text : display
font.pixelSize: 10
Layout.fillWidth: true
background: Rectangle
{
color : "white"
}
onEditingFinished:
{
console.log("Editing finished, new text is :"+ text + " at index :" + index)
model.names = text //The roles here are defined in model class
}
}
}
}
ScrollBar.horizontal: ScrollBar {}
ScrollBar.vertical: ScrollBar {}
// // Optional: Spaltenbreiten setzen
// onModelChanged: {
// for (let i = 0; i < model.columns; ++i)
// table.setColumnWidth(i, 100)
// }
}
}

47
qml/xqtreeview.qml Normal file
View File

@@ -0,0 +1,47 @@
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
TreeView
{
anchors.fill: parent
clip: true
columnSpacing: 1
rowSpacing: 1
model: xtrChildModel
columnWidthProvider: function(column)
{
var z= 1.7*(width / columns);
return z;
}
delegate: Rectangle
{
required property int row
required property int column
required property var model
border.width: 0
implicitWidth: 30
implicitHeight: 20
border.color: "#cccccc"
//color: index % 2 === 0 ? "#f9f9f9" : "#e0e0e0"
color: TreeView.isSelected ? "#d0eaff" : (row % 2 === 0 ? "#f9f9f9" : "#ffffff")
Text
{
anchors.centerIn: parent
text: display
font.pixelSize: 12
}
}
ScrollBar.horizontal: ScrollBar {}
ScrollBar.vertical: ScrollBar {}
}

View File

@@ -1,35 +0,0 @@
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
TableView
{
id: table
anchors.fill: parent
columnSpacing: 2
rowSpacing: 2
model: meinModel // z.B. QStandardItemModel mit 9 Spalten
delegate: Rectangle
{
required property string display
width: 100
height: 20
border.color: "#ccc"
Text
{
anchors.centerIn: parent
text: display
font.pixelSize: 10
}
}
// // Optional: Spaltenbreiten setzen
// onModelChanged: {
// for (let i = 0; i < model.columns; ++i)
// table.setColumnWidth(i, 100)
// }
}

View File

@@ -38,6 +38,7 @@ const QString c_ProjectID = "ProjectID";
const QString c_ModelSheetFileName = "xml/modelsheets.xml"; const QString c_ModelSheetFileName = "xml/modelsheets.xml";
const QString c_ModelDummyFileName = "xml/saved_testfile.xtr"; const QString c_ModelDummyFileName = "xml/saved_testfile.xtr";
const QString c_DocumentDirectory = "xml/"; const QString c_DocumentDirectory = "xml/";
const QString c_DocumentFileName1 = "xml/modeldata1.xtr"; const QString c_DocumentFileName1 = "xml/modeldata1.xtr";
const QString c_DocumentFileName2 = "xml/modeldata2.xtr"; const QString c_DocumentFileName2 = "xml/modeldata2.xtr";
const QString c_DocumentFileName3 = "xml/modeldata3.xtr"; const QString c_DocumentFileName3 = "xml/modeldata3.xtr";

View File

@@ -55,18 +55,12 @@ void XQChildModel::addModelData( const XQNodePtr& contentRoot )
if (!_sections.hasValidSection(key)) if (!_sections.hasValidSection(key))
continue; continue;
XQModelSection& section = _sections.at( key ); const XQModelSection& section = _sections.sectionByKey( key );
// wir speichern das parent des datenknoten auch in der
// section.
// contentEntry->parent == _contentRoot, aber halt nur weil das model flach ist
//qDebug() << " --- add section ENTRY: " << key << " TagName: " << contentEntry->attribute("TagName");
section.setContentRootNode( contentEntry->parent() ); section.setContentRootNode( contentEntry->parent() );
int newRow = _sections.lastRow(section); int newRow = _sections.lastRow(section);
XQNodePtr sheetNode = section.sheetRootNode(); XQNodePtr sheetNode = section.sheetRootNode();
XQItemList list = _itemFactory.makeRow( XQItemFactory::mData, sheetNode, contentEntry ); XQItemList list = _itemFactory.makeRow( sheetNode, contentEntry );
// als Baum? // als Baum?
//section.headerItem().appendRow( list ); //section.headerItem().appendRow( list );
@@ -76,24 +70,30 @@ void XQChildModel::addModelData( const XQNodePtr& contentRoot )
} }
//! Erzeugt eine model-section und fügt den zugehörigen header ein.
void XQChildModel::addSectionEntry( const QString& key, const XQNodePtr& contentEntry ) void XQChildModel::addSectionEntry( const QString& key, const XQNodePtr& contentEntry )
{ {
XQModelSection& section = _sections.at( key ); const XQModelSection& section = _sections.sectionByKey( key );
if(section.isValid() ) if(section.isValid() )
{ {
section.setContentRootNode( contentEntry->parent() ); section.setContentRootNode( contentEntry->parent() );
int newRow =_sections.lastRow(section); int newRow =_sections.lastRow(section);
XQNodePtr sheetNode = section.sheetRootNode(); XQNodePtr sheetNode = section.sheetRootNode();
XQItemList list = _itemFactory.makeRow( XQItemFactory::mHeader, sheetNode, contentEntry ); XQItemList list = _itemFactory.makeRow( sheetNode, nullptr );
insertRow( newRow, list); insertRow( newRow, list);
} }
} }
//! erzeugt ein adhoc-contextmenu, je nachdem welche aktionen gerade möflich sind.
//! erzeugt ein adhoc-contextmenu, je nachdem welche aktionen gerade möglich sind.
void XQChildModel::initContextMenu() void XQChildModel::initContextMenu()
{ {
_sections.dump();
// __fixme! add a menu title // __fixme! add a menu title
_contextMenu->clear(); _contextMenu->clear();
@@ -113,7 +113,7 @@ void XQChildModel::initContextMenu()
// __fixme! set 'toggle section <name>' entry // __fixme! set 'toggle section <name>' entry
//contextMenu.actions().first()->setText("<name>"); //contextMenu.actions().first()->setText("<name>");
_contextMenu->addAction( "icn29Dummy", "Toggle Section", XQCommand::cmdToggleSection, hasSel); _contextMenu->addAction( "icn29Dummy", "Hide Section", XQCommand::cmdToggleSection, true );
} }

View File

@@ -18,8 +18,8 @@
//! erzeugt ein docukument //! erzeugt ein docukument
XQDocument::XQDocument(const QString& aFileName, const QString& aFriendlyName, XQItem* aTreeItem, XQViewModel* aModelView ) XQDocument::XQDocument(const QString& aFileName, const QString& aFriendlyName, XQItem* aTreeItem, XQViewModel* aViewModel )
: fileName{ aFileName }, friendlyName{ aFriendlyName }, treeItem{ aTreeItem }, modelView{ aModelView } : fileName{ aFileName }, friendlyName{ aFriendlyName }, treeItem{ aTreeItem }, viewModel{ aViewModel }
{ {
} }
@@ -44,9 +44,9 @@ XQDocumentStore::~XQDocumentStore()
//! erzeugt ein document eintrag //! erzeugt ein document eintrag
void XQDocumentStore::addDocument( const QString& aFileName, const QString& aFriendlyName, XQItem* aTreeItem, XQViewModel* aModelView ) void XQDocumentStore::addDocument(const QString& aFileName, const QString& aFriendlyName, XQItem* aTreeItem, XQViewModel* aViewModel )
{ {
XQDocument newDocument( aFileName, aFriendlyName, aTreeItem, aModelView ); XQDocument newDocument( aFileName, aFriendlyName, aTreeItem, aViewModel );
addAtKey( aFileName, newDocument ); addAtKey( aFileName, newDocument );
// attention: this assumes the presence of the 'ProjectID' value // attention: this assumes the presence of the 'ProjectID' value
//addAlias( aFileName, aTreeItem->attribute(c_ProjectID) ); //addAlias( aFileName, aTreeItem->attribute(c_ProjectID) );

View File

@@ -28,12 +28,10 @@ struct XQDocument
XQDocument() = default; XQDocument() = default;
XQDocument( const QString& aFileName, const QString& aFriendlyName, XQItem* aTreeItem, XQViewModel* aModelView ); XQDocument( const QString& aFileName, const QString& aFriendlyName, XQItem* aTreeItem, XQViewModel* aModelView );
virtual ~XQDocument() = default;
QString fileName; // also used as key QString fileName; // also used as key
QString friendlyName; QString friendlyName;
XQItem* treeItem{}; XQItem* treeItem{};
XQViewModel* modelView{}; XQViewModel* viewModel{};
}; };
@@ -46,11 +44,7 @@ public:
XQDocumentStore() = default; XQDocumentStore() = default;
virtual ~ XQDocumentStore(); virtual ~ XQDocumentStore();
void addDocument( const QString& aFileName, const QString& aFriendlyName, XQItem* aTreeItem, XQViewModel* aModelView ); void addDocument( const QString& aFileName, const QString& aFriendlyName, XQItem* aTreeItem, XQViewModel* aViewModel );
protected:
XQNode _treeRootNode{ "treeRootNode" };
}; };

View File

@@ -45,57 +45,57 @@ void XQMainModel::initContextMenu()
XQItem* XQMainModel::addProjectItem( XQNodePtr contentNode ) XQItem* XQMainModel::addProjectItem( XQNodePtr contentNode )
{ {
// wir durchsuchen alle unsere section nach dem passenden content-type, // wir durchsuchen alle unsere sections nach dem passenden content-type,
// hier: content-type beschreibt die // hier: content-type beschreibt den projekt-status
const QString& sectionKey = contentNode->attribute(c_ContentType);
for(const auto& section : _sections ) if( _sections.hasValidSection( sectionKey ) )
{ {
const XQModelSection& section = _sections.sectionByKey( sectionKey );
if( contentNode->attribute( c_ContentType) == section.contentType() )
{
qDebug() << " --- add PROJECT: contentNode: " << contentNode->to_string(); qDebug() << " --- add PROJECT: contentNode: " << contentNode->to_string();
// __fixme! das ist mist! // __fixme! das ist mist!
const XQNodePtr sheetNode = section.sheetRootNode()->first_child(); const XQNodePtr sheetNode = section.sheetRootNode()->first_child();
XQItemList list = _itemFactory.makeRow( XQItemFactory::mSingle, sheetNode, contentNode, "ProjectName"); XQItem* newItem = _itemFactory.makeSingleItem( sheetNode, contentNode->attribute( "ProjectName") );
// den neuen eintrag in die passende section der übersicht eintragen ... // den neuen eintrag in die passende section der übersicht eintragen ...
section.headerItem().appendRow( list ); section.headerItem().appendRow( newItem );
// ... ausklappen...
const QModelIndex index = section.headerItem().index();
_treeTable->expand( index );
// ... und markieren
_treeTable->setCurrentIndex( index );
// quellknoten auch speichern
//newItem->setContentNode( contentNode );
//emit itemCreated( newItem );
XQItem* newItem = dynamic_cast<XQItem*>(list[0]);
// erzeuger sheet node speichern // erzeuger sheet node speichern
newItem->setSheetNode( sheetNode ); newItem->setSheetNode( sheetNode );
expandNewItem(section.headerItem().index() );
return newItem; return newItem;
} }
} /*
for(const auto& section : _sections )
{
if( contentNode->attribute(c_ContentType) == section.contentType() )
{
qDebug() << " --- add PROJECT: contentNode: " << contentNode->to_string();
// __fixme! das ist mist!
const XQNodePtr sheetNode = section.sheetRootNode()->first_child();
XQItem* newItem = _itemFactory.makeSingleItem( sheetNode, contentNode->attribute( "ProjectName") );
// den neuen eintrag in die passende section der übersicht eintragen ...
section.headerItem().appendRow( newItem );
// erzeuger sheet node speichern
newItem->setSheetNode( sheetNode );
expandNewItem(section.headerItem().index() );
return newItem;
}
}
*/
throw XQException( "addProjectItem: main model should not be empty!" ); throw XQException( "addProjectItem: main model should not be empty!" );
} }
void XQMainModel::addSectionItem( const XQModelSection& section, XQItem* projectItem ) void XQMainModel::addSectionItem( const XQModelSection& section, XQItem* projectItem )
{ {
return;
// ich brauche _meine_ section für den sheetNode!
XQNodePtr sheetNode = projectItem->sheetNode()->find_child_by_tag_name("CurrentSection"); XQNodePtr sheetNode = projectItem->sheetNode()->find_child_by_tag_name("CurrentSection");
XQItemList list = _itemFactory.makeRow( XQItemFactory::mSingle, sheetNode, nullptr, c_ContentType ); XQItem* newItem = _itemFactory.makeSingleItem( sheetNode, section.contentType() );
projectItem->appendRow( list ); projectItem->appendRow( newItem );
_treeTable->expand( projectItem->index() ); expandNewItem(projectItem->index() );
} }

View File

@@ -35,6 +35,7 @@ public:
XQItem* addProjectItem( XQNodePtr contentNode ); XQItem* addProjectItem( XQNodePtr contentNode );
void addSectionItem( const XQModelSection& section, XQItem* projectItem ); void addSectionItem( const XQModelSection& section, XQItem* projectItem );
protected: protected:
void initContextMenu() override; void initContextMenu() override;

View File

@@ -88,18 +88,26 @@ void XQMainWindow::initMainWindow()
connect( _actionExit, &QAction::triggered, this, &XQMainWindow::onExit ); connect( _actionExit, &QAction::triggered, this, &XQMainWindow::onExit );
connect( _actionAbout, &QAction::triggered, this, &XQMainWindow::onAbout ); connect( _actionAbout, &QAction::triggered, this, &XQMainWindow::onAbout );
//connect( _mainTreeView, SIGNAL(doubleClicked(QModelIndex)), this, SLOT(onDoubleClicked(QModelIndex)) ); connect( _tabWidget, SIGNAL(tabBarClicked(int)), this, SLOT(onChildViewTabClicked(int)) );
connect( _mainTreeView, SIGNAL(clicked(QModelIndex)), this, SLOT(onTreeItemClicked(QModelIndex)) );
connect( _tabWidget, SIGNAL(tabBarClicked(int)), this, SLOT(onTabClicked(int)) );
//connect(&_mainModel, &QStandardItemModel::itemChanged, this, &XQMainWindow::onTreeItemChanged );
//connect( _mainTreeView, SIGNAL(doubleClicked(QModelIndex)), this, SLOT(onDoubleClicked(QModelIndex)) );
//connect( _mainTreeView, SIGNAL(clicked(QModelIndex)), this, SLOT(onTreeItemClicked(QModelIndex)) );
connect(&_mainModel, &XQViewModel::xqItemChanged, this, &XQMainWindow::onTreeViewItemChanged );
connect( _mainTreeView, &QTreeView::clicked, this, [&,this](const QModelIndex& index)
{
onTreeViewItemClicked( XQItem::xqItemFromIndex(index) );
});
/* /*
connect( &_mainModelView, &XQViewModel::itemCreated, this, [=, this](XQItem* item) connect( &_mainModel, &XQViewModel::itemCreated, this, [=, this](XQItem* item)
{ {
// when a new main tree item has been created ... // when a new main tree item has been created ...
QString pID = item->contentNode()->attribute(c_ProjectID); QString pID = item.contentNode()->attribute(c_ProjectID);
_mainTreeView->setCurrentIndex( item->index() ); _mainTreeView->setCurrentIndex( item.index() );
// ... we set the current view to this node // ... we set the current view to this node
if( _documentStore.contains( pID ) ) if( _documentStore.contains( pID ) )
_tabWidget->setCurrentWidget( _documentStore[pID].modelView->treeTable() ); _tabWidget->setCurrentWidget( _documentStore[pID].modelView->treeTable() );
@@ -109,15 +117,16 @@ void XQMainWindow::initMainWindow()
try try
{ {
// hand over undostack // hand over undostack
_mainModelView.setUndoStack(&_undoStack); _mainModel.setUndoStack(&_undoStack);
// hand over left side navigation tree // hand over left side navigation tree
_mainModelView.setTreeTable(_mainTreeView); _mainModel.setTreeTable(_mainTreeView);
// #1. init the left side main tree view // #1. init the left side main tree view
_mainModelView.initModel( c_MainModelName ); _mainModel.initModel( c_MainModelName );
// #2. load demo data // #2. load demo data
loadDocument( c_DocumentFileName1 ); loadDocument( c_DocumentFileName1 );
//loadDocumentQML( c_DocumentFileName2 ); //loadDocumentQML( c_DocumentFileName2 );
loadDocument( c_DocumentFileName2 );
qDebug() << " --- all here: " << XQNode::s_Count; qDebug() << " --- all here: " << XQNode::s_Count;
@@ -232,7 +241,7 @@ void XQMainWindow::onAbout()
QMessageBox msgBox(QMessageBox::NoIcon, "About", "", QMessageBox::Ok); QMessageBox msgBox(QMessageBox::NoIcon, "About", "", QMessageBox::Ok);
QString text = "<b>xtree concept</b><br>"; QString text = "<b>xtree concept</b><br>";
text += "2024 c.holzheuer<br><br>"; text += "2024-2025 c.holzheuer<br><br>";
text += "<a href=\"https://sourceworx.org/xtree\">sourceworx.org/xtree</a>"; text += "<a href=\"https://sourceworx.org/xtree\">sourceworx.org/xtree</a>";
msgBox.setTextFormat(Qt::RichText); // This allows you to click the link msgBox.setTextFormat(Qt::RichText); // This allows you to click the link
@@ -242,46 +251,70 @@ void XQMainWindow::onAbout()
} }
//! wenn ein item im navigations-baum geklickt wird, soll die document //! wenn ein item im navigations-baum geklickt wird, soll die document
//! view rechts angepasst werden. //! view rechts angepasst werden.
void XQMainWindow::onTreeItemClicked(const QModelIndex& index ) void XQMainWindow::onTreeViewItemClicked( const XQItem& item )
{ {
/*
_mainTreeView->selectionModel()->select(item.index(), QItemSelectionModel::Select);
XQItem& entry = XQItem::xqItemFromIndex(index); if( XQNodePtr contentNode = item.contentNode() )
qDebug() << " --- XXX mainWindow onTreeItemClicked:" << entry.text();
_mainTreeView->selectionModel()->select(index, QItemSelectionModel::Select);
if( XQNodePtr contentNode = entry.contentNode() )
{ {
QString key = contentNode->attribute(c_ProjectID); QString key = contentNode->attribute(c_ProjectID);
qDebug() << " --- FIRZ: key: " << key;
bool isThere = _documentStore.contains(key); bool isThere = _documentStore.contains(key);
if( isThere) if( isThere)
_tabWidget->setCurrentWidget( _documentStore[key].modelView->treeTable() ); _tabWidget->setCurrentWidget( _documentStore[key].viewModel->treeTable() );
}
*/
qDebug() << " --- Tree item CLICK:" << item.text() << " : " << item.itemType().text();
if( item.itemType().text() == "TreeChildType" )
{
setChildTabByName( item.text() );
}
} }
void XQMainWindow::onTreeViewItemChanged(const XQItem& item )
{
qDebug() << " --- TREE VIEW itemChanged:" << item.text() << " : " << item.parent()->text();
// hier müssen wir erst das projekt aktivieren
XQItem* xqItem = static_cast<XQItem*>(item.parent());
onTreeViewItemClicked( *xqItem );
//if( item.itemType().text() == "TreeSectionType" )
{
int idx = _tabWidget->currentIndex();
if(_documentStore.contains(idx) )
{
qDebug() << " --- should toggle: " << item.text();
XQViewModel& childModel = *_documentStore[idx].viewModel;
childModel.onToggleSection(item.text());
}
}
} }
//! beim click auf ein tab im linken fenster wird der navigationsbaum angepasst. //! beim click auf ein tab im linken fenster wird der navigationsbaum angepasst.
void XQMainWindow::onTabClicked( int index ) void XQMainWindow::onChildViewTabClicked( int idx )
{ {
//const QString& key = _documentStore[index].treeItem->attribute( c_ProjectID ); if(_documentStore.contains(idx) )
//qDebug() << " ---- tab clicked: " << index << " : " << _documentStore[index].friendlyName;// << ": " << key; {
//_mainTreeView->setCurrentIndex( _documentStore[index].treeItem->index() ); QModelIndex treeIndex =_documentStore[idx].treeItem->index();
_mainModel.expandNewItem( treeIndex );
} }
}
//! firz
void XQMainWindow::onSectionCreated( const XQModelSection& section ) void XQMainWindow::onSectionCreated( const XQModelSection& section )
{ {
qDebug() << " --- XXX section created: " << section.contentType() << ":" << section.sheetRootNode()->to_string(); qDebug() << " --- XXX section created: " << section.contentType() << ":" << section.sheetRootNode()->to_string();
if( _currentProjectItem ) if( _currentProjectItem )
{ {
_mainModelView.addSectionItem( section, _currentProjectItem ); _mainModel.addSectionItem( section, _currentProjectItem );
} }
} }
@@ -290,16 +323,16 @@ void XQMainWindow::onSectionToggled( const XQModelSection& section )
//qDebug() << " --- XXX section toggled: " << section.contentType() << ":" << section.sheetRootNode()->to_string(); //qDebug() << " --- XXX section toggled: " << section.contentType() << ":" << section.sheetRootNode()->to_string();
} }
QStandardItemModel* createModel() { void XQMainWindow::setChildTabByName( const QString& key )
auto* model = new QStandardItemModel; {
model->setHorizontalHeaderLabels({ "Name" }); for( int i=0; i<_documentStore.size(); ++i )
{
QStandardItem* parent = new QStandardItem("Tiere"); if( key == _documentStore[i].friendlyName)
parent->appendRow(new QStandardItem("Hund")); {
parent->appendRow(new QStandardItem("Katze")); _tabWidget->setCurrentIndex(i);
model->appendRow(parent); return;
}
return model; }
} }
void XQMainWindow::loadDocumentQML( const QString& fileName ) void XQMainWindow::loadDocumentQML( const QString& fileName )
@@ -319,8 +352,6 @@ void XQMainWindow::loadDocumentQML( const QString& fileName )
// das als Namen verwendet wird. // das als Namen verwendet wird.
const QString& fName = contentRoot->friendly_name(); const QString& fName = contentRoot->friendly_name();
QStandardItemModel* model = createModel();
// Ein neues Child-Model erzeugen // Ein neues Child-Model erzeugen
XQChildModel* childModel = new XQChildModel(this); XQChildModel* childModel = new XQChildModel(this);
// die Modelstruktur anlegen // die Modelstruktur anlegen
@@ -331,13 +362,12 @@ void XQMainWindow::loadDocumentQML( const QString& fileName )
XQQuickWidget* quickChild = new XQQuickWidget(_tabWidget); XQQuickWidget* quickChild = new XQQuickWidget(_tabWidget);
//quickChild->setResizeMode(QQuickWidget::SizeViewToRootObject); //quickChild->setResizeMode(QQuickWidget::SizeViewToRootObject);
quickChild->rootContext()->setContextProperty("meinModel", childModel); quickChild->rootContext()->setContextProperty("xtrChildModel", childModel);
quickChild->setSource(QUrl(QStringLiteral("qrc:/quickview.qml"))); quickChild->setSource(QUrl("qrc:/xqtreeview.qml"));
_tabWidget->addTab( quickChild, "Fitze!" ); _tabWidget->addTab( quickChild, "QML:"+fName );
_tabWidget->setCurrentWidget( quickChild ); _tabWidget->setCurrentWidget( quickChild );
quickChild->setResizeMode(QQuickWidget::SizeRootObjectToView); quickChild->setResizeMode(QQuickWidget::SizeRootObjectToView);
} }
//! liest eine XML datei namens 'fileName' //! liest eine XML datei namens 'fileName'
@@ -369,13 +399,13 @@ void XQMainWindow::loadDocument( const QString& fileName )
// 'friendly Name' ist ein Link auf ein anderes Attribute // 'friendly Name' ist ein Link auf ein anderes Attribute
// das als Namen verwendet wird. // das als Namen verwendet wird.
const QString& fName = contentRoot->friendly_name(); const QString& fName = contentRoot->friendly_name();
QString pTitle = QString("Project %1: %2").arg( pID, fName ); QString pTabTitle = QString("Project %1: %2").arg( pID, fName );
// Eine neue TreeView erzeugn und im TabWidget parken. // Eine neue TreeView erzeugn und im TabWidget parken.
XQTreeTable* childTreeView = new XQTreeTable(_tabWidget); XQTreeTable* childTreeView = new XQTreeTable(_tabWidget);
_tabWidget->addTab( childTreeView, pTitle ); _tabWidget->addTab( childTreeView, pTabTitle );
_tabWidget->setCurrentWidget( childTreeView ); _tabWidget->setCurrentWidget( childTreeView );
setWindowTitle( pTitle ); setWindowTitle( pTabTitle );
// Ein neues Child-Model erzeugen // Ein neues Child-Model erzeugen
XQChildModel* childModel = new XQChildModel(this); XQChildModel* childModel = new XQChildModel(this);
@@ -390,8 +420,8 @@ void XQMainWindow::loadDocument( const QString& fileName )
childModel->setTreeTable(childTreeView); childModel->setTreeTable(childTreeView);
// neuen eintrag im übsichts-baum erzeugen // neuen eintrag im übsichts-baum erzeugen
_currentProjectItem = _mainModelView.addProjectItem( contentRoot ); _currentProjectItem = _mainModel.addProjectItem( contentRoot );
_documentStore.addDocument( fileName, pTitle, _currentProjectItem, childModel ); _documentStore.addDocument( fileName, fName, _currentProjectItem, childModel );
// die Modelstruktur anlegen // die Modelstruktur anlegen
childModel->initModel( c_ChildModelName ); childModel->initModel( c_ChildModelName );
@@ -409,7 +439,9 @@ void XQMainWindow::saveDocument( const QString& fileName )
{ {
XQNodeWriter nodeWriter; XQNodeWriter nodeWriter;
int curIdx = _tabWidget->currentIndex(); int curIdx = _tabWidget->currentIndex();
XQNodePtr rootNode = _documentStore[curIdx].treeItem->contentNode(); //XQNodePtr rootNode = _documentStore[curIdx].treeItem->contentNode();
XQNodePtr rootNode = _documentStore[curIdx].viewModel->contentRootNode();
Q_ASSERT(rootNode);
nodeWriter.dumpTree( rootNode, fileName ); nodeWriter.dumpTree( rootNode, fileName );
} }

View File

@@ -35,6 +35,11 @@ public:
public slots: public slots:
virtual void onMyFirz(XQItem& item)
{
qDebug() << " --- myFirz: " << item.text();
}
void onUndo(); void onUndo();
void onRedo(); void onRedo();
@@ -46,30 +51,32 @@ public slots:
void onAbout(); void onAbout();
void onExit(); void onExit();
void onTreeItemClicked(const QModelIndex& index ); void onTreeViewItemClicked( const XQItem& item );
void onTabClicked( int index ); void onTreeViewItemChanged( const XQItem& item );
void onChildViewTabClicked( int index );
//void onItemCreated( XQItem* item ); //void onItemCreated( XQItem* item );
void onSectionCreated( const XQModelSection& section); void onSectionCreated( const XQModelSection& section);
void onSectionToggled( const XQModelSection& section ); void onSectionToggled( const XQModelSection& section );
void setChildTabByName( const QString& key );
static void setupWorkingDir();
protected: protected:
void setupWorkingDir();
// fixme implement // fixme implement
void showDocumnet( const QString& key ){} void showDocument( const QString& key ){}
void loadDocument( const QString& fileName ); void loadDocument( const QString& fileName );
void loadDocumentQML( const QString& fileName ); void loadDocumentQML( const QString& fileName );
void saveDocument( const QString& fileName ); void saveDocument( const QString& fileName );
QUndoStack _undoStack; QUndoStack _undoStack;
XQDocumentStore _documentStore; XQDocumentStore _documentStore;
XQMainModel _mainModelView; XQMainModel _mainModel;
XQItem* _currentProjectItem{}; XQItem* _currentProjectItem{};
//XQChildModel* _currentChildModel{};
}; };

View File

@@ -116,6 +116,8 @@ XQItem::XQPrefixExponentMap XQItem::s_PrefixExponentMap
}; };
//! Default konstruktor, setzt einen ungültigen (dummy)
//! itemType.
XQItem::XQItem() XQItem::XQItem()
: XQItem{XQItemType::staticItemType()} : XQItem{XQItemType::staticItemType()}
@@ -123,6 +125,9 @@ XQItem::XQItem()
} }
//! Default konstruktor mit einem vorhandenen itemType.
XQItem::XQItem( XQItemType* itemType ) XQItem::XQItem( XQItemType* itemType )
: QStandardItem{} : QStandardItem{}
{ {
@@ -130,12 +135,21 @@ XQItem::XQItem( XQItemType* itemType )
} }
//! konstruiert ein daten-item mit zeiger auf 'unser' attribut
//! im übergeordneten content-node.
XQItem::XQItem(XQItemType* itemType, const QString* content ) XQItem::XQItem(XQItemType* itemType, const QString* content )
: XQItem{ itemType } : XQItem{ itemType }
{ {
setContent(content); // hier setzen wir direkt ohne umwege den string pointer
QStandardItem::setData( QVariant::fromValue<const QString*>(content), XQItem::ContentRole );
} }
XQItem::XQItem( XQItemType* itemType, const QString& content )
: XQItem{ itemType }
{
setText(content);
}
//! ruft den copy-konstruktor auf. //! ruft den copy-konstruktor auf.
XQItem* XQItem::clone() const XQItem* XQItem::clone() const
@@ -147,21 +161,35 @@ XQItem* XQItem::clone() const
//! false für ein ungültiges item. 'ungültig' heisst hier, dass nur ein //! false für ein ungültiges item. 'ungültig' heisst hier, dass nur ein
//! mockup-itemtype gesetzt ist. //! mockup-itemtype gesetzt ist.
bool XQItem::isValid() const bool XQItem::isValidX() const
{ {
XQItemType* dummyType = XQItemType::staticItemType(); XQItemType* dummyType = XQItemType::staticItemType();
return QStandardItem::data( XQItem::ItemTypeRole ).value<XQItemType*>() != dummyType; return QStandardItem::data( XQItem::ItemTypeRole ).value<XQItemType*>() != dummyType;
} }
bool XQItem::hasContentNode() const
{
if( column() == 0)
{
QVariant value = QStandardItem::data( XQItem::ContentNodeRole );
return !value.isNull();
}
// sonst: delegieren an den node-Besitzer
QModelIndex pIndex = model()->index( row(), 0 );
if( pIndex.isValid() )
{
XQItem& firstItem = xqItemFromIndex( pIndex );
return firstItem.hasContentNode();
}
}
//! gibt den content-node zurück. //! gibt den content-node zurück.
XQNodePtr XQItem::contentNode() const XQNodePtr XQItem::contentNode() const
{ {
XQNodePtr node = data( ContentNodeRole ).value<XQNodePtr>(); return data( ContentNodeRole ).value<XQNodePtr>();
if( node )
return node;
throw XQException("XQItem::contentNode() nullptr");
} }
@@ -319,37 +347,23 @@ QString XQItem::rawText() const
//! Gibt den string-zeiger auf das attribut aus unseren XQNodePtr zurück. //! Gibt den string-zeiger auf das attribut aus unseren XQNodePtr zurück.
/*
QString* XQItem::content() const QString* XQItem::content() const
{ {
// macht jetzt das, ws draufsteht: gibt einen string* zurück // macht jetzt das, was draufsteht: gibt einen string* zurück
return data( XQItem::ContentRole ).value<QString*>(); return data( XQItem::ContentRole ).value<QString*>();
} }
*/
//! set den content()-string pointer. (als leihgabe) //! Gibt den content-format string zurück
void XQItem::setContent( const QString* content )
{
setData( QVariant::fromValue<const QString*>(content), XQItem::ContentRole );
}
//! holt den schlüssel bzw. bezeicher des content() string aus 'unserem' content knoten.
QString XQItem::contentKey() const
{
return contentNode()->attributes().key_of( rawText() );
}
//! gibt den content-format string zurück
QString XQItem::contentFormat() const QString XQItem::contentFormat() const
{ {
return data( XQItem::ContentFormatRole ).toString(); return data( XQItem::ContentFormatRole ).toString();
} }
//! setz den den content format-string. wird im itemType gespeichert. //! Setzt den den content format-string. wird im itemType gespeichert.
void XQItem::setContentFormat(const QString& contentFormat) void XQItem::setContentFormat(const QString& contentFormat)
{ {
@@ -357,7 +371,7 @@ void XQItem::setContentFormat(const QString& contentFormat)
} }
//! gibt das read-only auswahl-model zurück (wenn dieses item als //! Gibt das read-only auswahl-model zurück (wenn dieses item als
//! combobox gerendert wird). wird im itemType gespeichert. //! combobox gerendert wird). wird im itemType gespeichert.
QStandardItemModel* XQItem::fixedChoices() const QStandardItemModel* XQItem::fixedChoices() const
@@ -413,6 +427,30 @@ QString XQItem::dataRoleName(int role) const
return XQItem::fetchItemDataRoleName(role); return XQItem::fetchItemDataRoleName(role);
} }
bool XQItem::hasContentPtr() const
{
return !QStandardItem::data( XQItem::ContentRole ).isNull();
}
//! Gibt den content()-String zurück, sofern vorhanden.
//! sonst: gibt der ihnalt der Qt::DisplayRole als fallback
//! zurück.
QString XQItem::contentFallBackText() const
{
if( hasContentPtr() )
{
const QString* contentPtr = QStandardItem::data( XQItem::ContentRole ).value<const QString*>();
if(contentPtr)
return *contentPtr;
}
// wenn wir keinen contentPtr haben, benutzen wir als fallback
// die basis-text() role
return QStandardItem::data( Qt::DisplayRole ).toString();
}
//! angespasste variante von qstandarditem::setData. geteilte attribute //! angespasste variante von qstandarditem::setData. geteilte attribute
//! werden vom xqitemtype geholt //! werden vom xqitemtype geholt
@@ -438,33 +476,34 @@ QVariant XQItem::data(int role ) const
return itemType().data(role); return itemType().data(role);
} }
// Zugriffe auf den sichtbaren inhalt geben den inhalt des string pointer case XQItem::ContentRole:
// auf ein feld in content node wieder.
// DisplayRole gibt den formatieren inhalt wieder. die formatierung übernimmt
// der item type
// auf den original inhalt im content node zurückgeben.
case Qt::DisplayRole :
{ {
if( itemType().renderStyle() == XQItem::FormattedStyle)//return "display:"+content(); qDebug() << " --- data(XQItem::ContentRole) should NOT be called!";
return itemType().formatText( *this ); return *QStandardItem::data( XQItem::ContentRole ).value<QString*>();
[[fallthrough]];
} }
// EditRole & ContentRole sollen den 'rohen' inhalt unseres string-pointers // EditRole & ContentRole sollen den 'rohen' inhalt unseres string-pointers
// auf den original inhalt im content node zurückgeben. // auf den original inhalt im content node zurückgeben.
case Qt::EditRole : case Qt::EditRole :
case XQItem::ContentRole:
{ {
// Zugriffe auf den text-inhalt geben den inhalt des string pointer
// auf ein feld in content-node wieder. Wenn kein content-node vorhanden
// ist (single-items), wird Qt::DisplayRole zurückgeliefert.
const QString* contentPtr = QStandardItem::data( XQItem::ContentRole ).value<const QString*>(); return contentFallBackText();
if(contentPtr) //[[fallthrough]];
return *contentPtr; }
static const QString s_dummyContent("-"); // DisplayRole gibt den formatierten inhalt wieder. die formatierung übernimmt
return s_dummyContent; // der item type
case Qt::DisplayRole :
{
QString plainText = contentFallBackText();
if( renderStyle() == XQItem::FormattedStyle)
return XQItemType::formatToSI( plainText, unitType() );
return plainText;
} }
case Qt::ToolTipRole: case Qt::ToolTipRole:
@@ -482,14 +521,28 @@ QVariant XQItem::data(int role ) const
// Das Node-Besitzer-Item wohnt in der ersten Spalte, // Das Node-Besitzer-Item wohnt in der ersten Spalte,
// wenn wir also der Node-Besitzer item sind ... // wenn wir also der Node-Besitzer item sind ...
if( column() == 0) if( column() == 0)
return QStandardItem::data( XQItem::ContentNodeRole ); {
QVariant value = QStandardItem::data( XQItem::ContentNodeRole );
if( !value.isNull() )
return value;
// das gibt immerhin was zurück, was auf nullptr getestet werden kann,
return QVariant::fromValue<XQNodePtr>(nullptr);
// diese variante erzieht uns zur verwendung von 'hasContentNode()'
// was ist besser ?
throw XQException( "ContentNode is nullptr!");
}
// sonst: delegieren an den node-Besitzer // sonst: delegieren an den node-Besitzer
QModelIndex pIndex = model()->index( row(), 0 ); QModelIndex pIndex = model()->index( row(), 0 );
if( pIndex.isValid())
{
XQItem& firstItem = xqItemFromIndex( pIndex ); XQItem& firstItem = xqItemFromIndex( pIndex );
return firstItem.data( XQItem::ContentNodeRole ); return firstItem.data( XQItem::ContentNodeRole );
} }
throw XQException( "Item has no valid index (yet)!");
}
case Qt::StatusTipRole: case Qt::StatusTipRole:
case Qt::WhatsThisRole: case Qt::WhatsThisRole:
@@ -537,7 +590,6 @@ void XQItem::setData(const QVariant& value, int role )
{ {
switch(role) switch(role)
{ {
case RenderStyleRole : case RenderStyleRole :
case EditorTypeRole : case EditorTypeRole :
case UnitTypeRole: case UnitTypeRole:
@@ -557,30 +609,31 @@ void XQItem::setData(const QVariant& value, int role )
return; return;
} }
// set the raw, unformatted data
case ContentRole:
{
// string ptr setzen kann die basis.
break;
}
case Qt::EditRole :
{
qDebug() << " --- setting EDITrole: " << value.toString();
break;
}
case Qt::DisplayRole: case Qt::DisplayRole:
case Qt::EditRole:
case XQItem::ContentRole:
{ {
// what will happen? value is a string ptr ?! QVariant newValue;
qDebug() << " --- setting DISPLAYrole: " << value.toString(); if( itemType().renderStyle() == XQItem::FormattedStyle)
break; newValue = XQItemType::unFormatFromSI( value.toString() );
else
newValue = value;
// fallback: wenns keinen content node gibt, dann nehmen wir
// das standardverfahren.
if( !hasContentPtr() )
return QStandardItem::setData( newValue, Qt::DisplayRole );
// wir nehmen den string pointer
const QString* constContentPtr = QStandardItem::data( XQItem::ContentRole ).value<const QString*>();
// aua, aua, muss aber sein, weil sonst alle anderen consts nicht durchgehalten werden könnten
*const_cast<QString*>(constContentPtr) = newValue.toString();
return;
} }
// alles andere wie gehabt // alles andere wie gehabt
case ContentNodeRole: case ContentNodeRole:
case SheetNodeRole: case SheetNodeRole:
//case TypeKeyRole: not used //case TypeKeyRole: not used
default: default:
break; break;
@@ -694,13 +747,10 @@ XQItem::UnitType XQItem::fetchUnitType(const QString& unitTypeKey)
return s_UnitTypeMap.key(unitTypeKey); return s_UnitTypeMap.key(unitTypeKey);
} }
//! gibt die bezeichung für den gegebenen unitType aus. //! gibt die bezeichung für den gegebenen unitType aus.
QString XQItem::fetchUnitTypeToString( UnitType unitType) QString XQItem::fetchUnitTypeToString( UnitType unitType)
{ {
return s_UnitTypeMap[unitType]; return s_UnitTypeMap[unitType];
} }
/// ---
/// ---
/// ---

View File

@@ -15,6 +15,7 @@
#ifndef XQITEM_H #ifndef XQITEM_H
#define XQITEM_H #define XQITEM_H
#include <QtQmlIntegration>
#include <QVariant> #include <QVariant>
#include <QVector> #include <QVector>
#include <QStandardItem> #include <QStandardItem>
@@ -35,6 +36,8 @@ class XQItemType;
class XQItem : public QStandardItem class XQItem : public QStandardItem
{ {
QML_ELEMENT
friend class XQItemFactory; friend class XQItemFactory;
public: public:
@@ -130,6 +133,7 @@ public:
XQItem(); XQItem();
XQItem( XQItemType* itemType ); XQItem( XQItemType* itemType );
XQItem( XQItemType* itemType, const QString* content ); XQItem( XQItemType* itemType, const QString* content );
XQItem( XQItemType* itemType, const QString& content );
virtual ~XQItem() = default; virtual ~XQItem() = default;
@@ -137,14 +141,16 @@ public:
//! -- not used at the moment -- //! -- not used at the moment --
XQItem* clone() const override; XQItem* clone() const override;
//! //! __fix Tested, ob ein itemtype vorhanden ist.
bool isValid() const; bool isValidX() const;
bool hasContentNode() const;
//! gibt den zu diesem item gehörigen datenknoten zurück //! gibt den zu diesem item gehörigen datenknoten zurück
virtual XQNodePtr contentNode() const; XQNodePtr contentNode() const;
virtual XQNodePtr sheetNode() const;
virtual void setSheetNode( const XQNodePtr& sheetNode ); XQNodePtr sheetNode() const;
void setSheetNode( const XQNodePtr& sheetNode );
XQItemType& itemType() const; XQItemType& itemType() const;
void setItemType( XQItemType* itemTypePtr ); void setItemType( XQItemType* itemTypePtr );
@@ -159,9 +165,8 @@ public:
QString rawText() const; QString rawText() const;
// changed: gibt jetzt den pointer zurück. // changed: gibt jetzt den pointer zurück.
QString* content() const; //QString* content() const;
QString contentKey() const; //void setContent( const QString* content );
void setContent( const QString* content );
// //
// Convenience-Funktionen zum Memberzugriff, die Implementierung // Convenience-Funktionen zum Memberzugriff, die Implementierung
@@ -238,6 +243,10 @@ protected:
XQItem(const XQItem& other) = default; XQItem(const XQItem& other) = default;
XQItem& operator=(const XQItem& other) = default; XQItem& operator=(const XQItem& other) = default;
bool hasContentPtr() const;
QString contentFallBackText() const;
// das ist protected, weil damit der content()-zugriff demoliert werden kann
void setContentNode(const XQNodePtr& contentNode ); void setContentNode(const XQNodePtr& contentNode );
using XQItemFlagMap = QMap<QString,int>; using XQItemFlagMap = QMap<QString,int>;
@@ -259,9 +268,7 @@ protected:
}; };
Q_DECLARE_METATYPE(XQItem);
Q_DECLARE_METATYPE(XQItem::RenderStyle); Q_DECLARE_METATYPE(XQItem::RenderStyle);
Q_DECLARE_METATYPE(XQItem::EditorType); Q_DECLARE_METATYPE(XQItem::EditorType);
Q_DECLARE_METATYPE(XQItem::UnitType); Q_DECLARE_METATYPE(XQItem::UnitType);

View File

@@ -28,6 +28,8 @@
#include <xqviewmodel.h> #include <xqviewmodel.h>
//! firz
class XQItemEditorFactory : public QItemEditorFactory class XQItemEditorFactory : public QItemEditorFactory
{ {
public: public:
@@ -60,6 +62,7 @@ public:
}; };
//! firz
XQItemDelegate::XQItemDelegate( XQViewModel& modelView) XQItemDelegate::XQItemDelegate( XQViewModel& modelView)
: _modelView{modelView} : _modelView{modelView}
@@ -69,6 +72,8 @@ XQItemDelegate::XQItemDelegate( XQViewModel& modelView)
} }
//! firz
XQTreeTable* XQItemDelegate::treeTable() const XQTreeTable* XQItemDelegate::treeTable() const
{ {
return _modelView.treeTable(); return _modelView.treeTable();
@@ -81,14 +86,15 @@ XQItem& XQItemDelegate::xqItemFromIndex( const QModelIndex& index ) const
} }
//! firz
void XQItemDelegate::paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const void XQItemDelegate::paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const
{ {
if( !index.isValid() ) if( !index.isValid() )
qDebug() << " index DEAD!"; qDebug() << " index DEAD!";
XQItem& item = xqItemFromIndex( index ); XQItem& item = xqItemFromIndex( index );
if( item.isValid() )
{
switch( item.renderStyle() ) switch( item.renderStyle() )
{ {
@@ -109,12 +115,11 @@ void XQItemDelegate::paint(QPainter* painter, const QStyleOptionViewItem& option
break; break;
} // switch } // switch
}
QStyledItemDelegate::paint(painter, option, index); QStyledItemDelegate::paint(painter, option, index);
} }
//! einen section header im header-style zeichnen //! einen section header im header-style zeichnen
void XQItemDelegate::drawHeaderStyle(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const void XQItemDelegate::drawHeaderStyle(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const
@@ -150,6 +155,9 @@ void XQItemDelegate::drawHeaderStyle(QPainter* painter, const QStyleOptionViewIt
} }
} }
//! firz
void XQItemDelegate::drawProgressBarStyle(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const void XQItemDelegate::drawProgressBarStyle(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const
{ {
@@ -168,6 +176,9 @@ void XQItemDelegate::drawProgressBarStyle(QPainter *painter, const QStyleOptionV
} }
//! firz
void XQItemDelegate::drawComboBoxStyle(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const void XQItemDelegate::drawComboBoxStyle(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const
{ {
@@ -197,6 +208,8 @@ void XQItemDelegate::drawComboBoxStyle(QPainter *painter, const QStyleOptionView
painter->restore(); painter->restore();
} }
//! firz
void XQItemDelegate::drawSpinBoxStyle(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const void XQItemDelegate::drawSpinBoxStyle(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const
{ {
@@ -214,32 +227,44 @@ void XQItemDelegate::drawSpinBoxStyle(QPainter* painter, const QStyleOptionViewI
} }
//! firz
QSize XQItemDelegate::sizeHint(const QStyleOptionViewItem& option, const QModelIndex& index) const QSize XQItemDelegate::sizeHint(const QStyleOptionViewItem& option, const QModelIndex& index) const
{ {
return QStyledItemDelegate::sizeHint(option, index); return QStyledItemDelegate::sizeHint(option, index);
} }
//! Erzeugt ein editor-widget, sofern ein gültiger content-Ptr vorhanden und ein editor-Type gesetzt ist.
QWidget* XQItemDelegate::createEditor(QWidget* parent, const QStyleOptionViewItem& option, const QModelIndex& index) const QWidget* XQItemDelegate::createEditor(QWidget* parent, const QStyleOptionViewItem& option, const QModelIndex& index) const
{ {
XQItem& item = xqItemFromIndex(index);
return QStyledItemDelegate::createEditor( parent, option, index ); XQItem::EditorType edType = item.editorType();
if( edType == XQItem::NoEditorType )
int editorType = XQItem::xqItemFromIndex(index).editorType();
QWidget* editor = itemEditorFactory()->createEditor(editorType, parent);
if( editor )
{ {
return editor; qDebug() << "---- NO Content or NO EditorType";
return nullptr;
} }
qDebug() << "---- ed type:" << XQItem::fetchEditorTypeToString( edType ) << ": " << edType;
//return QStyledItemDelegate::createEditor( parent, option, index );
return itemEditorFactory()->createEditor(edType, parent);
} }
//! Füttert einen editor mit den model-daten
void XQItemDelegate::setEditorData(QWidget* editor, const QModelIndex& index) const void XQItemDelegate::setEditorData(QWidget* editor, const QModelIndex& index) const
{ {
XQItem& item = xqItemFromIndex( index ); XQItem& item = xqItemFromIndex( index );
switch( item.editorType() ) XQItem::EditorType edType = item.editorType();
if( edType == XQItem::NoEditorType )
return;
switch( edType )
{ {
case XQItemType::ComboBoxType : case XQItemType::ComboBoxType :
{ {
@@ -251,13 +276,26 @@ void XQItemDelegate::setEditorData(QWidget* editor, const QModelIndex& index) co
} }
default: default:
break;
// wir benutzen hier die DisplayRole wenn der Inhalt schon formatiert ist.
int role = item.renderStyle() == XQItem::FormattedStyle ? Qt::DisplayRole : Qt::EditRole;
QVariant value = index.data(role);
QByteArray userProp = editor->metaObject()->userProperty().name();
if (!userProp.isEmpty())
{
if (!value.isValid())
value = QVariant(editor->property(userProp).metaType());
editor->setProperty(userProp, value);
}
} }
QStyledItemDelegate::setEditorData(editor, index);
} }
//! Schreibt die daten aus dem editor ins model zurück
void XQItemDelegate::setModelData(QWidget* editor, QAbstractItemModel* model, const QModelIndex& index) const void XQItemDelegate::setModelData(QWidget* editor, QAbstractItemModel* model, const QModelIndex& index) const
{ {
@@ -265,7 +303,6 @@ void XQItemDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, co
switch( item.editorType() ) switch( item.editorType() )
{ {
case XQItem::ComboBoxType : case XQItem::ComboBoxType :
{ {
QComboBox* comboBox = qobject_cast<QComboBox*>(editor); QComboBox* comboBox = qobject_cast<QComboBox*>(editor);
@@ -280,6 +317,9 @@ void XQItemDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, co
QStyledItemDelegate::setModelData(editor, model, index); QStyledItemDelegate::setModelData(editor, model, index);
} }
//! firz
void XQItemDelegate::updateEditorGeometry(QWidget* editor, const QStyleOptionViewItem& option, const QModelIndex& index) const void XQItemDelegate::updateEditorGeometry(QWidget* editor, const QStyleOptionViewItem& option, const QModelIndex& index) const
{ {
//qDebug() << " --- update Editor Geometry"; //qDebug() << " --- update Editor Geometry";

View File

@@ -99,6 +99,7 @@ XQItemType* XQItemFactory::makeItemType(const XQNodePtr& sheetEntry )
return itemType; return itemType;
} }
//! sucht einen item typ aus der map mit 'vorgefertigen' itemtypen. //! sucht einen item typ aus der map mit 'vorgefertigen' itemtypen.
XQItemType* XQItemFactory::findItemTypeTemplate(const QString& key ) const XQItemType* XQItemFactory::findItemTypeTemplate(const QString& key ) const
@@ -256,10 +257,6 @@ QVariant XQItemFactory::makeVariant( int dataRole, const QString& source ) const
/// ------------------------------------------------ /// ------------------------------------------------
/// ///
/* /*
XQItemList XQItemFactory::makeEmptyRow( const XQNodePtr& contentNode, const XQNodePtr& sheetNode ) XQItemList XQItemFactory::makeEmptyRow( const XQNodePtr& contentNode, const XQNodePtr& sheetNode )
{ {
@@ -304,7 +301,7 @@ XQItemList XQItemFactory::createGenericRow( const XQNodePtr& contentNode, const
//! erzeugt eine item-row. //! erzeugt eine item-row.
XQItemList XQItemFactory::makeRow(CreationMode mode, const XQNodePtr& sheetNode, const XQNodePtr& contentNode, const QString& captionKey ) XQItemList XQItemFactory::makeRow(const XQNodePtr& sheetNode, const XQNodePtr& contentNode )
{ {
XQItemList list; XQItemList list;
@@ -320,24 +317,23 @@ XQItemList XQItemFactory::makeRow(CreationMode mode, const XQNodePtr& sheetNode,
// //
for( const auto& sheetEntry : sheetNode->children() ) for( const auto& sheetEntry : sheetNode->children() )
list.append( makeItem( mode, sheetEntry, contentNode, captionKey ) ); list.append( makeItem( sheetEntry, contentNode ) );
Q_ASSERT(!list.empty()); Q_ASSERT(!list.empty());
// wir merken uns den original content node auch, aber // wir merken uns den original content node auch, aber
// im ersten Item. // im ersten Item. Kann null sein, macht aber erstmal nix.
dynamic_cast<XQItem*>(list[0])->setContentNode(contentNode); dynamic_cast<XQItem*>(list[0])->setContentNode(contentNode);
return list; return list;
} }
//! fixme! unsinn! //! Erzeugt ein XQItem aus einer typ-beschreibung ('sheetNode') und einem daten-knoten ('contentNode').
//! erzeugt ein XQItem aus einer typ-beschreibung ('sheetNode') und einem daten-knoten ('contentNode'). //! Wenn der content node nicht gesetzt ist, wird stattdess das attribut 'Caption' aus der typ-beschreibung
//! wenn der content node nicht gesetzt ist, wird stattdess das attribut 'Caption' aus der typ-beschreibung //! verwendet: es handelt sich dann um ein header item
//! verwendet: es handelt sich dann um ein header item, das erzeugt wurde.
XQItem* XQItemFactory::makeItem(CreationMode mode, const XQNodePtr& sheetNode, const XQNodePtr& contentNode, const QString& captionKey ) XQItem* XQItemFactory::makeItem(const XQNodePtr& sheetNode, const XQNodePtr& contentNode )
{ {
// den itemtype des neuen items rausfinden // den itemtype des neuen items rausfinden
XQItemType* itemType = makeItemType(sheetNode); // throws XQItemType* itemType = makeItemType(sheetNode); // throws
@@ -347,19 +343,10 @@ XQItem* XQItemFactory::makeItem(CreationMode mode, const XQNodePtr& sheetNode, c
// das ist Unterschied vom HeaderItem zum normalen Item: Der Titel kommt aus der Modelbeschreibung, // das ist Unterschied vom HeaderItem zum normalen Item: Der Titel kommt aus der Modelbeschreibung,
// sonst wird der content indirekt über den tag-name des sheetnode geholt // sonst wird der content indirekt über den tag-name des sheetnode geholt
switch( mode ) if( !contentNode )
{ contentPtr = sheetNode->attribute_ptr(c_Caption);
case mHeader: else
contentPtr = sheetNode->attribute_ptr(captionKey);
break;
case mData:
contentPtr = contentNode->attribute_ptr( sheetNode->tag_name() ); contentPtr = contentNode->attribute_ptr( sheetNode->tag_name() );
break;
case mSingle:
contentPtr = contentNode->attribute_ptr( captionKey );
}
XQItem* newItem = new XQItem( itemType, contentPtr); XQItem* newItem = new XQItem( itemType, contentPtr);
@@ -371,3 +358,18 @@ XQItem* XQItemFactory::makeItem(CreationMode mode, const XQNodePtr& sheetNode, c
return newItem; return newItem;
} }
//! Erzeugt ein Item _ohne_ internen content node, sondern
XQItem* XQItemFactory::makeSingleItem( const XQNodePtr& sheetNode, const QString& caption )
{
// den itemtype des neuen items rausfinden
XQItemType* itemType = makeItemType(sheetNode); // throws
XQItem* newItem = new XQItem( itemType, caption);
// __fixme!
if( newItem->isCheckable() )
{
newItem->setCheckState( Qt::Checked );
}
return newItem;
}

View File

@@ -28,23 +28,12 @@ class XQItemFactory : public xsingleton<XQItemFactory>
public: public:
enum CreationMode
{
mHeader,
mData,
mSingle
};
void initItemFactory(const QString& modelSheetFileName ); void initItemFactory(const QString& modelSheetFileName );
XQNodePtr findModelSheet( const QString& modelName ) const; XQNodePtr findModelSheet( const QString& modelName ) const;
//XQItemList makeEmptyRow( const XQNodePtr& contentNode, const XQNodePtr& sheetNode ); XQItemList makeRow( const XQNodePtr& sheetNode, const XQNodePtr& contentNode );
XQItem* makeSingleItem( const XQNodePtr& sheetNode, const QString& caption );
XQItemList makeRow( CreationMode mode, const XQNodePtr& sheetNode, const XQNodePtr& contentNode, const QString& captionKey=c_Caption );
// wozu ist das gut?
//XQItemList createGenericRow( const XQNodePtr& contentNode, const XQNodePtr& sheetNode );
void setItemDataFromString( XQItem& item, const QString& roleKey, const QString& source ) const; void setItemDataFromString( XQItem& item, const QString& roleKey, const QString& source ) const;
@@ -56,7 +45,7 @@ protected:
bool isValid(); bool isValid();
XQItem* makeItem( CreationMode mode, const XQNodePtr& sheetNode, const XQNodePtr& contentNode, const QString& captionKey ); XQItem* makeItem(const XQNodePtr& sheetNode, const XQNodePtr& contentNode );
// shortcuts // shortcuts
using ItemConfigFunc = std::function<void( XQItem* item, const QString& attrValue, XQNodePtr contentNode, XQNodePtr sheetNode )>; using ItemConfigFunc = std::function<void( XQItem* item, const QString& attrValue, XQNodePtr contentNode, XQNodePtr sheetNode )>;

View File

@@ -134,22 +134,9 @@ XQItemType* XQItemType::replaceAttribute( const QVariant& newValue, int role )
} }
//! formatiert den content() string eines items.
QVariant XQItemType::formatText( const XQItem& item ) const
{
XQItem::UnitType uType = unitType();
//qDebug() << " --- formatText: " << XQItem::fetchUnitTypeToString( uType);
const QString& cont = item.rawText();
if( uType != XQItem::NoUnitType )
return formatToSI( cont, uType );
return cont;
}
//! formatiert einen zahlenwert als string mit einheit. //! formatiert einen zahlenwert als string mit einheit.
QString XQItemType::formatToSI( const QString& valueTxt, XQItem::UnitType unitType ) const QString XQItemType::formatToSI( const QString& valueTxt, XQItem::UnitType unitType )
{ {
if( valueTxt.isEmpty() ) if( valueTxt.isEmpty() )
@@ -180,18 +167,18 @@ QString XQItemType::formatToSI( const QString& valueTxt, XQItem::UnitType unitTy
strVal = sysLocale.toString(nVal, 'f', 2); strVal = sysLocale.toString(nVal, 'f', 2);
strPrefix = s_PrefixExponentMap.key(exp); strPrefix = s_PrefixExponentMap.key(exp);
//qDebug() << " convert: " << dVal << " : " << valueTxt << ": " << strVal << ":" << exp << " : " << strPrefix << ": " << nVal; //qDebug() << " convert: " << dVal << " : " << valueTxt << ": " << strVal << ":" << exp << " : " << strPrefix << ": " << nVal;
QString unitStr = XQItem::fetchUnitTypeToString( unitType);
return QString("%1 %2%3").arg( strVal, strPrefix, unitTypeToString() ); return QString("%1 %2%3").arg( strVal, strPrefix, unitStr );
} }
//! entfernt die einheit aus einem formatierten string //! entfernt die einheit aus einem formatierten string
QString XQItemType::unFormatFromSI(const QString& formText ) const QString XQItemType::unFormatFromSI(const QString& formText )
{ {
QString input = formText.simplified(); const QString input = formText.simplified();
// #1: strip numeric part // #1: strip numeric part
if( input.isEmpty() ) if( input.isEmpty() )
return input; return input;

View File

@@ -40,17 +40,14 @@ public:
QVariant data( int role ) const override; QVariant data( int role ) const override;
void setData(const QVariant& value, int role ) override; void setData(const QVariant& value, int role ) override;
QVariant formatText( const XQItem& item ) const;
QString formatToSI(const QString& rawText, XQItem::UnitType unitType ) const;
QString unFormatFromSI(const QString& valueText ) const;
int roleForAttributeKey( const QString& attrKey ); int roleForAttributeKey( const QString& attrKey );
XQItemType* replaceAttribute(const QVariant& newValue, int role ); XQItemType* replaceAttribute(const QVariant& newValue, int role );
QString makeItemTypeKey(); QString makeItemTypeKey();
static XQItemType* staticItemType(); static XQItemType* staticItemType();
static QString formatToSI(const QString& rawText, XQItem::UnitType unitType );
static QString unFormatFromSI(const QString& valueText );
protected: protected:

View File

@@ -15,6 +15,13 @@
#include <QDebug> #include <QDebug>
#include <QApplication> #include <QApplication>
#include <QMetaType> #include <QMetaType>
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QUrl>
#include <QQmlContext>
#include <xqchildmodel.h>
#include <xqquickwidget.h>
#include <xqmainwindow.h> #include <xqmainwindow.h>
@@ -49,25 +56,64 @@ who is who:
*/ */
XQChildModel* createChildModel()
{
XQChildModel* myModel = new XQChildModel();
myModel->initModel( c_ChildModelName );
XQNodeFactory treeLoader;
// xml daten laden
XQNodePtr rawTree = treeLoader.load_tree( qPrintable(c_DocumentFileName1) );
// versteckten root node ignorieren
XQNodePtr contentRoot = rawTree->first_child();
myModel->addModelData( contentRoot->first_child() );
return myModel;
}
using namespace Qt::Literals::StringLiterals;
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
QApplication app(argc, argv); QApplication app(argc, argv);
//app.setStyle("WindowsVista");
/*
// Signal für einzelne QStandardItem-Änderungen
connect(model, &QStandardItemModel::itemChanged,
this, [](QStandardItem *changedItem){
QVariant state = changedItem->data(Qt::CheckStateRole);
qDebug() << "Neuer Check-State:" << state.toInt();
});
*/
//app.setStyle("fusion");
XQMainWindow window; XQMainWindow window;
window.show(); window.show();
/*
QApplication app(argc, argv);
XQMainWindow::setupWorkingDir();
XQItemFactory::instance().initItemFactory( c_ModelSheetFileName );
XQChildModel* myModel = createChildModel();
qmlRegisterType< XQChildModel>("MyApp.Models", 1, 0, "MyChildModel");
QQmlApplicationEngine engine;
engine.rootContext()->setContextProperty("myChildModel", myModel);
QObject::connect(
&engine,
&QQmlApplicationEngine::objectCreationFailed,
&app,
[]() { QCoreApplication::exit(-1); },
Qt::QueuedConnection);
qDebug() << " fitz!";
engine.load( QUrl(QStringLiteral("qrc:/dummyview.qml")) );
//engine.load( QUrl(QStringLiteral("qrc:/xqtableview.qml")) );
qDebug() << " hhakl!";
*/
return app.exec(); return app.exec();
} }

View File

@@ -31,7 +31,7 @@ void XQNodeStore::dumpList( const QString& title ) const
//! kostruktor. übergibt command-type und die aufrufende modelView. //! kostruktor. übergibt command-type und die aufrufende modelView.
XQCommand::XQCommand(CmdType cmdType, XQViewModel* modelView ) XQCommand::XQCommand(CmdType cmdType, XQViewModel* modelView )
: _cmdType{ cmdType }, _model(modelView) : _cmdType{ cmdType }, _viewModel(modelView)
{ {
} }
@@ -66,7 +66,7 @@ void XQCommand::setCommandType( XQCommand::CmdType cmdType )
void XQCommand::redo() void XQCommand::redo()
{ {
_model->onCommandRedo( *this ); _viewModel->onCommandRedo( *this );
} }
@@ -74,7 +74,7 @@ void XQCommand::redo()
void XQCommand::undo() void XQCommand::undo()
{ {
_model->onCommandUndo( *this ); _viewModel->onCommandUndo( *this );
} }
@@ -121,7 +121,7 @@ void XQCommand::saveNodes( const QModelIndexList& list )
//! erzeugt einen string aus dem command-type, fürs debuggen. //! erzeugt einen string aus dem command-type, fürs debuggen.
QString XQCommand::toString() QString XQCommand::toString() const
{ {
static QMap<CmdType,QString> s_CmdTypeMap static QMap<CmdType,QString> s_CmdTypeMap

View File

@@ -80,12 +80,12 @@ public:
void redo() override; void redo() override;
void undo() override; void undo() override;
QString toString(); QString toString() const;
protected: protected:
CmdType _cmdType{cmdInvalid}; CmdType _cmdType{cmdInvalid};
XQViewModel* _model{}; // needed for redo() / undo() XQViewModel* _viewModel{}; // needed for redo() / undo()
QModelIndex _originIndex; QModelIndex _originIndex;
/* /*

View File

@@ -12,7 +12,7 @@
***************************************************************************/ ***************************************************************************/
#include <xqmodelsectionlist.h> #include <xqsectionmanager.h>
//! kontstruktor. übergibt den start-index und einen model-knoten mit der beschreibung //! kontstruktor. übergibt den start-index und einen model-knoten mit der beschreibung
@@ -40,9 +40,9 @@ bool XQModelSection::isValid() const
return _modelIndex.isValid() && _sectionRootNode; return _modelIndex.isValid() && _sectionRootNode;
} }
const QModelIndex& XQModelSection::modelIndex() const QModelIndex XQModelSection::startIndex() const
{ {
return _modelIndex; return _modelIndex.operator QModelIndex();
} }
XQNodePtr XQModelSection::sectionRootNode() const XQNodePtr XQModelSection::sectionRootNode() const
@@ -72,7 +72,7 @@ XQNodePtr XQModelSection::contentRootNode() const
return _contentRootNode; return _contentRootNode;
} }
void XQModelSection::setContentRootNode( const XQNodePtr contentRootNode ) void XQModelSection::setContentRootNode( const XQNodePtr contentRootNode ) const
{ {
_contentRootNode = contentRootNode; _contentRootNode = contentRootNode;
} }
@@ -80,7 +80,7 @@ void XQModelSection::setContentRootNode( const XQNodePtr contentRootNode )
//! gibt die zeile des start-index zurück. //! gibt die zeile des start-index zurück.
int XQModelSection::XQModelSection::row() const int XQModelSection::XQModelSection::firstRow() const
{ {
return _modelIndex.row(); return _modelIndex.row();
} }
@@ -104,89 +104,98 @@ XQItem& XQModelSection::XQModelSection::headerItem() const
//! testet, ob die unter 'sectionKey' eine gültige section vorhanden ist. //! testet, ob die unter 'sectionKey' eine gültige section vorhanden ist.
bool XQModelSectionList::hasValidSection(const QString& sectionKey) const bool XQSectionManager::hasValidSection(const QString& sectionKey) const
{ {
if (!contains(sectionKey) ) if (!_sections.contains(sectionKey) )
return false; return false;
return at(sectionKey).isValid(); return _sections.at(sectionKey).isValid();
} }
const XQModelSection& XQSectionManager::sectionByKey( const QString& sectionKey ) const
//! gibt für einen model index die 'zuständige' section zurück.
const XQModelSection& XQModelSectionList::sectionFromIndex( const QModelIndex& index ) const
{ {
return sectionFromRow( index.row() ); if( hasValidSection( sectionKey ) )
return _sections.at(sectionKey);
static const XQModelSection s_DummySection;
return s_DummySection;
} }
//! gibt für eine zeile die 'zuständige' section zurück: der bestand an section wird //! gibt für eine zeile die 'zuständige' section zurück: der bestand an section wird
//! nach der passenden section durchsucht. //! nach der passenden section durchsucht.
const XQModelSection& XQModelSectionList::sectionFromRow(int itemRow ) const const XQModelSection& XQSectionManager::sectionByRow(int itemRow ) const
{ {
int i = _sections.size() - 1;
int i = size() - 1;
for (; i >= 0; --i) for (; i >= 0; --i)
{ {
if ( at(i).modelIndex().row() < itemRow ) if ( _sections.at(i).startIndex().row() < itemRow )
return at(i); return _sections.at(i);
} }
static XQModelSection s_DummySection; static XQModelSection s_DummySection;
return s_DummySection; return s_DummySection;
} }
const XQModelSection& XQSectionManager::createSection(const QString& sectionKey, const QModelIndex& modelIndex, XQNodePtr sheetNode)
//! ermittelt die erste zeile einer section.
int XQModelSectionList::firstRow(const QModelIndex& idx) const
{ {
return sectionFromRow(idx.row() ).row(); // 6. jetzt können wir auch die sction erzeugen
XQModelSection section(modelIndex, sheetNode );
_sections.addAtKey( sectionKey, section);
return sectionByKey(sectionKey);
} }
//! ermittelt die zeile unterhalb des gegebenen modelindex, //! ermittelt die zeile unterhalb des gegebenen modelindex,
//! zum einfügen neuer items ebendort. //! zum einfügen neuer items ebendort.
int XQModelSectionList::lastRow(const QModelIndex& idx) const /*
int XQSectionManager::lastRow(const QModelIndex& idx) const
{ {
return lastRow(sectionFromRow(idx.row())); return lastRow(sectionByRow(idx.row()));
} }
//! ermittelt die zeile unterhalb der gegebenen section, //! ermittelt die zeile unterhalb der gegebenen section,
//! zum einfügen neuer items ebendort. //! zum einfügen neuer items ebendort.
*/
int XQModelSectionList::lastRow(const XQModelSection& section ) const int XQSectionManager::lastRow(const XQModelSection& section ) const
{ {
//qDebug() << " -- last row in section: " << section.modelIndex.data().toString() << " --> " << section.modelIndex.row(); qDebug() << " -- last row in section: " << section.startIndex().data().toString() << " --> " << section.startIndex().row();
// row() der section unterhalb dieser // row() der section unterhalb dieser
// __fix? index mit speichern? // __fix? index mit speichern?
int index = indexOf(section); int index = _sections.indexOf(section);
if (index > -1) if (index > -1)
{ {
// last section? return last row of model // last section? return last row of model
if (index == size() - 1) if (index == _sections.size() - 1)
return section.modelIndex().model()->rowCount();// - 1; return section.startIndex().model()->rowCount() - 1;
// return row above the row of the next section -> last row of given section // return row above the row of the next section -> last row of given section
return at(index+1).row(); return _sections.at(index+1).firstRow() - 1;
} }
return -1; return -1;
} }
XQSectionRange XQSectionManager::sectionRange(const XQModelSection& section ) const
{
qDebug() << " ---- Section RANGE: " << section.startIndex().row() << " -> " << lastRow(section);
return XQSectionRange{ section.startIndex().row(), lastRow(section) };
}
//! gibt alle sections aus, zum ankucken. //! gibt alle sections aus, zum ankucken.
void XQModelSectionList::dump() const void XQSectionManager::dump() const
{ {
qDebug() << " --- sections dump(): " <<size() << " entries."; qDebug() << " --- sections dump(): " <<_sections.size() << " entries.";
for( int i = 0; i<size(); ++i ) for( int i = 0; i<_sections.size(); ++i )
{ {
QModelIndex idx = at(i).modelIndex(); QModelIndex idx = _sections.at(i).startIndex();
qDebug() << " --- sections:" << i << "row: " << idx.row() << " keyOf(i): " << keyOf(i) << " indexData: "<< idx.data().toString() << " itemData: " << XQItem::xqItemFromIndex(idx).data(Qt::DisplayRole).toString(); qDebug() << " --- sections:" << i << "row: " << idx.row() << " keyOf(i): " << _sections.keyOf(i) << " indexData: "<< idx.data().toString() << " itemData: " << XQItem::xqItemFromIndex(idx).data(Qt::DisplayRole).toString();
} }
} }

View File

@@ -12,17 +12,18 @@
***************************************************************************/ ***************************************************************************/
#ifndef XQMODELSECTIONLIST_H #ifndef XQSECTIONMANAGER_H
#define XQMODELSECTIONLIST_H #define XQSECTIONMANAGER_H
#include <QPersistentModelIndex> #include <QPersistentModelIndex>
#include <xqmaptor.h> #include <xqmaptor.h>
#include <xqitem.h> #include <xqitem.h>
/**
* @brief Struct containing data for a header section
*/
//! Daten zur beschreibung einer 'sektion' des models.
class XQModelSection class XQModelSection
{ {
@@ -35,13 +36,13 @@ public:
bool operator==(const XQModelSection& other) const; bool operator==(const XQModelSection& other) const;
bool isValid() const; bool isValid() const;
int row() const; int firstRow() const;
const QModelIndex& modelIndex() const; QModelIndex startIndex() const;
XQNodePtr sectionRootNode() const; XQNodePtr sectionRootNode() const;
XQNodePtr sheetRootNode() const; XQNodePtr sheetRootNode() const;
XQNodePtr contentRootNode() const; XQNodePtr contentRootNode() const;
void setContentRootNode( const XQNodePtr dataRootNode ); void setContentRootNode( const XQNodePtr dataRootNode ) const;
const QString& contentType() const; const QString& contentType() const;
XQItem& headerItem() const; XQItem& headerItem() const;
@@ -50,32 +51,42 @@ protected:
QPersistentModelIndex _modelIndex; QPersistentModelIndex _modelIndex;
XQNodePtr _sectionRootNode{}; mutable XQNodePtr _sectionRootNode{};
XQNodePtr _contentRootNode{}; mutable XQNodePtr _contentRootNode{};
}; };
Q_DECLARE_METATYPE(XQModelSection) Q_DECLARE_METATYPE(XQModelSection)
/** //! Erste und letzte ziele einer XQModelSection
* @brief Maptor containing all header sections. struct XQSectionRange
*/ {
int firstRow{-1};
int lastRow{-1};
};
class XQModelSectionList : public XQMaptor<XQModelSection>
//! struktur, die alle sections enthält
class XQSectionManager
{ {
public: public:
bool hasValidSection(const QString& sectionKey) const; bool hasValidSection(const QString& sectionKey) const;
const XQModelSection& sectionFromRow( int row ) const; const XQModelSection& sectionByKey( const QString& sectionKey ) const;
const XQModelSection& sectionFromIndex( const QModelIndex& index ) const; const XQModelSection& sectionByRow( int row ) const;
int firstRow(const QModelIndex& idx) const; const XQModelSection& createSection(const QString& sectionKey, const QModelIndex& modelIndex, XQNodePtr sheetNode);
int lastRow(const QModelIndex& idx) const;
int lastRow(const XQModelSection& section ) const; int lastRow(const XQModelSection& section ) const;
XQSectionRange sectionRange(const XQModelSection &section) const;
void dump()const override; void dump()const;
protected:
XQMaptor<XQModelSection> _sections;
}; };
#endif // XQMODELSECTIONLIST_H #endif // XQSECTIONMANAGER_H

View File

@@ -35,18 +35,28 @@
void showItemList( const XQItemList& list) void showItemList( const XQItemList& list)
{ {
for(const auto& entry : list ) for(const auto& entry : list )
qDebug() << " --- itemList: " << ((XQItem*)entry)->content(); qDebug() << " --- itemList: " << entry->text();
qDebug(); qDebug();
} }
//! Konstruktur mit parent. //! Konstruktor mit parent.
XQViewModel::XQViewModel( QObject* parent ) XQViewModel::XQViewModel( QObject* parent )
: QStandardItemModel{ parent }, _itemFactory{ XQItemFactory::instance() } : QStandardItemModel{ parent }, _itemFactory{ XQItemFactory::instance() }
{ {
invisibleRootItem()->setData( "[rootItem]", Qt::DisplayRole ); invisibleRootItem()->setData( "[rootItem]", Qt::DisplayRole );
setItemPrototype( new XQItem ); setItemPrototype( new XQItem );
// auf änderungen kann in den unterklassen reagiert werden
connect(this, &QStandardItemModel::itemChanged, this, [this](QStandardItem *item)
{
XQItem* xqItem = static_cast<XQItem*>(item);
emit xqItemChanged( *xqItem );
});
//qRegisterMetaType<XQItem>("XQItem");
} }
@@ -59,7 +69,14 @@ const XQItem& XQViewModel::xqRootItem()
// dynamisch über den ItemData Mechanismus wie in QStandardItem // dynamisch über den ItemData Mechanismus wie in QStandardItem
return *static_cast<XQItem*>(invisibleRootItem()); return *static_cast<XQItem*>(invisibleRootItem());
}
//! Gibt den daten root node des models zurück.
XQNodePtr XQViewModel::contentRootNode()
{
return _contentRoot;
} }
@@ -83,6 +100,16 @@ XQItem& XQViewModel::xqFirstItem(int row) const
return *static_cast<XQItem*>( QStandardItemModel::item(row) ); return *static_cast<XQItem*>( QStandardItemModel::item(row) );
} }
void XQViewModel::expandNewItem(const QModelIndex& index)
{
if( _treeTable )
{
// ... ausklappen...
_treeTable->expand( index );
// ... und markieren
_treeTable->setCurrentIndex( index );
}
}
//! initialisiert dieses model über den namen. Es wird hier //! initialisiert dieses model über den namen. Es wird hier
//! nur die strukur erzeugt, keine inhalte. //! nur die strukur erzeugt, keine inhalte.
@@ -111,7 +138,7 @@ void XQViewModel::initModel(const QString& modelName)
const XQNodePtr header = sectionNode->find_child_by_tag_name( c_Header ); const XQNodePtr header = sectionNode->find_child_by_tag_name( c_Header );
if( header ) if( header )
{ {
XQItemList list = _itemFactory.makeRow( XQItemFactory::mHeader, header, nullptr ); XQItemList list = _itemFactory.makeRow( header, nullptr );
addSection(list, sectionNode ); addSection(list, sectionNode );
} }
} }
@@ -138,9 +165,9 @@ void XQViewModel::addSection(const XQItemList& list, const XQNodePtr& sectionNod
// 5. das erzeugt dann auch valide indices // 5. das erzeugt dann auch valide indices
appendRow(list); appendRow(list);
const QString &sectionKey = sectionNode->attribute(c_ContentType);
// 6. jetzt können wir auch die sction erzeugen // 6. jetzt können wir auch die sction erzeugen
XQModelSection section(list[0]->index(), sectionNode ); const XQModelSection& section = _sections.createSection( sectionKey, list[0]->index(), sectionNode );
_sections.addAtKey(sectionNode->attribute( c_ContentType), section);
// ... und es der welt mitteilen. // ... und es der welt mitteilen.
emit sectionCreated( section ); emit sectionCreated( section );
@@ -148,6 +175,43 @@ void XQViewModel::addSection(const XQItemList& list, const XQNodePtr& sectionNod
} }
//! SLOT, toggled die section mit dem 'sectionKey' (hier: contentType)
void XQViewModel::onToggleSection(const QString& sectionKey )
{
toggleSection( _sections.sectionByKey(sectionKey) );
}
//! toggled die gegebene model section.
void XQViewModel::toggleSection( const XQModelSection& section )
{
qDebug() << " --- toggleSection: " << section.contentType();
if( section.isValid() && _treeTable )
{
XQSectionRange pos = _sections.sectionRange(section);
//int fstRow = _sections.firstRow(index);
//int lstRow = _sections.lastRow(index);
//_treeTable->toggleRowsHidden(fstRow, lstRow);
// hier nicht!?
//emit sectionToggled(section);
}
}
/*
//! SLOT als weiterleitung vom SIGNAL itemchanged
void XQViewModel::onItemChanged(XQItem* item )
{
qDebug() << " --- BASE item changed: " << item->text();
}
*/
//! SLOT, der aufgerufen wird, wenn eine edit-action getriggert wurde. //! SLOT, der aufgerufen wird, wenn eine edit-action getriggert wurde.
void XQViewModel::onActionTriggered(QAction* action) void XQViewModel::onActionTriggered(QAction* action)
@@ -195,35 +259,10 @@ void XQViewModel::onActionTriggered(QAction* action)
} }
/*
switch (command.commandType())
{
case XQCommand::cmdToggleSection:
return cmdToggleSection( command.originIndex() );
case XQCommand::cmdCut:
return cmdCut( command );
case XQCommand::cmdPaste:
return cmdPaste( command );
case XQCommand::cmdNew:
return cmdNew( command );
case XQCommand::cmdDelete:
return cmdDelete( command );
case XQCommand::cmdMove:
break;
default:
qDebug() << " --- onCommandRedo: default: not handled: " << command.toString();
}
*/
//! führt die 'redo' action des gegebenen commnds aus. //! führt die 'redo' action des gegebenen commnds aus.
void XQViewModel::onCommandRedo( XQCommand& command ) void XQViewModel::onCommandRedo( const XQCommand& command )
{ {
static MemCallMap redoCalls static MemCallMap redoCalls
{ {
@@ -249,45 +288,10 @@ void XQViewModel::onCommandRedo( XQCommand& command )
} }
} }
/*
try
{
switch (command.commandType())
{
case XQCommand::cmdToggleSection:
return cmdToggleSection( command.originIndex() );
break;
// undo Cut -> perform undoCut
case XQCommand::cmdCut:
return cmdCutUndo( command );
// undo Paste -> perform Cut
case XQCommand::cmdPaste:
return cmdPasteUndo( command );
// undo Move -> perform move back
case XQCommand::cmdMove:
// not yet implemented
break;
// undo New -> perform Delete
case XQCommand::cmdNew:
cmdNewUndo( command );
break;
// undo Delete -> perform New
case XQCommand::cmdDelete:
qDebug() << " --- onCommandUndo: delete: " << command.toString();
return cmdDeleteUndo( command );
default:
qDebug() << " --- onCommandUndo: default: not handled: " << command.toString();
}
*/
//! führt die 'undo' action des gegebenen commnds aus. //! führt die 'undo' action des gegebenen commnds aus.
void XQViewModel::onCommandUndo( XQCommand& command ) void XQViewModel::onCommandUndo( const XQCommand& command )
{ {
qDebug() << " --- onCommandUndo: count: " << XQNode::s_Count; qDebug() << " --- onCommandUndo: count: " << XQNode::s_Count;
@@ -319,7 +323,7 @@ void XQViewModel::onCommandUndo( XQCommand& command )
//! markierte knoten entfernen, 'command' enthält die liste //! markierte knoten entfernen, 'command' enthält die liste
void XQViewModel::cmdCut( XQCommand& command ) void XQViewModel::cmdCut( const XQCommand& command )
{ {
// wir gehen rückwärts über alle gemerkten knoten ... // wir gehen rückwärts über alle gemerkten knoten ...
for (auto it = command.rbegin(); it != command.rend(); ++it) for (auto it = command.rbegin(); it != command.rend(); ++it)
@@ -340,19 +344,19 @@ void XQViewModel::cmdCut( XQCommand& command )
//! entfernte knoten wieder einfügen , 'command' enthält die liste //! entfernte knoten wieder einfügen , 'command' enthält die liste
void XQViewModel::cmdCutUndo( XQCommand& command ) void XQViewModel::cmdCutUndo( const XQCommand& command )
{ {
// die anfangsposition // die anfangsposition
int itmPos = command.first().itemPos; int itmPos = command.first().itemPos;
// die 'zuständige' section rausfinden // die 'zuständige' section rausfinden
const XQModelSection& section = _sections.sectionFromRow( itmPos ); const XQModelSection& section = _sections.sectionByRow( itmPos );
// über alle einträge ... // über alle einträge ...
for (auto& entry : command ) for (auto& entry : command )
{ {
const XQNodePtr& savedNode = entry.contentNode; const XQNodePtr& savedNode = entry.contentNode;
// __fix! should not be _contentRoot! // __fix! should not be _contentRoot!
savedNode->add_me_at( entry.nodePos, _contentRoot ); savedNode->add_me_at( entry.nodePos, _contentRoot );
XQItemList list = _itemFactory.makeRow( XQItemFactory::mData, section.sheetRootNode(), savedNode ); XQItemList list = _itemFactory.makeRow( section.sheetRootNode(), savedNode );
XQItem& firstItem = *((XQItem*)list[0]); XQItem& firstItem = *((XQItem*)list[0]);
qDebug() << " --- Cut Undo: " << firstItem.text() << " " << firstItem.row() << " id#" << entry.contentNode->_id << " count: " << entry.contentNode.use_count(); qDebug() << " --- Cut Undo: " << firstItem.text() << " " << firstItem.row() << " id#" << entry.contentNode->_id << " count: " << entry.contentNode.use_count();
@@ -364,7 +368,7 @@ void XQViewModel::cmdCutUndo( XQCommand& command )
//! clipboard inhalte einfügen //! clipboard inhalte einfügen
void XQViewModel::cmdPaste( XQCommand& command ) void XQViewModel::cmdPaste( const XQCommand& command )
{ {
// selection holen ... // selection holen ...
QItemSelectionModel* selectionModel = treeTable()->selectionModel(); QItemSelectionModel* selectionModel = treeTable()->selectionModel();
@@ -379,7 +383,7 @@ void XQViewModel::cmdPaste( XQCommand& command )
int nodePos = item.contentNode()->own_pos()+1; int nodePos = item.contentNode()->own_pos()+1;
// die zugehörige section finden // die zugehörige section finden
const XQModelSection& section = _sections.sectionFromRow( insRow-1 ); const XQModelSection& section = _sections.sectionByRow( insRow-1 );
// wir pasten das clipboard // wir pasten das clipboard
for (auto& entry : _clipBoard ) for (auto& entry : _clipBoard )
{ {
@@ -388,7 +392,7 @@ void XQViewModel::cmdPaste( XQCommand& command )
// ... diesen einfügen ... // ... diesen einfügen ...
newNode->add_me_at( nodePos ); newNode->add_me_at( nodePos );
// ... und damit eine frische item-row erzeugen // ... und damit eine frische item-row erzeugen
XQItemList list = _itemFactory.makeRow( XQItemFactory::mData, section.sheetRootNode(), newNode ); XQItemList list = _itemFactory.makeRow( section.sheetRootNode(), newNode );
insertRow( insRow, list ); insertRow( insRow, list );
// die neue item-row selektieren // die neue item-row selektieren
const QModelIndex& selIdx = list[0]->index(); const QModelIndex& selIdx = list[0]->index();
@@ -399,14 +403,16 @@ void XQViewModel::cmdPaste( XQCommand& command )
} }
// unsere änderungen merken fürs 'undo' // unsere änderungen merken fürs 'undo'
command.saveNodes( selectionModel->selectedRows() );
/// fix_xx
const_cast<XQCommand&>(command).saveNodes( selectionModel->selectedRows() );
} }
//! einfügen aus dem clipboard wieder rückgängig machen //! einfügen aus dem clipboard wieder rückgängig machen
void XQViewModel::cmdPasteUndo( XQCommand& command ) void XQViewModel::cmdPasteUndo( const XQCommand& command )
{ {
command.dumpList("Paste UNDO"); command.dumpList("Paste UNDO");
// wir gehen rückwärts über alle markieren knoten ... // wir gehen rückwärts über alle markieren knoten ...
@@ -427,7 +433,7 @@ void XQViewModel::cmdPasteUndo( XQCommand& command )
//! entfernen der selection ohne copy in clipboard. //! entfernen der selection ohne copy in clipboard.
void XQViewModel::cmdDelete( XQCommand& command ) void XQViewModel::cmdDelete( const XQCommand& command )
{ {
// wir gehen rückwärts über alle markieren knoten ... // wir gehen rückwärts über alle markieren knoten ...
for (auto it = command.rbegin(); it != command.rend(); ++it) for (auto it = command.rbegin(); it != command.rend(); ++it)
@@ -442,9 +448,9 @@ void XQViewModel::cmdDelete( XQCommand& command )
} }
} }
//! macht 'delete' wirder rückgängig. //! macht 'delete' wieder rückgängig.
void XQViewModel::cmdDeleteUndo( XQCommand& command ) void XQViewModel::cmdDeleteUndo( const XQCommand& command )
{ {
} }
@@ -452,66 +458,55 @@ void XQViewModel::cmdDeleteUndo( XQCommand& command )
//! legt eine neue, leere zeile an. //! legt eine neue, leere zeile an.
void XQViewModel::cmdNew( XQCommand& command ) void XQViewModel::cmdNew( const XQCommand& command )
{ {
// __fix
/*
const QModelIndex& origin = command.originIndex(); const QModelIndex& origin = command.originIndex();
if( !origin.isValid() )
throw XQException("cmdNewRow failed: index not valid ");
XQItem* target = xqItemFromIndex( origin ); XQItem& target = xqItemFromIndex( origin );
// current data node // current data node
XQNodePtr node = target->contentNode(); XQNodePtr node = target.contentNode();
// we create a new data node // we create a new data node
//XQNodePtr newNode = new XQNodePtr( node->tag_name(), node->parent() ); XQNodePtr newNode = XQNode::make_node( node->tag_name(), node->tag_value() );
XQNodePtr newNode = XQNode::make_node( node->tag_name(), node->tag_value(), node->parent() );
// store node in node->parent() // store node in node->parent()
//node->add_before_me( newNode ); newNode->add_me_at( node->own_pos(), node->parent() );
// store node also in 'command' to enable undo
const XQModelSection& section = _sections.sectionFromIndex( origin );
// create new item row
XQItemList list = _itemFactory.createGenericRow( newNode, section.sheetRootNode );
// add it to the treeview ... //...
const XQModelSection& section = _sections.sectionByRow( origin.row() );
// neue, leere zeile erzeugen ...
XQItemList list =_itemFactory.makeRow( section.sheetRootNode(), newNode );
// ... zur treeview hinzufügen ...
insertRow( origin.row(), list ); insertRow( origin.row(), list );
// ... editierbar machen ...
QModelIndex newIndex = list[0]->index();
treeTable()->setCurrentIndex( newIndex );
treeTable()->edit( newIndex );
// ,,, und fürs undo speichern
const_cast<XQCommand&>(command).saveNodes( {newIndex} );
// ... and make it ...
treeTable()->setCurrentIndex( list[0]->index() );
// ... editable
treeTable()->edit( list[0]->index() );
*/
} }
//! entfernt die neu angelegte zeile. //! entfernt die neu angelegte zeile.
void XQViewModel::cmdNewUndo( XQCommand& command ) void XQViewModel::cmdNewUndo( const XQCommand& command )
{ {
cmdDelete( command );
} }
//! schaltet eine section sichtbar oder unsichtbar. //! schaltet eine section sichtbar oder unsichtbar.
void XQViewModel::cmdToggleSection( XQCommand& command ) void XQViewModel::cmdToggleSection( const XQCommand& command )
{ {
const QModelIndex& index = command.originIndex(); const QModelIndex& index = command.originIndex();
Q_ASSERT(index.isValid()); Q_ASSERT(index.isValid());
toggleSection( _sections.sectionByRow(index.row()) );
int fstRow = _sections.firstRow( index );
int lstRow = _sections.lastRow( index );
bool hidden =_treeTable->isRowHidden( fstRow, _treeTable->rootIndex() );
for (int row = fstRow; row < lstRow; ++row )
_treeTable->setRowHidden( row, _treeTable->rootIndex(), !hidden );
emit sectionToggled( _sections.sectionFromIndex(index) );
} }
//! git die treetable zurück //! gibt die treetable zurück
XQTreeTable* XQViewModel::treeTable() XQTreeTable* XQViewModel::treeTable()
{ {
@@ -524,7 +519,7 @@ void XQViewModel::setTreeTable(XQTreeTable* mainView )
{ {
// store view for direct access: the maintree // store view for direct access: the maintree
_treeTable = mainView; _treeTable = mainView;
// connect myself as model to the mainview // set myself as model to the mainview
_treeTable->setModel(this); _treeTable->setModel(this);
XQItemDelegate* delegate = new XQItemDelegate( *this ); XQItemDelegate* delegate = new XQItemDelegate( *this );
_treeTable->setItemDelegate( delegate ); _treeTable->setItemDelegate( delegate );

View File

@@ -19,9 +19,10 @@
#include <QMenu> #include <QMenu>
#include <QStandardItemModel> #include <QStandardItemModel>
#include <QAbstractItemView> #include <QAbstractItemView>
#include <QtQmlIntegration>
#include <xqsimpleclipboard.h> #include <xqsimpleclipboard.h>
#include <xqmodelsectionlist.h> #include <xqsectionmanager.h>
#include <xqitemfactory.h> #include <xqitemfactory.h>
#include <xqcontextmenu.h> #include <xqcontextmenu.h>
@@ -36,12 +37,15 @@ class XQCommand;
class XQViewModel : public QStandardItemModel class XQViewModel : public QStandardItemModel
{ {
Q_OBJECT Q_OBJECT
QML_ELEMENT
public: public:
XQViewModel(QObject* parent = nullptr); XQViewModel(QObject* parent = nullptr);
virtual ~XQViewModel() = default; virtual ~XQViewModel() = default;
QHash<int, QByteArray> roleNames() const override;
XQTreeTable* treeTable(); XQTreeTable* treeTable();
virtual void setTreeTable( XQTreeTable* mainView ); virtual void setTreeTable( XQTreeTable* mainView );
@@ -50,76 +54,63 @@ public:
virtual void initModel( const QString& modelName); virtual void initModel( const QString& modelName);
void expandNewItem(const QModelIndex& index);
void toggleSection( const XQModelSection& section );
//little helpers //little helpers
const XQItem& xqRootItem(); const XQItem& xqRootItem();
XQNodePtr contentRootNode();
XQItem& xqItemFromIndex(const QModelIndex& index) const; XQItem& xqItemFromIndex(const QModelIndex& index) const;
XQItem& xqFirstItem(int row) const; XQItem& xqFirstItem(int row) const;
// undo-/redo-able stuff // undo-/redo-able stuff
virtual void cmdToggleSection( XQCommand& command ); virtual void cmdToggleSection( const XQCommand& command );
virtual void cmdCut( XQCommand& command ); virtual void cmdCut( const XQCommand& command );
virtual void cmdCutUndo( XQCommand& command ); virtual void cmdCutUndo( const XQCommand& command );
virtual void cmdPaste( XQCommand& command ); virtual void cmdPaste( const XQCommand& command );
virtual void cmdPasteUndo( XQCommand& command ); virtual void cmdPasteUndo( const XQCommand& command );
virtual void cmdDelete( XQCommand& command ); virtual void cmdDelete( const XQCommand& command );
virtual void cmdDeleteUndo( XQCommand& command ); virtual void cmdDeleteUndo( const XQCommand& command );
virtual void cmdNew( XQCommand& command ); virtual void cmdNew( const XQCommand& command );
virtual void cmdNewUndo( XQCommand& command ); virtual void cmdNewUndo( const XQCommand& command );
QHash<int, QByteArray> roleNames() const override; // Derzeit wird die default-implementierung von data/setData genutzt. hier wäre dann die
// Stelle um setData & data an externe 'handler' umzubiegen, siehe giovannies 'model-injection'
/*! signals:
Derzeit wird die default-implementierung von data/setData genutzt. hier wäre dann die void xqItemChanged( const XQItem& item );
Stelle um setData & data an externe 'handler' umzubiegen, siehe giovannies 'model-injection' void itemCreated( XQItem* newItem );
void sectionCreated( const XQModelSection& section );
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override void sectionToggled( const XQModelSection& section );
{
return QStandardItemModel::data( index, role );
}
bool setData(const QModelIndex& index, const QVariant& value, int role = Qt::EditRole) override
{
qDebug() << " --- setData: " << value.toString();
return QStandardItemModel::setData( index, value, role );
}
*/
public slots: public slots:
virtual void onShowContextMenu(const QPoint& point); virtual void onShowContextMenu(const QPoint& point);
virtual void onActionTriggered(QAction* action); virtual void onActionTriggered(QAction* action);
virtual void onToggleSection(const QString& sectionKey );
// handle XQCommands ( == UndoCommand ) // handle XQCommands ( == UndoCommand )
virtual void onCommandRedo( XQCommand& command ); virtual void onCommandRedo( const XQCommand& command );
virtual void onCommandUndo( XQCommand& command ); virtual void onCommandUndo( const XQCommand& command );
signals:
void itemCreated( XQItem* newItem );
void sectionCreated( const XQModelSection& section );
void sectionToggled( const XQModelSection& section );
protected: protected:
void addSection(const XQItemList& list, const XQNodePtr& sheetNode ); void addSection(const XQItemList& list, const XQNodePtr& sheetNode );
virtual void initContextMenu() = 0; virtual void initContextMenu() = 0;
// __fixme: should be created from xml // __fixme: should be created from xml
virtual void setupViewProperties(); virtual void setupViewProperties();
protected: protected:
using MemCall = void (XQViewModel::*)(XQCommand&); using MemCall = void (XQViewModel::*)(const XQCommand&);
using MemCallMap = QMap<XQCommand::CmdType,MemCall>; using MemCallMap = QMap<XQCommand::CmdType,MemCall>;
// das eine reference auf ein globales singleton // das eine reference auf ein globales singleton
XQItemFactory& _itemFactory; XQItemFactory& _itemFactory;
XQSimpleClipBoard _clipBoard; XQSimpleClipBoard _clipBoard;
XQModelSectionList _sections; XQSectionManager _sections;
XQTreeTable* _treeTable{}; XQTreeTable* _treeTable{};
//QAbstractItemView* _treeTable{}; //QAbstractItemView* _treeTable{};

View File

@@ -78,6 +78,7 @@ namespace znode
zweak_node _parent; zweak_node _parent;
znode_list _children; znode_list _children;
// functor, der auf pointer gleichheit prüft.
struct match_node struct match_node
{ {
match_node( zbasic_node* match ) match_node( zbasic_node* match )
@@ -95,9 +96,11 @@ namespace znode
public: public:
//! shortcut auf std::make_shared... //! shortcut auf std::make_shared...
static zshared_node make_node( str_cref arg1, str_cref arg2 = "" , zshared_cref parent = nullptr ) //! beachte: der eltern-knoten wird hier nicht gesetzt, der neue knoten
//! wird nirgends eingefügt.
static zshared_node make_node( str_cref arg1, str_cref arg2 = "" )
{ {
return std::make_shared<zbasic_node>( arg1, arg2, parent ); return std::make_shared<zbasic_node>( arg1, arg2 );
} }
//! leerer konstruktor //! leerer konstruktor
@@ -136,7 +139,7 @@ namespace znode
zbasic_node(const zbasic_node&) = delete; zbasic_node(const zbasic_node&) = delete;
zbasic_node& operator=(const zbasic_node&) = delete; zbasic_node& operator=(const zbasic_node&) = delete;
// 'move' geht (shared_from_this bleibt gültig) //! 'move' geht (shared_from_this bleibt gültig)
zbasic_node(zbasic_node&&) noexcept = default; zbasic_node(zbasic_node&&) noexcept = default;
zbasic_node& operator=(zbasic_node&&) noexcept = default; zbasic_node& operator=(zbasic_node&&) noexcept = default;
@@ -178,31 +181,31 @@ namespace znode
return _parent.lock(); return _parent.lock();
} }
//! gibt den nachfolge-knoten oder 'end()' zurück.
zshared_node sibling() zshared_node sibling()
{ {
if( !parent() ) if( parent() )
//return zshared_node( make_node("WTF1") ); {
return zshared_node();
znode_list& childs = _parent->_children; znode_list& childs = _parent->_children;
auto it = std::find( childs.begin(), childs.end(), this->shared_from_this() ); auto it = std::find( childs.begin(), childs.end(), this->shared_from_this() );
if( ++it != childs.end())
return *(it); return *(it);
}
//return zshared_node( make_node("WTF?") ); throw std::runtime_error("sibling(): no parent node");
return zshared_node();
} }
//! gibt den vector mit kind-knoten zurück
inline const znode_list& children() const inline const znode_list& children() const
{ {
return _children; return _children;
} }
//! testet, ob kinder vorhanden sind.
bool has_children() const bool has_children() const
{ {
return !children().empty(); return !children().empty();
} }
//! gibt das erste kind zurück
zshared_node first_child() zshared_node first_child()
{ {
if(!children().empty()) if(!children().empty())
@@ -210,6 +213,7 @@ namespace znode
return nullptr; return nullptr;
} }
//! gibt das letzte kind oder nullptr zurück
zshared_node last_child() zshared_node last_child()
{ {
if(!children().empty()) if(!children().empty())
@@ -237,7 +241,6 @@ namespace znode
int add_child_at( int idx, const zshared_node& node ) int add_child_at( int idx, const zshared_node& node )
{ {
// _fixme! was ist, wenn da schon ein elternknoten ist? // _fixme! was ist, wenn da schon ein elternknoten ist?
_children.insert(children().begin() + idx, node ); _children.insert(children().begin() + idx, node );
node->_parent = this->shared_from_this(); node->_parent = this->shared_from_this();
return int(children().size() - 1); return int(children().size() - 1);
@@ -250,10 +253,9 @@ namespace znode
parent()->add_child_at( offset, this->shared_from_this() ); parent()->add_child_at( offset, this->shared_from_this() );
else else
throw std::runtime_error("add_me_at(offset): no parent node"); throw std::runtime_error("add_me_at(offset): no parent node");
} }
//! fügt einen shard_ptr von 'mir' in die kinderliste des übergebenen knotens ein //! fügt einen shared_ptr von 'mir' in die kinderliste des übergebenen knotens ein
//! und macht diesen zu meinem elternknoten. //! und macht diesen zu meinem elternknoten.
void add_me_at( int offset, const zshared_node& parent_node ) void add_me_at( int offset, const zshared_node& parent_node )
{ {
@@ -266,18 +268,17 @@ namespace znode
{ {
throw std::runtime_error("add_me_at(offset,parent): no parent node"); throw std::runtime_error("add_me_at(offset,parent): no parent node");
} }
} }
//! findet die eigene position im eltern-knoten
int own_pos() int own_pos()
{ {
if( parent()) if( parent())
return parent()->child_pos( this->shared_from_this() ); return parent()->child_pos( this->shared_from_this() );
return -1; return -1;
} }
//int child_pos(zbasic_node* child) //! findet die postion eines kind-knotens
int child_pos(const zshared_node& child) int child_pos(const zshared_node& child)
{ {
//auto pos = std::find_if(children().begin(), children().end(), match_node(child) ); //auto pos = std::find_if(children().begin(), children().end(), match_node(child) );
@@ -287,7 +288,7 @@ namespace znode
return -1; return -1;
} }
//zshared_node unlink_child( zbasic_node* node ) //! findet die postion eines kind-knotens
zshared_node unlink_child( const zshared_node& node ) zshared_node unlink_child( const zshared_node& node )
{ {
auto it = std::find(_children.begin(), _children.end(), node); auto it = std::find(_children.begin(), _children.end(), node);
@@ -315,11 +316,10 @@ namespace znode
{ {
for( auto child : _children ) for( auto child : _children )
{ {
qDebug() << " --#- " << child->name() << " : " << child->has_attribute( attrkey, attrvalue );
if( child->has_attribute( attrkey, attrvalue )) if( child->has_attribute( attrkey, attrvalue ))
return child; return child;
} }
return zshared_node(); return nullptr;
} }
// //
@@ -330,7 +330,7 @@ namespace znode
if( child->tag_name() == tagname ) if( child->tag_name() == tagname )
return child; return child;
} }
return zshared_node(); return nullptr;
} }
zshared_node find_child_by_id( int id ) zshared_node find_child_by_id( int id )
@@ -340,46 +340,7 @@ namespace znode
if (child->_id == id) if (child->_id == id)
return child; return child;
} }
return zshared_node(); return nullptr;
}
void dump(int indent = 0) const
{
// fix_me!
qDebug() << std::string(indent * 2, ' ').c_str() << this->to_string();
//qDebug() << to_string();
//qDebug() << '\n';// std::endl;
if (!children().empty())
{
for (auto child : _children)
{
//qDebug() << " --- type: " << typeid(child).name();
child.get()->dump( indent + 1 );
}
}
}
template<typename T>
bool for_each_x( T func, int depth = 0 )
//bool for_each( auto func ) const
{
if( !apply( func, depth ) )
return false;
if( !children().empty() )
{
for( auto child : _children )
{
if( !child->for_each( func, depth+1 ) )
return false;
}
}
return true;
} }
// find ... // find ...
@@ -392,22 +353,6 @@ namespace znode
}; };
class zbasic_node_walker
{
public:
virtual void begin()
{}
template<typename str_t>
void for_each_node( zbasic_node<str_t>* node );
virtual void end()
{}
};
} //namespace znode } //namespace znode

View File

@@ -100,7 +100,7 @@ namespace znode
//parent->add_child( new_node ); //parent->add_child( new_node );
//zbasic_node<str_t>* new_node = new zbasic_node<str_t>( node.name(), node.child_value(), parent ); //zbasic_node<str_t>* new_node = new zbasic_node<str_t>( node.name(), node.child_value(), parent );
zshared_node new_node = zbasic_node<str_t>::make_node( xml_node.name(), xml_node.child_value(), parent ); zshared_node new_node = zbasic_node<str_t>::make_node( xml_node.name(), xml_node.child_value() );
parent->add_child( new_node ); parent->add_child( new_node );
if( !xml_node.attributes().empty() ) if( !xml_node.attributes().empty() )

View File

@@ -73,6 +73,16 @@ public:
return _data.end(); return _data.end();
} }
auto begin() const
{
return _data.begin();
}
auto end() const
{
return _data.end();
}
inline int size() const inline int size() const
{ {
return (int) _data.size(); return (int) _data.size();
@@ -94,13 +104,11 @@ public:
return mapIndex().contains(key); return mapIndex().contains(key);
} }
inline const XQMapIndex& mapIndex() const inline const XQMapIndex& mapIndex() const
{ {
return _index; return _index;
} }
int indexOf( const QString& key ) const int indexOf( const QString& key ) const
{ {
return mapIndex().indexOf(key); return mapIndex().indexOf(key);
@@ -121,7 +129,6 @@ public:
return mapIndex().key( index ); return mapIndex().key( index );
} }
T& operator[]( int index ) T& operator[]( int index )
{ {
if( contains(index) ) if( contains(index) )
@@ -129,7 +136,6 @@ public:
throw XQException("XQMaptor operator[ int index ]: out of range"); throw XQException("XQMaptor operator[ int index ]: out of range");
} }
const T& operator[]( int index ) const const T& operator[]( int index ) const
{ {
if ( contains(index) ) if ( contains(index) )
@@ -154,7 +160,6 @@ public:
return _data[ _index[key] ]; return _data[ _index[key] ];
} }
const T& operator[]( const QString& key ) const const T& operator[]( const QString& key ) const
{ {
if (key.isEmpty() || !contains(key)) if (key.isEmpty() || !contains(key))
@@ -162,7 +167,6 @@ public:
return _data[_index[key]]; return _data[_index[key]];
} }
T& at( const QString& key ) T& at( const QString& key )
{ {
return (*this)[key]; return (*this)[key];
@@ -179,7 +183,6 @@ public:
return _data.size()-1; return _data.size()-1;
} }
virtual void addAtIndex( int index, const T& item ) virtual void addAtIndex( int index, const T& item )
{ {
if(contains(index)) if(contains(index))
@@ -187,14 +190,12 @@ public:
_data[index] = item; _data[index] = item;
} }
// convenience method to mimic QMap<T,QString> // convenience method to mimic QMap<T,QString>
virtual void insert( const T& item, const QString& key ) virtual void insert( const T& item, const QString& key )
{ {
addAtKey(key, item ); addAtKey(key, item );
} }
virtual void addAtKey( const QString& key, const T& item ) virtual void addAtKey( const QString& key, const T& item )
{ {
XQMapIndex::iterator pos = _index.find( key ); XQMapIndex::iterator pos = _index.find( key );
@@ -209,7 +210,6 @@ public:
} }
} }
bool addAlias( const QString& key, const QString& alias ) bool addAlias( const QString& key, const QString& alias )
{ {
// look for 'original' key // look for 'original' key
@@ -227,20 +227,17 @@ public:
return true; return true;
} }
void addKey( const QString& key, int index ) void addKey( const QString& key, int index )
{ {
_index.addKey( key, index ); _index.addKey( key, index );
} }
virtual void clear() virtual void clear()
{ {
_data.clear(); _data.clear();
_index.clear(); _index.clear();
} }
virtual bool killEntry( const QString& key ) virtual bool killEntry( const QString& key )
{ {
int idx = indexOf( key ); int idx = indexOf( key );
@@ -249,7 +246,6 @@ public:
return killEntry( (int) idx ); return killEntry( (int) idx );
} }
virtual bool killEntry( int index ) virtual bool killEntry( int index )
{ {
if( index >= this->_data.size() ) if( index >= this->_data.size() )
@@ -261,19 +257,16 @@ public:
return true; return true;
} }
virtual QString toString() const virtual QString toString() const
{ {
return join( ";" ); return join( ";" );
} }
virtual void dump() const virtual void dump() const
{ {
throw XQException("XQMaptor: dump not implemented!" ); throw XQException("XQMaptor: dump not implemented!" );
} }
virtual QString join( const QString& sep, int from=0, int to=-1) const virtual QString join( const QString& sep, int from=0, int to=-1) const
{ {
Q_UNUSED(sep) Q_UNUSED(sep)
@@ -283,7 +276,6 @@ public:
return "--"; return "--";
} }
int replaceKey( const QString& oldkey, const QString& newkey ) int replaceKey( const QString& oldkey, const QString& newkey )
{ {
int idx = indexOf( oldkey ); int idx = indexOf( oldkey );

View File

@@ -31,7 +31,7 @@ void XQContextMenu::addAction(const QString& text, XQCommand::CmdType commandTyp
QAction* newAction = new QAction(text, this); QAction* newAction = new QAction(text, this);
newAction->setData(commandType); newAction->setData(commandType);
_actionMap[commandType] = newAction; _actionMap[commandType] = newAction;
QWidget::addAction(newAction); QMenu::addAction(newAction);
setActionEnabled( commandType, enabled ); setActionEnabled( commandType, enabled );
} }
@@ -53,7 +53,7 @@ void XQContextMenu::addAction(const QIcon& icon, const QString& text, XQCommand:
QAction* newAction = new QAction(icon, text, this); QAction* newAction = new QAction(icon, text, this);
newAction->setData(commandType); newAction->setData(commandType);
_actionMap[commandType] = newAction; _actionMap[commandType] = newAction;
QWidget::addAction(newAction); QMenu::addAction(newAction);
setActionEnabled( commandType, enabled ); setActionEnabled( commandType, enabled );
} }

View File

@@ -51,6 +51,12 @@ XQItem& XQTreeTable::xqItemFromIndex(const QModelIndex& index )
return modelView()->xqItemFromIndex( index ); return modelView()->xqItemFromIndex( index );
} }
void XQTreeTable::toggleRowsHidden( int fstRow, int lstRow )
{
bool hidden = isRowHidden( fstRow, rootIndex() );
for (int row = fstRow; row < lstRow; ++row )
setRowHidden( row, rootIndex(), !hidden );
}
//! override von 'currentChanged' (noch nicht implementiert) //! override von 'currentChanged' (noch nicht implementiert)

View File

@@ -41,6 +41,8 @@ public:
XQViewModel* modelView(); XQViewModel* modelView();
XQItem& xqItemFromIndex(const QModelIndex& index ); XQItem& xqItemFromIndex(const QModelIndex& index );
void toggleRowsHidden(int fstRow, int lstRow );
protected: protected:
void currentChanged(const QModelIndex& current, const QModelIndex& previous) override; void currentChanged(const QModelIndex& current, const QModelIndex& previous) override;

View File

@@ -1,7 +1,10 @@
QT += core gui widgets quick quickwidgets QT += core gui widgets quick quickwidgets
# widgets-private # widgets-private
CONFIG += c++20 CONFIG += c++20 qmltypes
QML_IMPORT_NAME = org.sourceworx.qmlcomponents
QML_IMPORT_MAJOR_VERSION = 1
# You can make your code fail to compile if it uses deprecated APIs. # You can make your code fail to compile if it uses deprecated APIs.
# In order to do so, uncomment the following line. # In order to do so, uncomment the following line.
@@ -20,9 +23,9 @@ HEADERS += \
items/xqitemtype.h \ items/xqitemtype.h \
items/xqitemdelegate.h \ items/xqitemdelegate.h \
model/xqcommand.h \ model/xqcommand.h \
model/xqmodelsectionlist.h \
model/xqnode.h \ model/xqnode.h \
model/xqnodewriter.h \ model/xqnodewriter.h \
model/xqsectionmanager.h \
model/xqselectionmodel.h \ model/xqselectionmodel.h \
model/xqsimpleclipboard.h \ model/xqsimpleclipboard.h \
model/xqviewmodel.h \ model/xqviewmodel.h \
@@ -58,9 +61,9 @@ SOURCES += \
items/xqitemdelegate.cpp \ items/xqitemdelegate.cpp \
main.cpp \ main.cpp \
model/xqcommand.cpp \ model/xqcommand.cpp \
model/xqmodelsectionlist.cpp \
model/xqnode.cpp \ model/xqnode.cpp \
model/xqnodewriter.cpp \ model/xqnodewriter.cpp \
model/xqsectionmanager.cpp \
model/xqselectionmodel.cpp \ model/xqselectionmodel.cpp \
model/xqsimpleclipboard.cpp \ model/xqsimpleclipboard.cpp \
model/xqviewmodel.cpp \ model/xqviewmodel.cpp \

View File

@@ -4,7 +4,11 @@
<file alias="modeldata2.xtr">../xml/modeldata2.xtr</file> <file alias="modeldata2.xtr">../xml/modeldata2.xtr</file>
<file alias="modeldata3.xtr">../xml/modeldata3.xtr</file> <file alias="modeldata3.xtr">../xml/modeldata3.xtr</file>
<file alias="modelsheet.xml">../xml/modelsheets.xml</file> <file alias="modelsheet.xml">../xml/modelsheets.xml</file>
<file alias="quickview.qml">../quick/quickview.qml</file> <file alias="xqtableview.qml">../qml/xqtableview.qml</file>
<file alias="HorizontalHeaderViewDelegate.qml">../qml/HorizontalHeaderViewDelegate.qml</file>
<file alias="XMain.qml">../qml/XMain.qml</file>
<file alias="VerticalHeaderViewDelegate.qml">../qml/VerticalHeaderViewDelegate.qml</file>
<file alias="dummyview.qml">../qml/dummyview.qml</file>
<file alias="xqtreeview.qml">../qml/xqtreeview.qml</file>
</qresource> </qresource>
</RCC> </RCC>

View File

@@ -7,18 +7,18 @@
--> -->
<ItemTypes> <ItemTypes>
<TreeParentType RenderStyle="PlainStyle" ItemFlags="IsEnabled|IsDropEnabled" Icon="DirIcon" /> <TreeParentType RenderStyle="PlainStyle" EditorType="LineEditType" ItemFlags="IsEnabled|IsDropEnabled" Icon="DirIcon" />
<TreeSectionType RenderStyle="PlainStyle" ItemFlags="IsEnabled" Icon="DesktopIcon"/> <TreeChildType RenderStyle="PlainStyle" EditorType="LineEditType" ItemFlags="IsEnabled" Icon="MediaPlay"/>
<TreeChildType RenderStyle="PlainStyle" ItemFlags="IsUserCheckable|IsEnabled" Icon="MediaPlay"/> <TreeSectionType RenderStyle="PlainStyle" EditorType="LineEditType" ItemFlags="IsUserCheckable|IsEnabled" Icon="DesktopIcon"/>
<HeaderType RenderStyle="HeaderStyle" ItemFlags="IsEnabled"/> <HeaderType RenderStyle="HeaderStyle" EditorType="LineEditType" ItemFlags="IsEnabled"/>
<HiddenType RenderStyle="HiddenStyle"/> <HiddenType RenderStyle="HiddenStyle"/>
<StaticType RenderStyle="PlainStyle"/> <StaticType RenderStyle="PlainStyle"/>
<PlainType RenderStyle="PlainStyle" ItemFlags="IsEnabled|IsEditable|IsSelectable"/> <PlainType RenderStyle="PlainStyle" EditorType="LineEditType" ItemFlags="IsEnabled|IsEditable|IsSelectable"/>
<ValueType RenderStyle="FormattedStyle" ItemFlags="IsEnabled|IsEditable|IsSelectable" UnitType="Coulomb"/> <ValueType RenderStyle="FormattedStyle" EditorType="LineEditType" ItemFlags="IsEnabled|IsEditable|IsSelectable" UnitType="Coulomb"/>
<CheckableType RenderStyle="FormattedStyle" ItemFlags="IsEnabled|IsEditable|IsSelectable" UnitType="###"/> <CheckableType RenderStyle="FormattedStyle" EditorType="LineEditType" ItemFlags="IsEnabled|IsEditable|IsSelectable" UnitType="###"/>
<PercentageType RenderStyle="ProgressBarStyle" ItemFlags="IsEnabled|IsSelectable"/> <PercentageType RenderStyle="ProgressBarStyle" EditorType="LineEditType" ItemFlags="IsEnabled|IsSelectable"/>
<ChoiceType RenderStyle="ComboBoxStyle" ItemFlags="IsEnabled|IsSelectable|IsEditable" FixedChoices="la|le|lo|lu"/> <ChoiceType RenderStyle="ComboBoxStyle" EditorType="ComboBoxType" ItemFlags="IsEnabled|IsSelectable|IsEditable" FixedChoices="la|le|lo|lu"/>
<IntValueType RenderStyle="SpinBoxStyle" ItemFlags="IsEnabled|IsSelectable"/> <IntValueType RenderStyle="SpinBoxStyle" EditorType="SpinBoxType" ItemFlags="IsEnabled|IsSelectable"/>
</ItemTypes> </ItemTypes>
@@ -75,7 +75,7 @@
<!-- 'Icon' überschreibt den default wert im ItemType und erzeugt damit einen neuen ItemType--> <!-- 'Icon' überschreibt den default wert im ItemType und erzeugt damit einen neuen ItemType-->
<PanelID ItemType="PlainType" Icon="DesktopIcon"/> <PanelID ItemType="PlainType" Icon="DesktopIcon"/>
<PanelName ItemType="PlainType" Icon="BrowserStop"/> <PanelName ItemType="PlainType" Icon="BrowserStop"/>
<Manufacturer ItemType="ValueType"/> <Manufacturer ItemType="PlainType"/>
<!-- 'UnitType' überschreibt den default wert im ItemType und erzeugt damit einen neuen ItemType--> <!-- 'UnitType' überschreibt den default wert im ItemType und erzeugt damit einen neuen ItemType-->
<WattPeak ItemType="ValueType" UnitType="Wp"/> <WattPeak ItemType="ValueType" UnitType="Wp"/>
<Width ItemType="CheckableType" Icon="VistaShield" UnitType="m"/> <Width ItemType="CheckableType" Icon="VistaShield" UnitType="m"/>
@@ -98,20 +98,20 @@
<Weight Caption="Weight" ItemType="HeaderType" /> <Weight Caption="Weight" ItemType="HeaderType" />
</Header> </Header>
<ModelSheet> <ModelSheet>
<InverterID Caption="Inverter" ItemType="ValueType" /> <InverterID Caption="Inverter" ItemType="PlainType" />
<InverterName Caption="Name" ItemType="ValueType" /> <InverterName Caption="Name" ItemType="PlainType" />
<Manufacturer Caption="Manufacturer" ItemType="ValueType" /> <Manufacturer Caption="Manufacturer" ItemType="PlainType" />
<MaxPowerInput Caption="max. Input" ItemType="ValueType" ItemType="ChoiceType" ChoiceModelSheetSource="MaxPowerInputChoice" UnitType="W"/> <MaxPowerInput Caption="max. Input" ItemType="ValueType" ItemType="ChoiceType" ChoiceModelSheetSource="MaxPowerInputChoice" UnitType="W"/>
<MaxPowerOutput Caption="max Output" ItemType="ValueType" UnitType="W"/> <MaxPowerOutput Caption="max Output" ItemType="ValueType" UnitType="W"/>
<NumStrings Caption="Strings" ItemType="ValueType" /> <NumStrings Caption="Strings" ItemType="PlainType" />
<Weight Caption="Weight" ItemType="ValueType" UnitType="kg"/> <Weight Caption="Weight" ItemType="ValueType" UnitType="kg"/>
</ModelSheet> </ModelSheet>
</Section> </Section>
<Section ContentType="Battery" > <Section ContentType="Battery" >
<Header> <Header>
<BatteryID Caption="Name" ItemType="HeaderType" /> <BatteryID Caption="Battery" ItemType="HeaderType" />
<BatteryName Caption="Battery" ItemType="HeaderType" /> <BatteryName Caption="Name" ItemType="HeaderType" />
<Manufacturer Caption="Manufacturer" ItemType="HeaderType" /> <Manufacturer Caption="Manufacturer" ItemType="HeaderType" />
<Capacity Caption="Capacity" ItemType="HeaderType"/> <Capacity Caption="Capacity" ItemType="HeaderType"/>
<Yield Caption="Yield" ItemType="HeaderType" /> <Yield Caption="Yield" ItemType="HeaderType" />
@@ -119,9 +119,9 @@
<MaxVolt Caption="max. Volt" ItemType="HeaderType" /> <MaxVolt Caption="max. Volt" ItemType="HeaderType" />
</Header> </Header>
<ModelSheet> <ModelSheet>
<BatteryID Caption="Battery" ItemType="ValueType" /> <BatteryID Caption="Battery" ItemType="PlainType" />
<BatteryName Caption="Name" ItemType="ValueType" /> <BatteryName Caption="Name" ItemType="PlainType" />
<Manufacturer Caption="Manufacturer" ItemType="ValueType" /> <Manufacturer Caption="Manufacturer" ItemType="PlainType" />
<Capacity Caption="Capacity" ItemType="ValueType" UnitType="Wh"/> <Capacity Caption="Capacity" ItemType="ValueType" UnitType="Wh"/>
<Yield Caption="Yield" ItemType="ValueType" ItemType="PercentageType" UnitType="%"/> <Yield Caption="Yield" ItemType="ValueType" ItemType="PercentageType" UnitType="%"/>
<MaxCurrent Caption="max. Current" ItemType="ValueType" UnitType="A"/> <MaxCurrent Caption="max. Current" ItemType="ValueType" UnitType="A"/>

View File

@@ -1,10 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<Project Established="2006" FriendlyName="@ProjectName" ProjectID="HA01" ProjectName="Wiebelbach West" State="runnning" WattPeak="84000">
<Components> <Components>
<Panel FriendlyName="@PanelName" Height="2,70" Manufacturer="JA Solar 1 XX" MaxAmpere="11" MaxVolt="67" PanelID="#1 JA 01" PanelName="JA 01 Solar T62B" WattPeak="620" Weight="12" Width="1,10"/> <Panel FriendlyName="@PanelName" Height="2,70" Manufacturer="JA Solar 1 XX" MaxAmpere="11" MaxVolt="67" PanelID="#1 JA 01" PanelName="JA 01 Solar T62B" WattPeak="620" Weight="12" Width="1,10"/>
<Panel FriendlyName="@PanelName" Height="1,70" Manufacturer="JA Solar 2" MaxAmpere="11" MaxVolt="42" PanelID="#2 JA 02" PanelName="JA 02 Solar X58C" WattPeak="440" Weight="12" Width="1,10"/> <Panel FriendlyName="@PanelName" Height="1,70" Manufacturer="JA Solar 2" MaxAmpere="11" MaxVolt="42" PanelID="#2 JA 02" PanelName="maa" WattPeak="440" Weight="12" Width="1,10"/>
<Panel FriendlyName="@PanelName" Height="2,70" Manufacturer="JA Solar 3" MaxAmpere="11" MaxVolt="67" PanelID="#3 JA 03" PanelName="JA 03 Solar T62B" WattPeak="620" Weight="12" Width="1,10"/> <Panel FriendlyName="@PanelName" Height="2,70" Manufacturer="JA Solar 3" MaxAmpere="11" MaxVolt="67" PanelID="#3 JA 03" PanelName="JA 03 Solar T62B" WattPeak="620" Weight="12" Width="1,10"/>
<Panel FriendlyName="@PanelName" Height="1,70" Manufacturer="JA Solar 4" MaxAmpere="11" MaxVolt="42" PanelID="#4 JA 04" PanelName="JA 04 Solar X58C" WattPeak="440" Weight="12" Width="1,10"/> <Panel FriendlyName="@PanelName" Height="1,70" Manufacturer="JA Solar 4" MaxAmpere="11" MaxVolt="42" PanelID="#4 JA 04" PanelName="moo" WattPeak="440" Weight="12" Width="1,10"/>
<Panel FriendlyName="@PanelName" Height="1,70" Manufacturer="JA Solar 5" MaxAmpere="11" MaxVolt="42" PanelID="#5 JA 05" PanelName="JA 05 Solar X58C" WattPeak="440" Weight="12" Width="1,10"/> <Panel FriendlyName="@PanelName" Height="1,70" Manufacturer="JA Solar 5" MaxAmpere="11" MaxVolt="42" PanelID="#5 JA 05" PanelName="JA 05 Solar X58C" WattPeak="440" Weight="12" Width="1,10"/>
<Panel FriendlyName="@PanelName" Height="1,70" Manufacturer="JA Solar 6" MaxAmpere="11" MaxVolt="42" PanelID="#6 JA 06" PanelName="JA 06 Solar X58C" WattPeak="440" Weight="12" Width="1,10"/> <Panel FriendlyName="@PanelName" Height="1,70" Manufacturer="JA Solar 6" MaxAmpere="11" MaxVolt="42" PanelID="#6 JA 06" PanelName="JA 06 Solar X58C" WattPeak="440" Weight="12" Width="1,10"/>
<Inverter FriendlyName="@InverterName" InverterID="#1 HM600 01" InverterName="01 HM600 S2 TMax" Manufacturer="HoyMiles" MaxPowerInput="2000" MaxPowerInputChoice="2000;4000;6000" MaxPowerOutput="600" NumStrings="2" Weight="28"/> <Inverter FriendlyName="@InverterName" InverterID="#1 HM600 01" InverterName="01 HM600 S2 TMax" Manufacturer="HoyMiles" MaxPowerInput="2000" MaxPowerInputChoice="2000;4000;6000" MaxPowerOutput="600" NumStrings="2" Weight="28"/>
@@ -23,5 +22,3 @@
<Battery BatteryID="#6 GroWatt 06 G4K" BatteryName="06 BYD T02 Stackable" Capacity="9000" FriendlyName="@BatteryName" Manufacturer="GroWatt" MaxCurrent="120" MaxVolt="48" Yield="49"/> <Battery BatteryID="#6 GroWatt 06 G4K" BatteryName="06 BYD T02 Stackable" Capacity="9000" FriendlyName="@BatteryName" Manufacturer="GroWatt" MaxCurrent="120" MaxVolt="48" Yield="49"/>
<Battery BatteryID="#7 Pyne 07 G4K" BatteryName="07 Pyne K7 Stackable" Capacity="9000" FriendlyName="@BatteryName" Manufacturer="PyNe" MaxCurrent="120" MaxVolt="48" Yield="49"/> <Battery BatteryID="#7 Pyne 07 G4K" BatteryName="07 Pyne K7 Stackable" Capacity="9000" FriendlyName="@BatteryName" Manufacturer="PyNe" MaxCurrent="120" MaxVolt="48" Yield="49"/>
</Components> </Components>
<IrgendWasAnderes/>
</Project>