Compare commits
	
		
			35 Commits
		
	
	
		
			5057edb9ad
			...
			experiment
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| fd94b2d354 | |||
| cc441d094c | |||
|   | d5c1f8925c | ||
| fd41138175 | |||
|   | 03b0dafdcc | ||
| a0064b2566 | |||
|   | cbe8b92582 | ||
| 809ef10c0d | |||
|   | 95b7b026ff | ||
| 05bc5ad5d9 | |||
| 93ec52933e | |||
| 3ac129ef26 | |||
| 50703a4c44 | |||
| 1531ec14f1 | |||
| 0fe15d6043 | |||
| 89c671295f | |||
| a9dacca684 | |||
| 3887748c1a | |||
| b8f0893d59 | |||
| 9c6f7688d7 | |||
| 8d26c32e51 | |||
| c9b61c1c2b | |||
| d6ccac1d85 | |||
| 5d2fb1b378 | |||
| 89c5fd21f1 | |||
| f8bd0886d3 | |||
|   | 831daf898c | ||
|   | 3e7b65dca5 | ||
| 147769bf60 | |||
|   | 527de65074 | ||
| 4d49a495fd | |||
| 952409ab1a | |||
| c6454f3106 | |||
| 04b0f650d6 | |||
| 6ee677c595 | 
| @@ -1,5 +1,14 @@ | |||||||
| # XTree | # XTree | ||||||
|  |  | ||||||
|  | ## keys | ||||||
|  |  | ||||||
|  |  - Widgetset für XML Daten | ||||||
|  |  - experimenteller qml support | ||||||
|  |  - docs erzeugen | ||||||
|  |  -  | ||||||
|  |   | ||||||
|  |  experimenelle | ||||||
|  |  | ||||||
| ## Also, noch mal von vorn: | ## Also, noch mal von vorn: | ||||||
|  |  | ||||||
| - Es geht um das Editieren von XML Daten in einer baumartigen Darstellung am Bildschirm. | - Es geht um das Editieren von XML Daten in einer baumartigen Darstellung am Bildschirm. | ||||||
|   | |||||||
| @@ -1,44 +0,0 @@ | |||||||
| // 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 |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| @@ -1,26 +0,0 @@ | |||||||
| 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
									
									
									
									
									
								
							
							
						
						
									
										161
									
								
								qml/XMain.qml
									
									
									
									
									
								
							| @@ -1,161 +0,0 @@ | |||||||
| // 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 |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| @@ -1,45 +0,0 @@ | |||||||
| import QtQuick |  | ||||||
| import QtQuick.Controls |  | ||||||
| import QtQuick.Layouts |  | ||||||
| import QtQuick.Window |  | ||||||
|  |  | ||||||
| ApplicationWindow |  | ||||||
| { |  | ||||||
|     visible: true |  | ||||||
|     width: 600 |  | ||||||
|     height: 400 |  | ||||||
|     title: "TableView mit myChildModel" |  | ||||||
|  |  | ||||||
|     TreeView |  | ||||||
|     { |  | ||||||
|         anchors.fill: parent |  | ||||||
|         clip: true |  | ||||||
|         columnSpacing: 1 |  | ||||||
|         rowSpacing: 1 |  | ||||||
|  |  | ||||||
|         model: myChildModel |  | ||||||
|  |  | ||||||
|         delegate: Rectangle |  | ||||||
|         { |  | ||||||
|             implicitWidth: 150 |  | ||||||
|             implicitHeight: 40 |  | ||||||
|             border.color: "#cccccc" |  | ||||||
|             //color: index % 2 === 0 ? "#f9f9f9" : "#e0e0e0" |  | ||||||
|  |  | ||||||
|             Text { |  | ||||||
|                 anchors.centerIn: parent |  | ||||||
|                 text: display |  | ||||||
|                 font.pixelSize: 14 |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|  |  | ||||||
|         ScrollBar.horizontal: ScrollBar {} |  | ||||||
|         ScrollBar.vertical: ScrollBar {} |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|  |  | ||||||
| } |  | ||||||
| @@ -1,65 +0,0 @@ | |||||||
| 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) |  | ||||||
|         // } |  | ||||||
|     } |  | ||||||
|  |  | ||||||
| } |  | ||||||
							
								
								
									
										63
									
								
								qml/xqtreeview.qml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										63
									
								
								qml/xqtreeview.qml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,63 @@ | |||||||
|  | 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") | ||||||
|  |         //color: TreeView.isSelected ? "#d0eaff" : (row % 2 === 0 ? "#f9f9f9" : "#ffffff") | ||||||
|  |  | ||||||
|  |         TextField | ||||||
|  |         { | ||||||
|  |             id: entry | ||||||
|  |             anchors.centerIn: parent | ||||||
|  |             text:  display | ||||||
|  |             font.pixelSize: 12 | ||||||
|  |  | ||||||
|  |             background: Rectangle | ||||||
|  |             { | ||||||
|  |                 //color: entry.enabled ? "transparent" : "#353637" | ||||||
|  |                 //border.color: entry.enabled ? "#21be2b" : "transparent" | ||||||
|  |                 border.color: "transparent" | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             onEditingFinished: | ||||||
|  |             { | ||||||
|  |                 console.log("Editing finished, new text is :"+ text + " at index :" + index) | ||||||
|  |                 model.display = text //The roles here are defined in model class | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     ScrollBar.horizontal: ScrollBar {} | ||||||
|  |     ScrollBar.vertical: ScrollBar {} | ||||||
|  | } | ||||||
|  |  | ||||||
|  |  | ||||||
| @@ -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"; | ||||||
|   | |||||||
| @@ -36,9 +36,8 @@ XQChildModel::XQChildModel( QObject *parent ) | |||||||
| void XQChildModel::addModelData( const XQNodePtr& contentRoot ) | void XQChildModel::addModelData( const XQNodePtr& contentRoot ) | ||||||
| { | { | ||||||
|  |  | ||||||
|   // __fix: set object name ?? |   setObjectName( contentRoot->to_string() ); | ||||||
|  |   //qDebug() << " --- create Model Data: " << contentRoot->to_string(); | ||||||
|   qDebug() << " --- create Model Data: " << contentRoot->to_string(); |  | ||||||
|  |  | ||||||
|   // Die Datenbasis als shared_ptr sichern |   // Die Datenbasis als shared_ptr sichern | ||||||
|   _contentRoot = contentRoot; |   _contentRoot = contentRoot; | ||||||
| @@ -55,65 +54,72 @@ 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 ); | ||||||
|     insertRow( newRow, list); |  | ||||||
|  |     // _hinter_ der letzen zeile einfügen | ||||||
|  |     insertRow( newRow+1, list); | ||||||
|  |  | ||||||
|  |     if( contentEntry->has_children() ) | ||||||
|  |     { | ||||||
|  |  | ||||||
|  |     } | ||||||
|  |  | ||||||
|   } // for |   } // for | ||||||
|  |  | ||||||
| } | } | ||||||
|  |  | ||||||
|  |  | ||||||
|  | //! 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() | ||||||
| { | { | ||||||
|  |  | ||||||
|   // __fixme! add a menu title |   // __fixme! add a menu title | ||||||
|   _contextMenu->clear(); |   _contextMenu->clear(); | ||||||
|  |  | ||||||
|   const QModelIndex& curIdx = _treeTable->currentIndex(); |   const QModelIndex& curIdx = _treeTable->currentIndex(); | ||||||
|   bool hasSel = curIdx.isValid() && _treeTable->selectionModel()->hasSelection(); |  | ||||||
|   bool canPaste = _clipBoard.canPaste( curIdx ); |  | ||||||
|  |  | ||||||
|   _contextMenu->addAction( "icn11Dummy", "Undo",   XQCommand::cmdUndo,   _undoStack->canUndo() ); |   _contextMenu->addAction( "icn11Dummy", "Undo",   XQCommand::cmdUndo,   _undoStack->canUndo() ); | ||||||
|   _contextMenu->addAction( "icn17Dummy", "Redo",   XQCommand::cmdRedo,   _undoStack->canRedo() ); |   _contextMenu->addAction( "icn17Dummy", "Redo",   XQCommand::cmdRedo,   _undoStack->canRedo() ); | ||||||
|  |  | ||||||
|   _contextMenu->addAction( "icn58Dummy", "Cut",    XQCommand::cmdCut,    hasSel ); |   // editieren nur wenns kein header ist. | ||||||
|   _contextMenu->addAction( "icn61Dummy", "Paste",  XQCommand::cmdPaste, canPaste ); |   if ( !xqItemFromIndex(curIdx).isHeaderStyle() ) | ||||||
|   _contextMenu->addAction( "icn55Dummy", "Copy",   XQCommand::cmdCopy,   hasSel ); |   { | ||||||
|   //_contextMenu->addAction( "icn35Dummy", "Move",   XQCommand::cmdMove,   hasSel ); |     bool hasSel = curIdx.isValid() && _treeTable->selectionModel()->hasSelection(); | ||||||
|   _contextMenu->addAction( "icn70Dummy", "New",    XQCommand::cmdNew,    hasSel ); |     bool canPaste = _clipBoard.canPaste( curIdx ); | ||||||
|   _contextMenu->addAction( "icn50Dummy", "Delete", XQCommand::cmdDelete, hasSel ); |  | ||||||
|  |  | ||||||
|  |     _contextMenu->addAction( "icn58Dummy", "Cut",    XQCommand::cmdCut,    hasSel ); | ||||||
|  |     _contextMenu->addAction( "icn61Dummy", "Paste",  XQCommand::cmdPaste, canPaste ); | ||||||
|  |     _contextMenu->addAction( "icn55Dummy", "Copy",   XQCommand::cmdCopy,   hasSel ); | ||||||
|  |     //_contextMenu->addAction( "icn35Dummy", "Move",   XQCommand::cmdMove,   hasSel ); | ||||||
|  |     _contextMenu->addAction( "icn70Dummy", "New",    XQCommand::cmdNew,    hasSel ); | ||||||
|  |     _contextMenu->addAction( "icn50Dummy", "Delete", XQCommand::cmdDelete, hasSel ); | ||||||
|  |   } | ||||||
|   // __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 ); | ||||||
| } | } | ||||||
|  |  | ||||||
|  |  | ||||||
|   | |||||||
| @@ -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) ); | ||||||
|   | |||||||
| @@ -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" }; |  | ||||||
|  |  | ||||||
| }; | }; | ||||||
|  |  | ||||||
|   | |||||||
| @@ -45,57 +45,36 @@ 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 ); | ||||||
|  |     // __fixme! das ist mist! | ||||||
|  |     const XQNodePtr sheetNode = section.sheetRootNode()->first_child(); | ||||||
|  |     XQItem* newItem = _itemFactory.makeSingleItem( sheetNode, contentNode->attribute( "ProjectName") ); | ||||||
|  |  | ||||||
|     if( contentNode->attribute( c_ContentType) == section.contentType() ) |     // den neuen eintrag in die passende section der übersicht eintragen ... | ||||||
|     { |     section.headerItem().appendRow( newItem ); | ||||||
|  |     // erzeuger sheet node speichern | ||||||
|       qDebug() << " --- add PROJECT: contentNode: " << contentNode->to_string(); |     newItem->setSheetNode( sheetNode ); | ||||||
|  |     expandNewItem(section.headerItem().index() ); | ||||||
|       // __fixme! das ist mist! |     return newItem; | ||||||
|       const XQNodePtr sheetNode = section.sheetRootNode()->first_child(); |  | ||||||
|       XQItemList list = _itemFactory.makeRow( XQItemFactory::mSingle, sheetNode, contentNode, "ProjectName"); |  | ||||||
|  |  | ||||||
|       // den neuen eintrag in die passende section der übersicht eintragen ... |  | ||||||
|       section.headerItem().appendRow( list ); |  | ||||||
|       // ... 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 |  | ||||||
|       newItem->setSheetNode( sheetNode ); |  | ||||||
|       return newItem; |  | ||||||
|  |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |  | ||||||
|   throw XQException( "addProjectItem: main model should not be empty!" ); |   throw XQException( "addProjectItem: main model should not be empty!" ); | ||||||
| } | } | ||||||
|  |  | ||||||
|  |  | ||||||
|  | //! erzeugt einen einzelen baum-eintrag mit hilfe der section und den projekt-daten | ||||||
|  |  | ||||||
| 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() ); | ||||||
|  |  | ||||||
| } | } | ||||||
|  |  | ||||||
|  |  | ||||||
|   | |||||||
| @@ -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; | ||||||
|   | |||||||
| @@ -88,36 +88,33 @@ 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( _tabWidget,    SIGNAL(tabBarClicked(int)),    this, SLOT(onChildViewTabClicked(int)) ); | ||||||
|  |  | ||||||
|  |   //connect(&_mainModel, &QStandardItemModel::itemChanged, this, &XQMainWindow::onTreeItemChanged ); | ||||||
|   //connect( _mainTreeView, SIGNAL(doubleClicked(QModelIndex)), this, SLOT(onDoubleClicked(QModelIndex)) ); |   //connect( _mainTreeView, SIGNAL(doubleClicked(QModelIndex)), this, SLOT(onDoubleClicked(QModelIndex)) ); | ||||||
|   connect( _mainTreeView, SIGNAL(clicked(QModelIndex)),  this, SLOT(onTreeItemClicked(QModelIndex)) ); |   //connect( _mainTreeView, SIGNAL(clicked(QModelIndex)),  this, SLOT(onTreeItemClicked(QModelIndex)) ); | ||||||
|   connect( _tabWidget,    SIGNAL(tabBarClicked(int)),    this, SLOT(onTabClicked(int)) ); |  | ||||||
|  |  | ||||||
|  |   connect(&_mainModel, &XQViewModel::xqItemChanged, this, &XQMainWindow::onTreeViewItemChanged ); | ||||||
|  |  | ||||||
|  |   connect( _mainTreeView, &QTreeView::clicked, this, [&,this](const QModelIndex& index) | ||||||
|   /* |  | ||||||
|   connect( &_mainModelView, &XQViewModel::itemCreated, this, [=, this](XQItem* item) |  | ||||||
|   { |   { | ||||||
|     // when a new main tree item has been created ... |     onTreeViewItemClicked( XQItem::xqItemFromIndex(index) ); | ||||||
|     QString pID = item->contentNode()->attribute(c_ProjectID); |   }); | ||||||
|     _mainTreeView->setCurrentIndex( item->index() ); |  | ||||||
|     // ... we set the current view to this node |  | ||||||
|     if( _documentStore.contains( pID ) ) |  | ||||||
|       _tabWidget->setCurrentWidget( _documentStore[pID].modelView->treeTable() ); |  | ||||||
|   } ); |  | ||||||
|   */ |  | ||||||
|  |  | ||||||
|   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 ); | ||||||
|  |     //loadDocument( c_DocumentFileName3 ); | ||||||
|  |  | ||||||
|     qDebug() << " --- all here: " << XQNode::s_Count; |     qDebug() << " --- all here: " << XQNode::s_Count; | ||||||
|  |  | ||||||
| @@ -131,9 +128,6 @@ void XQMainWindow::initMainWindow() | |||||||
| } | } | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
| //! slot für zentrales undo | //! slot für zentrales undo | ||||||
|  |  | ||||||
| void XQMainWindow::onUndo() | void XQMainWindow::onUndo() | ||||||
| @@ -235,7 +229,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 | ||||||
| @@ -245,64 +239,93 @@ 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 ) | ||||||
| { | { | ||||||
|  |   //qDebug() << " --- Tree item CLICK:"  << item.text() << " : " << item.itemType().text(); | ||||||
|   XQItem& entry = XQItem::xqItemFromIndex(index); |   if( item.itemType().text() == "TreeChildType" ) | ||||||
|  |  | ||||||
|   qDebug() << " --- XXX mainWindow onTreeItemClicked:" << entry.text(); |  | ||||||
|   _mainTreeView->selectionModel()->select(index, QItemSelectionModel::Select); |  | ||||||
|  |  | ||||||
|   if( XQNodePtr contentNode = entry.contentNode() ) |  | ||||||
|   { |   { | ||||||
|     QString key = contentNode->attribute(c_ProjectID); |     setChildTabByName( item.text() ); | ||||||
|     qDebug() << " --- FIRZ: key: " << key; |  | ||||||
|  |  | ||||||
|     bool isThere = _documentStore.contains(key); |  | ||||||
|     if( isThere) |  | ||||||
|       _tabWidget->setCurrentWidget( _documentStore[key].modelView->treeTable() ); |  | ||||||
|   } |   } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void XQMainWindow::onTreeViewItemChanged(const XQItem& item ) | ||||||
|  | { | ||||||
|  |   qDebug() << " --- TREE VIEW itemChanged:" << item.text() << " : " << item.parent()->text()  << " : " << (void*)&_mainModel << " : " << (void*) sender(); | ||||||
|  |   // 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() ); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| void XQMainWindow::onSectionCreated( const XQModelSection& section ) |  | ||||||
| { |  | ||||||
|   qDebug() << " --- XXX section created: " << section.contentType() << ":" << section.sheetRootNode()->to_string(); |  | ||||||
|   if( _currentProjectItem ) |  | ||||||
|   { |   { | ||||||
|      _mainModelView.addSectionItem( section, _currentProjectItem ); |     QModelIndex treeIndex =_documentStore[idx].treeItem->index(); | ||||||
|  |     _mainModel.expandNewItem( treeIndex ); | ||||||
|   } |   } | ||||||
| } | } | ||||||
|  |  | ||||||
| void XQMainWindow::onSectionToggled( const XQModelSection& section ) |  | ||||||
|  | //! SLOT, der aufgerufen wird, sobald eine section erzeugt worden ist. | ||||||
|  |  | ||||||
|  | void XQMainWindow::onSectionCreated( const XQModelSection& section ) | ||||||
| { | { | ||||||
|   //qDebug() << " --- XXX section toggled: " << section.contentType() << ":" << section.sheetRootNode()->to_string(); |   if( _currentProjectItem ) | ||||||
|  |   { | ||||||
|  |      _mainModel.addSectionItem( section, _currentProjectItem ); | ||||||
|  |   } | ||||||
| } | } | ||||||
|  |  | ||||||
| QStandardItemModel* createModel() { |  | ||||||
|   auto* model = new QStandardItemModel; |  | ||||||
|   model->setHorizontalHeaderLabels({ "Name" }); |  | ||||||
|  |  | ||||||
|   QStandardItem* parent = new QStandardItem("Tiere"); | //! SLOT, der aufgerufen wird, wenn eine section getoggelt wurde. | ||||||
|   parent->appendRow(new QStandardItem("Hund")); |  | ||||||
|   parent->appendRow(new QStandardItem("Katze")); |  | ||||||
|   model->appendRow(parent); |  | ||||||
|  |  | ||||||
|   return model; | void XQMainWindow::onSectionToggled( const XQModelSection& section ) | ||||||
|  | { | ||||||
|  |   qDebug() << " --- XXX section toggled: " << section.contentType() << ":" << section.sheetRootNode()->to_string(); | ||||||
|  |   { | ||||||
|  |     for (int row = 0; row < _currentProjectItem->rowCount(); ++row) | ||||||
|  |     { | ||||||
|  |       QStandardItem* child = _currentProjectItem->child(row); | ||||||
|  |       if (child->text() == section.contentType() ) | ||||||
|  |       { | ||||||
|  |         bool checked = (child->checkState() == Qt::Checked); | ||||||
|  |         child->setCheckState( checked ?  Qt::Unchecked :Qt::Checked ); | ||||||
|  |         break; | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | } | ||||||
|  |  | ||||||
|  |  | ||||||
|  | //! aktiviert das tab, das zum dokument mit dem schlüssel 'key' gehört. | ||||||
|  |  | ||||||
|  | void XQMainWindow::setChildTabByName( const QString& key ) | ||||||
|  | { | ||||||
|  |   for( int i=0; i<_documentStore.size(); ++i ) | ||||||
|  |   { | ||||||
|  |     if( key == _documentStore[i].friendlyName) | ||||||
|  |     { | ||||||
|  |       _tabWidget->setCurrentIndex(i); | ||||||
|  |       return; | ||||||
|  |     } | ||||||
|  |   } | ||||||
| } | } | ||||||
|  |  | ||||||
| void XQMainWindow::loadDocumentQML( const QString& fileName ) | void XQMainWindow::loadDocumentQML( const QString& fileName ) | ||||||
| @@ -332,8 +355,8 @@ 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("myChildModel", childModel); |   quickChild->rootContext()->setContextProperty("xtrChildModel", childModel); | ||||||
|    quickChild->setSource(QUrl("qrc:/xqtableview.qml")); |    quickChild->setSource(QUrl("qrc:/xqtreeview.qml")); | ||||||
|   _tabWidget->addTab( quickChild, "QML:"+fName ); |   _tabWidget->addTab( quickChild, "QML:"+fName ); | ||||||
|   _tabWidget->setCurrentWidget( quickChild ); |   _tabWidget->setCurrentWidget( quickChild ); | ||||||
|   quickChild->setResizeMode(QQuickWidget::SizeRootObjectToView); |   quickChild->setResizeMode(QQuickWidget::SizeRootObjectToView); | ||||||
| @@ -369,13 +392,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 +413,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 +432,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 ); | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -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,31 +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(); |   static void setupWorkingDir(); | ||||||
|  |  | ||||||
| protected: | protected: | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|   // 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{}; | ||||||
|  |  | ||||||
| }; | }; | ||||||
|  |  | ||||||
|   | |||||||
| @@ -64,7 +64,7 @@ XQItem::XQRenderStyleMap XQItem::s_RenderStyleMap | |||||||
|   { "CustomRenderStyle", CustomRenderStyle }, |   { "CustomRenderStyle", CustomRenderStyle }, | ||||||
|   { "PickerStyle",       PickerStyle }, |   { "PickerStyle",       PickerStyle }, | ||||||
|   { "SpinBoxStyle",      SpinBoxStyle }, |   { "SpinBoxStyle",      SpinBoxStyle }, | ||||||
|   { "ProgressBarStyle",  ProgressBarStyle}, |   { "ColorBarStyle",  ColorBarStyle}, | ||||||
|   { "FormattedStyle",    FormattedStyle}, |   { "FormattedStyle",    FormattedStyle}, | ||||||
| }; | }; | ||||||
|  |  | ||||||
| @@ -74,7 +74,7 @@ XQItem::XQEditorTypeMap XQItem::s_EditorTypeMap | |||||||
|   { "LineEditType",     LineEditType }, |   { "LineEditType",     LineEditType }, | ||||||
|   { "ComboBoxType",     ComboBoxType }, |   { "ComboBoxType",     ComboBoxType }, | ||||||
|   { "PickerType",       PickerType }, |   { "PickerType",       PickerType }, | ||||||
|   { "ProgressBarType",  ProgressBarType }, |   { "ColorBarType",  ColorBarType }, | ||||||
|   { "SpinBoxType",      SpinBoxType}, |   { "SpinBoxType",      SpinBoxType}, | ||||||
|   { "CustomEditorType", CustomEditorType} |   { "CustomEditorType", CustomEditorType} | ||||||
| }; | }; | ||||||
| @@ -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 ) | |||||||
| } | } | ||||||
|  |  | ||||||
|  |  | ||||||
| XQItem::XQItem(XQItemType* itemType, const QString *content ) | //! konstruiert ein daten-item mit zeiger auf 'unser' attribut | ||||||
|  | //! im übergeordneten content-node. | ||||||
|  |  | ||||||
|  | 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,35 @@ 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) | ||||||
|  |       if( unitType() != XQItem::NoUnitType) | ||||||
|  |         return XQItemType::formatToSI( plainText, unitType() ); | ||||||
|  |       return plainText; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     case Qt::ToolTipRole: |     case Qt::ToolTipRole: | ||||||
| @@ -479,16 +519,30 @@ QVariant XQItem::data(int role ) const | |||||||
|  |  | ||||||
|     case ContentNodeRole: |     case ContentNodeRole: | ||||||
|     { |     { | ||||||
|         // 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; | ||||||
|  |  | ||||||
|         // sonst: delegieren an den node-Besitzer |         // das gibt immerhin was zurück, was auf nullptr getestet werden kann, | ||||||
|         QModelIndex pIndex = model()->index( row(), 0  ); |         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 | ||||||
|  |       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: | ||||||
| @@ -537,7 +591,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 +610,33 @@ void XQItem::setData(const QVariant& value, int role ) | |||||||
|       return; |       return; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     // set the raw, unformatted data |     case Qt::DisplayRole: | ||||||
|     case ContentRole: |     case Qt::EditRole: | ||||||
|  |     case XQItem::ContentRole: | ||||||
|     { |     { | ||||||
|        // string ptr setzen kann die basis. |       QVariant newValue; | ||||||
|       break; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     case Qt::EditRole : |       //if( itemType().renderStyle() == XQItem::FormattedStyle) | ||||||
|     { |       if( unitType() != XQItem::NoUnitType) | ||||||
|       qDebug() << " --- setting EDITrole: " << value.toString(); |         newValue = XQItemType::unFormatFromSI( value.toString() ); | ||||||
|       break; |       else | ||||||
|     } |         newValue = value; | ||||||
|  |  | ||||||
|     case Qt::DisplayRole : |       // fallback: wenns keinen content node gibt, dann nehmen wir | ||||||
|     { |       // das standardverfahren. | ||||||
|       // what will happen? value is a string ptr ?! |       if( !hasContentPtr() ) | ||||||
|       qDebug() << " --- setting DISPLAYrole: " << value.toString(); |         return QStandardItem::setData( newValue, Qt::DisplayRole ); | ||||||
|       break; |  | ||||||
|  |       // 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; | ||||||
| @@ -591,6 +647,133 @@ void XQItem::setData(const QVariant& value, int role ) | |||||||
|  |  | ||||||
| } | } | ||||||
|  |  | ||||||
|  | //! erzeugt eine QVariant zur gegebenen rolle aus dem gegebenen string. | ||||||
|  | //! Hack: Das Item wird hier als zusätzliche datenquelle übergeben, | ||||||
|  | //! um _vorher_ erzeugte eigenschaften des items als parameter für _jetzt_ | ||||||
|  | //! erzeugte eigenschaft verwenden zu können. | ||||||
|  | //! Beispiel | ||||||
|  |  | ||||||
|  | QVariant XQItem::makeVariant( XQItem* item, int dataRole, const QString& source ) | ||||||
|  | { | ||||||
|  |  | ||||||
|  |   QVariant value; | ||||||
|  |  | ||||||
|  |   //qDebug() << " ----- makeVariant: " << XQItem::fetchItemDataRoleName( dataRole ); | ||||||
|  |  | ||||||
|  |   switch(dataRole) | ||||||
|  |   { | ||||||
|  |   // das ist ein pointer auf den  original-string aus dem XML | ||||||
|  |   case XQItem::ContentRole: | ||||||
|  |   { | ||||||
|  |     // content() -> QString* | ||||||
|  |     value = QVariant::fromValue(&source); | ||||||
|  |     break; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |     /* | ||||||
|  |     case XQItem::ItemTypeRole: | ||||||
|  |     { | ||||||
|  |       // itemType() -> XQItemType* | ||||||
|  |       XQItemType* itemType = findItemTypeTemplate( source ); | ||||||
|  |       value = QVariant::fromValue(itemType); | ||||||
|  |       break; | ||||||
|  |     } | ||||||
|  |     */ | ||||||
|  |  | ||||||
|  |   case XQItem::RenderStyleRole: | ||||||
|  |   { | ||||||
|  |     XQItem::RenderStyle renderStyle = XQItem::fetchRenderStyle( source ); | ||||||
|  |     value = QVariant::fromValue(renderStyle); | ||||||
|  |     break; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   case XQItem::EditorTypeRole: | ||||||
|  |   { | ||||||
|  |     XQItem::EditorType editorType = XQItem::fetchEditorType( source ); | ||||||
|  |     value = QVariant::fromValue(editorType); | ||||||
|  |     break; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   case XQItem::UnitTypeRole: | ||||||
|  |   { | ||||||
|  |     //qDebug() << " --- make unit type: " << source; | ||||||
|  |     XQItem::UnitType unitType = XQItem::fetchUnitType( source ); | ||||||
|  |     value = QVariant::fromValue(unitType); | ||||||
|  |     break; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   case XQItem::ContentFormatRole: | ||||||
|  |   { | ||||||
|  |     // contentFormat() -> QString | ||||||
|  |     value = QVariant::fromValue(source); | ||||||
|  |     break; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   case XQItem::FlagsRole: | ||||||
|  |   { | ||||||
|  |     QFlags itemFlags = Qt::NoItemFlags; | ||||||
|  |     const QStringList flagKeys = source.split( '|' ); | ||||||
|  |     for( const QString& flagKey : flagKeys ) | ||||||
|  |     { | ||||||
|  |       Qt::ItemFlag flag = XQItem::fetchItemFlag( flagKey ); | ||||||
|  |       itemFlags.setFlag( flag ); | ||||||
|  |     } | ||||||
|  |     value = QVariant::fromValue(itemFlags); | ||||||
|  |     break; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |  | ||||||
|  |   case XQItem::IconRole: | ||||||
|  |   { | ||||||
|  |     QIcon typeIcon = XQAppData::typeIcon(source); | ||||||
|  |     value = QVariant::fromValue(typeIcon); | ||||||
|  |     break; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |  | ||||||
|  |   case XQItem::FixedChoicesRole: | ||||||
|  |   { | ||||||
|  |     const QStringList choices = source.split( '|' ); | ||||||
|  |  | ||||||
|  |     QStandardItemModel* fixedChoices = new QStandardItemModel(); | ||||||
|  |     for( const QString& entry : choices ) | ||||||
|  |     { | ||||||
|  |       QString result = entry; | ||||||
|  |       if( item->unitType() != XQItem::NoUnitType ) | ||||||
|  |         result = XQItemType::formatToSI( entry, item->unitType() ); | ||||||
|  |       fixedChoices->appendRow( new QStandardItem( result ) ); | ||||||
|  |     } | ||||||
|  |     value = QVariant::fromValue(fixedChoices); | ||||||
|  |     break; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |     /* | ||||||
|  |     case XQItem::ContentNodeRole: | ||||||
|  |     { | ||||||
|  |       value = QVariant::fromValue(&source); | ||||||
|  |       break; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     case XQItem::XQItem::SheetNodeRole: | ||||||
|  |     { | ||||||
|  |       value = QVariant::fromValue(&source); | ||||||
|  |       break; | ||||||
|  |     } | ||||||
|  |     */ | ||||||
|  |  | ||||||
|  |   default: | ||||||
|  |   case XQItem::XQItem::NoRole: | ||||||
|  |   { | ||||||
|  |     break; | ||||||
|  |   } | ||||||
|  |   }; | ||||||
|  |  | ||||||
|  |   //if( !value.toString().isEmpty()) | ||||||
|  |   //  setData( value, dataRole); | ||||||
|  |  | ||||||
|  |   return value; | ||||||
|  |  | ||||||
|  | } | ||||||
|  |  | ||||||
| //! gibt ein statisches invalid-item zurück, anstelle von nullptr | //! gibt ein statisches invalid-item zurück, anstelle von nullptr | ||||||
|  |  | ||||||
| @@ -694,13 +877,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]; | ||||||
| } | } | ||||||
|  |  | ||||||
| /// --- |  | ||||||
| /// --- |  | ||||||
| /// --- |  | ||||||
|   | |||||||
| @@ -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: | ||||||
| @@ -81,7 +84,7 @@ public: | |||||||
|     ComboBoxStyle, |     ComboBoxStyle, | ||||||
|     PickerStyle, |     PickerStyle, | ||||||
|     SpinBoxStyle, |     SpinBoxStyle, | ||||||
|     ProgressBarStyle, |     ColorBarStyle, | ||||||
|     FormattedStyle, |     FormattedStyle, | ||||||
|     TreeHeaderStyle, |     TreeHeaderStyle, | ||||||
|     CustomRenderStyle,     |     CustomRenderStyle,     | ||||||
| @@ -96,7 +99,7 @@ public: | |||||||
|     LineEditType, |     LineEditType, | ||||||
|     ComboBoxType, |     ComboBoxType, | ||||||
|     PickerType, |     PickerType, | ||||||
|     ProgressBarType, |     ColorBarType, | ||||||
|     SpinBoxType, |     SpinBoxType, | ||||||
|     CustomEditorType, |     CustomEditorType, | ||||||
|     EditorTypeEnd |     EditorTypeEnd | ||||||
| @@ -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; | ||||||
|  |  | ||||||
|    //! gibt den zu diesem item gehörigen datenknoten zurück |   bool      hasContentNode() const; | ||||||
|   virtual XQNodePtr contentNode() const; |   //! gibt den zu diesem item gehörigen datenknoten zurück | ||||||
|  |   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 | ||||||
| @@ -219,6 +224,8 @@ public: | |||||||
|   /// Static convenience methods |   /// Static convenience methods | ||||||
|   /// |   /// | ||||||
|  |  | ||||||
|  |   static QVariant      makeVariant( XQItem* item, int dataRole, const QString& source ); | ||||||
|  |  | ||||||
|   static XQItem&       xqItemFromIndex( const QModelIndex& index ); |   static XQItem&       xqItemFromIndex( const QModelIndex& index ); | ||||||
|   static XQItem&       fallBackDummyItem(); |   static XQItem&       fallBackDummyItem(); | ||||||
|  |  | ||||||
| @@ -238,6 +245,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 +270,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); | ||||||
|   | |||||||
| @@ -17,6 +17,7 @@ | |||||||
| #include <QComboBox> | #include <QComboBox> | ||||||
| #include <QDoubleSpinBox> | #include <QDoubleSpinBox> | ||||||
| #include <QProgressBar> | #include <QProgressBar> | ||||||
|  | #include <QSlider> | ||||||
|  |  | ||||||
| #include <QPainter> | #include <QPainter> | ||||||
| #include <QHeaderView> | #include <QHeaderView> | ||||||
| @@ -28,153 +29,160 @@ | |||||||
| #include <xqviewmodel.h> | #include <xqviewmodel.h> | ||||||
|  |  | ||||||
|  |  | ||||||
|  | //! erzeugt eine editorfactory mit den hauseigenen editortypen. | ||||||
|  |  | ||||||
| class XQItemEditorFactory : public QItemEditorFactory | class XQItemEditorFactory : public QItemEditorFactory | ||||||
| { | { | ||||||
| public: | public: | ||||||
|  |  | ||||||
|   XQItemEditorFactory() |   XQItemEditorFactory() | ||||||
|   { |   { | ||||||
|  |  | ||||||
|     registerEditor(XQItem::LineEditType,      new QStandardItemEditorCreator<QLineEdit>()); |     registerEditor(XQItem::LineEditType,      new QStandardItemEditorCreator<QLineEdit>()); | ||||||
|     registerEditor(XQItem::ComboBoxType,      new QStandardItemEditorCreator<QLineEdit>()); |     registerEditor(XQItem::ComboBoxType,      new QStandardItemEditorCreator<QComboBox>()); | ||||||
|     registerEditor(XQItem::PickerType,        new QStandardItemEditorCreator<QLineEdit>()); |     registerEditor(XQItem::PickerType,        new QStandardItemEditorCreator<QLineEdit>()); | ||||||
|     registerEditor(XQItem::ProgressBarType,   new QStandardItemEditorCreator<QLineEdit>()); |     //registerEditor(XQItem::ColorBarType,   new QStandardItemEditorCreator<QProgressBar>()); | ||||||
|     registerEditor(XQItem::SpinBoxType,       new QStandardItemEditorCreator<QLineEdit>()); |     registerEditor(XQItem::ColorBarType,   new QStandardItemEditorCreator<QSlider>()); | ||||||
|  |     registerEditor(XQItem::SpinBoxType,       new QStandardItemEditorCreator<QSpinBox>()); | ||||||
|     registerEditor(XQItem::CustomEditorType,  new QStandardItemEditorCreator<QLineEdit>()); |     registerEditor(XQItem::CustomEditorType,  new QStandardItemEditorCreator<QLineEdit>()); | ||||||
|  |  | ||||||
| /* |  | ||||||
|     registerEditor(XQItem::LineEditStyle,    new QStandardItemEditorCreator<QLineEdit>()); |  | ||||||
|     registerEditor(XQItemType::ComboBoxStyle,    new QStandardItemEditorCreator<QComboBox>()); |  | ||||||
|     //registerEditor(XQItemType::ProgressBarStyle, new QStandardItemEditorCreator<QProgressBar>()); |  | ||||||
|     registerEditor(XQItemType::SpinBoxStyle,     new QStandardItemEditorCreator<QSpinBox>()); |  | ||||||
|   */ |  | ||||||
|     /* |  | ||||||
|     registerEditor(XQItem::etDoubleSpinType, new QStandardItemEditorCreator<QDoubleSpinBox>()); |  | ||||||
|     registerEditor(XQItemItemTypes::etDoubleSpinType, new QStandardItemEditorCreator<QDoubleSpinBox>()); |  | ||||||
|     registerEditor(XQItemItemTypes::etIPAddressType, new QStandardItemEditorCreator<NTIpAddressEdit>()); |  | ||||||
|     registerEditor(XQItemItemTypes::etLineEditBrowser, new QStandardItemEditorCreator<NTFileSelectLine>()); |  | ||||||
|     */ |  | ||||||
|  |  | ||||||
|   } |   } | ||||||
|  |  | ||||||
| }; | }; | ||||||
|  |  | ||||||
|  |  | ||||||
|  | //! kontruktor mit dem zusändigen viewModel | ||||||
|  |  | ||||||
| XQItemDelegate::XQItemDelegate( XQViewModel& modelView) | XQItemDelegate::XQItemDelegate( XQViewModel& viewModel) | ||||||
|     : _modelView{modelView} |     : _modelView{viewModel} | ||||||
| { | { | ||||||
|   static  XQItemEditorFactory s_EditorFactory; |   static  XQItemEditorFactory s_EditorFactory; | ||||||
|   setItemEditorFactory(&s_EditorFactory); |   setItemEditorFactory(&s_EditorFactory); | ||||||
| } | } | ||||||
|  |  | ||||||
|  |  | ||||||
|  | //! gibt die interne tree table zurück | ||||||
|  |  | ||||||
| XQTreeTable* XQItemDelegate::treeTable() const | XQTreeTable* XQItemDelegate::treeTable() const | ||||||
| { | { | ||||||
|   return _modelView.treeTable(); |   return _modelView.treeTable(); | ||||||
| } | } | ||||||
|  |  | ||||||
|  |  | ||||||
|  | //! shortcut: gibt das XQItem für den gegebenen index zurück. | ||||||
|  |  | ||||||
| XQItem& XQItemDelegate::xqItemFromIndex( const QModelIndex& index ) const | XQItem& XQItemDelegate::xqItemFromIndex( const QModelIndex& index ) const | ||||||
| { | { | ||||||
|   return _modelView.xqItemFromIndex( index ); |   return _modelView.xqItemFromIndex( index ); | ||||||
| } | } | ||||||
|  |  | ||||||
|  |  | ||||||
|  | //! überladene paint-methode: zeichnet das item je nach render-style. | ||||||
|  |  | ||||||
| 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!"; |  | ||||||
|  |  | ||||||
|   XQItem& item = xqItemFromIndex( index ); |  | ||||||
|   if( item.isValid() ) |  | ||||||
|   { |   { | ||||||
|  |     XQItem& item = xqItemFromIndex( index ); | ||||||
|     switch( item.renderStyle()  ) |     switch( item.renderStyle()  ) | ||||||
|     { |     { | ||||||
|         case XQItem::HeaderStyle : |         case XQItem::HeaderStyle : | ||||||
|           return drawHeaderStyle( painter, option, index ); |           return drawHeaderStyle( painter, option, item ); | ||||||
|  |  | ||||||
|         case XQItem::ComboBoxStyle : |         case XQItem::ComboBoxStyle : | ||||||
|            return drawComboBoxStyle( painter, option, index ); |           return drawComboBoxStyle( painter, option, item ); | ||||||
|  |  | ||||||
|  |         case XQItem::ColorBarStyle : | ||||||
|  |           return drawColorBarStyle( painter, option, item ); | ||||||
|  |  | ||||||
|  |           // das funktioniert nicht unter windows11 | ||||||
|  |           //case XQItem::SpinBoxStyle : | ||||||
|  |           //  return drawSpinBoxStyle( painter, option, item ); | ||||||
|  |  | ||||||
|         case XQItem::HiddenStyle : |         case XQItem::HiddenStyle : | ||||||
|           return; |           return; | ||||||
|  |  | ||||||
|       //case XQItem::ProgressBarStyle : |  | ||||||
|       //  return drawProgressBarStyle( painter, option, index ); |  | ||||||
|  |  | ||||||
|  |  | ||||||
|         default: |         default: | ||||||
|           break; |           break; | ||||||
|     } // switch |     } // switch | ||||||
|  |  | ||||||
|   } |   } | ||||||
|  |   else | ||||||
|  |   { | ||||||
|  |     qDebug() << " ---- paint: INDEX DEAD!"  ; | ||||||
|  |   } | ||||||
|   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 XQItem& item) const | ||||||
| { | { | ||||||
|   QStyleOptionHeader headerOption; |   QStyleOptionHeader headerOption; | ||||||
|  |  | ||||||
|    XQItem& item = xqItemFromIndex( index ); |  | ||||||
|  |  | ||||||
|   // use the header as "parent" for style init |   // use the header as "parent" for style init | ||||||
|    QWidget* srcWidget = treeTable();//->header(); |   QWidget* srcWidget = treeTable();//->header(); | ||||||
|   headerOption.initFrom(srcWidget); |   headerOption.initFrom(srcWidget); | ||||||
|   headerOption.text = index.data(Qt::DisplayRole).toString(); |   headerOption.text = item.text(); | ||||||
|   headerOption.rect = option.rect.adjusted(0,0,0,3); |   headerOption.rect = option.rect.adjusted(0,0,0,3); | ||||||
|   headerOption.styleObject = option.styleObject; |   headerOption.styleObject = option.styleObject; | ||||||
|   // __ch: reduce inner offset when painting |   // __ch: reduce inner offset when painting | ||||||
|   headerOption.textAlignment |= Qt::AlignVCenter; |   headerOption.textAlignment |= Qt::AlignVCenter; | ||||||
|   headerOption.icon = item.icon(); |   headerOption.icon = item.icon(); | ||||||
|  |  | ||||||
|   if (srcWidget != nullptr) |   // save painter | ||||||
|   { |   painter->save(); | ||||||
|     // save painter |  | ||||||
|     painter->save(); |  | ||||||
|     //value = index.data(Qt::ForegroundRole); |  | ||||||
|     //if (value.canConvert<QBrush>()) |  | ||||||
|     //headerOption.palette.setBrush(QPalette::Text, Qt::red ); |  | ||||||
|     //headerOption.palette.setBrush(QPalette::Window, Qt::red ); |  | ||||||
|     QCommonStyle itemStyle; |  | ||||||
|     //headerOption.backgroundBrush() |  | ||||||
|     //srcWidget->style()->drawControl(QStyle::CE_Header, &headerOption, painter, srcWidget); |  | ||||||
|     itemStyle.drawControl(QStyle::CE_Header, &headerOption, painter, srcWidget); |  | ||||||
|     // restore painter |  | ||||||
|     painter->restore(); |  | ||||||
|   } |  | ||||||
| } |  | ||||||
|  |  | ||||||
| void XQItemDelegate::drawProgressBarStyle(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const |   QStyle* widgetStyle = srcWidget->style(); | ||||||
| { |   widgetStyle->drawControl(QStyle::CE_Header, &headerOption, painter, srcWidget); | ||||||
|  |   // restore painter | ||||||
|   int progress = index.data(XQItem::ContentRole ).toInt(); |   painter->restore(); | ||||||
|  |  | ||||||
|   QStyleOptionProgressBar progressBarOption; |  | ||||||
|   progressBarOption.rect = option.rect; |  | ||||||
|   progressBarOption.minimum = 0; |  | ||||||
|   progressBarOption.maximum = 100; |  | ||||||
|   progressBarOption.progress = progress; |  | ||||||
|   progressBarOption.text = QString::number(progress) + "%"; |  | ||||||
|   progressBarOption.textAlignment = Qt::AlignCenter; |  | ||||||
|   progressBarOption.textVisible = true; |  | ||||||
|  |  | ||||||
|   QApplication::style()->drawControl(QStyle::CE_ProgressBar,&progressBarOption, painter); |  | ||||||
|  |  | ||||||
| } | } | ||||||
|  |  | ||||||
| void XQItemDelegate::drawComboBoxStyle(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const |  | ||||||
|  | //! Zeichnet prozent-werte als balken | ||||||
|  |  | ||||||
|  | void XQItemDelegate::drawColorBarStyle(QPainter* painter, const QStyleOptionViewItem& option, const XQItem& item) const | ||||||
| { | { | ||||||
|  |   //QStyledItemDelegate::paint(painter, option, item); | ||||||
|  |  | ||||||
|  |   // Wert aus dem Modell holen | ||||||
|  |   bool ok; | ||||||
|  |   int value = item.data(Qt::EditRole).toInt(&ok); | ||||||
|  |   if (!ok || value < 0 || value > 100) | ||||||
|  |     return; | ||||||
|  |  | ||||||
|  |   // Balkenbereich berechnen | ||||||
|  |   QRect rect = option.rect.adjusted(2, 2, -2, -2); // etwas Padding | ||||||
|  |   int barWidth = static_cast<int>(rect.width() * (value / 100.0)); | ||||||
|  |  | ||||||
|  |   // Balken zeichnen | ||||||
|  |   painter->save(); | ||||||
|  |   painter->setRenderHint(QPainter::Antialiasing); | ||||||
|  |  | ||||||
|  |   QRect barRect(rect.left(), rect.top(), barWidth, rect.height()); | ||||||
|  |   QColor barColor = QColor(100, 180, 255); // z. B. hellblau | ||||||
|  |   painter->setBrush(barColor); | ||||||
|  |   painter->setPen(Qt::NoPen); | ||||||
|  |   painter->drawRect(barRect); | ||||||
|  |  | ||||||
|  |   // Text (Zahl) zentriert zeichnen | ||||||
|  |   painter->setPen(Qt::black); | ||||||
|  |   //painter->drawText(rect, Qt::AlignCenter, QString::number(value)+" %"); | ||||||
|  |   painter->drawText(rect, Qt::AlignCenter, item.text() ); | ||||||
|  |  | ||||||
|  |   painter->restore(); | ||||||
|  |  | ||||||
|  | } | ||||||
|  |  | ||||||
|  |  | ||||||
|  | //! Zeichnet das Item als combo box. | ||||||
|  |  | ||||||
|  | void XQItemDelegate::drawComboBoxStyle(QPainter* painter, const QStyleOptionViewItem& option, const XQItem& item) const | ||||||
|  | { | ||||||
|  |   QStyleOptionComboBox comboOption; | ||||||
|  |  | ||||||
|   QWidget* srcWidget = qobject_cast<QWidget*>(option.styleObject); |   QWidget* srcWidget = qobject_cast<QWidget*>(option.styleObject); | ||||||
|   QStyleOptionComboBox comboOption; |  | ||||||
|   QStyle* comboStyle = srcWidget->style(); |  | ||||||
|  |  | ||||||
|   comboOption.initFrom(srcWidget); |   comboOption.initFrom(srcWidget); | ||||||
|  |  | ||||||
|   // set options |   // set options | ||||||
| @@ -182,68 +190,103 @@ void XQItemDelegate::drawComboBoxStyle(QPainter *painter, const QStyleOptionView | |||||||
|   comboOption.state = option.state | QStyle::State_Selected | QStyle::State_Enabled; |   comboOption.state = option.state | QStyle::State_Selected | QStyle::State_Enabled; | ||||||
|   // not editable => only visual, but painter needs to know it |   // not editable => only visual, but painter needs to know it | ||||||
|   comboOption.editable = false; |   comboOption.editable = false; | ||||||
|   comboOption.currentText = index.data(Qt::DisplayRole).toString(); |   comboOption.currentText = item.text(); | ||||||
|   // decoration (if any) |   // decoration (if any) | ||||||
|   comboOption.currentIcon = qvariant_cast<QIcon>(index.data(Qt::DecorationRole)); |   comboOption.currentIcon = qvariant_cast<QIcon>(item.data(Qt::DecorationRole)); | ||||||
|   comboOption.iconSize = comboOption.currentIcon.actualSize(QSize(option.rect.height() - 3, option.rect.height() - 3)); |   comboOption.iconSize = comboOption.currentIcon.actualSize(QSize(option.rect.height() - 3, option.rect.height() - 3)); | ||||||
|  |  | ||||||
|   // save painter |   // save painter | ||||||
|   painter->save(); |   painter->save(); | ||||||
|  |   QStyle* widgetStyle = srcWidget->style(); | ||||||
|   // draw combo |   // draw combo | ||||||
|   comboStyle->drawComplexControl(QStyle::CC_ComboBox, &comboOption, painter, srcWidget); |   widgetStyle->drawComplexControl(QStyle::CC_ComboBox, &comboOption, painter, srcWidget); | ||||||
|   // and combobox label |   // and combobox label | ||||||
|   comboStyle->drawControl(QStyle::CE_ComboBoxLabel, &comboOption, painter, srcWidget); |   widgetStyle->drawControl(QStyle::CE_ComboBoxLabel, &comboOption, painter, srcWidget); | ||||||
|   // restore painter |   // restore painter | ||||||
|   painter->restore(); |   painter->restore(); | ||||||
| } | } | ||||||
|  |  | ||||||
| void XQItemDelegate::drawSpinBoxStyle(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const |  | ||||||
|  | //! Zeichnet das Item als spin box. | ||||||
|  |  | ||||||
|  | void XQItemDelegate::drawSpinBoxStyle(QPainter* painter, const QStyleOptionViewItem& option, const XQItem& item) const | ||||||
| { | { | ||||||
|  |  | ||||||
|   // xx_fix! |   qDebug() << " --- jawas +++? SPINBOX!"; | ||||||
|   //int value = index.data(XQItem::ContentRole ).toInt(); |  | ||||||
|   QStyleOptionSpinBox spinBoxOption; |   QWidget* srcWidget = qobject_cast<QWidget*>(option.styleObject); | ||||||
|   spinBoxOption.rect = option.rect; |   QStyleOptionViewItem viewOption(option); | ||||||
|   /* |   QStyleOptionSpinBox spinBoxOption; | ||||||
|   spinBoxOption.text = QString::number(value); |   spinBoxOption.initFrom(srcWidget); | ||||||
|   spinBoxOption.textAlignment = Qt::AlignCenter; |  | ||||||
|   spinBoxOption.textVisible = true; |  | ||||||
|   */ |   // 1. Grundlegende Optionen initialisieren und Hintergrund zeichnen (wichtig für Selektion) | ||||||
|  |   initStyleOption(&viewOption, item.index()); | ||||||
|  |   if (option.state & QStyle::State_HasFocus) | ||||||
|  |   { | ||||||
|  |     viewOption.state = viewOption.state ^ QStyle::State_HasFocus; // Fokus nicht auf dem Hintergrund malen | ||||||
|  |   } | ||||||
|  |   QApplication::style()->drawPrimitive(QStyle::PE_PanelItemViewItem, &viewOption, painter); | ||||||
|  |  | ||||||
|  |   spinBoxOption.rect = option.rect; | ||||||
|  |   spinBoxOption.state = option.state | QStyle::State_Sunken; // Sunken-State für den "LineEdit"-Look | ||||||
|  |   spinBoxOption.buttonSymbols = QAbstractSpinBox::UpDownArrows; | ||||||
|  |   spinBoxOption.stepEnabled = QAbstractSpinBox::StepUpEnabled | QAbstractSpinBox::StepDownEnabled; | ||||||
|  |   spinBoxOption.frame = true; | ||||||
|  |  | ||||||
|  |   QStyle* widgetStyle = srcWidget->style(); | ||||||
|  |   widgetStyle->drawComplexControl(QStyle::CC_SpinBox, &spinBoxOption, painter, nullptr); | ||||||
|  |   QRect editRect = widgetStyle->subControlRect(QStyle::CC_SpinBox, &spinBoxOption, QStyle::SC_SpinBoxEditField, nullptr); | ||||||
|  |   painter->drawText(editRect.adjusted(1, 0, -1, 0), Qt::AlignCenter, item.text()); | ||||||
|  |  | ||||||
|   QApplication::style()->drawComplexControl(QStyle::CC_SpinBox,&spinBoxOption, painter); |  | ||||||
| } | } | ||||||
|  |  | ||||||
|  |  | ||||||
| QSize XQItemDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const | //! Überschreibt QStyledItemDelegate::sizeHint(option, index); | ||||||
|  |  | ||||||
|  | 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 | ||||||
| { | { | ||||||
|  |   Q_UNUSED(option); | ||||||
|  |  | ||||||
|   return QStyledItemDelegate::createEditor( parent, option, index ); |   XQItem& item  = xqItemFromIndex(index); | ||||||
|  |   XQItem::EditorType edType = item.editorType(); | ||||||
|   int editorType = XQItem::xqItemFromIndex(index).editorType(); |   if( edType == XQItem::NoEditorType ) | ||||||
|   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; | ||||||
|  |  | ||||||
|  |   QWidget* editor = itemEditorFactory()->createEditor(edType, parent);; | ||||||
|  |   //return QStyledItemDelegate::createEditor( parent, option, index ); | ||||||
|  |   return editor; | ||||||
| } | } | ||||||
|  |  | ||||||
|  |  | ||||||
|  | //! 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 : | ||||||
|     { |     { | ||||||
|       QComboBox* comboBox = qobject_cast<QComboBox*>(editor); |       QComboBox* comboBox = qobject_cast<QComboBox*>(editor); | ||||||
|  |       // wir erwarten hier ein gültiges model? | ||||||
|       comboBox->setModel( item.fixedChoices()); |       comboBox->setModel( item.fixedChoices()); | ||||||
|       comboBox->setCurrentText( item.data().toString() ); |       comboBox->setCurrentText( item.data().toString() ); | ||||||
|       comboBox->showPopup(); |       comboBox->showPopup(); | ||||||
| @@ -251,24 +294,37 @@ 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); |  | ||||||
| } | } | ||||||
|  |  | ||||||
| void XQItemDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const |  | ||||||
|  | //! Schreibt die daten aus dem editor ins model zurück | ||||||
|  |  | ||||||
|  | void XQItemDelegate::setModelData(QWidget* editor, QAbstractItemModel* model, const QModelIndex& index) const | ||||||
| { | { | ||||||
|  |  | ||||||
|   XQItem& item = xqItemFromIndex( index ); |   XQItem& item = xqItemFromIndex( index ); | ||||||
|  |  | ||||||
|   switch( item.editorType()  ) |   switch( item.editorType()  ) | ||||||
|   { |   { | ||||||
|  |  | ||||||
|     case XQItem::ComboBoxType : |     case XQItem::ComboBoxType : | ||||||
|     { |     { | ||||||
|       QComboBox* comboBox = qobject_cast<QComboBox*>(editor); |       QComboBox* comboBox = qobject_cast<QComboBox*>(editor); | ||||||
|  |       item.setData( comboBox->currentText(), Qt::DisplayRole ); | ||||||
|       return; |       return; | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @@ -280,8 +336,12 @@ void XQItemDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, co | |||||||
|   QStyledItemDelegate::setModelData(editor, model, index); |   QStyledItemDelegate::setModelData(editor, model, index); | ||||||
| } | } | ||||||
|  |  | ||||||
|  |  | ||||||
|  | //! Überschreibt QItemDelegate::updateEditorGeometry. Nicht implementiert. | ||||||
|  |  | ||||||
| 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"; | ||||||
|   QStyledItemDelegate::updateEditorGeometry(editor, option, index); |   QStyledItemDelegate::updateEditorGeometry(editor, option, index); | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -32,24 +32,24 @@ class XQItemDelegate : public QStyledItemDelegate | |||||||
|  |  | ||||||
| public: | public: | ||||||
|  |  | ||||||
|   explicit XQItemDelegate(XQViewModel& modelView); |   explicit XQItemDelegate(XQViewModel& viewModel); | ||||||
|  |  | ||||||
|   XQTreeTable* treeTable() const; |   XQTreeTable* treeTable() const; | ||||||
|   XQItem&     xqItemFromIndex( const QModelIndex& index ) const; |   XQItem&     xqItemFromIndex( const QModelIndex& index ) const; | ||||||
|  |  | ||||||
|   void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const override; |   void paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const override; | ||||||
|   QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const override; |   QSize sizeHint(const QStyleOptionViewItem& option, const QModelIndex& index) const override; | ||||||
|   QWidget* createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const override; |   QWidget* createEditor(QWidget* parent, const QStyleOptionViewItem& option, const QModelIndex& index) const override; | ||||||
|   void setEditorData(QWidget *editor, const QModelIndex &index) const override; |   void setEditorData(QWidget* editor, const QModelIndex& index) const override; | ||||||
|   void setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const override; |   void setModelData(QWidget* editor, QAbstractItemModel *model, const QModelIndex& index) const override; | ||||||
|   void updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const override; |   void updateEditorGeometry(QWidget* editor, const QStyleOptionViewItem& option, const QModelIndex& index) const override; | ||||||
|  |  | ||||||
| protected: | protected: | ||||||
|  |  | ||||||
|   void drawHeaderStyle(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const; |   void drawHeaderStyle(QPainter* painter, const QStyleOptionViewItem& option, const XQItem& item ) const; | ||||||
|   void drawProgressBarStyle(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const; |   void drawColorBarStyle(QPainter* painter, const QStyleOptionViewItem& option, const XQItem& item) const; | ||||||
|   void drawComboBoxStyle(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const; |   void drawComboBoxStyle(QPainter* painter, const QStyleOptionViewItem& option, const XQItem& item) const; | ||||||
|   void drawSpinBoxStyle(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const; |   void drawSpinBoxStyle(QPainter* painter, const QStyleOptionViewItem& option, const XQItem& item) const; | ||||||
|  |  | ||||||
|   XQViewModel& _modelView; |   XQViewModel& _modelView; | ||||||
|  |  | ||||||
|   | |||||||
| @@ -29,7 +29,7 @@ void XQItemFactory::initItemFactory( const QString& modelSheetFileName ) | |||||||
|     for( const auto& [key,value] : sheetNode->attributes() ) |     for( const auto& [key,value] : sheetNode->attributes() ) | ||||||
|     { |     { | ||||||
|       //qDebug() << " --- conf item Type: " << key << " : " << value; |       //qDebug() << " --- conf item Type: " << key << " : " << value; | ||||||
|       setItemDataFromString( *itemType, key, value );      |       setItemTypeDataFromString( *itemType, key, value ); | ||||||
|     } |     } | ||||||
|   }; |   }; | ||||||
|  |  | ||||||
| @@ -91,7 +91,7 @@ XQItemType* XQItemFactory::makeItemType(const XQNodePtr& sheetEntry ) | |||||||
|     // wenn ja, überschreiben |     // wenn ja, überschreiben | ||||||
|     if( role != XQItem::NoRole ) |     if( role != XQItem::NoRole ) | ||||||
|     { |     { | ||||||
|       QVariant newValue = makeVariant(role, attrEntry.second ); |       QVariant newValue = XQItem::makeVariant( itemType, role, attrEntry.second ); | ||||||
|       itemType = itemType->replaceAttribute( newValue, role ); |       itemType = itemType->replaceAttribute( newValue, role ); | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @@ -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 | ||||||
| @@ -123,143 +124,24 @@ XQNodePtr XQItemFactory::findModelSheet( const QString& modelName ) const | |||||||
|  |  | ||||||
| //! erzeugt eine QVariant aus dem gegebenen string und setzt diese dann via role im item. | //! erzeugt eine QVariant aus dem gegebenen string und setzt diese dann via role im item. | ||||||
|  |  | ||||||
| void XQItemFactory::setItemDataFromString( XQItem& item, const QString& roleKey, const QString& source ) const | void XQItemFactory::setItemTypeDataFromString( XQItem& item, const QString& roleKey, const QString& source ) const | ||||||
| { | { | ||||||
|   int dataRole = XQItem::fetchItemDataRole( roleKey ); |   int dataRole = XQItem::fetchItemDataRole( roleKey ); | ||||||
|   if( dataRole != XQItem::NoRole) |   if( dataRole != XQItem::NoRole) | ||||||
|   { |   { | ||||||
|     QVariant variant = makeVariant( dataRole, source ); |     QVariant variant = XQItem::makeVariant( &item, dataRole, source ); | ||||||
|     if( !variant.isNull() && variant.isValid() ) |     if( !variant.isNull() && variant.isValid() ) | ||||||
|       item.setData( variant, dataRole ); |       item.setData( variant, dataRole ); | ||||||
|   } |   } | ||||||
| } | } | ||||||
|  |  | ||||||
|  |  | ||||||
| //! erzeugt eine QVariant aus dem gegebenen string |  | ||||||
|  |  | ||||||
| QVariant XQItemFactory::makeVariant( int dataRole, const QString& source ) const |  | ||||||
| { |  | ||||||
|  |  | ||||||
|   QVariant value; |  | ||||||
|  |  | ||||||
|   switch(dataRole) |  | ||||||
|   { |  | ||||||
|     // das ist ein pointer auf den  original-string aus dem XML |  | ||||||
|     case XQItem::ContentRole: |  | ||||||
|     { |  | ||||||
|       // content() -> QString* |  | ||||||
|       value = QVariant::fromValue(&source); |  | ||||||
|       break; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     case XQItem::ItemTypeRole: |  | ||||||
|     { |  | ||||||
|       // itemType() -> XQItemType* |  | ||||||
|       //qDebug() << " --- makeVariant: make ItemType: " << source; |  | ||||||
|       XQItemType* itemType = findItemTypeTemplate( source ); |  | ||||||
|       value = QVariant::fromValue(itemType); |  | ||||||
|       break; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     case XQItem::RenderStyleRole: |  | ||||||
|     { |  | ||||||
|       XQItem::RenderStyle renderStyle = XQItem::fetchRenderStyle( source ); |  | ||||||
|       value = QVariant::fromValue(renderStyle); |  | ||||||
|       break; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     case XQItem::EditorTypeRole: |  | ||||||
|     { |  | ||||||
|       XQItem::EditorType editorType = XQItem::fetchEditorType( source ); |  | ||||||
|       value = QVariant::fromValue(editorType); |  | ||||||
|       break; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     case XQItem::UnitTypeRole: |  | ||||||
|     { |  | ||||||
|       //qDebug() << " --- make unit type: " << source; |  | ||||||
|       XQItem::UnitType unitType = XQItem::fetchUnitType( source ); |  | ||||||
|       value = QVariant::fromValue(unitType); |  | ||||||
|       break; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     case XQItem::ContentFormatRole: |  | ||||||
|     { |  | ||||||
|       // contentFormat() -> QString |  | ||||||
|       value = QVariant::fromValue(source); |  | ||||||
|       break; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     case XQItem::FlagsRole: |  | ||||||
|     { |  | ||||||
|       QFlags itemFlags = Qt::NoItemFlags; |  | ||||||
|       const QStringList flagKeys = source.split( '|' ); |  | ||||||
|       for( const QString& flagKey : flagKeys ) |  | ||||||
|       { |  | ||||||
|         Qt::ItemFlag flag = XQItem::fetchItemFlag( flagKey ); |  | ||||||
|         itemFlags.setFlag( flag ); |  | ||||||
|       } |  | ||||||
|       value = QVariant::fromValue(itemFlags); |  | ||||||
|       break; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|  |  | ||||||
|     case XQItem::IconRole: |  | ||||||
|     {       |  | ||||||
|       QIcon typeIcon = XQAppData::typeIcon(source); |  | ||||||
|       value = QVariant::fromValue(typeIcon); |  | ||||||
|       break; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|  |  | ||||||
|     case XQItem::FixedChoicesRole: |  | ||||||
|     { |  | ||||||
|       const QStringList choices = source.split( '|' ); |  | ||||||
|  |  | ||||||
|       QStandardItemModel* fixedChoices = new QStandardItemModel(); |  | ||||||
|       for( const QString& entry : choices ) |  | ||||||
|         fixedChoices->appendRow( new QStandardItem( entry ) ); |  | ||||||
|       value = QVariant::fromValue(fixedChoices); |  | ||||||
|       break; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     /* |  | ||||||
|  |  | ||||||
|     case XQItem::ContentNodeRole: |  | ||||||
|     { |  | ||||||
|       value = QVariant::fromValue(&source); |  | ||||||
|       break; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     case XQItem::XQItem::SheetNodeRole: |  | ||||||
|     { |  | ||||||
|       value = QVariant::fromValue(&source); |  | ||||||
|       break; |  | ||||||
|     } |  | ||||||
|     */ |  | ||||||
|  |  | ||||||
|     default: |  | ||||||
|     case XQItem::XQItem::NoRole: |  | ||||||
|     { |  | ||||||
|       break; |  | ||||||
|     } |  | ||||||
|   }; |  | ||||||
|  |  | ||||||
|   //if( !value.toString().isEmpty()) |  | ||||||
|   //  setData( value, dataRole); |  | ||||||
|  |  | ||||||
|   return value; |  | ||||||
|  |  | ||||||
| } |  | ||||||
|  |  | ||||||
| /// | /// | ||||||
| /// ------------------------------------------------ | /// ------------------------------------------------ | ||||||
| /// | /// | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
| /* | /* | ||||||
| XQItemList XQItemFactory::makeEmptyRow( const XQNodePtr& contentNode, const XQNodePtr& sheetNode ) | XQItemList XQItemFactory::makeEmptyRow( const XQNodePtr& contentNode, const XQNodePtr& sheetNode ) | ||||||
| { | { | ||||||
| @@ -304,7 +186,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 +202,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 +228,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); |     contentPtr = contentNode->attribute_ptr( sheetNode->tag_name() ); | ||||||
|       break; |  | ||||||
|  |  | ||||||
|     case mData: |  | ||||||
|       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 +243,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; | ||||||
|  | } | ||||||
|   | |||||||
| @@ -28,35 +28,24 @@ 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 ); |   void        setItemTypeDataFromString( XQItem& item, const QString& roleKey, const QString& source ) const; | ||||||
|  |  | ||||||
|   // wozu ist das gut? |  | ||||||
|   //XQItemList createGenericRow( const XQNodePtr& contentNode, const XQNodePtr& sheetNode ); |  | ||||||
|  |  | ||||||
|   void setItemDataFromString( XQItem& item, const QString& roleKey, const QString& source ) const; |  | ||||||
|  |  | ||||||
|   XQItemType* makeItemType(const XQNodePtr& sheetEntry ); |   XQItemType* makeItemType(const XQNodePtr& sheetEntry ); | ||||||
|   XQItemType* findItemTypeTemplate(const QString& key ) const; |   XQItemType* findItemTypeTemplate(const QString& key ) const; | ||||||
|   QVariant    makeVariant(int dataRole, const QString &value ) const; |  | ||||||
|  |  | ||||||
| protected: | 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 )>; | ||||||
|   | |||||||
| @@ -113,6 +113,7 @@ XQItemType* XQItemType::replaceAttribute( const QVariant& newValue, int role ) | |||||||
|   // Gibt es den geänderten ItemType schon? |   // Gibt es den geänderten ItemType schon? | ||||||
|   QString newKey = myClone->makeItemTypeKey(); |   QString newKey = myClone->makeItemTypeKey(); | ||||||
|   // jawoll |   // jawoll | ||||||
|  |  | ||||||
|   if( s_ItemTypeMap.contains( newKey ) ) |   if( s_ItemTypeMap.contains( newKey ) ) | ||||||
|   { |   { | ||||||
|     // abräumen ... |     // abräumen ... | ||||||
| @@ -134,22 +135,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 +168,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; | ||||||
|   | |||||||
| @@ -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: | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										50
									
								
								src/main.cpp
									
									
									
									
									
								
							
							
						
						
									
										50
									
								
								src/main.cpp
									
									
									
									
									
								
							| @@ -19,6 +19,7 @@ | |||||||
| #include <QQmlApplicationEngine> | #include <QQmlApplicationEngine> | ||||||
| #include <QUrl> | #include <QUrl> | ||||||
| #include <QQmlContext> | #include <QQmlContext> | ||||||
|  | #include <QStyleFactory> | ||||||
|  |  | ||||||
| #include <xqchildmodel.h> | #include <xqchildmodel.h> | ||||||
| #include <xqquickwidget.h> | #include <xqquickwidget.h> | ||||||
| @@ -74,59 +75,23 @@ XQChildModel* createChildModel() | |||||||
| } | } | ||||||
|  |  | ||||||
|  |  | ||||||
| class DummyModel : public XQChildModel |  | ||||||
| { |  | ||||||
|  |  | ||||||
| public: |  | ||||||
|  |  | ||||||
|   DummyModel() |  | ||||||
|   { |  | ||||||
|  |  | ||||||
|     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(); |  | ||||||
|     addModelData( contentRoot->first_child() ); |  | ||||||
|  |  | ||||||
|     //XQTreeTable* treeTable = new XQTreeTable; |  | ||||||
|     //treeTable->setModel(this); |  | ||||||
|     //setTreeTable( treeTable ); |  | ||||||
|  |  | ||||||
|     //treeTable->show(); |  | ||||||
|   } |  | ||||||
| }; |  | ||||||
|  |  | ||||||
|  |  | ||||||
| using namespace Qt::Literals::StringLiterals; | using namespace Qt::Literals::StringLiterals; | ||||||
|  |  | ||||||
| int main(int argc, char *argv[]) | int main(int argc, char *argv[]) | ||||||
| { | { | ||||||
|  |  | ||||||
|   /* |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|    // 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(); |  | ||||||
| }); |  | ||||||
|   */ |  | ||||||
|  |  | ||||||
|   /* |  | ||||||
|   QApplication app(argc, argv); |   QApplication app(argc, argv); | ||||||
|   //app.setStyle("fusion"); |   //qDebug() << QStyleFactory::keys(); | ||||||
|  |   //QApplication::setStyle("fusion"); | ||||||
|  |   //QApplication::setStyle("windowsvista"); | ||||||
|  |   //QApplication::setStyle("windows"); | ||||||
|  |  | ||||||
|   XQMainWindow window; |   XQMainWindow window; | ||||||
|   window.show(); |   window.show(); | ||||||
| */ |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |   /* | ||||||
|   QApplication app(argc, argv); |   QApplication app(argc, argv); | ||||||
|  |  | ||||||
|  |  | ||||||
|   XQMainWindow::setupWorkingDir(); |   XQMainWindow::setupWorkingDir(); | ||||||
|   XQItemFactory::instance().initItemFactory( c_ModelSheetFileName ); |   XQItemFactory::instance().initItemFactory( c_ModelSheetFileName ); | ||||||
|  |  | ||||||
| @@ -152,6 +117,7 @@ connect(model, &QStandardItemModel::itemChanged, | |||||||
|  |  | ||||||
|     qDebug() << " hhakl!"; |     qDebug() << " hhakl!"; | ||||||
|  |  | ||||||
|  | */ | ||||||
|   return app.exec(); |   return app.exec(); | ||||||
|  |  | ||||||
| } | } | ||||||
|   | |||||||
| @@ -28,10 +28,10 @@ void XQNodeStore::dumpList( const QString& title ) const | |||||||
| } | } | ||||||
|  |  | ||||||
|  |  | ||||||
| //! kostruktor. übergibt command-type und die aufrufende modelView. | //! kostruktor. übergibt command-type und die aufrufende viewModel. | ||||||
|  |  | ||||||
| XQCommand::XQCommand(CmdType cmdType, XQViewModel* modelView ) | XQCommand::XQCommand(CmdType cmdType, XQViewModel* viewModel ) | ||||||
|   : _cmdType{ cmdType }, _viewModel(modelView) |   : _cmdType{ cmdType }, _viewModel(viewModel) | ||||||
| { | { | ||||||
|    |    | ||||||
| } | } | ||||||
| @@ -108,20 +108,22 @@ void XQCommand::setOriginIndex( const QModelIndex& origin ) | |||||||
| void XQCommand::saveNodes( const QModelIndexList& list ) | void XQCommand::saveNodes( const QModelIndexList& list ) | ||||||
| { | { | ||||||
|   clear(); |   clear(); | ||||||
|   // über jede zeil |   // über jede zeile | ||||||
|   for( auto entry : list ) |   for( auto entry : list ) | ||||||
|   { |   { | ||||||
|     // knoten holen |     // knoten holen | ||||||
|     const XQNodePtr& contentNode = XQItem::xqItemFromIndex( entry ).contentNode(); |     const XQNodePtr& contentNode = XQItem::xqItemFromIndex( entry ).contentNode(); | ||||||
|     // hier speichern wir den original knoten, nicht einen clone, wie im clipboard. |     // hier speichern wir den original knoten, nicht einen clone, wie im clipboard. | ||||||
|     push_back( {entry.row(), contentNode->own_pos(), contentNode } ); |     // obacht: bei einem Header is der content node null | ||||||
|  |     if(contentNode) | ||||||
|  |       push_back( {entry.row(), contentNode->own_pos(), contentNode } ); | ||||||
|   } |   } | ||||||
| } | } | ||||||
|  |  | ||||||
|  |  | ||||||
| //! 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 | ||||||
|   | |||||||
| @@ -66,7 +66,7 @@ public: | |||||||
|     cmdExtern //?? |     cmdExtern //?? | ||||||
|   }; |   }; | ||||||
|  |  | ||||||
|   XQCommand(CmdType cmdType, XQViewModel* modelView ); |   XQCommand(CmdType cmdType, XQViewModel* viewModel ); | ||||||
|   virtual ~XQCommand(); |   virtual ~XQCommand(); | ||||||
|  |  | ||||||
|   CmdType                commandType() const; |   CmdType                commandType() const; | ||||||
| @@ -80,7 +80,7 @@ public: | |||||||
|   void redo() override; |   void redo() override; | ||||||
|   void undo() override; |   void undo() override; | ||||||
|    |    | ||||||
|   QString toString(); |   QString toString() const; | ||||||
|  |  | ||||||
| protected: | protected: | ||||||
|  |  | ||||||
|   | |||||||
| @@ -1,206 +0,0 @@ | |||||||
| /*************************************************************************** |  | ||||||
|  |  | ||||||
|     source::worx xtree |  | ||||||
|     Copyright © 2024-2025 c.holzheuer |  | ||||||
|     christoph.holzheuer@gmail.com |  | ||||||
|  |  | ||||||
|     This program is free software; you can redistribute it and/or modify |  | ||||||
|     it under the terms of the GNU General Public License as published by |  | ||||||
|     the Free Software Foundation; either version 2 of the License, or |  | ||||||
|     (at your option) any later version. |  | ||||||
|  |  | ||||||
| ***************************************************************************/ |  | ||||||
|  |  | ||||||
|  |  | ||||||
| #include <xqmodelsectionlist.h> |  | ||||||
|  |  | ||||||
|  |  | ||||||
| //! kontstruktor. übergibt den start-index und einen model-knoten mit der beschreibung |  | ||||||
| //! der datenknoten. |  | ||||||
|  |  | ||||||
| XQModelSection::XQModelSection(const QModelIndex& modelIndex, XQNodePtr sheetNode) |  | ||||||
|   : _modelIndex{ modelIndex }, _sectionRootNode{ sheetNode } |  | ||||||
| { |  | ||||||
|  |  | ||||||
| } |  | ||||||
|  |  | ||||||
|  |  | ||||||
| //! elementvergleich. |  | ||||||
|  |  | ||||||
| bool XQModelSection::operator==(const XQModelSection& other) const |  | ||||||
| { |  | ||||||
|   return _modelIndex == other._modelIndex && _sectionRootNode == other._sectionRootNode; |  | ||||||
| } |  | ||||||
|  |  | ||||||
|  |  | ||||||
| //! true wenn der start-index valide und ein model-knoten vorhanden. |  | ||||||
|  |  | ||||||
| bool XQModelSection::isValid() const |  | ||||||
| { |  | ||||||
|   return _modelIndex.isValid() && _sectionRootNode; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| QModelIndex XQModelSection::persistentModelIndex() const |  | ||||||
| { |  | ||||||
|   return _modelIndex.operator QModelIndex(); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| XQNodePtr XQModelSection::sectionRootNode() const |  | ||||||
| { |  | ||||||
|   return _sectionRootNode; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| //! Gibt den sheet-node zurück, das ist die model-beschreibung, |  | ||||||
| //! siehe modelsheet.xml: |  | ||||||
| //! <section> |  | ||||||
| //!   <header> |  | ||||||
| //!   <data> <- dort |  | ||||||
|  |  | ||||||
| //! __fix! das versteht doch kein mensch! |  | ||||||
|  |  | ||||||
| XQNodePtr XQModelSection::sheetRootNode() const |  | ||||||
| { |  | ||||||
|   return _sectionRootNode->find_child_by_tag_name( c_ModelSheet ); |  | ||||||
| } |  | ||||||
|  |  | ||||||
|  |  | ||||||
| //! Gibt den content root node zurück, das ist der |  | ||||||
| //! zeiger auf die realen inhalte. |  | ||||||
|  |  | ||||||
| XQNodePtr XQModelSection::contentRootNode() const |  | ||||||
| { |  | ||||||
|   return _contentRootNode; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| void XQModelSection::setContentRootNode( const XQNodePtr contentRootNode ) |  | ||||||
| { |  | ||||||
|   _contentRootNode = contentRootNode; |  | ||||||
| } |  | ||||||
|  |  | ||||||
|  |  | ||||||
| //! gibt die zeile des start-index zurück. |  | ||||||
|  |  | ||||||
| int XQModelSection::XQModelSection::row() const |  | ||||||
| { |  | ||||||
|   return _modelIndex.row(); |  | ||||||
| } |  | ||||||
|  |  | ||||||
|  |  | ||||||
| //! gibt den 'content type' zurück. |  | ||||||
|  |  | ||||||
| const QString& XQModelSection::contentType() const |  | ||||||
| { |  | ||||||
|   return _sectionRootNode->attribute( c_ContentType ); |  | ||||||
| } |  | ||||||
|  |  | ||||||
|  |  | ||||||
| //! gibt das dieser section entsprechende header-item zurück. |  | ||||||
|  |  | ||||||
| XQItem& XQModelSection::XQModelSection::headerItem() const |  | ||||||
| { |  | ||||||
|   return XQItem::xqItemFromIndex( _modelIndex ); |  | ||||||
| } |  | ||||||
|  |  | ||||||
|  |  | ||||||
| //! testet, ob die unter 'sectionKey' eine gültige section vorhanden ist. |  | ||||||
|  |  | ||||||
| bool XQModelSectionList::hasValidSection(const QString& sectionKey) const |  | ||||||
| { |  | ||||||
|   if (!contains(sectionKey) ) |  | ||||||
|     return false; |  | ||||||
|   return at(sectionKey).isValid(); |  | ||||||
| } |  | ||||||
|  |  | ||||||
|  |  | ||||||
| //! gibt für einen model index die 'zuständige' section zurück. |  | ||||||
|  |  | ||||||
| const XQModelSection& XQModelSectionList::sectionFromIndex( const QModelIndex& index ) const |  | ||||||
| { |  | ||||||
|   return sectionFromRow( index.row() ); |  | ||||||
| } |  | ||||||
|  |  | ||||||
|  |  | ||||||
| //! gibt für eine zeile die 'zuständige' section zurück: der bestand an section wird |  | ||||||
| //! nach der passenden section durchsucht. |  | ||||||
|  |  | ||||||
| const XQModelSection& XQModelSectionList::sectionFromRow(int itemRow ) const |  | ||||||
| { |  | ||||||
|  |  | ||||||
|   int i = size() - 1; |  | ||||||
|   for (; i >= 0; --i) |  | ||||||
|   { |  | ||||||
|     if ( at(i).persistentModelIndex().row() < itemRow ) |  | ||||||
|       return at(i); |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   static XQModelSection s_DummySection; |  | ||||||
|  |  | ||||||
|   return s_DummySection; |  | ||||||
|  |  | ||||||
| } |  | ||||||
|  |  | ||||||
|  |  | ||||||
| //! ermittelt die erste zeile einer section. |  | ||||||
|  |  | ||||||
| int XQModelSectionList::firstRow(const QModelIndex& idx) const |  | ||||||
| { |  | ||||||
|   return sectionFromRow(idx.row() ).row(); |  | ||||||
| } |  | ||||||
|  |  | ||||||
|  |  | ||||||
| //! ermittelt die zeile unterhalb des gegebenen modelindex, |  | ||||||
| //! zum einfügen neuer items ebendort. |  | ||||||
|  |  | ||||||
| int XQModelSectionList::lastRow(const QModelIndex& idx) const |  | ||||||
| { |  | ||||||
|   return lastRow(sectionFromRow(idx.row())); |  | ||||||
| } |  | ||||||
|  |  | ||||||
|  |  | ||||||
| //! ermittelt die zeile unterhalb der gegebenen section, |  | ||||||
| //! zum einfügen neuer items ebendort. |  | ||||||
|  |  | ||||||
| int XQModelSectionList::lastRow(const XQModelSection& section ) const |  | ||||||
| { |  | ||||||
|   //qDebug() << " -- last row in section: " << section.modelIndex.data().toString() << " --> " << section.modelIndex.row(); |  | ||||||
|   // row() der section unterhalb dieser |  | ||||||
|   // __fix? index mit speichern? |  | ||||||
|   int index = indexOf(section); |  | ||||||
|   if (index > -1) |  | ||||||
|   { |  | ||||||
|     // last section? return last row of model |  | ||||||
|     if (index == size() - 1) |  | ||||||
|       return section.persistentModelIndex().model()->rowCount();// - 1; |  | ||||||
|     // return row above the row of the next section -> last row of given section |  | ||||||
|     return at(index+1).row(); |  | ||||||
|   } |  | ||||||
|   return -1; |  | ||||||
| } |  | ||||||
|  |  | ||||||
|  |  | ||||||
| //! gibt alle sections aus, zum ankucken. |  | ||||||
|  |  | ||||||
| void XQModelSectionList::dump() const |  | ||||||
| { |  | ||||||
|   qDebug() << " --- sections dump(): " <<size() << " entries."; |  | ||||||
|   for( int i = 0; i<size(); ++i ) |  | ||||||
|   { |  | ||||||
|     QModelIndex idx = at(i).persistentModelIndex(); |  | ||||||
|     qDebug() << " --- sections:" << i << "row: " << idx.row() << " keyOf(i): " << keyOf(i) << " indexData: "<< idx.data().toString() << " itemData: " << XQItem::xqItemFromIndex(idx).data(Qt::DisplayRole).toString(); |  | ||||||
|   } |  | ||||||
|  |  | ||||||
| } |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
							
								
								
									
										207
									
								
								src/model/xqsectionmanager.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										207
									
								
								src/model/xqsectionmanager.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,207 @@ | |||||||
|  | /*************************************************************************** | ||||||
|  |  | ||||||
|  |     source::worx xtree | ||||||
|  |     Copyright © 2024-2025 c.holzheuer | ||||||
|  |     christoph.holzheuer@gmail.com | ||||||
|  |  | ||||||
|  |     This program is free software; you can redistribute it and/or modify | ||||||
|  |     it under the terms of the GNU General Public License as published by | ||||||
|  |     the Free Software Foundation; either version 2 of the License, or | ||||||
|  |     (at your option) any later version. | ||||||
|  |  | ||||||
|  | ***************************************************************************/ | ||||||
|  |  | ||||||
|  |  | ||||||
|  | #include <xqsectionmanager.h> | ||||||
|  |  | ||||||
|  |  | ||||||
|  | //! kontstruktor. übergibt den start-index und einen model-knoten mit der beschreibung | ||||||
|  | //! der datenknoten. | ||||||
|  |  | ||||||
|  | XQModelSection::XQModelSection(const QModelIndex& modelIndex, XQNodePtr sheetNode) | ||||||
|  |   : _modelIndex{ modelIndex }, _sectionSheetRootNode{ sheetNode } | ||||||
|  | { | ||||||
|  |  | ||||||
|  | } | ||||||
|  |  | ||||||
|  |  | ||||||
|  | //! elementvergleich. | ||||||
|  |  | ||||||
|  | bool XQModelSection::operator==(const XQModelSection& other) const | ||||||
|  | { | ||||||
|  |   return _modelIndex == other._modelIndex && _sectionSheetRootNode == other._sectionSheetRootNode; | ||||||
|  | } | ||||||
|  |  | ||||||
|  |  | ||||||
|  | //! true wenn der start-index valide und ein model-knoten vorhanden. | ||||||
|  |  | ||||||
|  | bool XQModelSection::isValid() const | ||||||
|  | { | ||||||
|  |   return _modelIndex.isValid() && _sectionSheetRootNode; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | QModelIndex XQModelSection::startIndex() const | ||||||
|  | { | ||||||
|  |   return _modelIndex.operator QModelIndex(); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | XQNodePtr XQModelSection::sectionRootNode() const | ||||||
|  | { | ||||||
|  |   return _sectionSheetRootNode; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | //! Gibt den sheet-node zurück, das ist die model-beschreibung, | ||||||
|  | //! siehe modelsheet.xml: | ||||||
|  | //! <section> | ||||||
|  | //!   <header> | ||||||
|  | //!   <data> <- dort | ||||||
|  |  | ||||||
|  | //! __fix! das versteht doch kein mensch! | ||||||
|  |  | ||||||
|  | XQNodePtr XQModelSection::sheetRootNode() const | ||||||
|  | { | ||||||
|  |   return _sectionSheetRootNode->find_child_by_tag_name( c_ModelSheet ); | ||||||
|  | } | ||||||
|  |  | ||||||
|  |  | ||||||
|  | //! Gibt den content root node zurück, das ist der | ||||||
|  | //! zeiger auf die realen inhalte. | ||||||
|  |  | ||||||
|  | XQNodePtr XQModelSection::contentRootNode() const | ||||||
|  | { | ||||||
|  |   return _contentRootNode; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void XQModelSection::setContentRootNode( const XQNodePtr contentRootNode ) const | ||||||
|  | { | ||||||
|  |   _contentRootNode = contentRootNode; | ||||||
|  | } | ||||||
|  |  | ||||||
|  |  | ||||||
|  | //! gibt die zeile des start-index zurück. | ||||||
|  |  | ||||||
|  | int XQModelSection::XQModelSection::firstRow() const | ||||||
|  | { | ||||||
|  |   return _modelIndex.row(); | ||||||
|  | } | ||||||
|  |  | ||||||
|  |  | ||||||
|  | //! gibt den 'content type' zurück. | ||||||
|  |  | ||||||
|  | const QString& XQModelSection::contentType() const | ||||||
|  | { | ||||||
|  |   //qDebug() << " ---AUA & AUS!"; | ||||||
|  |   return _sectionSheetRootNode->attribute( c_ContentType ); | ||||||
|  | } | ||||||
|  |  | ||||||
|  |  | ||||||
|  | //! gibt das dieser section entsprechende header-item zurück. | ||||||
|  |  | ||||||
|  | XQItem& XQModelSection::XQModelSection::headerItem() const | ||||||
|  | { | ||||||
|  |   return XQItem::xqItemFromIndex( _modelIndex ); | ||||||
|  | } | ||||||
|  |  | ||||||
|  |  | ||||||
|  | //! testet, ob die unter 'sectionKey' eine gültige section vorhanden ist. | ||||||
|  |  | ||||||
|  | bool XQSectionManager::hasValidSection(const QString& sectionKey) const | ||||||
|  | { | ||||||
|  |   if (!_sections.contains(sectionKey) ) | ||||||
|  |     return false; | ||||||
|  |   return _sections.at(sectionKey).isValid(); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | const XQModelSection& XQSectionManager::sectionByKey( const QString& sectionKey ) const | ||||||
|  | { | ||||||
|  |   if( hasValidSection( sectionKey ) ) | ||||||
|  |     return _sections.at(sectionKey); | ||||||
|  |  | ||||||
|  |   throw XQException( "No section for key: ", sectionKey); | ||||||
|  |  | ||||||
|  | } | ||||||
|  |  | ||||||
|  |  | ||||||
|  | //! gibt für eine zeile die 'zuständige' section zurück: der bestand an section wird | ||||||
|  | //! nach der passenden section durchsucht. | ||||||
|  |  | ||||||
|  | const XQModelSection& XQSectionManager::sectionByRow(int itemRow ) const | ||||||
|  | { | ||||||
|  |  | ||||||
|  |  | ||||||
|  |   for (const auto& section : _sections) | ||||||
|  |   { | ||||||
|  |     qDebug() << " ---- SEC: " << itemRow  << " -> " <<  section.firstRow() << " :  " << lastRow( section ); | ||||||
|  |     XQSectionRange range = sectionRange(section); | ||||||
|  |     if( itemRow >= range.firstRow && itemRow <= range.lastRow) | ||||||
|  |       return section; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   throw XQException( "No section for item row: ", QString::number(itemRow)); | ||||||
|  |  | ||||||
|  | } | ||||||
|  |  | ||||||
|  |  | ||||||
|  | const XQModelSection& XQSectionManager::createSection(const QModelIndex& modelIndex, XQNodePtr sheetNode) | ||||||
|  | { | ||||||
|  |   const QString& sectionKey = sheetNode->attribute(c_ContentType); | ||||||
|  |   //qDebug() << " --- create Section: " << sectionKey << ": " << modelIndex.data().toString(); | ||||||
|  |   XQModelSection section(modelIndex, sheetNode ); | ||||||
|  |   _sections.addAtKey( sectionKey, section); | ||||||
|  |   return sectionByKey(sectionKey); | ||||||
|  | } | ||||||
|  |  | ||||||
|  |  | ||||||
|  | //! ermittelt die zeile unterhalb des gegebenen modelindex, | ||||||
|  | //! zum einfügen neuer items ebendort. | ||||||
|  |  | ||||||
|  | int XQSectionManager::lastRow(const XQModelSection& section ) const | ||||||
|  | { | ||||||
|  |   //qDebug() << " -- last row in section: " << section.startIndex().data().toString() << " --> " << section.startIndex().row(); | ||||||
|  |   // row() der section unterhalb dieser | ||||||
|  |   // __fix? index mit speichern? | ||||||
|  |   int index = _sections.indexOf(section); | ||||||
|  |   if (index > -1) | ||||||
|  |   { | ||||||
|  |     // last section? return last row of model | ||||||
|  |     if (index == _sections.size() - 1) | ||||||
|  |       return section.startIndex().model()->rowCount() - 1; | ||||||
|  |     // return row above the row of the next section -> last row of given section | ||||||
|  |     return _sections.at(index+1).firstRow() - 1; | ||||||
|  |   } | ||||||
|  |   return -1; | ||||||
|  | } | ||||||
|  |  | ||||||
|  |  | ||||||
|  | XQSectionRange XQSectionManager::sectionRange(const XQModelSection& section ) const | ||||||
|  | { | ||||||
|  |   return XQSectionRange{ section.startIndex().row(), lastRow(section) }; | ||||||
|  | } | ||||||
|  |  | ||||||
|  |  | ||||||
|  | //! gibt alle sections aus, zum ankucken. | ||||||
|  |  | ||||||
|  | void XQSectionManager::dump() const | ||||||
|  | { | ||||||
|  |   qDebug() << " --- sections dump(): " <<_sections.size() << " entries."; | ||||||
|  |   for( int i = 0; i<_sections.size(); ++i ) | ||||||
|  |   { | ||||||
|  |     QModelIndex idx = _sections.at(i).startIndex(); | ||||||
|  |     qDebug() << " --- sections:" << i << "row: " << idx.row() << " keyOf(i): " << _sections.keyOf(i) << " indexData: "<< idx.data().toString() << " itemData: " << XQItem::xqItemFromIndex(idx).data(Qt::DisplayRole).toString(); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  | } | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
| @@ -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; | ||||||
| 
 | 
 | ||||||
|   QModelIndex        persistentModelIndex() 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 _sectionSheetRootNode{}; | ||||||
|   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 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 §ion) const; | ||||||
| 
 | 
 | ||||||
|   void dump()const override; |   void dump()const; | ||||||
|  | 
 | ||||||
|  | protected: | ||||||
|  | 
 | ||||||
|  |   XQMaptor<XQModelSection> _sections; | ||||||
| 
 | 
 | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| #endif // XQMODELSECTIONLIST_H
 | #endif // XQSECTIONMANAGER_H
 | ||||||
| @@ -35,28 +35,34 @@ XQSelectionModel::XQSelectionModel(QAbstractItemModel* model, QObject* parent) | |||||||
| } | } | ||||||
|  |  | ||||||
|  |  | ||||||
| //! firz | //! jetzt die selektierten indices, wie die basisklasse, aber nur die innerhalt einer section. | ||||||
|  |  | ||||||
| void XQSelectionModel::select(const QItemSelection& selection, QItemSelectionModel::SelectionFlags command) | void XQSelectionModel::select(const QItemSelection& selection, QItemSelectionModel::SelectionFlags command) | ||||||
| { | { | ||||||
|   // step #0: fetch selected indices. |   // step #0: die ursprüngliche selection bestimmen | ||||||
|   const QModelIndexList list = selection.indexes(); |   const QModelIndexList list = selection.indexes(); | ||||||
|   if (list.isEmpty() || selectedRows().isEmpty() ) |   if (list.isEmpty() || selectedRows().isEmpty() ) | ||||||
|     return QItemSelectionModel::select(selection, command); |     return QItemSelectionModel::select(selection, command); | ||||||
|  |  | ||||||
|   // fetch first index |   // step 01: den ersten index bestimmen | ||||||
|   QModelIndex firstValid = list.first();   |   QModelIndex firstValid = list.first();   | ||||||
|   if (hasSelection() ) |   if (hasSelection() ) | ||||||
|     firstValid = selectedRows().first(); |     firstValid = selectedRows().first(); | ||||||
|  |  | ||||||
|   //XQItem& firstItem = XQItem::xqItemFromIndex(firstValid); |   // step 02: finde das erste item gültigem content node. | ||||||
|   //if( firstItem.isValid() ) |   XQNodePtr firstNode = XQItem::xqItemFromIndex(firstValid).contentNode(); | ||||||
|  |   while( !firstNode) | ||||||
|   { |   { | ||||||
|  |     firstValid = firstValid.siblingAtRow( firstValid.row()+1); | ||||||
|  |     firstNode = XQItem::xqItemFromIndex(firstValid).contentNode(); | ||||||
|  |   } | ||||||
|  |  | ||||||
|     XQNodePtr firstNode = XQItem::xqItemFromIndex(firstValid).contentNode(); |   // step 03: selektiere nur knoten, die den gleichen tag_name haben, sich also | ||||||
|  |   // in der selben section befinden | ||||||
|  |  | ||||||
|  |   if( firstNode ) | ||||||
|  |   { | ||||||
|     QItemSelection newSelection; |     QItemSelection newSelection; | ||||||
|     // __fixme! das crasht! |  | ||||||
|  |  | ||||||
|     for (const QModelIndex& idx : list) |     for (const QModelIndex& idx : list) | ||||||
|     { |     { | ||||||
|       XQNodePtr nextNode = XQItem::xqItemFromIndex(idx).contentNode(); |       XQNodePtr nextNode = XQItem::xqItemFromIndex(idx).contentNode(); | ||||||
| @@ -66,5 +72,7 @@ void XQSelectionModel::select(const QItemSelection& selection, QItemSelectionMod | |||||||
|     } |     } | ||||||
|     return QItemSelectionModel::select(newSelection, command); |     return QItemSelectionModel::select(newSelection, command); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |   // fallback | ||||||
|   QItemSelectionModel::select(selection, command); |   QItemSelectionModel::select(selection, command); | ||||||
| } | } | ||||||
|   | |||||||
| @@ -35,18 +35,34 @@ | |||||||
| 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(); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void showSelectionList( const QModelIndexList& list) | ||||||
|  | { | ||||||
|  |   for(const auto& entry : list ) | ||||||
|  |     qDebug() << " --- SelectionList: " << entry.data().toString(); | ||||||
|   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 ); | ||||||
|  |   }); | ||||||
|  |   // not needed | ||||||
|  |   //qRegisterMetaType<XQItem>("XQItem"); | ||||||
| } | } | ||||||
|  |  | ||||||
|  |  | ||||||
| @@ -59,7 +75,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 +106,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. | ||||||
| @@ -99,9 +132,7 @@ void XQViewModel::initModel(const QString& modelName) | |||||||
|  |  | ||||||
|    */ |    */ | ||||||
|   setObjectName( modelName ); |   setObjectName( modelName ); | ||||||
|   qDebug() << " --- initModel: " << objectName(); |    // model rootnode finden -> <DocumentTreeModel> | ||||||
|  |  | ||||||
|   // model rootnode finden -> <DocumentTreeModel> |  | ||||||
|   XQNodePtr modelSheet = _itemFactory.findModelSheet(  modelName ); // throws |   XQNodePtr modelSheet = _itemFactory.findModelSheet(  modelName ); // throws | ||||||
|  |  | ||||||
|   // #1: über alle sections |   // #1: über alle sections | ||||||
| @@ -111,7 +142,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 ); | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
| @@ -122,25 +153,24 @@ void XQViewModel::initModel(const QString& modelName) | |||||||
| //! die section kann erst gültig sein, wenn die items im model gelandet sind, | //! die section kann erst gültig sein, wenn die items im model gelandet sind, | ||||||
| //! deswegen ist das hier zusammengefasst. | //! deswegen ist das hier zusammengefasst. | ||||||
|  |  | ||||||
| //! Wrzeugt dann eine section aus einer frisch erzeugten itemlist. Der erste modelindex | //! Erzeugt dann eine section aus einer frisch erzeugten itemlist. Der erste modelindex | ||||||
| //! der liste und der root knoten der model-beschreibung werden gespeichert. | //! der liste und der root knoten der model-beschreibung werden gespeichert. | ||||||
|  |  | ||||||
| void XQViewModel::addSection(const XQItemList& list, const XQNodePtr& sectionNode ) | void XQViewModel::addSection(const XQItemList& list, const XQNodePtr& sheetNode ) | ||||||
| { | { | ||||||
|   // 1. die liste darf nicht leer sein |   // 1. die liste darf nicht leer sein | ||||||
|   Q_ASSERT(!list.isEmpty()); |   Q_ASSERT(!list.isEmpty()); | ||||||
|   // 2. sectionNode muss da sein |   // 2. sheetNode muss da sein | ||||||
|   Q_ASSERT(sectionNode); |   Q_ASSERT(sheetNode); | ||||||
|   // 3. 'ContenType' muss vorhanden sein |   // 3. 'ContenType' muss vorhanden sein | ||||||
|   if( !sectionNode->has_attribute( c_ContentType) ) |   if( !sheetNode->has_attribute( c_ContentType) ) | ||||||
|     throw XQException( "section list: Section node needs attribute 'ContentType'!"); |     throw XQException( "section list: Section node needs attribute 'ContentType'!"); | ||||||
|  |  | ||||||
|   // 5. das erzeugt dann auch valide indices |   // 5. das erzeugt dann auch valide indices | ||||||
|   appendRow(list); |   appendRow(list); | ||||||
|  |  | ||||||
|   // 6. jetzt können wir auch die sction erzeugen |   // 6. jetzt können wir auch die section erzeugen | ||||||
|   XQModelSection section(list[0]->index(), sectionNode ); |   const XQModelSection& section = _sections.createSection( list[0]->index(), sheetNode ); | ||||||
|  _sections.addAtKey(sectionNode->attribute( c_ContentType), section); |  | ||||||
|  |  | ||||||
|   // ... und es der welt mitteilen. |   // ... und es der welt mitteilen. | ||||||
|   emit sectionCreated( section ); |   emit sectionCreated( section ); | ||||||
| @@ -148,11 +178,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 ) | ||||||
|  | { | ||||||
|  |   if( section.isValid() && _treeTable ) | ||||||
|  |   {     | ||||||
|  |     XQSectionRange pos = _sections.sectionRange(section); | ||||||
|  |     qDebug() << " --- Section RANGE: " << pos.firstRow << " -> " << pos.lastRow; | ||||||
|  |  | ||||||
|  |     _treeTable->toggleRowsHidden(pos.firstRow, pos.lastRow );    | ||||||
|  |   } | ||||||
|  | } | ||||||
|  |  | ||||||
|  |  | ||||||
|  | /* | ||||||
|  | //! 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) | ||||||
| { | { | ||||||
|   qDebug() << " --- onActionTriggered: count:" << XQNode::s_Count; |   qDebug() << " --- onActionTriggered: count:" << action->text() <<": " << XQNode::s_Count; | ||||||
|  |  | ||||||
|   // all selected indices |   // all selected indices | ||||||
|   QModelIndexList selectionList = treeTable()->selectionModel()->selectedRows(); |   QModelIndexList selectionList = treeTable()->selectionModel()->selectedRows(); | ||||||
| @@ -161,6 +223,7 @@ void XQViewModel::onActionTriggered(QAction* action) | |||||||
|  |  | ||||||
|   switch( cmdType ) |   switch( cmdType ) | ||||||
|   { |   { | ||||||
|  |  | ||||||
|     // just handle undo ... |     // just handle undo ... | ||||||
|     case XQCommand::cmdUndo : |     case XQCommand::cmdUndo : | ||||||
|       return _undoStack->undo(); |       return _undoStack->undo(); | ||||||
| @@ -185,45 +248,22 @@ void XQViewModel::onActionTriggered(QAction* action) | |||||||
|  |  | ||||||
|   // we create a command |   // we create a command | ||||||
|   XQCommand* command = new XQCommand( cmdType, this ); |   XQCommand* command = new XQCommand( cmdType, this ); | ||||||
|  |   QModelIndex currentIndex = treeTable()->currentIndex(); | ||||||
|  |   command->setOriginIndex(currentIndex); | ||||||
|   // store the row positions of the selected indices |   // store the row positions of the selected indices | ||||||
|  |   showSelectionList(selectionList); | ||||||
|   command->saveNodes( selectionList ); |   command->saveNodes( selectionList ); | ||||||
|   command->setOriginIndex( treeTable()->currentIndex() ); |  | ||||||
|  |  | ||||||
|   // execute command |   // execute command | ||||||
|   _undoStack->push( command ); |   _undoStack->push( command ); | ||||||
|  |  | ||||||
|  |  | ||||||
| } | } | ||||||
|  |  | ||||||
| /* |  | ||||||
|     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 +289,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,18 +324,26 @@ 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 ) | ||||||
| { | { | ||||||
|  |  | ||||||
|  |   int itmPos  = command.first().itemPos; | ||||||
|  |   const XQModelSection& section = _sections.sectionByRow( itmPos ); | ||||||
|  |   qDebug()  << " --- HEADSHOT I: " << itmPos << "->" << section.contentType(); | ||||||
|  |  | ||||||
|   // 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) | ||||||
|   { |   { | ||||||
|  |  | ||||||
|  |  | ||||||
|     // ... holen das erste item, das auch den content node enthält |     // ... holen das erste item, das auch den content node enthält | ||||||
|     //const XQNodeBackup& entry = *it; |     //const XQNodeBackup& entry = *it; | ||||||
|     // jetzt löschen, dabei wird die parent-verbindung entfernt |     // jetzt löschen, dabei wird die parent-verbindung entfernt | ||||||
|     const XQNodeBackup& entry = *it; |     const XQNodeBackup& entry = *it; | ||||||
|  |  | ||||||
|     XQItem& firstItem = xqFirstItem( (*it).itemPos ); |     XQItem& firstItem = xqFirstItem( (*it).itemPos ); | ||||||
|     qDebug() << " --- Cut: "  << firstItem.text() << " " << firstItem.row() << " id#" << entry.contentNode->_id; |     //qDebug() << " --- Cut: "  << firstItem.text() << " " << firstItem.row() << " id#" << entry.contentNode->_id; | ||||||
|  |     qDebug() << " ---- command CUT: itemPos: " << entry.itemPos << "  nodePos: "<< entry.nodePos << " is " << entry.contentNode->friendly_name(); | ||||||
|  |  | ||||||
|     entry.contentNode->unlink_self(); |     entry.contentNode->unlink_self(); | ||||||
|     removeRow(entry.itemPos ); |     removeRow(entry.itemPos ); | ||||||
| @@ -340,31 +353,37 @@ 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 ); | ||||||
|  |  | ||||||
|  |   qDebug()  << " --- HEADSHOT II: " << itmPos << "->" << section.contentType(); | ||||||
|  |  | ||||||
|   // ü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 ); | ||||||
|  |     insertRow( entry.itemPos, list ); | ||||||
|  |  | ||||||
|     XQItem& firstItem = *((XQItem*)list[0]); |     XQItem& firstItem = *((XQItem*)list[0]); | ||||||
|  |  | ||||||
|  |     qDebug() << " ---- command cut UNDO2: itemPos: " << entry.itemPos << "  nodePos: "<< entry.nodePos << " is " << entry.contentNode->friendly_name(); | ||||||
|     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(); | ||||||
|  |  | ||||||
|     insertRow( entry.itemPos, list ); |  | ||||||
|   } |   } | ||||||
| } | } | ||||||
|  |  | ||||||
|  |  | ||||||
| //! 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 +398,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 +407,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 +418,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 +448,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) | ||||||
| @@ -435,83 +456,85 @@ void XQViewModel::cmdDelete( XQCommand& command ) | |||||||
|     // ... holen das erste item, das auch den content node enthält |     // ... holen das erste item, das auch den content node enthält | ||||||
|     const XQNodeBackup& entry = *it; |     const XQNodeBackup& entry = *it; | ||||||
|     XQItem& firstItem = xqFirstItem( (*it).itemPos ); |     XQItem& firstItem = xqFirstItem( (*it).itemPos ); | ||||||
|     qDebug() << " --- Cut: "  << firstItem.text() << " " << firstItem.row(); |     qDebug() << " --- delete: "  << firstItem.text() << " " << firstItem.row(); | ||||||
|     // jetzt löschen |     // jetzt löschen | ||||||
|     entry.contentNode->unlink_self(); |     entry.contentNode->unlink_self(); | ||||||
|     removeRow(entry.itemPos ); |     removeRow(entry.itemPos ); | ||||||
|   } |   } | ||||||
| } | } | ||||||
|  |  | ||||||
| //! macht 'delete' wirder rückgängig. | //! macht 'delete' wieder rückgängig. | ||||||
|  |  | ||||||
| void XQViewModel::cmdDeleteUndo( XQCommand& command ) | void XQViewModel::cmdDeleteUndo( const XQCommand& command ) | ||||||
| { | { | ||||||
|  |   for (const auto& entry : command) | ||||||
|  |   { | ||||||
|  |     qDebug() << " --- delete UNDo: " << entry.contentNode->friendly_name(); | ||||||
|  |   } | ||||||
|  |   cmdCutUndo(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 = XQNode::make_node( node->tag_name(), node->tag_value() ); | ||||||
|   //XQNodePtr newNode = new XQNodePtr( node->tag_name(), node->parent() ); |  | ||||||
|   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()); | ||||||
|  |   const XQModelSection& section = _sections.sectionByRow(index.row()); | ||||||
|  |  | ||||||
|   int fstRow = _sections.firstRow( index ); |   // Obacht! Das ist hier etwas unsauber, 'toogleSection'' ändert den check-State | ||||||
|   int lstRow = _sections.lastRow( index ); |   // im document-tree, was wiederum die 'toggleSection' auslöst, das gibt also | ||||||
|  |   // einen doppelten Aufruf und wir sind dann wieder im Anfangszustand. | ||||||
|  |  | ||||||
|   bool hidden =_treeTable->isRowHidden( fstRow, _treeTable->rootIndex() ); |   //toggleSection( section ); | ||||||
|   for (int row = fstRow; row < lstRow; ++row ) |  | ||||||
|     _treeTable->setRowHidden( row, _treeTable->rootIndex(), !hidden ); |   emit sectionToggled(section); | ||||||
|  |  | ||||||
|   emit sectionToggled( _sections.sectionFromIndex(index) ); |  | ||||||
| } | } | ||||||
|  |  | ||||||
|  |  | ||||||
| //! git die treetable zurück | //! gibt die treetable zurück | ||||||
|  |  | ||||||
| XQTreeTable* XQViewModel::treeTable() | XQTreeTable* XQViewModel::treeTable() | ||||||
| { | { | ||||||
| @@ -524,7 +547,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 ); | ||||||
|   | |||||||
| @@ -22,7 +22,7 @@ | |||||||
| #include <QtQmlIntegration> | #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> | ||||||
|  |  | ||||||
| @@ -37,7 +37,7 @@ class XQCommand; | |||||||
| class XQViewModel : public QStandardItemModel | class XQViewModel : public QStandardItemModel | ||||||
| { | { | ||||||
|   Q_OBJECT |   Q_OBJECT | ||||||
|   //QML_ELEMENT |   QML_ELEMENT | ||||||
|  |  | ||||||
| public: | public: | ||||||
|  |  | ||||||
| @@ -54,78 +54,65 @@ 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 ); | ||||||
|  |  | ||||||
|  |   // 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: | ||||||
|  |  | ||||||
|   /*! |   void xqItemChanged( const XQItem& item ); | ||||||
|  |   void itemCreated( XQItem* newItem ); | ||||||
|   Derzeit wird die default-implementierung von data/setData genutzt. hier wäre dann die |   void sectionCreated( const XQModelSection& section ); | ||||||
|   Stelle um setData & data an externe 'handler' umzubiegen, siehe giovannies 'model-injection' |   void sectionToggled( const XQModelSection& section ); | ||||||
|  |  | ||||||
|   QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override |  | ||||||
|   { |  | ||||||
|     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(){} |   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{}; | ||||||
|   QUndoStack*       _undoStack{}; |   QUndoStack*       _undoStack{}; | ||||||
|   XQContextMenu*    _contextMenu{}; |   XQContextMenu*    _contextMenu{}; | ||||||
|   | |||||||
| @@ -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; | ||||||
|  |           auto it = std::find( childs.begin(), childs.end(), this->shared_from_this() ); | ||||||
|         znode_list& childs = _parent->_children; |  | ||||||
|         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 | ||||||
|  |  | ||||||
|  |  | ||||||
|   | |||||||
| @@ -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() ) | ||||||
|   | |||||||
| @@ -73,12 +73,23 @@ 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(); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|   inline bool isEmpty() const |   inline bool isEmpty() const | ||||||
|   { |   { | ||||||
|     return (_data.size()==0); |     return (_data.size()==0); | ||||||
| @@ -94,13 +105,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 +130,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 +137,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) ) | ||||||
| @@ -150,19 +157,17 @@ public: | |||||||
|   T& operator[]( const QString& key ) |   T& operator[]( const QString& key ) | ||||||
|   { |   { | ||||||
|     if( key.isEmpty() || !contains(key) ) |     if( key.isEmpty() || !contains(key) ) | ||||||
|       throw XQException("maprow operator[]: key empty || not found: " + key); |       throw XQException("XQMaptor operator[]: key empty || not found: " + key); | ||||||
|     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)) | ||||||
|       throw XQException("maprow operator[]: key empty || not found: " + key); |       throw XQException("XQMaptor operator[]: key empty || not found: " + key); | ||||||
|     return _data[_index[key]]; |     return _data[_index[key]]; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |  | ||||||
|   T& at( const QString& key ) |   T& at( const QString& key ) | ||||||
|   { |   { | ||||||
|     return (*this)[key]; |     return (*this)[key]; | ||||||
| @@ -173,28 +178,54 @@ public: | |||||||
|     return (*this)[key]; |     return (*this)[key]; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |   const T& last() const | ||||||
|  |   { | ||||||
|  |     if(_data.isEmpty()) | ||||||
|  |       throw XQException( "XQMaptor last: is empty!" ); | ||||||
|  |     return _data.last(); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   const T& first() const | ||||||
|  |   { | ||||||
|  |     if(_data.isEmpty()) | ||||||
|  |       throw XQException( "XQMaptor first: is empty!" ); | ||||||
|  |     return _data.first(); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   T& last() | ||||||
|  |   { | ||||||
|  |     if(_data.isEmpty()) | ||||||
|  |       throw XQException( "XQMaptor last: is empty!" ); | ||||||
|  |     return _data.last(); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   T& first() | ||||||
|  |   { | ||||||
|  |     if(_data.isEmpty()) | ||||||
|  |       throw XQException( "XQMaptor first: is empty!" ); | ||||||
|  |     return _data.first(); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |  | ||||||
|   virtual int add( const T& item ) |   virtual int add( const T& item ) | ||||||
|   { |   { | ||||||
|     _data.push_back( item ); |     _data.push_back( item ); | ||||||
|     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)) | ||||||
|       throw XQException( "QStringrow::add: index out of range!" ); |       throw XQException( "XQMaptor add at index: index out of range!" ); | ||||||
|     _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 +240,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 +257,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 +276,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 +287,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 +306,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 ); | ||||||
|   | |||||||
| @@ -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 ); | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -14,7 +14,7 @@ | |||||||
|  |  | ||||||
| #include <xqquickwidget.h> | #include <xqquickwidget.h> | ||||||
|  |  | ||||||
| XQQuickWidget::XQQuickWidget(QWidget *parent) | XQQuickWidget::XQQuickWidget(QWidget* parent) | ||||||
|   : QQuickWidget(parent) |   : QQuickWidget(parent) | ||||||
| { | { | ||||||
|  |  | ||||||
|   | |||||||
| @@ -23,7 +23,7 @@ class XQQuickWidget : public QQuickWidget | |||||||
|  |  | ||||||
| public: | public: | ||||||
|  |  | ||||||
|   XQQuickWidget(QWidget *parent = nullptr); |   XQQuickWidget(QWidget* parent = nullptr); | ||||||
| }; | }; | ||||||
|  |  | ||||||
| #endif // XQQUICKWIDGET_H | #endif // XQQUICKWIDGET_H | ||||||
|   | |||||||
| @@ -38,7 +38,7 @@ XQTreeTable::XQTreeTable(QWidget* parent) | |||||||
|  |  | ||||||
| //! gibt die verbundene modelview zurück, cast auf 'model()' | //! gibt die verbundene modelview zurück, cast auf 'model()' | ||||||
|  |  | ||||||
| XQViewModel* XQTreeTable::modelView() | XQViewModel* XQTreeTable::viewModel() | ||||||
| { | { | ||||||
|   return static_cast<XQViewModel*>(model()); |   return static_cast<XQViewModel*>(model()); | ||||||
| } | } | ||||||
| @@ -48,7 +48,18 @@ XQViewModel* XQTreeTable::modelView() | |||||||
|  |  | ||||||
| XQItem& XQTreeTable::xqItemFromIndex(const QModelIndex& index ) | XQItem& XQTreeTable::xqItemFromIndex(const QModelIndex& index ) | ||||||
| { | { | ||||||
|   return modelView()->xqItemFromIndex( index ); |   return viewModel()->xqItemFromIndex( index ); | ||||||
|  | } | ||||||
|  |  | ||||||
|  |  | ||||||
|  | //! rows sichtbar/unsichtbar schalten, von 'fstRow' bis _einschliesslich_ | ||||||
|  | //! 'lstRow' | ||||||
|  |  | ||||||
|  | void XQTreeTable::toggleRowsHidden( int fstRow, int lstRow ) | ||||||
|  | { | ||||||
|  |   bool hidden = isRowHidden( fstRow, rootIndex() ); | ||||||
|  |   for (int row = fstRow; row <= lstRow; ++row ) | ||||||
|  |    setRowHidden( row, rootIndex(), !hidden ); | ||||||
| } | } | ||||||
|  |  | ||||||
|  |  | ||||||
| @@ -71,7 +82,7 @@ void XQTreeTable::currentChanged(const QModelIndex& current, const QModelIndex& | |||||||
| } | } | ||||||
|  |  | ||||||
|  |  | ||||||
| //! firz | //! ändert die breite eines header-feldes anhand der maus-position | ||||||
|  |  | ||||||
| void XQTreeTable::mouseResizeHeaderEntry(int xpos) | void XQTreeTable::mouseResizeHeaderEntry(int xpos) | ||||||
| { | { | ||||||
| @@ -96,7 +107,7 @@ void XQTreeTable::mouseResizeHeaderEntry(int xpos) | |||||||
| } | } | ||||||
|  |  | ||||||
|  |  | ||||||
| //! firz | //! behandelt den mouse-drag zur grössenänderung der header-felder. | ||||||
|  |  | ||||||
| void XQTreeTable::mouseMoveEvent(QMouseEvent* event) | void XQTreeTable::mouseMoveEvent(QMouseEvent* event) | ||||||
| { | { | ||||||
| @@ -106,10 +117,9 @@ void XQTreeTable::mouseMoveEvent(QMouseEvent* event) | |||||||
|   bool leftBtn = (event->buttons() & Qt::LeftButton); |   bool leftBtn = (event->buttons() & Qt::LeftButton); | ||||||
|   QPoint eventPos = event->pos(); |   QPoint eventPos = event->pos(); | ||||||
|  |  | ||||||
|   // splitcursor ist active |   // splitcursor ist gesetzt | ||||||
|   bool splitCursor = (cursor().shape() == Qt::SplitHCursor); |   bool splitCursor = (cursor().shape() == Qt::SplitHCursor); | ||||||
|  |  | ||||||
|  |  | ||||||
|   // sind wir schon am 'draggen'? |   // sind wir schon am 'draggen'? | ||||||
|   if (_indexToResize.isValid() && splitCursor && leftBtn) |   if (_indexToResize.isValid() && splitCursor && leftBtn) | ||||||
|   { |   { | ||||||
|   | |||||||
| @@ -38,9 +38,11 @@ public: | |||||||
|   XQTreeTable(QWidget* parent = nullptr ); |   XQTreeTable(QWidget* parent = nullptr ); | ||||||
|   virtual ~XQTreeTable() = default; |   virtual ~XQTreeTable() = default; | ||||||
|  |  | ||||||
|   XQViewModel* modelView(); |   XQViewModel* viewModel(); | ||||||
|   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; | ||||||
|   | |||||||
| @@ -2,6 +2,7 @@ QT       += core gui widgets quick quickwidgets | |||||||
| # widgets-private | # widgets-private | ||||||
|  |  | ||||||
| CONFIG += c++20 qmltypes | CONFIG += c++20 qmltypes | ||||||
|  | CONFIG -= qml_debug | ||||||
|  |  | ||||||
| QML_IMPORT_NAME = org.sourceworx.qmlcomponents | QML_IMPORT_NAME = org.sourceworx.qmlcomponents | ||||||
| QML_IMPORT_MAJOR_VERSION = 1 | QML_IMPORT_MAJOR_VERSION = 1 | ||||||
| @@ -23,9 +24,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 \ | ||||||
| @@ -61,9 +62,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 \ | ||||||
|   | |||||||
| @@ -1,13 +1,9 @@ | |||||||
| <RCC> | <RCC> | ||||||
| 	<qresource prefix="/"> |     <qresource prefix="/"> | ||||||
| 		<file alias="modeldata1.xtr">../xml/modeldata1.xtr</file> |         <file alias="modeldata1.xtr">../xml/modeldata1.xtr</file> | ||||||
| 		<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="xqtableview.qml">../qml/xqtableview.qml</file> |         <file alias="xqtreeview.qml">../qml/xqtreeview.qml</file> | ||||||
| 		<file alias="HorizontalHeaderViewDelegate.qml">../qml/HorizontalHeaderViewDelegate.qml</file> |     </qresource> | ||||||
| 		<file alias="XMain.qml">../qml/XMain.qml</file> |  | ||||||
| 		<file alias="VerticalHeaderViewDelegate.qml">../qml/VerticalHeaderViewDelegate.qml</file> |  | ||||||
| 		<file alias="dummyview.qml">../qml/dummyview.qml</file> |  | ||||||
| 	</qresource> |  | ||||||
| </RCC> | </RCC> | ||||||
| @@ -10,10 +10,10 @@ | |||||||
| 		<Panel PanelID="#4 JA 04" FriendlyName="@PanelName" PanelName="JA 04 Solar X58C" Manufacturer="JA Solar 4" WattPeak="440" Height="1,70" Width="1,10" Weight="12" MaxVolt="42" MaxAmpere="11"/>			 | 		<Panel PanelID="#4 JA 04" FriendlyName="@PanelName" PanelName="JA 04 Solar X58C" Manufacturer="JA Solar 4" WattPeak="440" Height="1,70" Width="1,10" Weight="12" MaxVolt="42" MaxAmpere="11"/>			 | ||||||
| 		<Panel PanelID="#5 JA 05" FriendlyName="@PanelName" PanelName="JA 05 Solar X58C" Manufacturer="JA Solar 5" WattPeak="440" Height="1,70" Width="1,10" Weight="12" MaxVolt="42" MaxAmpere="11"/>			 | 		<Panel PanelID="#5 JA 05" FriendlyName="@PanelName" PanelName="JA 05 Solar X58C" Manufacturer="JA Solar 5" WattPeak="440" Height="1,70" Width="1,10" Weight="12" MaxVolt="42" MaxAmpere="11"/>			 | ||||||
| 		<Panel PanelID="#6 JA 06" FriendlyName="@PanelName" PanelName="JA 06 Solar X58C" Manufacturer="JA Solar 6"  WattPeak="440" Height="1,70" Width="1,10" Weight="12" MaxVolt="42" MaxAmpere="11"/>					 | 		<Panel PanelID="#6 JA 06" FriendlyName="@PanelName" PanelName="JA 06 Solar X58C" Manufacturer="JA Solar 6"  WattPeak="440" Height="1,70" Width="1,10" Weight="12" MaxVolt="42" MaxAmpere="11"/>					 | ||||||
| 		<Inverter InverterID="#1 HM600 01" FriendlyName="@InverterName" InverterName="01 HM600 S2 TMax" Manufacturer="HoyMiles" MaxPowerInput="2000" MaxPowerInputChoice="2000;4000;6000" MaxPowerOutput="600" NumStrings="2" Weight="28"/>				 | 		<Inverter InverterID="#1 HM600 01" FriendlyName="@InverterName" InverterName="01 HM600 S2 TMax" Manufacturer="HoyMiles" MaxPowerInput="3000,00" MaxPowerInputChoice="2000;4000;6000" MaxPowerOutput="600" NumStrings="2" Weight="28"/>				 | ||||||
| 		<Inverter InverterID="#2 HM800 02" FriendlyName="@InverterName" InverterName="02 HM800 S2 TMax" Manufacturer="HoyMiles" MaxPowerInput="4000" MaxPowerInputChoice="2000;4000;6000" MaxPowerOutput="800" NumStrings="2" Weight="29"/>				 | 		<Inverter InverterID="#2 HM800 02" FriendlyName="@InverterName" InverterName="02 HM800 S2 TMax" Manufacturer="HoyMiles" MaxPowerInput="4000" MaxPowerInputChoice="4000;6000;8000" MaxPowerOutput="800" NumStrings="2" Weight="29"/>				 | ||||||
| 		<Inverter InverterID="#3 HM1600 03" FriendlyName="@InverterName" InverterName="03 HM1600 S4 TMax" Manufacturer="HoyMiles" MaxPowerInput="6000" MaxPowerInputChoice="2000;4000;6000" MaxPowerOutput="1600" NumStrings="4" Weight="32"/>				 | 		<Inverter InverterID="#3 HM1600 03" FriendlyName="@InverterName" InverterName="03 HM1600 S4 TMax" Manufacturer="HoyMiles" MaxPowerInput="9000,00" MaxPowerInputChoice="6000;8000;10000" MaxPowerOutput="1600" NumStrings="4" Weight="32"/>				 | ||||||
| 		<Inverter InverterID="#4 D12K 04" FriendlyName="@InverterName" InverterName="04 HM600 S2 TMax" Manufacturer="Deye"  MaxPowerInput="12000,33" MaxPowerInputChoice="6000;8000;12000" MaxPowerOutput="600" NumStrings="2" Weight="28"/>				 | 		<Inverter InverterID="#4 D12K 04" FriendlyName="@InverterName" InverterName="04 HM600 S2 TMax" Manufacturer="Deye"  MaxPowerInput="8000" MaxPowerInputChoice="6000;8000;12000" MaxPowerOutput="600" NumStrings="2" Weight="28"/>				 | ||||||
| 		<Battery BatteryID="#1 BYD 01" FriendlyName="@BatteryName" BatteryName="01 BYD T01 Stackable" Manufacturer="BYD" Capacity="4500" Yield="90" MaxCurrent="120" MaxVolt="48">		 | 		<Battery BatteryID="#1 BYD 01" FriendlyName="@BatteryName" BatteryName="01 BYD T01 Stackable" Manufacturer="BYD" Capacity="4500" Yield="90" MaxCurrent="120" MaxVolt="48">		 | ||||||
| 			<AdditionalData DataItem="Image"       DataValue="image.png"/> | 			<AdditionalData DataItem="Image"       DataValue="image.png"/> | ||||||
| 			<AdditionalData DataItem="Manual"      DataValue="manual.docx"/> | 			<AdditionalData DataItem="Manual"      DataValue="manual.docx"/> | ||||||
| @@ -21,10 +21,10 @@ | |||||||
| 		</Battery> | 		</Battery> | ||||||
| 		<Battery BatteryID="#2 BYD 02" FriendlyName="@BatteryName" BatteryName="02 BYD T02 Stackable" Manufacturer="BYD" Capacity="9000" Yield="94" MaxCurrent="120" MaxVolt="48"/>	 | 		<Battery BatteryID="#2 BYD 02" FriendlyName="@BatteryName" BatteryName="02 BYD T02 Stackable" Manufacturer="BYD" Capacity="9000" Yield="94" MaxCurrent="120" MaxVolt="48"/>	 | ||||||
| 		<Battery BatteryID="#3 BYD 03" FriendlyName="@BatteryName" BatteryName="03 BYD T01 Stackable" Manufacturer="BYD" Capacity="4500" Yield="86" MaxCurrent="120" MaxVolt="48"/>		 | 		<Battery BatteryID="#3 BYD 03" FriendlyName="@BatteryName" BatteryName="03 BYD T01 Stackable" Manufacturer="BYD" Capacity="4500" Yield="86" MaxCurrent="120" MaxVolt="48"/>		 | ||||||
| 		<Battery BatteryID="#4 BYD 04" FriendlyName="@BatteryName" BatteryName="04 BYD T02 Stackable" Manufacturer="BYD" Capacity="9000" Yield="98" MaxCurrent="120" MaxVolt="48"/>	 | 		<Battery BatteryID="#4 BYD 04" FriendlyName="@BatteryName" BatteryName="04 BYD T02 Stackable" Manufacturer="BYD" Capacity="9000" Yield="91" MaxCurrent="120" MaxVolt="48"/>	 | ||||||
| 		<Battery BatteryID="#5 GroWatt 05 G2K" FriendlyName="@BatteryName" BatteryName="05 BYD T01 Stackable" Manufacturer="GroWatt" Capacity="4500" Yield="94" MaxCurrent="120" MaxVolt="48"/>		 | 		<Battery BatteryID="#5 GroWatt 05 G2K" FriendlyName="@BatteryName" BatteryName="05 BYD T01 Stackable" Manufacturer="GroWatt" Capacity="4500" Yield="94" MaxCurrent="120" MaxVolt="48"/>		 | ||||||
| 		<Battery BatteryID="#6 GroWatt 06 G4K" FriendlyName="@BatteryName" BatteryName="06 BYD T02 Stackable" Manufacturer="GroWatt" Capacity="9000" Yield="49" MaxCurrent="120" MaxVolt="48"/>	 | 		<Battery BatteryID="#6 GroWatt 06 G4K" FriendlyName="@BatteryName" BatteryName="06 BYD T02 Stackable" Manufacturer="GroWatt" Capacity="9000" Yield="49" MaxCurrent="120" MaxVolt="48"/>	 | ||||||
| 		<Battery BatteryID="#7 Pyne 07 G4K" FriendlyName="@BatteryName" BatteryName="07 Pyne K7 Stackable" Manufacturer="PyNe" Capacity="9000" Yield="49" MaxCurrent="120" MaxVolt="48"/>		 | 		<Battery BatteryID="#7 Pyne 07 G4K" FriendlyName="@BatteryName" BatteryName="07 Pyne K7 Stackable" Manufacturer="PyNe" Capacity="9000" Yield="68" MaxCurrent="120" MaxVolt="48"/>		 | ||||||
|  |  | ||||||
| 	</Components>	 | 	</Components>	 | ||||||
| 	<IrgendWasAnderes> | 	<IrgendWasAnderes> | ||||||
|   | |||||||
| @@ -4,9 +4,9 @@ | |||||||
| <Project ProjectID="HA02" FriendlyName="@ProjectName" ProjectName="Gerbrunn Ost" Established="2006" WattPeak="9840"  ContentType="planned"> | <Project ProjectID="HA02" FriendlyName="@ProjectName" ProjectName="Gerbrunn Ost" Established="2006" WattPeak="9840"  ContentType="planned"> | ||||||
| 	<Components>	 | 	<Components>	 | ||||||
| 		<Panel PanelID="Jingli 01" FriendlyName="@PanelName" PanelName="Jingli 01 Solar T62B" Manufacturer="Jingli Solar" WattPeak="620" Height="2,70" Width="1,10" Weight="12" MaxVolt="67" MaxAmpere="11">			 | 		<Panel PanelID="Jingli 01" FriendlyName="@PanelName" PanelName="Jingli 01 Solar T62B" Manufacturer="Jingli Solar" WattPeak="620" Height="2,70" Width="1,10" Weight="12" MaxVolt="67" MaxAmpere="11">			 | ||||||
| 			<AdditionalData DataItem="Image"       DataValue="image,png"/> | 			<AdditionalData DataItem="Image"       DataValue="image.png"/> | ||||||
| 			<AdditionalData DataItem="Manual"      DataValue="manual,docx"/> | 			<AdditionalData DataItem="Manual"      DataValue="manual.docx"/> | ||||||
| 			<AdditionalData DataItem="Certificate" DataValue="certificate,pdf"/> | 			<AdditionalData DataItem="Certificate" DataValue="certificate.pdf"/> | ||||||
| 		</Panel> | 		</Panel> | ||||||
| 		<Panel PanelID="Jingli 02" FriendlyName="@PanelName" PanelName="Jingli 02 Solar X58C" Manufacturer="Jingli Solar" WattPeak="440" Height="1,70" Width="1,10" Weight="12" MaxVolt="42" MaxAmpere="11"/>			 | 		<Panel PanelID="Jingli 02" FriendlyName="@PanelName" PanelName="Jingli 02 Solar X58C" Manufacturer="Jingli Solar" WattPeak="440" Height="1,70" Width="1,10" Weight="12" MaxVolt="42" MaxAmpere="11"/>			 | ||||||
| 		<Panel PanelID="Jingli 03" FriendlyName="@PanelName" PanelName="Jingli 03 Solar T62B" Manufacturer="Jingli Solar" WattPeak="620" Height="2,70" Width="1,10" Weight="12" MaxVolt="67" MaxAmpere="11"/>			 | 		<Panel PanelID="Jingli 03" FriendlyName="@PanelName" PanelName="Jingli 03 Solar T62B" Manufacturer="Jingli Solar" WattPeak="620" Height="2,70" Width="1,10" Weight="12" MaxVolt="67" MaxAmpere="11"/>			 | ||||||
|   | |||||||
| @@ -1,6 +1,6 @@ | |||||||
| <?xml version='1.0' encoding='UTF-8'?> | <?xml version='1.0' encoding='UTF-8'?> | ||||||
| 		 | 		 | ||||||
| <Project ProjectID="HA03" FriendlyName="@ProjectName" ProjectName="Neubrunn Süd" Established="2006" WattPeak="9840" ContentType="runnning"> | <Project ProjectID="HA03" FriendlyName="@ProjectName" ProjectName="Tauberbischoffsheim SÜD" Established="2006" WattPeak="9840" ContentType="runnning"> | ||||||
| 	<Components>	 | 	<Components>	 | ||||||
| 		<Panel PanelID="AIKO 01" FriendlyName="@PanelName" PanelName="AIKO 01 Solar T62B" Manufacturer="AIKO Solar" WattPeak="620" Height="2,70" Width="1,10" Weight="12" MaxVolt="67" MaxAmpere="11">			 | 		<Panel PanelID="AIKO 01" FriendlyName="@PanelName" PanelName="AIKO 01 Solar T62B" Manufacturer="AIKO Solar" WattPeak="620" Height="2,70" Width="1,10" Weight="12" MaxVolt="67" MaxAmpere="11">			 | ||||||
| 			<AdditionalData DataItem="Image"       DataValue="image.png"/> | 			<AdditionalData DataItem="Image"       DataValue="image.png"/> | ||||||
|   | |||||||
| @@ -6,28 +6,29 @@ | |||||||
|  |  | ||||||
| --> | --> | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
| <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" />	 | ||||||
| 	<PercentageType   RenderStyle="ProgressBarStyle" ItemFlags="IsEnabled|IsSelectable"/> | 	<PercentageType   RenderStyle="ColorBarStyle"    EditorType="ColorBarType" ItemFlags="IsEnabled|IsEditable|IsSelectable" UnitType="%"/> | ||||||
| 	<ChoiceType       RenderStyle="ComboBoxStyle"    ItemFlags="IsEnabled|IsSelectable|IsEditable" FixedChoices="la|le|lo|lu"/>	 | 	<ChoiceType       RenderStyle="ComboBoxStyle"    EditorType="ComboBoxType" ItemFlags="IsEnabled|IsEditable|IsSelectable" UnitType="W" FixedChoices="2000|4000|6000|8000" />	 | ||||||
| 	<IntValueType     RenderStyle="SpinBoxStyle"	 ItemFlags="IsEnabled|IsSelectable"/>	 | 	<IntValueType     RenderStyle="SpinBoxStyle"	 EditorType="SpinBoxType"  ItemFlags="IsEnabled|IsEditable|IsSelectable"/>	 | ||||||
| </ItemTypes> | </ItemTypes> | ||||||
|  |  | ||||||
|  |  | ||||||
| <DocumentTreeModel> | <DocumentTreeModel> | ||||||
| 	<Section ContentType="runnning"> | 	<Section ContentType="runnning"> | ||||||
| 		<Header> | 		<Header> | ||||||
| 			<Entry Caption="Active Projects" ItemType="TreeParentType"/> | 			<Entry Caption="Active Projects" ItemType="TreeParentType"/> | ||||||
| 		</Header> | 		</Header> | ||||||
| 		<ModelSheet firz="running"> | 		<ModelSheet> | ||||||
| 			<Project Caption="@ProjectName" ItemType="TreeChildType"> | 			<Project Caption="@ProjectName" ItemType="TreeChildType"> | ||||||
| 				<CurrentSection ItemType="TreeSectionType"/> | 				<CurrentSection ItemType="TreeSectionType"/> | ||||||
| 			</Project> | 			</Project> | ||||||
| @@ -37,7 +38,7 @@ | |||||||
| 		<Header> | 		<Header> | ||||||
| 			<Entry Caption="Planned Projects" ItemType="TreeParentType"/> | 			<Entry Caption="Planned Projects" ItemType="TreeParentType"/> | ||||||
| 		</Header> | 		</Header> | ||||||
| 		<ModelSheet firz="planned"> | 		<ModelSheet> | ||||||
| 			<Project Caption="@ProjectName" ItemType="TreeChildType">				 | 			<Project Caption="@ProjectName" ItemType="TreeChildType">				 | ||||||
| 				<CurrentSection ItemType="TreeSectionType"/> | 				<CurrentSection ItemType="TreeSectionType"/> | ||||||
| 			</Project> | 			</Project> | ||||||
| @@ -47,7 +48,7 @@ | |||||||
| 		<Header> | 		<Header> | ||||||
| 			<Entry Caption="Finished Projects" ItemType="TreeParentType"/> | 			<Entry Caption="Finished Projects" ItemType="TreeParentType"/> | ||||||
| 		</Header> | 		</Header> | ||||||
| 		<ModelSheet firz="finished"> | 		<ModelSheet> | ||||||
| 			<Project Caption="@ProjectName" ItemType="TreeChildType">	 | 			<Project Caption="@ProjectName" ItemType="TreeChildType">	 | ||||||
| 				<CurrentSection ItemType="TreeSectionType"/> | 				<CurrentSection ItemType="TreeSectionType"/> | ||||||
| 			</Project> | 			</Project> | ||||||
| @@ -75,10 +76,10 @@ | |||||||
| 			<!-- '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="ValueType" Icon="VistaShield" UnitType="m"/>	 | ||||||
| 			<Height ItemType="ValueType" UnitType="m"/> | 			<Height ItemType="ValueType" UnitType="m"/> | ||||||
| 			<Weight ItemType="ValueType" UnitType="kg"/>	 | 			<Weight ItemType="ValueType" UnitType="kg"/>	 | ||||||
| 			<MaxVolt ItemType="ValueType" UnitType="V"/> | 			<MaxVolt ItemType="ValueType" UnitType="V"/> | ||||||
| @@ -86,8 +87,7 @@ | |||||||
| 		</ModelSheet> | 		</ModelSheet> | ||||||
| 	</Section> | 	</Section> | ||||||
| 	 | 	 | ||||||
| 	 | 		<Section ContentType="Inverter" >  | ||||||
| 	<Section ContentType="Inverter" >  |  | ||||||
| 		<Header > | 		<Header > | ||||||
| 			<InverterID Caption="Inverter" ItemType="HeaderType" /> | 			<InverterID Caption="Inverter" ItemType="HeaderType" /> | ||||||
| 			<InverterName Caption="Name" ItemType="HeaderType" /> | 			<InverterName Caption="Name" ItemType="HeaderType" /> | ||||||
| @@ -98,20 +98,20 @@ | |||||||
| 			<Weight Caption="Weight" ItemType="HeaderType" /> | 			<Weight Caption="Weight" ItemType="HeaderType" /> | ||||||
| 		</Header> | 		</Header> | ||||||
| 		<ModelSheet> | 		<ModelSheet> | ||||||
| 			<InverterID Caption="Inverter" ItemType="ValueType" /> | 			<InverterID ItemType="PlainType" /> | ||||||
| 			<InverterName Caption="Name" ItemType="ValueType" /> | 			<InverterName ItemType="PlainType" /> | ||||||
| 			<Manufacturer Caption="Manufacturer" ItemType="ValueType" /> | 			<Manufacturer ItemType="PlainType" /> | ||||||
| 			<MaxPowerInput Caption="max. Input" ItemType="ValueType" ItemType="ChoiceType" ChoiceModelSheetSource="MaxPowerInputChoice" UnitType="W"/> | 			<MaxPowerInput ItemType="ChoiceType" FixedChoices="2000|4000|6000|8000" UnitType="W"/> | ||||||
| 			<MaxPowerOutput Caption="max Output" ItemType="ValueType"  UnitType="W"/> | 			<MaxPowerOutput ItemType="ValueType" UnitType="W"/> | ||||||
| 			<NumStrings Caption="Strings" ItemType="ValueType" />		 | 			<NumStrings ItemType="IntValueType" />		 | ||||||
| 			<Weight Caption="Weight" ItemType="ValueType"  UnitType="kg"/> | 			<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,13 +119,13 @@ | |||||||
| 			<MaxVolt Caption="max. Volt" ItemType="HeaderType" />		 | 			<MaxVolt Caption="max. Volt" ItemType="HeaderType" />		 | ||||||
| 		</Header> | 		</Header> | ||||||
| 		<ModelSheet> | 		<ModelSheet> | ||||||
| 			<BatteryID Caption="Battery" ItemType="ValueType" /> | 			<BatteryID ItemType="PlainType" /> | ||||||
| 			<BatteryName Caption="Name" ItemType="ValueType" /> | 			<BatteryName ItemType="PlainType" /> | ||||||
| 			<Manufacturer Caption="Manufacturer" ItemType="ValueType" /> | 			<Manufacturer ItemType="PlainType" /> | ||||||
| 			<Capacity Caption="Capacity" ItemType="ValueType"  UnitType="Wh"/> | 			<Capacity ItemType="ValueType"  UnitType="Wh"/> | ||||||
| 			<Yield Caption="Yield" ItemType="ValueType" ItemType="PercentageType" UnitType="%"/> | 			<Yield ItemType="PercentageType" UnitType="%"/> | ||||||
| 			<MaxCurrent Caption="max. Current" ItemType="ValueType"  UnitType="A"/> | 			<MaxCurrent ItemType="ValueType"  UnitType="A"/> | ||||||
| 			<MaxVolt  Caption="max. Volt" ItemType="ValueType"  UnitType="V"/>				 | 			<MaxVolt ItemType="ValueType"  UnitType="V"/>				 | ||||||
| 		</ModelSheet> | 		</ModelSheet> | ||||||
| 	</Section> | 	</Section> | ||||||
|  |  | ||||||
|   | |||||||
| @@ -1,27 +1,24 @@ | |||||||
| <?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="JA 02 Solar X58C" 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="JA 04 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 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="3000,00" 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"/> |     <Inverter FriendlyName="@InverterName" InverterID="#2 HM800 02" InverterName="02 HM800 S2 TMax" Manufacturer="HoyMiles" MaxPowerInput="4000" MaxPowerInputChoice="4000;6000;8000" MaxPowerOutput="800" NumStrings="7" Weight="29"/> | ||||||
|         <Inverter FriendlyName="@InverterName" InverterID="#2 HM800 02" InverterName="02 HM800 S2 TMax" Manufacturer="HoyMiles" MaxPowerInput="4000" MaxPowerInputChoice="2000;4000;6000" MaxPowerOutput="800" NumStrings="2" Weight="29"/> |     <Inverter FriendlyName="@InverterName" InverterID="#3 HM1600 03" InverterName="03 HM1600 S4 TMax" Manufacturer="HoyMiles" MaxPowerInput="9000,00" MaxPowerInputChoice="6000;8000;10000" MaxPowerOutput="1600" NumStrings="4" Weight="32"/> | ||||||
|         <Inverter FriendlyName="@InverterName" InverterID="#3 HM1600 03" InverterName="03 HM1600 S4 TMax" Manufacturer="HoyMiles" MaxPowerInput="6000" MaxPowerInputChoice="2000;4000;6000" MaxPowerOutput="1600" NumStrings="4" Weight="32"/> |     <Inverter FriendlyName="@InverterName" InverterID="#4 D12K 04" InverterName="04 HM600 S2 TMax" Manufacturer="Deye" MaxPowerInput="8000" MaxPowerInputChoice="6000;8000;12000" MaxPowerOutput="600" NumStrings="2" Weight="28"/> | ||||||
|         <Inverter FriendlyName="@InverterName" InverterID="#4 D12K 04" InverterName="04 HM600 S2 TMax" Manufacturer="Deye" MaxPowerInput="12000,33" MaxPowerInputChoice="6000;8000;12000" MaxPowerOutput="600" NumStrings="2" Weight="28"/> |     <Battery BatteryID="#1 BYD 01" BatteryName="01 BYD T01 Stackable" Capacity="4500" FriendlyName="@BatteryName" Manufacturer="BYD" MaxCurrent="120" MaxVolt="48" Yield="90"> | ||||||
|         <Battery BatteryID="#1 BYD 01" BatteryName="01 BYD T01 Stackable" Capacity="4500" FriendlyName="@BatteryName" Manufacturer="BYD" MaxCurrent="120" MaxVolt="48" Yield="90"> |         <AdditionalData DataItem="Image" DataValue="image.png"/> | ||||||
|             <AdditionalData DataItem="Image" DataValue="image.png"/> |         <AdditionalData DataItem="Manual" DataValue="manual.docx"/> | ||||||
|             <AdditionalData DataItem="Manual" DataValue="manual.docx"/> |         <AdditionalData DataItem="Certificate" DataValue="certificate.pdf"/> | ||||||
|             <AdditionalData DataItem="Certificate" DataValue="certificate.pdf"/> |     </Battery> | ||||||
|         </Battery> |     <Battery BatteryID="#2 BYD 02" BatteryName="02 BYD T02 Stackable" Capacity="9000" FriendlyName="@BatteryName" Manufacturer="BYD" MaxCurrent="120" MaxVolt="48" Yield="94"/> | ||||||
|         <Battery BatteryID="#2 BYD 02" BatteryName="02 BYD T02 Stackable" Capacity="9000" FriendlyName="@BatteryName" Manufacturer="BYD" MaxCurrent="120" MaxVolt="48" Yield="94"/> |     <Battery BatteryID="#3 BYD 03" BatteryName="03 BYD T01 Stackable" Capacity="4500" FriendlyName="@BatteryName" Manufacturer="BYD" MaxCurrent="120" MaxVolt="48" Yield="86"/> | ||||||
|         <Battery BatteryID="#3 BYD 03" BatteryName="03 BYD T01 Stackable" Capacity="4500" FriendlyName="@BatteryName" Manufacturer="BYD" MaxCurrent="120" MaxVolt="48" Yield="86"/> |     <Battery BatteryID="#4 BYD 04" BatteryName="04 BYD T02 Stackable" Capacity="9000" FriendlyName="@BatteryName" Manufacturer="BYD" MaxCurrent="120" MaxVolt="48" Yield="91"/> | ||||||
|         <Battery BatteryID="#4 BYD 04" BatteryName="04 BYD T02 Stackable" Capacity="9000" FriendlyName="@BatteryName" Manufacturer="BYD" MaxCurrent="120" MaxVolt="48" Yield="98"/> |     <Battery BatteryID="#5 GroWatt 05 G2K" BatteryName="05 BYD T01 Stackable" Capacity="4500" FriendlyName="@BatteryName" Manufacturer="GroWatt" MaxCurrent="120" MaxVolt="48" Yield="94"/> | ||||||
|         <Battery BatteryID="#5 GroWatt 05 G2K" BatteryName="05 BYD T01 Stackable" Capacity="4500" FriendlyName="@BatteryName" Manufacturer="GroWatt" MaxCurrent="120" MaxVolt="48" Yield="94"/> |     <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="68"/> | ||||||
|         <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> |  | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user