Compare commits
21 Commits
a39ce321f2
...
main
Author | SHA1 | Date | |
---|---|---|---|
3887748c1a | |||
b8f0893d59 | |||
9c6f7688d7 | |||
8d26c32e51 | |||
c9b61c1c2b | |||
d6ccac1d85 | |||
5d2fb1b378 | |||
89c5fd21f1 | |||
f8bd0886d3 | |||
![]() |
831daf898c | ||
![]() |
3e7b65dca5 | ||
147769bf60 | |||
![]() |
527de65074 | ||
4d49a495fd | |||
952409ab1a | |||
c6454f3106 | |||
04b0f650d6 | |||
6ee677c595 | |||
5057edb9ad | |||
39909ad543 | |||
b217f2f9ad |
44
qml/HorizontalHeaderViewDelegate.qml
Normal file
44
qml/HorizontalHeaderViewDelegate.qml
Normal file
@@ -0,0 +1,44 @@
|
||||
// SPDX-FileCopyrightText: 2025 Martin Leutelt <martin.leutelt@basyskom.com>
|
||||
// SPDX-FileCopyrightText: 2025 basysKom GmbH
|
||||
//
|
||||
// SPDX-License-Identifier: LGPL-3.0-or-later
|
||||
|
||||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
|
||||
Control {
|
||||
id: container
|
||||
|
||||
required property int column
|
||||
required property var model
|
||||
property int sortOrder: Qt.AscendingOrder
|
||||
|
||||
signal clicked(int sortOrder)
|
||||
|
||||
padding: 8
|
||||
|
||||
background: Rectangle {
|
||||
color: tapHandler.pressed ? "gray" : "lightgray"
|
||||
|
||||
TapHandler {
|
||||
id: tapHandler
|
||||
|
||||
onTapped: {
|
||||
if (container.sortOrder === Qt.AscendingOrder) {
|
||||
container.sortOrder = Qt.DescendingOrder
|
||||
} else {
|
||||
container.sortOrder = Qt.AscendingOrder
|
||||
}
|
||||
|
||||
container.clicked(container.sortOrder)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
contentItem: Label {
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
elide: Text.ElideRight
|
||||
text: container.model.display
|
||||
}
|
||||
}
|
26
qml/VerticalHeaderViewDelegate.qml
Normal file
26
qml/VerticalHeaderViewDelegate.qml
Normal file
@@ -0,0 +1,26 @@
|
||||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
|
||||
Control {
|
||||
id: container
|
||||
|
||||
required property int row
|
||||
required property var model
|
||||
|
||||
padding: 8
|
||||
|
||||
background: Rectangle {
|
||||
color: tapHandler.pressed ? "gray" : "lightgray"
|
||||
|
||||
TapHandler {
|
||||
id: tapHandler
|
||||
}
|
||||
}
|
||||
|
||||
contentItem: Label {
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
elide: Text.ElideRight
|
||||
text: container.model.display
|
||||
}
|
||||
}
|
161
qml/XMain.qml
Normal file
161
qml/XMain.qml
Normal file
@@ -0,0 +1,161 @@
|
||||
// SPDX-FileCopyrightText: 2025 Martin Leutelt <martin.leutelt@basyskom.com>
|
||||
// SPDX-FileCopyrightText: 2025 basysKom GmbH
|
||||
//
|
||||
// SPDX-License-Identifier: LGPL-3.0-or-later
|
||||
|
||||
pragma ComponentBehavior: Bound
|
||||
|
||||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import QtQuick.Layouts
|
||||
|
||||
ApplicationWindow {
|
||||
width: 640
|
||||
height: 480
|
||||
visible: true
|
||||
title: Application.displayName
|
||||
|
||||
header: ToolBar {
|
||||
ColumnLayout {
|
||||
RowLayout {
|
||||
Label {
|
||||
text: "Rows"
|
||||
}
|
||||
SpinBox {
|
||||
id: rowSettings
|
||||
from: 1
|
||||
to: 20
|
||||
}
|
||||
|
||||
ToolSeparator {}
|
||||
|
||||
Label {
|
||||
text: "Columns"
|
||||
}
|
||||
SpinBox {
|
||||
id: columnSettings
|
||||
from: 1
|
||||
to: 20
|
||||
}
|
||||
|
||||
ToolSeparator {}
|
||||
|
||||
CheckBox {
|
||||
id: movableColumnsSetting
|
||||
|
||||
text: "Movable columns"
|
||||
}
|
||||
|
||||
ToolSeparator {}
|
||||
|
||||
CheckBox {
|
||||
id: resizableColumnsSetting
|
||||
|
||||
text: "Resizable columns"
|
||||
}
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
Label {
|
||||
text: "Selection"
|
||||
}
|
||||
ComboBox {
|
||||
id: selectionSetting
|
||||
textRole: "text"
|
||||
valueRole: "value"
|
||||
model: [
|
||||
{ text: "disabled", value: TableView.SelectionDisabled },
|
||||
{ text: "by cells", value: TableView.SelectCells },
|
||||
{ text: "by rows", value: TableView.SelectRows },
|
||||
{ text: "by columns", value: TableView.SelectColumns }
|
||||
]
|
||||
|
||||
onCurrentIndexChanged: tableView.selectionModel.clear()
|
||||
}
|
||||
Label {
|
||||
text: "Longpress to start selection, modify selection with CTRL/SHIFT of by mouse"
|
||||
visible: selectionSetting.currentIndex > 0
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: tableBackground
|
||||
|
||||
anchors.fill: parent
|
||||
|
||||
color: Application.styleHints.colorScheme === Qt.Light ? palette.mid : palette.midlight
|
||||
|
||||
HorizontalHeaderView {
|
||||
id: horizontalHeader
|
||||
|
||||
anchors.left: tableView.left
|
||||
anchors.top: parent.top
|
||||
|
||||
syncView: tableView
|
||||
movableColumns: movableColumnsSetting.checked
|
||||
resizableColumns: resizableColumnsSetting.checked
|
||||
clip: true
|
||||
boundsBehavior: tableView.boundsBehavior
|
||||
|
||||
delegate: HorizontalHeaderViewDelegate {
|
||||
onClicked: (sortOrder) => tableView.model.sort(column, sortOrder)
|
||||
}
|
||||
}
|
||||
|
||||
VerticalHeaderView {
|
||||
id: verticalHeader
|
||||
|
||||
anchors.top: tableView.top
|
||||
anchors.left: parent.left
|
||||
|
||||
syncView: tableView
|
||||
clip: true
|
||||
boundsBehavior: tableView.boundsBehavior
|
||||
|
||||
delegate: VerticalHeaderViewDelegate {}
|
||||
}
|
||||
|
||||
TableView {
|
||||
id: tableView
|
||||
|
||||
anchors.left: verticalHeader.right
|
||||
anchors.top: horizontalHeader.bottom
|
||||
anchors.right: parent.right
|
||||
anchors.bottom: parent.bottom
|
||||
|
||||
clip: true
|
||||
columnSpacing: 1
|
||||
rowSpacing: 1
|
||||
rowHeightProvider: (row) => 40
|
||||
boundsBehavior: TableView.StopAtBounds
|
||||
selectionModel: ItemSelectionModel {}
|
||||
selectionBehavior: selectionSetting.currentValue
|
||||
|
||||
model: SortFilterModel {
|
||||
sourceModel: TableModel {
|
||||
columns: columnSettings.value
|
||||
rows: rowSettings.value
|
||||
|
||||
// when adding a new column its width isn't properly applied to the header, so we do that manually
|
||||
onColumnsInserted: {
|
||||
if (columns > 1) {
|
||||
horizontalHeader.setColumnWidth(columns - 1, tableView.implicitColumnWidth(columns - 1))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
delegate: TableViewDelegate {
|
||||
implicitWidth: tableView.width / columnSettings.to
|
||||
}
|
||||
|
||||
ScrollBar.horizontal: ScrollBar {}
|
||||
ScrollBar.vertical: ScrollBar {}
|
||||
}
|
||||
|
||||
SelectionRectangle {
|
||||
target: tableView
|
||||
}
|
||||
}
|
||||
}
|
56
qml/dummyview.qml
Normal file
56
qml/dummyview.qml
Normal file
@@ -0,0 +1,56 @@
|
||||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import QtQuick.Layouts
|
||||
import QtQuick.Window
|
||||
|
||||
ApplicationWindow
|
||||
{
|
||||
visible: true
|
||||
width: 600
|
||||
height: 400
|
||||
|
||||
TreeView
|
||||
{
|
||||
anchors.fill: parent
|
||||
clip: true
|
||||
columnSpacing: 1
|
||||
rowSpacing: 1
|
||||
|
||||
model: myChildModel
|
||||
|
||||
columnWidthProvider: function(column)
|
||||
{
|
||||
var z= 2*(width / columns);
|
||||
console.log("Firz:", z);
|
||||
console.log("Berechne Spaltenbreite für column:", column);
|
||||
console.log("Aktuelle TreeView-Breite:", width);
|
||||
return z;
|
||||
}
|
||||
|
||||
delegate: Rectangle
|
||||
{
|
||||
required property int row
|
||||
required property int column
|
||||
required property var model
|
||||
|
||||
border.width: 0
|
||||
|
||||
implicitWidth: 30
|
||||
implicitHeight: 30
|
||||
border.color: "#cccccc"
|
||||
//color: index % 2 === 0 ? "#f9f9f9" : "#e0e0e0"
|
||||
color: TreeView.isSelected ? "#d0eaff" : (row % 2 === 0 ? "#f9f9f9" : "#ffffff")
|
||||
|
||||
Text
|
||||
{
|
||||
anchors.centerIn: parent
|
||||
text: display
|
||||
font.pixelSize: 14
|
||||
}
|
||||
}
|
||||
|
||||
ScrollBar.horizontal: ScrollBar {}
|
||||
ScrollBar.vertical: ScrollBar {}
|
||||
}
|
||||
|
||||
}
|
65
qml/xqtableview.qml
Normal file
65
qml/xqtableview.qml
Normal file
@@ -0,0 +1,65 @@
|
||||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import QtQuick.Layouts
|
||||
|
||||
Window
|
||||
{
|
||||
width: 640
|
||||
height: 480
|
||||
visible: true
|
||||
title: qsTr("StringListModel")
|
||||
|
||||
TableView
|
||||
{
|
||||
id: childTableView
|
||||
anchors.fill: parent
|
||||
|
||||
model: myChildModel // z. B. QStandardItemModel mit 9 Spalten
|
||||
|
||||
delegate: Rectangle
|
||||
{
|
||||
required property string display
|
||||
|
||||
//height: 5
|
||||
//width: childTableView.width
|
||||
color : "blue"
|
||||
border.color: "#ccc"
|
||||
width: childTableView.width;
|
||||
|
||||
RowLayout
|
||||
{
|
||||
anchors.fill: parent
|
||||
anchors.margins: 2
|
||||
|
||||
TextField
|
||||
{
|
||||
text : display
|
||||
font.pixelSize: 10
|
||||
Layout.fillWidth: true
|
||||
|
||||
background: Rectangle
|
||||
{
|
||||
color : "white"
|
||||
}
|
||||
|
||||
onEditingFinished:
|
||||
{
|
||||
console.log("Editing finished, new text is :"+ text + " at index :" + index)
|
||||
model.names = text //The roles here are defined in model class
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
ScrollBar.horizontal: ScrollBar {}
|
||||
ScrollBar.vertical: ScrollBar {}
|
||||
|
||||
// // Optional: Spaltenbreiten setzen
|
||||
// onModelChanged: {
|
||||
// for (let i = 0; i < model.columns; ++i)
|
||||
// table.setColumnWidth(i, 100)
|
||||
// }
|
||||
}
|
||||
|
||||
}
|
47
qml/xqtreeview.qml
Normal file
47
qml/xqtreeview.qml
Normal file
@@ -0,0 +1,47 @@
|
||||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import QtQuick.Layouts
|
||||
|
||||
|
||||
TreeView
|
||||
{
|
||||
anchors.fill: parent
|
||||
clip: true
|
||||
columnSpacing: 1
|
||||
rowSpacing: 1
|
||||
|
||||
model: xtrChildModel
|
||||
|
||||
columnWidthProvider: function(column)
|
||||
{
|
||||
var z= 1.7*(width / columns);
|
||||
return z;
|
||||
}
|
||||
|
||||
delegate: Rectangle
|
||||
{
|
||||
required property int row
|
||||
required property int column
|
||||
required property var model
|
||||
|
||||
border.width: 0
|
||||
|
||||
implicitWidth: 30
|
||||
implicitHeight: 20
|
||||
border.color: "#cccccc"
|
||||
//color: index % 2 === 0 ? "#f9f9f9" : "#e0e0e0"
|
||||
color: TreeView.isSelected ? "#d0eaff" : (row % 2 === 0 ? "#f9f9f9" : "#ffffff")
|
||||
|
||||
Text
|
||||
{
|
||||
anchors.centerIn: parent
|
||||
text: display
|
||||
font.pixelSize: 12
|
||||
}
|
||||
}
|
||||
|
||||
ScrollBar.horizontal: ScrollBar {}
|
||||
ScrollBar.vertical: ScrollBar {}
|
||||
}
|
||||
|
||||
|
@@ -1,35 +0,0 @@
|
||||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import QtQuick.Layouts
|
||||
|
||||
TableView
|
||||
{
|
||||
id: table
|
||||
anchors.fill: parent
|
||||
columnSpacing: 2
|
||||
rowSpacing: 2
|
||||
model: meinModel // z. B. QStandardItemModel mit 9 Spalten
|
||||
|
||||
delegate: Rectangle
|
||||
{
|
||||
|
||||
required property string display
|
||||
width: 100
|
||||
height: 20
|
||||
border.color: "#ccc"
|
||||
|
||||
Text
|
||||
{
|
||||
anchors.centerIn: parent
|
||||
text: display
|
||||
font.pixelSize: 10
|
||||
}
|
||||
}
|
||||
|
||||
// // Optional: Spaltenbreiten setzen
|
||||
// onModelChanged: {
|
||||
// for (let i = 0; i < model.columns; ++i)
|
||||
// table.setColumnWidth(i, 100)
|
||||
// }
|
||||
}
|
||||
|
@@ -38,6 +38,7 @@ const QString c_ProjectID = "ProjectID";
|
||||
const QString c_ModelSheetFileName = "xml/modelsheets.xml";
|
||||
const QString c_ModelDummyFileName = "xml/saved_testfile.xtr";
|
||||
const QString c_DocumentDirectory = "xml/";
|
||||
|
||||
const QString c_DocumentFileName1 = "xml/modeldata1.xtr";
|
||||
const QString c_DocumentFileName2 = "xml/modeldata2.xtr";
|
||||
const QString c_DocumentFileName3 = "xml/modeldata3.xtr";
|
||||
|
@@ -55,18 +55,12 @@ void XQChildModel::addModelData( const XQNodePtr& contentRoot )
|
||||
if (!_sections.hasValidSection(key))
|
||||
continue;
|
||||
|
||||
XQModelSection& section = _sections.at( 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");
|
||||
|
||||
const XQModelSection& section = _sections.sectionByKey( key );
|
||||
section.setContentRootNode( contentEntry->parent() );
|
||||
int newRow = _sections.lastRow(section);
|
||||
|
||||
XQNodePtr sheetNode = section.sheetRootNode();
|
||||
XQItemList list = _itemFactory.makeRow( XQItemFactory::mData, sheetNode, contentEntry );
|
||||
XQItemList list = _itemFactory.makeRow( sheetNode, contentEntry );
|
||||
|
||||
// als Baum?
|
||||
//section.headerItem().appendRow( list );
|
||||
@@ -76,24 +70,30 @@ void XQChildModel::addModelData( const XQNodePtr& contentRoot )
|
||||
|
||||
}
|
||||
|
||||
|
||||
//! Erzeugt eine model-section und fügt den zugehörigen header ein.
|
||||
|
||||
void XQChildModel::addSectionEntry( const QString& key, const XQNodePtr& contentEntry )
|
||||
{
|
||||
XQModelSection& section = _sections.at( key );
|
||||
const XQModelSection& section = _sections.sectionByKey( key );
|
||||
if(section.isValid() )
|
||||
{
|
||||
section.setContentRootNode( contentEntry->parent() );
|
||||
int newRow = _sections.lastRow(section);
|
||||
int newRow =_sections.lastRow(section);
|
||||
XQNodePtr sheetNode = section.sheetRootNode();
|
||||
XQItemList list = _itemFactory.makeRow( XQItemFactory::mHeader, sheetNode, contentEntry );
|
||||
XQItemList list = _itemFactory.makeRow( sheetNode, nullptr );
|
||||
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()
|
||||
{
|
||||
|
||||
_sections.dump();
|
||||
|
||||
// __fixme! add a menu title
|
||||
_contextMenu->clear();
|
||||
|
||||
@@ -113,7 +113,7 @@ void XQChildModel::initContextMenu()
|
||||
|
||||
// __fixme! set 'toggle section <name>' entry
|
||||
//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
|
||||
|
||||
XQDocument::XQDocument(const QString& aFileName, const QString& aFriendlyName, XQItem* aTreeItem, XQViewModel* aModelView )
|
||||
: fileName{ aFileName }, friendlyName{ aFriendlyName }, treeItem{ aTreeItem }, modelView{ aModelView }
|
||||
XQDocument::XQDocument(const QString& aFileName, const QString& aFriendlyName, XQItem* aTreeItem, XQViewModel* aViewModel )
|
||||
: fileName{ aFileName }, friendlyName{ aFriendlyName }, treeItem{ aTreeItem }, viewModel{ aViewModel }
|
||||
{
|
||||
|
||||
}
|
||||
@@ -44,9 +44,9 @@ XQDocumentStore::~XQDocumentStore()
|
||||
|
||||
//! 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 );
|
||||
// attention: this assumes the presence of the 'ProjectID' value
|
||||
//addAlias( aFileName, aTreeItem->attribute(c_ProjectID) );
|
||||
|
@@ -28,12 +28,10 @@ struct XQDocument
|
||||
XQDocument() = default;
|
||||
XQDocument( const QString& aFileName, const QString& aFriendlyName, XQItem* aTreeItem, XQViewModel* aModelView );
|
||||
|
||||
virtual ~XQDocument() = default;
|
||||
|
||||
QString fileName; // also used as key
|
||||
QString friendlyName;
|
||||
XQItem* treeItem{};
|
||||
XQViewModel* modelView{};
|
||||
XQViewModel* viewModel{};
|
||||
|
||||
};
|
||||
|
||||
@@ -46,11 +44,7 @@ public:
|
||||
XQDocumentStore() = default;
|
||||
virtual ~ XQDocumentStore();
|
||||
|
||||
void addDocument( const QString& aFileName, const QString& aFriendlyName, XQItem* aTreeItem, XQViewModel* aModelView );
|
||||
|
||||
protected:
|
||||
|
||||
XQNode _treeRootNode{ "treeRootNode" };
|
||||
void addDocument( const QString& aFileName, const QString& aFriendlyName, XQItem* aTreeItem, XQViewModel* aViewModel );
|
||||
|
||||
};
|
||||
|
||||
|
@@ -45,57 +45,57 @@ void XQMainModel::initContextMenu()
|
||||
|
||||
XQItem* XQMainModel::addProjectItem( XQNodePtr contentNode )
|
||||
{
|
||||
// wir durchsuchen alle unsere section nach dem passenden content-type,
|
||||
// hier: content-type beschreibt die
|
||||
// wir durchsuchen alle unsere sections nach dem passenden content-type,
|
||||
// hier: content-type beschreibt den projekt-status
|
||||
|
||||
const QString& sectionKey = contentNode->attribute(c_ContentType);
|
||||
if( _sections.hasValidSection( sectionKey ) )
|
||||
{
|
||||
const XQModelSection& section = _sections.sectionByKey( sectionKey );
|
||||
qDebug() << " --- add PROJECT: contentNode: " << contentNode->to_string();
|
||||
|
||||
// __fixme! das ist mist!
|
||||
const XQNodePtr sheetNode = section.sheetRootNode()->first_child();
|
||||
XQItem* newItem = _itemFactory.makeSingleItem( sheetNode, contentNode->attribute( "ProjectName") );
|
||||
|
||||
// den neuen eintrag in die passende section der übersicht eintragen ...
|
||||
section.headerItem().appendRow( newItem );
|
||||
// erzeuger sheet node speichern
|
||||
newItem->setSheetNode( sheetNode );
|
||||
expandNewItem(section.headerItem().index() );
|
||||
return newItem;
|
||||
}
|
||||
|
||||
/*
|
||||
for(const auto& section : _sections )
|
||||
{
|
||||
|
||||
if( contentNode->attribute( c_ContentType) == section.contentType() )
|
||||
if( contentNode->attribute(c_ContentType) == section.contentType() )
|
||||
{
|
||||
|
||||
qDebug() << " --- add PROJECT: contentNode: " << contentNode->to_string();
|
||||
|
||||
// __fixme! das ist mist!
|
||||
const XQNodePtr sheetNode = section.sheetRootNode()->first_child();
|
||||
XQItemList list = _itemFactory.makeRow( XQItemFactory::mSingle, sheetNode, contentNode, "ProjectName");
|
||||
XQItem* newItem = _itemFactory.makeSingleItem( sheetNode, contentNode->attribute( "ProjectName") );
|
||||
|
||||
// den neuen eintrag in die passende section der übersicht eintragen ...
|
||||
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]);
|
||||
section.headerItem().appendRow( newItem );
|
||||
// erzeuger sheet node speichern
|
||||
newItem->setSheetNode( sheetNode );
|
||||
expandNewItem(section.headerItem().index() );
|
||||
return newItem;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
*/
|
||||
|
||||
throw XQException( "addProjectItem: main model should not be empty!" );
|
||||
}
|
||||
|
||||
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");
|
||||
XQItemList list = _itemFactory.makeRow( XQItemFactory::mSingle, sheetNode, nullptr, c_ContentType );
|
||||
projectItem->appendRow( list );
|
||||
_treeTable->expand( projectItem->index() );
|
||||
|
||||
XQItem* newItem = _itemFactory.makeSingleItem( sheetNode, section.contentType() );
|
||||
projectItem->appendRow( newItem );
|
||||
expandNewItem(projectItem->index() );
|
||||
}
|
||||
|
||||
|
||||
|
@@ -35,6 +35,7 @@ public:
|
||||
XQItem* addProjectItem( XQNodePtr contentNode );
|
||||
void addSectionItem( const XQModelSection& section, XQItem* projectItem );
|
||||
|
||||
|
||||
protected:
|
||||
|
||||
void initContextMenu() override;
|
||||
|
@@ -88,18 +88,26 @@ void XQMainWindow::initMainWindow()
|
||||
connect( _actionExit, &QAction::triggered, this, &XQMainWindow::onExit );
|
||||
connect( _actionAbout, &QAction::triggered, this, &XQMainWindow::onAbout );
|
||||
|
||||
//connect( _mainTreeView, SIGNAL(doubleClicked(QModelIndex)), this, SLOT(onDoubleClicked(QModelIndex)) );
|
||||
connect( _mainTreeView, SIGNAL(clicked(QModelIndex)), this, SLOT(onTreeItemClicked(QModelIndex)) );
|
||||
connect( _tabWidget, SIGNAL(tabBarClicked(int)), this, SLOT(onTabClicked(int)) );
|
||||
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(clicked(QModelIndex)), this, SLOT(onTreeItemClicked(QModelIndex)) );
|
||||
|
||||
connect(&_mainModel, &XQViewModel::xqItemChanged, this, &XQMainWindow::onTreeViewItemChanged );
|
||||
|
||||
connect( _mainTreeView, &QTreeView::clicked, this, [&,this](const QModelIndex& index)
|
||||
{
|
||||
onTreeViewItemClicked( XQItem::xqItemFromIndex(index) );
|
||||
});
|
||||
|
||||
|
||||
/*
|
||||
connect( &_mainModelView, &XQViewModel::itemCreated, this, [=, this](XQItem* item)
|
||||
connect( &_mainModel, &XQViewModel::itemCreated, this, [=, this](XQItem* item)
|
||||
{
|
||||
// when a new main tree item has been created ...
|
||||
QString pID = item->contentNode()->attribute(c_ProjectID);
|
||||
_mainTreeView->setCurrentIndex( item->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() );
|
||||
@@ -109,15 +117,16 @@ void XQMainWindow::initMainWindow()
|
||||
try
|
||||
{
|
||||
// hand over undostack
|
||||
_mainModelView.setUndoStack(&_undoStack);
|
||||
_mainModel.setUndoStack(&_undoStack);
|
||||
// hand over left side navigation tree
|
||||
_mainModelView.setTreeTable(_mainTreeView);
|
||||
_mainModel.setTreeTable(_mainTreeView);
|
||||
// #1. init the left side main tree view
|
||||
_mainModelView.initModel( c_MainModelName );
|
||||
_mainModel.initModel( c_MainModelName );
|
||||
|
||||
// #2. load demo data
|
||||
loadDocument( c_DocumentFileName1 );
|
||||
//loadDocumentQML( c_DocumentFileName2 );
|
||||
loadDocument( c_DocumentFileName2 );
|
||||
|
||||
qDebug() << " --- all here: " << XQNode::s_Count;
|
||||
|
||||
@@ -232,7 +241,7 @@ void XQMainWindow::onAbout()
|
||||
QMessageBox msgBox(QMessageBox::NoIcon, "About", "", QMessageBox::Ok);
|
||||
|
||||
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>";
|
||||
|
||||
msgBox.setTextFormat(Qt::RichText); // This allows you to click the link
|
||||
@@ -242,46 +251,70 @@ void XQMainWindow::onAbout()
|
||||
}
|
||||
|
||||
|
||||
|
||||
//! wenn ein item im navigations-baum geklickt wird, soll die document
|
||||
//! view rechts angepasst werden.
|
||||
|
||||
void XQMainWindow::onTreeItemClicked(const QModelIndex& index )
|
||||
void XQMainWindow::onTreeViewItemClicked( const XQItem& item )
|
||||
{
|
||||
/*
|
||||
_mainTreeView->selectionModel()->select(item.index(), QItemSelectionModel::Select);
|
||||
|
||||
XQItem& entry = XQItem::xqItemFromIndex(index);
|
||||
|
||||
qDebug() << " --- XXX mainWindow onTreeItemClicked:" << entry.text();
|
||||
_mainTreeView->selectionModel()->select(index, QItemSelectionModel::Select);
|
||||
|
||||
if( XQNodePtr contentNode = entry.contentNode() )
|
||||
if( XQNodePtr contentNode = item.contentNode() )
|
||||
{
|
||||
QString key = contentNode->attribute(c_ProjectID);
|
||||
qDebug() << " --- FIRZ: key: " << key;
|
||||
|
||||
bool isThere = _documentStore.contains(key);
|
||||
if( isThere)
|
||||
_tabWidget->setCurrentWidget( _documentStore[key].modelView->treeTable() );
|
||||
_tabWidget->setCurrentWidget( _documentStore[key].viewModel->treeTable() );
|
||||
}
|
||||
*/
|
||||
|
||||
qDebug() << " --- Tree item CLICK:" << item.text() << " : " << item.itemType().text();
|
||||
if( item.itemType().text() == "TreeChildType" )
|
||||
{
|
||||
setChildTabByName( item.text() );
|
||||
}
|
||||
}
|
||||
|
||||
void XQMainWindow::onTreeViewItemChanged(const XQItem& item )
|
||||
{
|
||||
qDebug() << " --- TREE VIEW itemChanged:" << item.text() << " : " << item.parent()->text();
|
||||
// hier müssen wir erst das projekt aktivieren
|
||||
XQItem* xqItem = static_cast<XQItem*>(item.parent());
|
||||
onTreeViewItemClicked( *xqItem );
|
||||
//if( item.itemType().text() == "TreeSectionType" )
|
||||
{
|
||||
int idx = _tabWidget->currentIndex();
|
||||
if(_documentStore.contains(idx) )
|
||||
{
|
||||
qDebug() << " --- should toggle: " << item.text();
|
||||
XQViewModel& childModel = *_documentStore[idx].viewModel;
|
||||
childModel.onToggleSection(item.text());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//! beim click auf ein tab im linken fenster wird der navigationsbaum angepasst.
|
||||
|
||||
void XQMainWindow::onTabClicked( int index )
|
||||
void XQMainWindow::onChildViewTabClicked( int idx )
|
||||
{
|
||||
//const QString& key = _documentStore[index].treeItem->attribute( c_ProjectID );
|
||||
//qDebug() << " ---- tab clicked: " << index << " : " << _documentStore[index].friendlyName;// << ": " << key;
|
||||
//_mainTreeView->setCurrentIndex( _documentStore[index].treeItem->index() );
|
||||
if(_documentStore.contains(idx) )
|
||||
{
|
||||
QModelIndex treeIndex =_documentStore[idx].treeItem->index();
|
||||
_mainModel.expandNewItem( treeIndex );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//! firz
|
||||
|
||||
void XQMainWindow::onSectionCreated( const XQModelSection& section )
|
||||
{
|
||||
qDebug() << " --- XXX section created: " << section.contentType() << ":" << section.sheetRootNode()->to_string();
|
||||
if( _currentProjectItem )
|
||||
{
|
||||
_mainModelView.addSectionItem( section, _currentProjectItem );
|
||||
_mainModel.addSectionItem( section, _currentProjectItem );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -290,16 +323,16 @@ void XQMainWindow::onSectionToggled( const XQModelSection& section )
|
||||
//qDebug() << " --- XXX section toggled: " << section.contentType() << ":" << section.sheetRootNode()->to_string();
|
||||
}
|
||||
|
||||
QStandardItemModel* createModel() {
|
||||
auto* model = new QStandardItemModel;
|
||||
model->setHorizontalHeaderLabels({ "Name" });
|
||||
|
||||
QStandardItem* parent = new QStandardItem("Tiere");
|
||||
parent->appendRow(new QStandardItem("Hund"));
|
||||
parent->appendRow(new QStandardItem("Katze"));
|
||||
model->appendRow(parent);
|
||||
|
||||
return model;
|
||||
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 )
|
||||
@@ -319,8 +352,6 @@ void XQMainWindow::loadDocumentQML( const QString& fileName )
|
||||
// das als Namen verwendet wird.
|
||||
const QString& fName = contentRoot->friendly_name();
|
||||
|
||||
QStandardItemModel* model = createModel();
|
||||
|
||||
// Ein neues Child-Model erzeugen
|
||||
XQChildModel* childModel = new XQChildModel(this);
|
||||
// die Modelstruktur anlegen
|
||||
@@ -331,13 +362,12 @@ void XQMainWindow::loadDocumentQML( const QString& fileName )
|
||||
XQQuickWidget* quickChild = new XQQuickWidget(_tabWidget);
|
||||
//quickChild->setResizeMode(QQuickWidget::SizeViewToRootObject);
|
||||
|
||||
quickChild->rootContext()->setContextProperty("meinModel", childModel);
|
||||
quickChild->setSource(QUrl(QStringLiteral("qrc:/quickview.qml")));
|
||||
_tabWidget->addTab( quickChild, "Fitze!" );
|
||||
quickChild->rootContext()->setContextProperty("xtrChildModel", childModel);
|
||||
quickChild->setSource(QUrl("qrc:/xqtreeview.qml"));
|
||||
_tabWidget->addTab( quickChild, "QML:"+fName );
|
||||
_tabWidget->setCurrentWidget( quickChild );
|
||||
quickChild->setResizeMode(QQuickWidget::SizeRootObjectToView);
|
||||
|
||||
|
||||
}
|
||||
|
||||
//! liest eine XML datei namens 'fileName'
|
||||
@@ -369,13 +399,13 @@ void XQMainWindow::loadDocument( const QString& fileName )
|
||||
// 'friendly Name' ist ein Link auf ein anderes Attribute
|
||||
// das als Namen verwendet wird.
|
||||
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.
|
||||
XQTreeTable* childTreeView = new XQTreeTable(_tabWidget);
|
||||
_tabWidget->addTab( childTreeView, pTitle );
|
||||
_tabWidget->addTab( childTreeView, pTabTitle );
|
||||
_tabWidget->setCurrentWidget( childTreeView );
|
||||
setWindowTitle( pTitle );
|
||||
setWindowTitle( pTabTitle );
|
||||
|
||||
// Ein neues Child-Model erzeugen
|
||||
XQChildModel* childModel = new XQChildModel(this);
|
||||
@@ -390,8 +420,8 @@ void XQMainWindow::loadDocument( const QString& fileName )
|
||||
childModel->setTreeTable(childTreeView);
|
||||
|
||||
// neuen eintrag im übsichts-baum erzeugen
|
||||
_currentProjectItem = _mainModelView.addProjectItem( contentRoot );
|
||||
_documentStore.addDocument( fileName, pTitle, _currentProjectItem, childModel );
|
||||
_currentProjectItem = _mainModel.addProjectItem( contentRoot );
|
||||
_documentStore.addDocument( fileName, fName, _currentProjectItem, childModel );
|
||||
|
||||
// die Modelstruktur anlegen
|
||||
childModel->initModel( c_ChildModelName );
|
||||
@@ -409,7 +439,9 @@ void XQMainWindow::saveDocument( const QString& fileName )
|
||||
{
|
||||
XQNodeWriter nodeWriter;
|
||||
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 );
|
||||
}
|
||||
|
||||
|
@@ -35,6 +35,11 @@ public:
|
||||
|
||||
public slots:
|
||||
|
||||
virtual void onMyFirz(XQItem& item)
|
||||
{
|
||||
qDebug() << " --- myFirz: " << item.text();
|
||||
}
|
||||
|
||||
void onUndo();
|
||||
void onRedo();
|
||||
|
||||
@@ -46,30 +51,32 @@ public slots:
|
||||
void onAbout();
|
||||
void onExit();
|
||||
|
||||
void onTreeItemClicked(const QModelIndex& index );
|
||||
void onTabClicked( int index );
|
||||
void onTreeViewItemClicked( const XQItem& item );
|
||||
void onTreeViewItemChanged( const XQItem& item );
|
||||
void onChildViewTabClicked( int index );
|
||||
|
||||
//void onItemCreated( XQItem* item );
|
||||
void onSectionCreated( const XQModelSection& section);
|
||||
void onSectionToggled( const XQModelSection& section );
|
||||
|
||||
void setChildTabByName( const QString& key );
|
||||
|
||||
static void setupWorkingDir();
|
||||
|
||||
protected:
|
||||
|
||||
void setupWorkingDir();
|
||||
|
||||
// fixme implement
|
||||
void showDocumnet( const QString& key ){}
|
||||
void showDocument( const QString& key ){}
|
||||
void loadDocument( const QString& fileName );
|
||||
void loadDocumentQML( const QString& fileName );
|
||||
void saveDocument( const QString& fileName );
|
||||
|
||||
|
||||
QUndoStack _undoStack;
|
||||
XQDocumentStore _documentStore;
|
||||
|
||||
XQMainModel _mainModelView;
|
||||
XQMainModel _mainModel;
|
||||
XQItem* _currentProjectItem{};
|
||||
|
||||
//XQChildModel* _currentChildModel{};
|
||||
|
||||
};
|
||||
|
||||
|
@@ -116,6 +116,8 @@ XQItem::XQPrefixExponentMap XQItem::s_PrefixExponentMap
|
||||
};
|
||||
|
||||
|
||||
//! Default konstruktor, setzt einen ungültigen (dummy)
|
||||
//! itemType.
|
||||
|
||||
XQItem::XQItem()
|
||||
: XQItem{XQItemType::staticItemType()}
|
||||
@@ -123,6 +125,9 @@ XQItem::XQItem()
|
||||
|
||||
}
|
||||
|
||||
|
||||
//! Default konstruktor mit einem vorhandenen itemType.
|
||||
|
||||
XQItem::XQItem( XQItemType* itemType )
|
||||
: 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 }
|
||||
{
|
||||
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.
|
||||
|
||||
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
|
||||
//! mockup-itemtype gesetzt ist.
|
||||
|
||||
bool XQItem::isValid() const
|
||||
bool XQItem::isValidX() const
|
||||
{
|
||||
XQItemType* dummyType = XQItemType::staticItemType();
|
||||
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.
|
||||
|
||||
XQNodePtr XQItem::contentNode() const
|
||||
{
|
||||
XQNodePtr node = data( ContentNodeRole ).value<XQNodePtr>();
|
||||
if( node )
|
||||
return node;
|
||||
throw XQException("XQItem::contentNode() nullptr");
|
||||
return data( ContentNodeRole ).value<XQNodePtr>();
|
||||
}
|
||||
|
||||
|
||||
@@ -319,37 +347,23 @@ QString XQItem::rawText() const
|
||||
|
||||
|
||||
//! Gibt den string-zeiger auf das attribut aus unseren XQNodePtr zurück.
|
||||
|
||||
/*
|
||||
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*>();
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
//! set den content()-string pointer. (als leihgabe)
|
||||
|
||||
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
|
||||
//! Gibt den content-format string zurück
|
||||
|
||||
QString XQItem::contentFormat() const
|
||||
{
|
||||
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)
|
||||
{
|
||||
@@ -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.
|
||||
|
||||
QStandardItemModel* XQItem::fixedChoices() const
|
||||
@@ -413,6 +427,30 @@ QString XQItem::dataRoleName(int role) const
|
||||
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
|
||||
//! werden vom xqitemtype geholt
|
||||
|
||||
@@ -438,33 +476,34 @@ QVariant XQItem::data(int role ) const
|
||||
return itemType().data(role);
|
||||
}
|
||||
|
||||
// Zugriffe auf den sichtbaren inhalt geben den inhalt des string pointer
|
||||
// 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 :
|
||||
case XQItem::ContentRole:
|
||||
{
|
||||
if( itemType().renderStyle() == XQItem::FormattedStyle)//return "display:"+content();
|
||||
return itemType().formatText( *this );
|
||||
[[fallthrough]];
|
||||
qDebug() << " --- data(XQItem::ContentRole) should NOT be called!";
|
||||
return *QStandardItem::data( XQItem::ContentRole ).value<QString*>();
|
||||
}
|
||||
|
||||
// EditRole & ContentRole sollen den 'rohen' inhalt unseres string-pointers
|
||||
// auf den original inhalt im content node zurückgeben.
|
||||
|
||||
case Qt::EditRole :
|
||||
case XQItem::ContentRole:
|
||||
case Qt::EditRole :
|
||||
{
|
||||
// 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*>();
|
||||
if(contentPtr)
|
||||
return *contentPtr;
|
||||
return contentFallBackText();
|
||||
//[[fallthrough]];
|
||||
}
|
||||
|
||||
static const QString s_dummyContent("-");
|
||||
return s_dummyContent;
|
||||
// DisplayRole gibt den formatierten inhalt wieder. die formatierung übernimmt
|
||||
// der item type
|
||||
|
||||
case Qt::DisplayRole :
|
||||
{
|
||||
QString plainText = contentFallBackText();
|
||||
if( renderStyle() == XQItem::FormattedStyle)
|
||||
return XQItemType::formatToSI( plainText, unitType() );
|
||||
return plainText;
|
||||
}
|
||||
|
||||
case Qt::ToolTipRole:
|
||||
@@ -479,16 +518,30 @@ QVariant XQItem::data(int role ) const
|
||||
|
||||
case ContentNodeRole:
|
||||
{
|
||||
// Das Node-Besitzer-Item wohnt in der ersten Spalte,
|
||||
// wenn wir also der Node-Besitzer item sind ...
|
||||
if( column() == 0)
|
||||
return QStandardItem::data( XQItem::ContentNodeRole );
|
||||
// Das Node-Besitzer-Item wohnt in der ersten Spalte,
|
||||
// wenn wir also der Node-Besitzer item sind ...
|
||||
if( column() == 0)
|
||||
{
|
||||
QVariant value = QStandardItem::data( XQItem::ContentNodeRole );
|
||||
if( !value.isNull() )
|
||||
return value;
|
||||
|
||||
// sonst: delegieren an den node-Besitzer
|
||||
QModelIndex pIndex = model()->index( row(), 0 );
|
||||
// das gibt immerhin was zurück, was auf nullptr getestet werden kann,
|
||||
return QVariant::fromValue<XQNodePtr>(nullptr);
|
||||
|
||||
// diese variante erzieht uns zur verwendung von 'hasContentNode()'
|
||||
// was ist besser ?
|
||||
throw XQException( "ContentNode is nullptr!");
|
||||
}
|
||||
|
||||
// sonst: delegieren an den node-Besitzer
|
||||
QModelIndex pIndex = model()->index( row(), 0 );
|
||||
if( pIndex.isValid())
|
||||
{
|
||||
XQItem& firstItem = xqItemFromIndex( pIndex );
|
||||
|
||||
return firstItem.data( XQItem::ContentNodeRole );
|
||||
}
|
||||
throw XQException( "Item has no valid index (yet)!");
|
||||
}
|
||||
|
||||
case Qt::StatusTipRole:
|
||||
@@ -537,7 +590,6 @@ void XQItem::setData(const QVariant& value, int role )
|
||||
{
|
||||
switch(role)
|
||||
{
|
||||
|
||||
case RenderStyleRole :
|
||||
case EditorTypeRole :
|
||||
case UnitTypeRole:
|
||||
@@ -557,30 +609,31 @@ void XQItem::setData(const QVariant& value, int role )
|
||||
return;
|
||||
}
|
||||
|
||||
// set the raw, unformatted data
|
||||
case ContentRole:
|
||||
case Qt::DisplayRole:
|
||||
case Qt::EditRole:
|
||||
case XQItem::ContentRole:
|
||||
{
|
||||
// string ptr setzen kann die basis.
|
||||
break;
|
||||
}
|
||||
QVariant newValue;
|
||||
if( itemType().renderStyle() == XQItem::FormattedStyle)
|
||||
newValue = XQItemType::unFormatFromSI( value.toString() );
|
||||
else
|
||||
newValue = value;
|
||||
|
||||
case Qt::EditRole :
|
||||
{
|
||||
qDebug() << " --- setting EDITrole: " << value.toString();
|
||||
break;
|
||||
}
|
||||
// fallback: wenns keinen content node gibt, dann nehmen wir
|
||||
// das standardverfahren.
|
||||
if( !hasContentPtr() )
|
||||
return QStandardItem::setData( newValue, Qt::DisplayRole );
|
||||
|
||||
case Qt::DisplayRole :
|
||||
{
|
||||
// what will happen? value is a string ptr ?!
|
||||
qDebug() << " --- setting DISPLAYrole: " << value.toString();
|
||||
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
|
||||
case ContentNodeRole:
|
||||
case SheetNodeRole:
|
||||
|
||||
//case TypeKeyRole: not used
|
||||
default:
|
||||
break;
|
||||
@@ -694,13 +747,10 @@ XQItem::UnitType XQItem::fetchUnitType(const QString& unitTypeKey)
|
||||
return s_UnitTypeMap.key(unitTypeKey);
|
||||
}
|
||||
|
||||
|
||||
//! gibt die bezeichung für den gegebenen unitType aus.
|
||||
|
||||
QString XQItem::fetchUnitTypeToString( UnitType unitType)
|
||||
{
|
||||
return s_UnitTypeMap[unitType];
|
||||
}
|
||||
|
||||
/// ---
|
||||
/// ---
|
||||
/// ---
|
||||
|
@@ -15,6 +15,7 @@
|
||||
#ifndef XQITEM_H
|
||||
#define XQITEM_H
|
||||
|
||||
#include <QtQmlIntegration>
|
||||
#include <QVariant>
|
||||
#include <QVector>
|
||||
#include <QStandardItem>
|
||||
@@ -35,6 +36,8 @@ class XQItemType;
|
||||
class XQItem : public QStandardItem
|
||||
{
|
||||
|
||||
QML_ELEMENT
|
||||
|
||||
friend class XQItemFactory;
|
||||
|
||||
public:
|
||||
@@ -130,6 +133,7 @@ public:
|
||||
XQItem();
|
||||
XQItem( XQItemType* itemType );
|
||||
XQItem( XQItemType* itemType, const QString* content );
|
||||
XQItem( XQItemType* itemType, const QString& content );
|
||||
|
||||
virtual ~XQItem() = default;
|
||||
|
||||
@@ -137,14 +141,16 @@ public:
|
||||
//! -- not used at the moment --
|
||||
XQItem* clone() const override;
|
||||
|
||||
//!
|
||||
bool isValid() const;
|
||||
//! __fix Tested, ob ein itemtype vorhanden ist.
|
||||
bool isValidX() const;
|
||||
|
||||
//! gibt den zu diesem item gehörigen datenknoten zurück
|
||||
virtual XQNodePtr contentNode() const;
|
||||
bool hasContentNode() 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;
|
||||
void setItemType( XQItemType* itemTypePtr );
|
||||
@@ -159,9 +165,8 @@ public:
|
||||
QString rawText() const;
|
||||
|
||||
// changed: gibt jetzt den pointer zurück.
|
||||
QString* content() const;
|
||||
QString contentKey() const;
|
||||
void setContent( const QString* content );
|
||||
//QString* content() const;
|
||||
//void setContent( const QString* content );
|
||||
|
||||
//
|
||||
// Convenience-Funktionen zum Memberzugriff, die Implementierung
|
||||
@@ -238,6 +243,10 @@ protected:
|
||||
XQItem(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 );
|
||||
|
||||
using XQItemFlagMap = QMap<QString,int>;
|
||||
@@ -259,9 +268,7 @@ protected:
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
Q_DECLARE_METATYPE(XQItem);
|
||||
Q_DECLARE_METATYPE(XQItem::RenderStyle);
|
||||
Q_DECLARE_METATYPE(XQItem::EditorType);
|
||||
Q_DECLARE_METATYPE(XQItem::UnitType);
|
||||
|
@@ -28,6 +28,8 @@
|
||||
#include <xqviewmodel.h>
|
||||
|
||||
|
||||
//! firz
|
||||
|
||||
class XQItemEditorFactory : public QItemEditorFactory
|
||||
{
|
||||
public:
|
||||
@@ -60,6 +62,7 @@ public:
|
||||
};
|
||||
|
||||
|
||||
//! firz
|
||||
|
||||
XQItemDelegate::XQItemDelegate( XQViewModel& modelView)
|
||||
: _modelView{modelView}
|
||||
@@ -69,6 +72,8 @@ XQItemDelegate::XQItemDelegate( XQViewModel& modelView)
|
||||
}
|
||||
|
||||
|
||||
//! firz
|
||||
|
||||
XQTreeTable* XQItemDelegate::treeTable() const
|
||||
{
|
||||
return _modelView.treeTable();
|
||||
@@ -81,40 +86,40 @@ XQItem& XQItemDelegate::xqItemFromIndex( const QModelIndex& index ) const
|
||||
}
|
||||
|
||||
|
||||
//! firz
|
||||
|
||||
void XQItemDelegate::paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const
|
||||
{
|
||||
if( !index.isValid() )
|
||||
qDebug() << " index DEAD!";
|
||||
|
||||
XQItem& item = xqItemFromIndex( index );
|
||||
if( item.isValid() )
|
||||
|
||||
|
||||
switch( item.renderStyle() )
|
||||
{
|
||||
case XQItem::HeaderStyle :
|
||||
return drawHeaderStyle( painter, option, index );
|
||||
|
||||
switch( item.renderStyle() )
|
||||
{
|
||||
case XQItem::HeaderStyle :
|
||||
return drawHeaderStyle( painter, option, index );
|
||||
case XQItem::ComboBoxStyle :
|
||||
return drawComboBoxStyle( painter, option, index );
|
||||
|
||||
case XQItem::ComboBoxStyle :
|
||||
return drawComboBoxStyle( painter, option, index );
|
||||
case XQItem::HiddenStyle :
|
||||
return;
|
||||
|
||||
case XQItem::HiddenStyle :
|
||||
return;
|
||||
|
||||
//case XQItem::ProgressBarStyle :
|
||||
// return drawProgressBarStyle( painter, option, index );
|
||||
//case XQItem::ProgressBarStyle :
|
||||
// return drawProgressBarStyle( painter, option, index );
|
||||
|
||||
|
||||
default:
|
||||
break;
|
||||
} // switch
|
||||
|
||||
}
|
||||
default:
|
||||
break;
|
||||
} // switch
|
||||
|
||||
QStyledItemDelegate::paint(painter, option, index);
|
||||
|
||||
}
|
||||
|
||||
|
||||
//! einen section header im header-style zeichnen
|
||||
|
||||
void XQItemDelegate::drawHeaderStyle(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const
|
||||
@@ -150,7 +155,10 @@ void XQItemDelegate::drawHeaderStyle(QPainter* painter, const QStyleOptionViewIt
|
||||
}
|
||||
}
|
||||
|
||||
void XQItemDelegate::drawProgressBarStyle(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
|
||||
|
||||
//! firz
|
||||
|
||||
void XQItemDelegate::drawProgressBarStyle(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const
|
||||
{
|
||||
|
||||
int progress = index.data(XQItem::ContentRole ).toInt();
|
||||
@@ -168,7 +176,10 @@ void XQItemDelegate::drawProgressBarStyle(QPainter *painter, const QStyleOptionV
|
||||
|
||||
}
|
||||
|
||||
void XQItemDelegate::drawComboBoxStyle(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
|
||||
|
||||
//! firz
|
||||
|
||||
void XQItemDelegate::drawComboBoxStyle(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const
|
||||
{
|
||||
|
||||
QWidget* srcWidget = qobject_cast<QWidget*>(option.styleObject);
|
||||
@@ -197,6 +208,8 @@ void XQItemDelegate::drawComboBoxStyle(QPainter *painter, const QStyleOptionView
|
||||
painter->restore();
|
||||
}
|
||||
|
||||
//! firz
|
||||
|
||||
void XQItemDelegate::drawSpinBoxStyle(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const
|
||||
{
|
||||
|
||||
@@ -214,58 +227,82 @@ void XQItemDelegate::drawSpinBoxStyle(QPainter* painter, const QStyleOptionViewI
|
||||
}
|
||||
|
||||
|
||||
QSize XQItemDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const
|
||||
//! firz
|
||||
|
||||
QSize XQItemDelegate::sizeHint(const QStyleOptionViewItem& option, const QModelIndex& index) const
|
||||
{
|
||||
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
|
||||
{
|
||||
|
||||
return QStyledItemDelegate::createEditor( parent, option, index );
|
||||
|
||||
int editorType = XQItem::xqItemFromIndex(index).editorType();
|
||||
QWidget* editor = itemEditorFactory()->createEditor(editorType, parent);
|
||||
if( editor )
|
||||
XQItem& item = xqItemFromIndex(index);
|
||||
XQItem::EditorType edType = item.editorType();
|
||||
if( edType == XQItem::NoEditorType )
|
||||
{
|
||||
return editor;
|
||||
qDebug() << "---- NO Content or NO EditorType";
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
qDebug() << "---- ed type:" << XQItem::fetchEditorTypeToString( edType ) << ": " << edType;
|
||||
//return QStyledItemDelegate::createEditor( parent, option, index );
|
||||
|
||||
return itemEditorFactory()->createEditor(edType, parent);
|
||||
}
|
||||
|
||||
|
||||
//! Füttert einen editor mit den model-daten
|
||||
|
||||
void XQItemDelegate::setEditorData(QWidget* editor, const QModelIndex& index) const
|
||||
{
|
||||
|
||||
XQItem& item = xqItemFromIndex( index );
|
||||
switch( item.editorType() )
|
||||
{
|
||||
case XQItemType::ComboBoxType :
|
||||
{
|
||||
QComboBox* comboBox = qobject_cast<QComboBox*>(editor);
|
||||
comboBox->setModel( item.fixedChoices());
|
||||
comboBox->setCurrentText( item.data().toString() );
|
||||
comboBox->showPopup();
|
||||
return;
|
||||
}
|
||||
XQItem::EditorType edType = item.editorType();
|
||||
if( edType == XQItem::NoEditorType )
|
||||
return;
|
||||
|
||||
default:
|
||||
break;
|
||||
switch( edType )
|
||||
{
|
||||
case XQItemType::ComboBoxType :
|
||||
{
|
||||
QComboBox* comboBox = qobject_cast<QComboBox*>(editor);
|
||||
comboBox->setModel( item.fixedChoices());
|
||||
comboBox->setCurrentText( item.data().toString() );
|
||||
comboBox->showPopup();
|
||||
return;
|
||||
}
|
||||
|
||||
default:
|
||||
|
||||
// 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 );
|
||||
|
||||
switch( item.editorType() )
|
||||
{
|
||||
|
||||
case XQItem::ComboBoxType :
|
||||
{
|
||||
QComboBox* comboBox = qobject_cast<QComboBox*>(editor);
|
||||
@@ -280,6 +317,9 @@ void XQItemDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, co
|
||||
QStyledItemDelegate::setModelData(editor, model, index);
|
||||
}
|
||||
|
||||
|
||||
//! firz
|
||||
|
||||
void XQItemDelegate::updateEditorGeometry(QWidget* editor, const QStyleOptionViewItem& option, const QModelIndex& index) const
|
||||
{
|
||||
//qDebug() << " --- update Editor Geometry";
|
||||
|
@@ -37,19 +37,19 @@ public:
|
||||
XQTreeTable* treeTable() const;
|
||||
XQItem& xqItemFromIndex( const QModelIndex& index ) const;
|
||||
|
||||
void paint(QPainter *painter, 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;
|
||||
void setEditorData(QWidget *editor, 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 paint(QPainter* painter, 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;
|
||||
void setEditorData(QWidget* editor, 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;
|
||||
|
||||
protected:
|
||||
|
||||
void drawHeaderStyle(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const;
|
||||
void drawProgressBarStyle(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const;
|
||||
void drawComboBoxStyle(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const;
|
||||
void drawSpinBoxStyle(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const;
|
||||
void drawHeaderStyle(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const;
|
||||
void drawProgressBarStyle(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const;
|
||||
void drawComboBoxStyle(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const;
|
||||
void drawSpinBoxStyle(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const;
|
||||
|
||||
XQViewModel& _modelView;
|
||||
|
||||
|
@@ -99,6 +99,7 @@ XQItemType* XQItemFactory::makeItemType(const XQNodePtr& sheetEntry )
|
||||
return itemType;
|
||||
}
|
||||
|
||||
|
||||
//! sucht einen item typ aus der map mit 'vorgefertigen' itemtypen.
|
||||
|
||||
XQItemType* XQItemFactory::findItemTypeTemplate(const QString& key ) const
|
||||
@@ -256,10 +257,6 @@ QVariant XQItemFactory::makeVariant( int dataRole, const QString& source ) const
|
||||
/// ------------------------------------------------
|
||||
///
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
XQItemList XQItemFactory::makeEmptyRow( const XQNodePtr& contentNode, const XQNodePtr& sheetNode )
|
||||
{
|
||||
@@ -304,7 +301,7 @@ XQItemList XQItemFactory::createGenericRow( const XQNodePtr& contentNode, const
|
||||
|
||||
//! 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;
|
||||
@@ -320,24 +317,23 @@ XQItemList XQItemFactory::makeRow(CreationMode mode, const XQNodePtr& sheetNode,
|
||||
//
|
||||
|
||||
for( const auto& sheetEntry : sheetNode->children() )
|
||||
list.append( makeItem( mode, sheetEntry, contentNode, captionKey ) );
|
||||
list.append( makeItem( sheetEntry, contentNode ) );
|
||||
|
||||
Q_ASSERT(!list.empty());
|
||||
|
||||
// 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);
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
|
||||
//! fixme! unsinn!
|
||||
//! 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
|
||||
//! verwendet: es handelt sich dann um ein header item, das erzeugt wurde.
|
||||
//! 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
|
||||
//! verwendet: es handelt sich dann um ein header item
|
||||
|
||||
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
|
||||
XQItemType* itemType = makeItemType(sheetNode); // throws
|
||||
@@ -347,19 +343,10 @@ XQItem* XQItemFactory::makeItem(CreationMode mode, const XQNodePtr& sheetNode, c
|
||||
// das ist Unterschied vom HeaderItem zum normalen Item: Der Titel kommt aus der Modelbeschreibung,
|
||||
// sonst wird der content indirekt über den tag-name des sheetnode geholt
|
||||
|
||||
switch( mode )
|
||||
{
|
||||
case mHeader:
|
||||
contentPtr = sheetNode->attribute_ptr(captionKey);
|
||||
break;
|
||||
|
||||
case mData:
|
||||
contentPtr = contentNode->attribute_ptr( sheetNode->tag_name() );
|
||||
break;
|
||||
|
||||
case mSingle:
|
||||
contentPtr = contentNode->attribute_ptr( captionKey );
|
||||
}
|
||||
if( !contentNode )
|
||||
contentPtr = sheetNode->attribute_ptr(c_Caption);
|
||||
else
|
||||
contentPtr = contentNode->attribute_ptr( sheetNode->tag_name() );
|
||||
|
||||
XQItem* newItem = new XQItem( itemType, contentPtr);
|
||||
|
||||
@@ -371,3 +358,18 @@ XQItem* XQItemFactory::makeItem(CreationMode mode, const XQNodePtr& sheetNode, c
|
||||
|
||||
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,25 +28,14 @@ class XQItemFactory : public xsingleton<XQItemFactory>
|
||||
|
||||
public:
|
||||
|
||||
enum CreationMode
|
||||
{
|
||||
mHeader,
|
||||
mData,
|
||||
mSingle
|
||||
};
|
||||
|
||||
void initItemFactory(const QString& modelSheetFileName );
|
||||
|
||||
XQNodePtr findModelSheet( const QString& modelName ) const;
|
||||
|
||||
//XQItemList makeEmptyRow( const XQNodePtr& contentNode, const XQNodePtr& sheetNode );
|
||||
XQItemList makeRow( const XQNodePtr& sheetNode, const XQNodePtr& contentNode );
|
||||
XQItem* makeSingleItem( const XQNodePtr& sheetNode, const QString& caption );
|
||||
|
||||
XQItemList makeRow( CreationMode mode, const XQNodePtr& sheetNode, const XQNodePtr& contentNode, const QString& captionKey=c_Caption );
|
||||
|
||||
// wozu ist das gut?
|
||||
//XQItemList createGenericRow( const XQNodePtr& contentNode, const XQNodePtr& sheetNode );
|
||||
|
||||
void setItemDataFromString( XQItem& item, const QString& roleKey, const QString& source ) const;
|
||||
void setItemDataFromString( XQItem& item, const QString& roleKey, const QString& source ) const;
|
||||
|
||||
XQItemType* makeItemType(const XQNodePtr& sheetEntry );
|
||||
XQItemType* findItemTypeTemplate(const QString& key ) const;
|
||||
@@ -56,7 +45,7 @@ protected:
|
||||
|
||||
bool isValid();
|
||||
|
||||
XQItem* makeItem( CreationMode mode, const XQNodePtr& sheetNode, const XQNodePtr& contentNode, const QString& captionKey );
|
||||
XQItem* makeItem(const XQNodePtr& sheetNode, const XQNodePtr& contentNode );
|
||||
|
||||
// shortcuts
|
||||
using ItemConfigFunc = std::function<void( XQItem* item, const QString& attrValue, XQNodePtr contentNode, XQNodePtr sheetNode )>;
|
||||
|
@@ -134,22 +134,9 @@ XQItemType* XQItemType::replaceAttribute( const QVariant& newValue, int role )
|
||||
}
|
||||
|
||||
|
||||
//! formatiert den content() string eines items.
|
||||
|
||||
QVariant XQItemType::formatText( const XQItem& item ) const
|
||||
{
|
||||
XQItem::UnitType uType = unitType();
|
||||
//qDebug() << " --- formatText: " << XQItem::fetchUnitTypeToString( uType);
|
||||
const QString& cont = item.rawText();
|
||||
if( uType != XQItem::NoUnitType )
|
||||
return formatToSI( cont, uType );
|
||||
return cont;
|
||||
}
|
||||
|
||||
|
||||
//! formatiert einen zahlenwert als string mit einheit.
|
||||
|
||||
QString XQItemType::formatToSI( const QString& valueTxt, XQItem::UnitType unitType ) const
|
||||
QString XQItemType::formatToSI( const QString& valueTxt, XQItem::UnitType unitType )
|
||||
{
|
||||
|
||||
if( valueTxt.isEmpty() )
|
||||
@@ -180,18 +167,18 @@ QString XQItemType::formatToSI( const QString& valueTxt, XQItem::UnitType unitTy
|
||||
strVal = sysLocale.toString(nVal, 'f', 2);
|
||||
strPrefix = s_PrefixExponentMap.key(exp);
|
||||
//qDebug() << " convert: " << dVal << " : " << valueTxt << ": " << strVal << ":" << exp << " : " << strPrefix << ": " << nVal;
|
||||
|
||||
return QString("%1 %2%3").arg( strVal, strPrefix, unitTypeToString() );
|
||||
QString unitStr = XQItem::fetchUnitTypeToString( unitType);
|
||||
return QString("%1 %2%3").arg( strVal, strPrefix, unitStr );
|
||||
|
||||
}
|
||||
|
||||
|
||||
//! 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
|
||||
if( input.isEmpty() )
|
||||
return input;
|
||||
|
@@ -40,17 +40,14 @@ public:
|
||||
QVariant data( int role ) const 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 );
|
||||
XQItemType* replaceAttribute(const QVariant& newValue, int role );
|
||||
|
||||
QString makeItemTypeKey();
|
||||
|
||||
static XQItemType* staticItemType();
|
||||
static QString formatToSI(const QString& rawText, XQItem::UnitType unitType );
|
||||
static QString unFormatFromSI(const QString& valueText );
|
||||
|
||||
protected:
|
||||
|
||||
|
70
src/main.cpp
70
src/main.cpp
@@ -15,6 +15,13 @@
|
||||
#include <QDebug>
|
||||
#include <QApplication>
|
||||
#include <QMetaType>
|
||||
#include <QGuiApplication>
|
||||
#include <QQmlApplicationEngine>
|
||||
#include <QUrl>
|
||||
#include <QQmlContext>
|
||||
|
||||
#include <xqchildmodel.h>
|
||||
#include <xqquickwidget.h>
|
||||
|
||||
#include <xqmainwindow.h>
|
||||
|
||||
@@ -49,25 +56,64 @@ who is who:
|
||||
|
||||
*/
|
||||
|
||||
XQChildModel* createChildModel()
|
||||
{
|
||||
XQChildModel* myModel = new XQChildModel();
|
||||
|
||||
myModel->initModel( c_ChildModelName );
|
||||
|
||||
XQNodeFactory treeLoader;
|
||||
// xml daten laden
|
||||
XQNodePtr rawTree = treeLoader.load_tree( qPrintable(c_DocumentFileName1) );
|
||||
// versteckten root node ignorieren
|
||||
XQNodePtr contentRoot = rawTree->first_child();
|
||||
myModel->addModelData( contentRoot->first_child() );
|
||||
|
||||
return myModel;
|
||||
|
||||
}
|
||||
|
||||
|
||||
using namespace Qt::Literals::StringLiterals;
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
|
||||
QApplication app(argc, 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();
|
||||
});
|
||||
*/
|
||||
|
||||
|
||||
//app.setStyle("fusion");
|
||||
//app.setStyle("WindowsVista");
|
||||
XQMainWindow window;
|
||||
window.show();
|
||||
|
||||
|
||||
/*
|
||||
QApplication app(argc, argv);
|
||||
|
||||
XQMainWindow::setupWorkingDir();
|
||||
XQItemFactory::instance().initItemFactory( c_ModelSheetFileName );
|
||||
|
||||
XQChildModel* myModel = createChildModel();
|
||||
qmlRegisterType< XQChildModel>("MyApp.Models", 1, 0, "MyChildModel");
|
||||
|
||||
|
||||
QQmlApplicationEngine engine;
|
||||
|
||||
engine.rootContext()->setContextProperty("myChildModel", myModel);
|
||||
|
||||
QObject::connect(
|
||||
&engine,
|
||||
&QQmlApplicationEngine::objectCreationFailed,
|
||||
&app,
|
||||
[]() { QCoreApplication::exit(-1); },
|
||||
Qt::QueuedConnection);
|
||||
|
||||
qDebug() << " fitz!";
|
||||
|
||||
engine.load( QUrl(QStringLiteral("qrc:/dummyview.qml")) );
|
||||
//engine.load( QUrl(QStringLiteral("qrc:/xqtableview.qml")) );
|
||||
|
||||
qDebug() << " hhakl!";
|
||||
|
||||
*/
|
||||
return app.exec();
|
||||
|
||||
}
|
||||
|
@@ -31,7 +31,7 @@ void XQNodeStore::dumpList( const QString& title ) const
|
||||
//! kostruktor. übergibt command-type und die aufrufende modelView.
|
||||
|
||||
XQCommand::XQCommand(CmdType cmdType, XQViewModel* modelView )
|
||||
: _cmdType{ cmdType }, _model(modelView)
|
||||
: _cmdType{ cmdType }, _viewModel(modelView)
|
||||
{
|
||||
|
||||
}
|
||||
@@ -66,7 +66,7 @@ void XQCommand::setCommandType( XQCommand::CmdType cmdType )
|
||||
|
||||
void XQCommand::redo()
|
||||
{
|
||||
_model->onCommandRedo( *this );
|
||||
_viewModel->onCommandRedo( *this );
|
||||
}
|
||||
|
||||
|
||||
@@ -74,7 +74,7 @@ void XQCommand::redo()
|
||||
|
||||
void XQCommand::undo()
|
||||
{
|
||||
_model->onCommandUndo( *this );
|
||||
_viewModel->onCommandUndo( *this );
|
||||
}
|
||||
|
||||
|
||||
@@ -121,7 +121,7 @@ void XQCommand::saveNodes( const QModelIndexList& list )
|
||||
|
||||
//! erzeugt einen string aus dem command-type, fürs debuggen.
|
||||
|
||||
QString XQCommand::toString()
|
||||
QString XQCommand::toString() const
|
||||
{
|
||||
|
||||
static QMap<CmdType,QString> s_CmdTypeMap
|
||||
|
@@ -80,13 +80,13 @@ public:
|
||||
void redo() override;
|
||||
void undo() override;
|
||||
|
||||
QString toString();
|
||||
QString toString() const;
|
||||
|
||||
protected:
|
||||
|
||||
CmdType _cmdType{cmdInvalid};
|
||||
XQViewModel* _model{}; // needed for redo() / undo()
|
||||
QModelIndex _originIndex;
|
||||
CmdType _cmdType{cmdInvalid};
|
||||
XQViewModel* _viewModel{}; // needed for redo() / undo()
|
||||
QModelIndex _originIndex;
|
||||
|
||||
/*
|
||||
|
||||
|
@@ -12,7 +12,7 @@
|
||||
***************************************************************************/
|
||||
|
||||
|
||||
#include <xqmodelsectionlist.h>
|
||||
#include <xqsectionmanager.h>
|
||||
|
||||
|
||||
//! kontstruktor. übergibt den start-index und einen model-knoten mit der beschreibung
|
||||
@@ -40,9 +40,9 @@ bool XQModelSection::isValid() const
|
||||
return _modelIndex.isValid() && _sectionRootNode;
|
||||
}
|
||||
|
||||
const QModelIndex& XQModelSection::modelIndex() const
|
||||
QModelIndex XQModelSection::startIndex() const
|
||||
{
|
||||
return _modelIndex;
|
||||
return _modelIndex.operator QModelIndex();
|
||||
}
|
||||
|
||||
XQNodePtr XQModelSection::sectionRootNode() const
|
||||
@@ -72,7 +72,7 @@ XQNodePtr XQModelSection::contentRootNode() const
|
||||
return _contentRootNode;
|
||||
}
|
||||
|
||||
void XQModelSection::setContentRootNode( const XQNodePtr contentRootNode )
|
||||
void XQModelSection::setContentRootNode( const XQNodePtr contentRootNode ) const
|
||||
{
|
||||
_contentRootNode = contentRootNode;
|
||||
}
|
||||
@@ -80,7 +80,7 @@ void XQModelSection::setContentRootNode( const XQNodePtr contentRootNode )
|
||||
|
||||
//! gibt die zeile des start-index zurück.
|
||||
|
||||
int XQModelSection::XQModelSection::row() const
|
||||
int XQModelSection::XQModelSection::firstRow() const
|
||||
{
|
||||
return _modelIndex.row();
|
||||
}
|
||||
@@ -104,89 +104,98 @@ XQItem& XQModelSection::XQModelSection::headerItem() const
|
||||
|
||||
//! testet, ob die unter 'sectionKey' eine gültige section vorhanden ist.
|
||||
|
||||
bool XQModelSectionList::hasValidSection(const QString& sectionKey) const
|
||||
bool XQSectionManager::hasValidSection(const QString& sectionKey) const
|
||||
{
|
||||
if (!contains(sectionKey) )
|
||||
if (!_sections.contains(sectionKey) )
|
||||
return false;
|
||||
return at(sectionKey).isValid();
|
||||
return _sections.at(sectionKey).isValid();
|
||||
}
|
||||
|
||||
|
||||
//! gibt für einen model index die 'zuständige' section zurück.
|
||||
|
||||
const XQModelSection& XQModelSectionList::sectionFromIndex( const QModelIndex& index ) const
|
||||
const XQModelSection& XQSectionManager::sectionByKey( const QString& sectionKey ) const
|
||||
{
|
||||
return sectionFromRow( index.row() );
|
||||
if( hasValidSection( sectionKey ) )
|
||||
return _sections.at(sectionKey);
|
||||
|
||||
static const XQModelSection s_DummySection;
|
||||
return s_DummySection;
|
||||
|
||||
}
|
||||
|
||||
|
||||
//! gibt für eine zeile die 'zuständige' section zurück: der bestand an section wird
|
||||
//! nach der passenden section durchsucht.
|
||||
|
||||
const XQModelSection& XQModelSectionList::sectionFromRow(int itemRow ) const
|
||||
const XQModelSection& XQSectionManager::sectionByRow(int itemRow ) const
|
||||
{
|
||||
|
||||
int i = size() - 1;
|
||||
int i = _sections.size() - 1;
|
||||
for (; i >= 0; --i)
|
||||
{
|
||||
if ( at(i).modelIndex().row() < itemRow )
|
||||
return at(i);
|
||||
if ( _sections.at(i).startIndex().row() < itemRow )
|
||||
return _sections.at(i);
|
||||
}
|
||||
|
||||
static XQModelSection s_DummySection;
|
||||
|
||||
return s_DummySection;
|
||||
|
||||
}
|
||||
|
||||
|
||||
//! ermittelt die erste zeile einer section.
|
||||
|
||||
int XQModelSectionList::firstRow(const QModelIndex& idx) const
|
||||
const XQModelSection& XQSectionManager::createSection(const QString& sectionKey, const QModelIndex& modelIndex, XQNodePtr sheetNode)
|
||||
{
|
||||
return sectionFromRow(idx.row() ).row();
|
||||
// 6. jetzt können wir auch die sction erzeugen
|
||||
XQModelSection section(modelIndex, sheetNode );
|
||||
_sections.addAtKey( sectionKey, section);
|
||||
return sectionByKey(sectionKey);
|
||||
}
|
||||
|
||||
|
||||
//! ermittelt die zeile unterhalb des gegebenen modelindex,
|
||||
//! zum einfügen neuer items ebendort.
|
||||
|
||||
int XQModelSectionList::lastRow(const QModelIndex& idx) const
|
||||
/*
|
||||
int XQSectionManager::lastRow(const QModelIndex& idx) const
|
||||
{
|
||||
return lastRow(sectionFromRow(idx.row()));
|
||||
return lastRow(sectionByRow(idx.row()));
|
||||
}
|
||||
|
||||
|
||||
//! ermittelt die zeile unterhalb der gegebenen section,
|
||||
//! zum einfügen neuer items ebendort.
|
||||
*/
|
||||
|
||||
int XQModelSectionList::lastRow(const XQModelSection& section ) const
|
||||
int XQSectionManager::lastRow(const XQModelSection& section ) const
|
||||
{
|
||||
//qDebug() << " -- last row in section: " << section.modelIndex.data().toString() << " --> " << section.modelIndex.row();
|
||||
qDebug() << " -- last row in section: " << section.startIndex().data().toString() << " --> " << section.startIndex().row();
|
||||
// row() der section unterhalb dieser
|
||||
// __fix? index mit speichern?
|
||||
int index = indexOf(section);
|
||||
int index = _sections.indexOf(section);
|
||||
if (index > -1)
|
||||
{
|
||||
// last section? return last row of model
|
||||
if (index == size() - 1)
|
||||
return section.modelIndex().model()->rowCount();// - 1;
|
||||
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 at(index+1).row();
|
||||
return _sections.at(index+1).firstRow() - 1;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
XQSectionRange XQSectionManager::sectionRange(const XQModelSection& section ) const
|
||||
{
|
||||
qDebug() << " ---- Section RANGE: " << section.startIndex().row() << " -> " << lastRow(section);
|
||||
return XQSectionRange{ section.startIndex().row(), lastRow(section) };
|
||||
}
|
||||
|
||||
|
||||
//! gibt alle sections aus, zum ankucken.
|
||||
|
||||
void XQModelSectionList::dump() const
|
||||
void XQSectionManager::dump() const
|
||||
{
|
||||
qDebug() << " --- sections dump(): " <<size() << " entries.";
|
||||
for( int i = 0; i<size(); ++i )
|
||||
qDebug() << " --- sections dump(): " <<_sections.size() << " entries.";
|
||||
for( int i = 0; i<_sections.size(); ++i )
|
||||
{
|
||||
QModelIndex idx = at(i).modelIndex();
|
||||
qDebug() << " --- sections:" << i << "row: " << idx.row() << " keyOf(i): " << keyOf(i) << " indexData: "<< idx.data().toString() << " itemData: " << XQItem::xqItemFromIndex(idx).data(Qt::DisplayRole).toString();
|
||||
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
|
||||
#define XQMODELSECTIONLIST_H
|
||||
#ifndef XQSECTIONMANAGER_H
|
||||
#define XQSECTIONMANAGER_H
|
||||
|
||||
#include <QPersistentModelIndex>
|
||||
|
||||
#include <xqmaptor.h>
|
||||
#include <xqitem.h>
|
||||
|
||||
/**
|
||||
* @brief Struct containing data for a header section
|
||||
*/
|
||||
|
||||
|
||||
|
||||
//! Daten zur beschreibung einer 'sektion' des models.
|
||||
|
||||
class XQModelSection
|
||||
{
|
||||
@@ -35,13 +36,13 @@ public:
|
||||
|
||||
bool operator==(const XQModelSection& other) const;
|
||||
bool isValid() const;
|
||||
int row() const;
|
||||
int firstRow() const;
|
||||
|
||||
const QModelIndex& modelIndex() const;
|
||||
QModelIndex startIndex() const;
|
||||
XQNodePtr sectionRootNode() const;
|
||||
XQNodePtr sheetRootNode() const;
|
||||
XQNodePtr contentRootNode() const;
|
||||
void setContentRootNode( const XQNodePtr dataRootNode );
|
||||
void setContentRootNode( const XQNodePtr dataRootNode ) const;
|
||||
|
||||
const QString& contentType() const;
|
||||
XQItem& headerItem() const;
|
||||
@@ -50,32 +51,42 @@ protected:
|
||||
|
||||
QPersistentModelIndex _modelIndex;
|
||||
|
||||
XQNodePtr _sectionRootNode{};
|
||||
XQNodePtr _contentRootNode{};
|
||||
mutable XQNodePtr _sectionRootNode{};
|
||||
mutable XQNodePtr _contentRootNode{};
|
||||
|
||||
};
|
||||
|
||||
Q_DECLARE_METATYPE(XQModelSection)
|
||||
|
||||
/**
|
||||
* @brief Maptor containing all header sections.
|
||||
*/
|
||||
//! Erste und letzte ziele einer XQModelSection
|
||||
struct XQSectionRange
|
||||
{
|
||||
int firstRow{-1};
|
||||
int lastRow{-1};
|
||||
};
|
||||
|
||||
class XQModelSectionList : public XQMaptor<XQModelSection>
|
||||
|
||||
//! struktur, die alle sections enthält
|
||||
|
||||
class XQSectionManager
|
||||
{
|
||||
public:
|
||||
|
||||
bool hasValidSection(const QString& sectionKey) const;
|
||||
|
||||
const XQModelSection& sectionFromRow( int row ) const;
|
||||
const XQModelSection& sectionFromIndex( const QModelIndex& index ) const;
|
||||
const XQModelSection& sectionByKey( const QString& sectionKey ) const;
|
||||
const XQModelSection& sectionByRow( int row ) const;
|
||||
|
||||
int firstRow(const QModelIndex& idx) const;
|
||||
int lastRow(const QModelIndex& idx) const;
|
||||
int lastRow(const XQModelSection& section) const;
|
||||
const XQModelSection& createSection(const QString& sectionKey, const QModelIndex& modelIndex, XQNodePtr sheetNode);
|
||||
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,18 +35,28 @@
|
||||
void showItemList( const XQItemList& list)
|
||||
{
|
||||
for(const auto& entry : list )
|
||||
qDebug() << " --- itemList: " << ((XQItem*)entry)->content();
|
||||
qDebug() << " --- itemList: " << entry->text();
|
||||
qDebug();
|
||||
}
|
||||
|
||||
|
||||
//! Konstruktur mit parent.
|
||||
//! Konstruktor mit parent.
|
||||
|
||||
XQViewModel::XQViewModel( QObject* parent )
|
||||
: QStandardItemModel{ parent }, _itemFactory{ XQItemFactory::instance() }
|
||||
{
|
||||
invisibleRootItem()->setData( "[rootItem]", Qt::DisplayRole );
|
||||
setItemPrototype( new XQItem );
|
||||
|
||||
// auf änderungen kann in den unterklassen reagiert werden
|
||||
connect(this, &QStandardItemModel::itemChanged, this, [this](QStandardItem *item)
|
||||
{
|
||||
XQItem* xqItem = static_cast<XQItem*>(item);
|
||||
emit xqItemChanged( *xqItem );
|
||||
});
|
||||
|
||||
|
||||
//qRegisterMetaType<XQItem>("XQItem");
|
||||
}
|
||||
|
||||
|
||||
@@ -59,7 +69,14 @@ const XQItem& XQViewModel::xqRootItem()
|
||||
// dynamisch über den ItemData Mechanismus wie in QStandardItem
|
||||
|
||||
return *static_cast<XQItem*>(invisibleRootItem());
|
||||
}
|
||||
|
||||
|
||||
//! Gibt den daten root node des models zurück.
|
||||
|
||||
XQNodePtr XQViewModel::contentRootNode()
|
||||
{
|
||||
return _contentRoot;
|
||||
}
|
||||
|
||||
|
||||
@@ -83,6 +100,16 @@ XQItem& XQViewModel::xqFirstItem(int row) const
|
||||
return *static_cast<XQItem*>( QStandardItemModel::item(row) );
|
||||
}
|
||||
|
||||
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
|
||||
//! nur die strukur erzeugt, keine inhalte.
|
||||
@@ -111,7 +138,7 @@ void XQViewModel::initModel(const QString& modelName)
|
||||
const XQNodePtr header = sectionNode->find_child_by_tag_name( c_Header );
|
||||
if( header )
|
||||
{
|
||||
XQItemList list = _itemFactory.makeRow( XQItemFactory::mHeader, header, nullptr );
|
||||
XQItemList list = _itemFactory.makeRow( header, nullptr );
|
||||
addSection(list, sectionNode );
|
||||
}
|
||||
}
|
||||
@@ -138,9 +165,9 @@ void XQViewModel::addSection(const XQItemList& list, const XQNodePtr& sectionNod
|
||||
// 5. das erzeugt dann auch valide indices
|
||||
appendRow(list);
|
||||
|
||||
const QString §ionKey = sectionNode->attribute(c_ContentType);
|
||||
// 6. jetzt können wir auch die sction erzeugen
|
||||
XQModelSection section(list[0]->index(), sectionNode );
|
||||
_sections.addAtKey(sectionNode->attribute( c_ContentType), section);
|
||||
const XQModelSection& section = _sections.createSection( sectionKey, list[0]->index(), sectionNode );
|
||||
|
||||
// ... und es der welt mitteilen.
|
||||
emit sectionCreated( section );
|
||||
@@ -148,6 +175,43 @@ void XQViewModel::addSection(const XQItemList& list, const XQNodePtr& sectionNod
|
||||
}
|
||||
|
||||
|
||||
//! SLOT, toggled die section mit dem 'sectionKey' (hier: contentType)
|
||||
|
||||
void XQViewModel::onToggleSection(const QString& sectionKey )
|
||||
{
|
||||
toggleSection( _sections.sectionByKey(sectionKey) );
|
||||
}
|
||||
|
||||
|
||||
//! toggled die gegebene model section.
|
||||
|
||||
void XQViewModel::toggleSection( const XQModelSection& section )
|
||||
{
|
||||
qDebug() << " --- toggleSection: " << section.contentType();
|
||||
if( section.isValid() && _treeTable )
|
||||
{
|
||||
XQSectionRange pos = _sections.sectionRange(section);
|
||||
//int fstRow = _sections.firstRow(index);
|
||||
//int lstRow = _sections.lastRow(index);
|
||||
//_treeTable->toggleRowsHidden(fstRow, lstRow);
|
||||
|
||||
// hier nicht!?
|
||||
//emit sectionToggled(section);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
//! SLOT als weiterleitung vom SIGNAL itemchanged
|
||||
|
||||
void XQViewModel::onItemChanged(XQItem* item )
|
||||
{
|
||||
qDebug() << " --- BASE item changed: " << item->text();
|
||||
|
||||
}
|
||||
*/
|
||||
|
||||
//! SLOT, der aufgerufen wird, wenn eine edit-action getriggert wurde.
|
||||
|
||||
void XQViewModel::onActionTriggered(QAction* action)
|
||||
@@ -195,35 +259,10 @@ void XQViewModel::onActionTriggered(QAction* action)
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
switch (command.commandType())
|
||||
{
|
||||
case XQCommand::cmdToggleSection:
|
||||
return cmdToggleSection( command.originIndex() );
|
||||
|
||||
case XQCommand::cmdCut:
|
||||
return cmdCut( command );
|
||||
|
||||
case XQCommand::cmdPaste:
|
||||
return cmdPaste( command );
|
||||
|
||||
case XQCommand::cmdNew:
|
||||
return cmdNew( command );
|
||||
|
||||
case XQCommand::cmdDelete:
|
||||
return cmdDelete( command );
|
||||
|
||||
case XQCommand::cmdMove:
|
||||
break;
|
||||
|
||||
default:
|
||||
qDebug() << " --- onCommandRedo: default: not handled: " << command.toString();
|
||||
}
|
||||
*/
|
||||
|
||||
//! führt die 'redo' action des gegebenen commnds aus.
|
||||
|
||||
void XQViewModel::onCommandRedo( XQCommand& command )
|
||||
void XQViewModel::onCommandRedo( const XQCommand& command )
|
||||
{
|
||||
static MemCallMap redoCalls
|
||||
{
|
||||
@@ -249,45 +288,10 @@ void XQViewModel::onCommandRedo( XQCommand& command )
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
try
|
||||
{
|
||||
switch (command.commandType())
|
||||
{
|
||||
case XQCommand::cmdToggleSection:
|
||||
return cmdToggleSection( command.originIndex() );
|
||||
break;
|
||||
|
||||
// undo Cut -> perform undoCut
|
||||
case XQCommand::cmdCut:
|
||||
return cmdCutUndo( command );
|
||||
|
||||
// undo Paste -> perform Cut
|
||||
case XQCommand::cmdPaste:
|
||||
return cmdPasteUndo( command );
|
||||
|
||||
// undo Move -> perform move back
|
||||
case XQCommand::cmdMove:
|
||||
// not yet implemented
|
||||
break;
|
||||
|
||||
// undo New -> perform Delete
|
||||
case XQCommand::cmdNew:
|
||||
cmdNewUndo( command );
|
||||
break;
|
||||
|
||||
// undo Delete -> perform New
|
||||
case XQCommand::cmdDelete:
|
||||
qDebug() << " --- onCommandUndo: delete: " << command.toString();
|
||||
return cmdDeleteUndo( command );
|
||||
|
||||
default:
|
||||
qDebug() << " --- onCommandUndo: default: not handled: " << command.toString();
|
||||
}
|
||||
*/
|
||||
//! führt die 'undo' action des gegebenen commnds aus.
|
||||
|
||||
void XQViewModel::onCommandUndo( XQCommand& command )
|
||||
void XQViewModel::onCommandUndo( const XQCommand& command )
|
||||
{
|
||||
qDebug() << " --- onCommandUndo: count: " << XQNode::s_Count;
|
||||
|
||||
@@ -319,7 +323,7 @@ void XQViewModel::onCommandUndo( XQCommand& command )
|
||||
|
||||
//! markierte knoten entfernen, 'command' enthält die liste
|
||||
|
||||
void XQViewModel::cmdCut( XQCommand& command )
|
||||
void XQViewModel::cmdCut( const XQCommand& command )
|
||||
{
|
||||
// wir gehen rückwärts über alle gemerkten knoten ...
|
||||
for (auto it = command.rbegin(); it != command.rend(); ++it)
|
||||
@@ -340,19 +344,19 @@ void XQViewModel::cmdCut( XQCommand& command )
|
||||
|
||||
//! entfernte knoten wieder einfügen , 'command' enthält die liste
|
||||
|
||||
void XQViewModel::cmdCutUndo( XQCommand& command )
|
||||
void XQViewModel::cmdCutUndo( const XQCommand& command )
|
||||
{
|
||||
// die anfangsposition
|
||||
int itmPos = command.first().itemPos;
|
||||
// die 'zuständige' section rausfinden
|
||||
const XQModelSection& section = _sections.sectionFromRow( itmPos );
|
||||
const XQModelSection& section = _sections.sectionByRow( itmPos );
|
||||
// über alle einträge ...
|
||||
for (auto& entry : command )
|
||||
{
|
||||
const XQNodePtr& savedNode = entry.contentNode;
|
||||
// __fix! should not be _contentRoot!
|
||||
savedNode->add_me_at( entry.nodePos, _contentRoot );
|
||||
XQItemList list = _itemFactory.makeRow( XQItemFactory::mData, section.sheetRootNode(), savedNode );
|
||||
XQItemList list = _itemFactory.makeRow( section.sheetRootNode(), savedNode );
|
||||
|
||||
XQItem& firstItem = *((XQItem*)list[0]);
|
||||
qDebug() << " --- Cut Undo: " << firstItem.text() << " " << firstItem.row() << " id#" << entry.contentNode->_id << " count: " << entry.contentNode.use_count();
|
||||
@@ -364,7 +368,7 @@ void XQViewModel::cmdCutUndo( XQCommand& command )
|
||||
|
||||
//! clipboard inhalte einfügen
|
||||
|
||||
void XQViewModel::cmdPaste( XQCommand& command )
|
||||
void XQViewModel::cmdPaste( const XQCommand& command )
|
||||
{
|
||||
// selection holen ...
|
||||
QItemSelectionModel* selectionModel = treeTable()->selectionModel();
|
||||
@@ -379,7 +383,7 @@ void XQViewModel::cmdPaste( XQCommand& command )
|
||||
int nodePos = item.contentNode()->own_pos()+1;
|
||||
|
||||
// die zugehörige section finden
|
||||
const XQModelSection& section = _sections.sectionFromRow( insRow-1 );
|
||||
const XQModelSection& section = _sections.sectionByRow( insRow-1 );
|
||||
// wir pasten das clipboard
|
||||
for (auto& entry : _clipBoard )
|
||||
{
|
||||
@@ -388,7 +392,7 @@ void XQViewModel::cmdPaste( XQCommand& command )
|
||||
// ... diesen einfügen ...
|
||||
newNode->add_me_at( nodePos );
|
||||
// ... 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 );
|
||||
// die neue item-row selektieren
|
||||
const QModelIndex& selIdx = list[0]->index();
|
||||
@@ -399,14 +403,16 @@ void XQViewModel::cmdPaste( XQCommand& command )
|
||||
}
|
||||
|
||||
// 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
|
||||
|
||||
void XQViewModel::cmdPasteUndo( XQCommand& command )
|
||||
void XQViewModel::cmdPasteUndo( const XQCommand& command )
|
||||
{
|
||||
command.dumpList("Paste UNDO");
|
||||
// wir gehen rückwärts über alle markieren knoten ...
|
||||
@@ -427,7 +433,7 @@ void XQViewModel::cmdPasteUndo( XQCommand& command )
|
||||
|
||||
//! entfernen der selection ohne copy in clipboard.
|
||||
|
||||
void XQViewModel::cmdDelete( XQCommand& command )
|
||||
void XQViewModel::cmdDelete( const XQCommand& command )
|
||||
{
|
||||
// wir gehen rückwärts über alle markieren knoten ...
|
||||
for (auto it = command.rbegin(); it != command.rend(); ++it)
|
||||
@@ -442,9 +448,9 @@ void XQViewModel::cmdDelete( XQCommand& command )
|
||||
}
|
||||
}
|
||||
|
||||
//! macht 'delete' wirder rückgängig.
|
||||
//! macht 'delete' wieder rückgängig.
|
||||
|
||||
void XQViewModel::cmdDeleteUndo( XQCommand& command )
|
||||
void XQViewModel::cmdDeleteUndo( const XQCommand& command )
|
||||
{
|
||||
|
||||
}
|
||||
@@ -452,66 +458,55 @@ void XQViewModel::cmdDeleteUndo( XQCommand& command )
|
||||
|
||||
//! legt eine neue, leere zeile an.
|
||||
|
||||
void XQViewModel::cmdNew( XQCommand& command )
|
||||
void XQViewModel::cmdNew( const XQCommand& command )
|
||||
{
|
||||
|
||||
// __fix
|
||||
/*
|
||||
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
|
||||
XQNodePtr node = target->contentNode();
|
||||
|
||||
// we create a new data node
|
||||
//XQNodePtr newNode = new XQNodePtr( node->tag_name(), node->parent() );
|
||||
XQNodePtr newNode = XQNode::make_node( node->tag_name(), node->tag_value(), node->parent() );
|
||||
XQNodePtr node = target.contentNode();
|
||||
// we create a new data node
|
||||
XQNodePtr newNode = XQNode::make_node( node->tag_name(), node->tag_value() );
|
||||
// store node in node->parent()
|
||||
//node->add_before_me( newNode );
|
||||
// store node also in 'command' to enable undo
|
||||
const XQModelSection& section = _sections.sectionFromIndex( origin );
|
||||
newNode->add_me_at( node->own_pos(), node->parent() );
|
||||
|
||||
// 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 );
|
||||
// ... 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.
|
||||
|
||||
void XQViewModel::cmdNewUndo( XQCommand& command )
|
||||
void XQViewModel::cmdNewUndo( const XQCommand& command )
|
||||
{
|
||||
cmdDelete( command );
|
||||
}
|
||||
|
||||
|
||||
//! schaltet eine section sichtbar oder unsichtbar.
|
||||
|
||||
void XQViewModel::cmdToggleSection( XQCommand& command )
|
||||
void XQViewModel::cmdToggleSection( const XQCommand& command )
|
||||
{
|
||||
const QModelIndex& index = command.originIndex();
|
||||
Q_ASSERT(index.isValid());
|
||||
|
||||
int fstRow = _sections.firstRow( index );
|
||||
int lstRow = _sections.lastRow( index );
|
||||
|
||||
bool hidden =_treeTable->isRowHidden( fstRow, _treeTable->rootIndex() );
|
||||
for (int row = fstRow; row < lstRow; ++row )
|
||||
_treeTable->setRowHidden( row, _treeTable->rootIndex(), !hidden );
|
||||
|
||||
emit sectionToggled( _sections.sectionFromIndex(index) );
|
||||
toggleSection( _sections.sectionByRow(index.row()) );
|
||||
}
|
||||
|
||||
|
||||
//! git die treetable zurück
|
||||
//! gibt die treetable zurück
|
||||
|
||||
XQTreeTable* XQViewModel::treeTable()
|
||||
{
|
||||
@@ -524,7 +519,7 @@ void XQViewModel::setTreeTable(XQTreeTable* mainView )
|
||||
{
|
||||
// store view for direct access: the maintree
|
||||
_treeTable = mainView;
|
||||
// connect myself as model to the mainview
|
||||
// set myself as model to the mainview
|
||||
_treeTable->setModel(this);
|
||||
XQItemDelegate* delegate = new XQItemDelegate( *this );
|
||||
_treeTable->setItemDelegate( delegate );
|
||||
|
@@ -19,9 +19,10 @@
|
||||
#include <QMenu>
|
||||
#include <QStandardItemModel>
|
||||
#include <QAbstractItemView>
|
||||
#include <QtQmlIntegration>
|
||||
|
||||
#include <xqsimpleclipboard.h>
|
||||
#include <xqmodelsectionlist.h>
|
||||
#include <xqsectionmanager.h>
|
||||
#include <xqitemfactory.h>
|
||||
#include <xqcontextmenu.h>
|
||||
|
||||
@@ -36,12 +37,15 @@ class XQCommand;
|
||||
class XQViewModel : public QStandardItemModel
|
||||
{
|
||||
Q_OBJECT
|
||||
QML_ELEMENT
|
||||
|
||||
public:
|
||||
|
||||
XQViewModel(QObject* parent = nullptr);
|
||||
virtual ~XQViewModel() = default;
|
||||
|
||||
QHash<int, QByteArray> roleNames() const override;
|
||||
|
||||
XQTreeTable* treeTable();
|
||||
virtual void setTreeTable( XQTreeTable* mainView );
|
||||
|
||||
@@ -50,78 +54,65 @@ public:
|
||||
|
||||
virtual void initModel( const QString& modelName);
|
||||
|
||||
void expandNewItem(const QModelIndex& index);
|
||||
void toggleSection( const XQModelSection& section );
|
||||
|
||||
//little helpers
|
||||
const XQItem& xqRootItem();
|
||||
XQNodePtr contentRootNode();
|
||||
|
||||
XQItem& xqItemFromIndex(const QModelIndex& index) const;
|
||||
XQItem& xqFirstItem(int row) const;
|
||||
|
||||
// undo-/redo-able stuff
|
||||
|
||||
virtual void cmdToggleSection( XQCommand& command );
|
||||
virtual void cmdCut( XQCommand& command );
|
||||
virtual void cmdCutUndo( XQCommand& command );
|
||||
virtual void cmdPaste( XQCommand& command );
|
||||
virtual void cmdPasteUndo( XQCommand& command );
|
||||
virtual void cmdDelete( XQCommand& command );
|
||||
virtual void cmdDeleteUndo( XQCommand& command );
|
||||
virtual void cmdNew( XQCommand& command );
|
||||
virtual void cmdNewUndo( XQCommand& command );
|
||||
virtual void cmdToggleSection( const XQCommand& command );
|
||||
virtual void cmdCut( const XQCommand& command );
|
||||
virtual void cmdCutUndo( const XQCommand& command );
|
||||
virtual void cmdPaste( const XQCommand& command );
|
||||
virtual void cmdPasteUndo( const XQCommand& command );
|
||||
virtual void cmdDelete( const XQCommand& command );
|
||||
virtual void cmdDeleteUndo( const XQCommand& command );
|
||||
virtual void cmdNew( const XQCommand& command );
|
||||
virtual void cmdNewUndo( const XQCommand& command );
|
||||
|
||||
QHash<int, QByteArray> roleNames() const override;
|
||||
// Derzeit wird die default-implementierung von data/setData genutzt. hier wäre dann die
|
||||
// Stelle um setData & data an externe 'handler' umzubiegen, siehe giovannies 'model-injection'
|
||||
|
||||
/*!
|
||||
signals:
|
||||
|
||||
Derzeit wird die default-implementierung von data/setData genutzt. hier wäre dann die
|
||||
Stelle um setData & data an externe 'handler' umzubiegen, siehe giovannies 'model-injection'
|
||||
|
||||
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 );
|
||||
}
|
||||
|
||||
*/
|
||||
void xqItemChanged( const XQItem& item );
|
||||
void itemCreated( XQItem* newItem );
|
||||
void sectionCreated( const XQModelSection& section );
|
||||
void sectionToggled( const XQModelSection& section );
|
||||
|
||||
public slots:
|
||||
|
||||
virtual void onShowContextMenu(const QPoint& point);
|
||||
virtual void onActionTriggered(QAction* action);
|
||||
|
||||
virtual void onToggleSection(const QString& sectionKey );
|
||||
// handle XQCommands ( == UndoCommand )
|
||||
virtual void onCommandRedo( XQCommand& command );
|
||||
virtual void onCommandUndo( XQCommand& command );
|
||||
|
||||
signals:
|
||||
|
||||
void itemCreated( XQItem* newItem );
|
||||
void sectionCreated( const XQModelSection& section );
|
||||
void sectionToggled( const XQModelSection& section );
|
||||
virtual void onCommandRedo( const XQCommand& command );
|
||||
virtual void onCommandUndo( const XQCommand& command );
|
||||
|
||||
protected:
|
||||
|
||||
void addSection(const XQItemList& list, const XQNodePtr& sheetNode );
|
||||
virtual void initContextMenu() = 0;
|
||||
|
||||
// __fixme: should be created from xml
|
||||
virtual void setupViewProperties();
|
||||
|
||||
protected:
|
||||
|
||||
using MemCall = void (XQViewModel::*)(XQCommand&);
|
||||
using MemCall = void (XQViewModel::*)(const XQCommand&);
|
||||
using MemCallMap = QMap<XQCommand::CmdType,MemCall>;
|
||||
|
||||
// das eine reference auf ein globales singleton
|
||||
XQItemFactory& _itemFactory;
|
||||
XQSimpleClipBoard _clipBoard;
|
||||
XQModelSectionList _sections;
|
||||
XQItemFactory& _itemFactory;
|
||||
XQSimpleClipBoard _clipBoard;
|
||||
XQSectionManager _sections;
|
||||
|
||||
XQTreeTable* _treeTable{};
|
||||
XQTreeTable* _treeTable{};
|
||||
//QAbstractItemView* _treeTable{};
|
||||
QUndoStack* _undoStack{};
|
||||
XQContextMenu* _contextMenu{};
|
||||
|
@@ -78,6 +78,7 @@ namespace znode
|
||||
zweak_node _parent;
|
||||
znode_list _children;
|
||||
|
||||
// functor, der auf pointer gleichheit prüft.
|
||||
struct match_node
|
||||
{
|
||||
match_node( zbasic_node* match )
|
||||
@@ -95,9 +96,11 @@ namespace znode
|
||||
public:
|
||||
|
||||
//! 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
|
||||
@@ -136,7 +139,7 @@ namespace znode
|
||||
zbasic_node(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& operator=(zbasic_node&&) noexcept = default;
|
||||
|
||||
@@ -178,31 +181,31 @@ namespace znode
|
||||
return _parent.lock();
|
||||
}
|
||||
|
||||
//! gibt den nachfolge-knoten oder 'end()' zurück.
|
||||
zshared_node sibling()
|
||||
{
|
||||
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() );
|
||||
if( ++it != childs.end())
|
||||
if( parent() )
|
||||
{
|
||||
znode_list& childs = _parent->_children;
|
||||
auto it = std::find( childs.begin(), childs.end(), this->shared_from_this() );
|
||||
return *(it);
|
||||
|
||||
//return zshared_node( make_node("WTF?") );
|
||||
return zshared_node();
|
||||
}
|
||||
throw std::runtime_error("sibling(): no parent node");
|
||||
}
|
||||
|
||||
//! gibt den vector mit kind-knoten zurück
|
||||
inline const znode_list& children() const
|
||||
{
|
||||
return _children;
|
||||
}
|
||||
|
||||
//! testet, ob kinder vorhanden sind.
|
||||
bool has_children() const
|
||||
{
|
||||
return !children().empty();
|
||||
}
|
||||
|
||||
//! gibt das erste kind zurück
|
||||
zshared_node first_child()
|
||||
{
|
||||
if(!children().empty())
|
||||
@@ -210,6 +213,7 @@ namespace znode
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
//! gibt das letzte kind oder nullptr zurück
|
||||
zshared_node last_child()
|
||||
{
|
||||
if(!children().empty())
|
||||
@@ -237,7 +241,6 @@ namespace znode
|
||||
int add_child_at( int idx, const zshared_node& node )
|
||||
{
|
||||
// _fixme! was ist, wenn da schon ein elternknoten ist?
|
||||
|
||||
_children.insert(children().begin() + idx, node );
|
||||
node->_parent = this->shared_from_this();
|
||||
return int(children().size() - 1);
|
||||
@@ -250,10 +253,9 @@ namespace znode
|
||||
parent()->add_child_at( offset, this->shared_from_this() );
|
||||
else
|
||||
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.
|
||||
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");
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
//! findet die eigene position im eltern-knoten
|
||||
int own_pos()
|
||||
{
|
||||
if( parent())
|
||||
return parent()->child_pos( this->shared_from_this() );
|
||||
return -1;
|
||||
|
||||
}
|
||||
|
||||
//int child_pos(zbasic_node* child)
|
||||
//! findet die postion eines kind-knotens
|
||||
int child_pos(const zshared_node& child)
|
||||
{
|
||||
//auto pos = std::find_if(children().begin(), children().end(), match_node(child) );
|
||||
@@ -287,7 +288,7 @@ namespace znode
|
||||
return -1;
|
||||
}
|
||||
|
||||
//zshared_node unlink_child( zbasic_node* node )
|
||||
//! findet die postion eines kind-knotens
|
||||
zshared_node unlink_child( const zshared_node& node )
|
||||
{
|
||||
auto it = std::find(_children.begin(), _children.end(), node);
|
||||
@@ -315,11 +316,10 @@ namespace znode
|
||||
{
|
||||
for( auto child : _children )
|
||||
{
|
||||
qDebug() << " --#- " << child->name() << " : " << child->has_attribute( attrkey, attrvalue );
|
||||
if( child->has_attribute( attrkey, attrvalue ))
|
||||
return child;
|
||||
}
|
||||
return zshared_node();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
//
|
||||
@@ -330,7 +330,7 @@ namespace znode
|
||||
if( child->tag_name() == tagname )
|
||||
return child;
|
||||
}
|
||||
return zshared_node();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
zshared_node find_child_by_id( int id )
|
||||
@@ -340,46 +340,7 @@ namespace znode
|
||||
if (child->_id == id)
|
||||
return child;
|
||||
}
|
||||
return zshared_node();
|
||||
}
|
||||
|
||||
|
||||
|
||||
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;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// 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
|
||||
|
||||
|
||||
|
@@ -100,7 +100,7 @@ namespace znode
|
||||
//parent->add_child( new_node );
|
||||
|
||||
//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 );
|
||||
|
||||
if( !xml_node.attributes().empty() )
|
||||
|
@@ -73,6 +73,16 @@ public:
|
||||
return _data.end();
|
||||
}
|
||||
|
||||
auto begin() const
|
||||
{
|
||||
return _data.begin();
|
||||
}
|
||||
|
||||
auto end() const
|
||||
{
|
||||
return _data.end();
|
||||
}
|
||||
|
||||
inline int size() const
|
||||
{
|
||||
return (int) _data.size();
|
||||
@@ -94,13 +104,11 @@ public:
|
||||
return mapIndex().contains(key);
|
||||
}
|
||||
|
||||
|
||||
inline const XQMapIndex& mapIndex() const
|
||||
{
|
||||
return _index;
|
||||
}
|
||||
|
||||
|
||||
int indexOf( const QString& key ) const
|
||||
{
|
||||
return mapIndex().indexOf(key);
|
||||
@@ -121,7 +129,6 @@ public:
|
||||
return mapIndex().key( index );
|
||||
}
|
||||
|
||||
|
||||
T& operator[]( int index )
|
||||
{
|
||||
if( contains(index) )
|
||||
@@ -129,7 +136,6 @@ public:
|
||||
throw XQException("XQMaptor operator[ int index ]: out of range");
|
||||
}
|
||||
|
||||
|
||||
const T& operator[]( int index ) const
|
||||
{
|
||||
if ( contains(index) )
|
||||
@@ -154,7 +160,6 @@ public:
|
||||
return _data[ _index[key] ];
|
||||
}
|
||||
|
||||
|
||||
const T& operator[]( const QString& key ) const
|
||||
{
|
||||
if (key.isEmpty() || !contains(key))
|
||||
@@ -162,7 +167,6 @@ public:
|
||||
return _data[_index[key]];
|
||||
}
|
||||
|
||||
|
||||
T& at( const QString& key )
|
||||
{
|
||||
return (*this)[key];
|
||||
@@ -179,7 +183,6 @@ public:
|
||||
return _data.size()-1;
|
||||
}
|
||||
|
||||
|
||||
virtual void addAtIndex( int index, const T& item )
|
||||
{
|
||||
if(contains(index))
|
||||
@@ -187,14 +190,12 @@ public:
|
||||
_data[index] = item;
|
||||
}
|
||||
|
||||
|
||||
// convenience method to mimic QMap<T,QString>
|
||||
virtual void insert( const T& item, const QString& key )
|
||||
{
|
||||
addAtKey(key, item );
|
||||
}
|
||||
|
||||
|
||||
virtual void addAtKey( const QString& key, const T& item )
|
||||
{
|
||||
XQMapIndex::iterator pos = _index.find( key );
|
||||
@@ -209,7 +210,6 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool addAlias( const QString& key, const QString& alias )
|
||||
{
|
||||
// look for 'original' key
|
||||
@@ -227,20 +227,17 @@ public:
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void addKey( const QString& key, int index )
|
||||
{
|
||||
_index.addKey( key, index );
|
||||
}
|
||||
|
||||
|
||||
virtual void clear()
|
||||
{
|
||||
_data.clear();
|
||||
_index.clear();
|
||||
}
|
||||
|
||||
|
||||
virtual bool killEntry( const QString& key )
|
||||
{
|
||||
int idx = indexOf( key );
|
||||
@@ -249,7 +246,6 @@ public:
|
||||
return killEntry( (int) idx );
|
||||
}
|
||||
|
||||
|
||||
virtual bool killEntry( int index )
|
||||
{
|
||||
if( index >= this->_data.size() )
|
||||
@@ -261,19 +257,16 @@ public:
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
virtual QString toString() const
|
||||
{
|
||||
return join( ";" );
|
||||
}
|
||||
|
||||
|
||||
virtual void dump() const
|
||||
{
|
||||
throw XQException("XQMaptor: dump not implemented!" );
|
||||
}
|
||||
|
||||
|
||||
virtual QString join( const QString& sep, int from=0, int to=-1) const
|
||||
{
|
||||
Q_UNUSED(sep)
|
||||
@@ -283,7 +276,6 @@ public:
|
||||
return "--";
|
||||
}
|
||||
|
||||
|
||||
int replaceKey( const QString& oldkey, const QString& newkey )
|
||||
{
|
||||
int idx = indexOf( oldkey );
|
||||
|
@@ -31,7 +31,7 @@ void XQContextMenu::addAction(const QString& text, XQCommand::CmdType commandTyp
|
||||
QAction* newAction = new QAction(text, this);
|
||||
newAction->setData(commandType);
|
||||
_actionMap[commandType] = newAction;
|
||||
QWidget::addAction(newAction);
|
||||
QMenu::addAction(newAction);
|
||||
setActionEnabled( commandType, enabled );
|
||||
}
|
||||
|
||||
@@ -53,7 +53,7 @@ void XQContextMenu::addAction(const QIcon& icon, const QString& text, XQCommand:
|
||||
QAction* newAction = new QAction(icon, text, this);
|
||||
newAction->setData(commandType);
|
||||
_actionMap[commandType] = newAction;
|
||||
QWidget::addAction(newAction);
|
||||
QMenu::addAction(newAction);
|
||||
setActionEnabled( commandType, enabled );
|
||||
}
|
||||
|
||||
|
@@ -14,7 +14,7 @@
|
||||
|
||||
#include <xqquickwidget.h>
|
||||
|
||||
XQQuickWidget::XQQuickWidget(QWidget *parent)
|
||||
XQQuickWidget::XQQuickWidget(QWidget* parent)
|
||||
: QQuickWidget(parent)
|
||||
{
|
||||
|
||||
|
@@ -23,7 +23,7 @@ class XQQuickWidget : public QQuickWidget
|
||||
|
||||
public:
|
||||
|
||||
XQQuickWidget(QWidget *parent = nullptr);
|
||||
XQQuickWidget(QWidget* parent = nullptr);
|
||||
};
|
||||
|
||||
#endif // XQQUICKWIDGET_H
|
||||
|
@@ -51,6 +51,12 @@ XQItem& XQTreeTable::xqItemFromIndex(const QModelIndex& index )
|
||||
return modelView()->xqItemFromIndex( index );
|
||||
}
|
||||
|
||||
void XQTreeTable::toggleRowsHidden( int fstRow, int lstRow )
|
||||
{
|
||||
bool hidden = isRowHidden( fstRow, rootIndex() );
|
||||
for (int row = fstRow; row < lstRow; ++row )
|
||||
setRowHidden( row, rootIndex(), !hidden );
|
||||
}
|
||||
|
||||
//! override von 'currentChanged' (noch nicht implementiert)
|
||||
|
||||
|
@@ -41,6 +41,8 @@ public:
|
||||
XQViewModel* modelView();
|
||||
XQItem& xqItemFromIndex(const QModelIndex& index );
|
||||
|
||||
void toggleRowsHidden(int fstRow, int lstRow );
|
||||
|
||||
protected:
|
||||
|
||||
void currentChanged(const QModelIndex& current, const QModelIndex& previous) override;
|
||||
|
@@ -1,7 +1,10 @@
|
||||
QT += core gui widgets quick quickwidgets
|
||||
# widgets-private
|
||||
|
||||
CONFIG += c++20
|
||||
CONFIG += c++20 qmltypes
|
||||
|
||||
QML_IMPORT_NAME = org.sourceworx.qmlcomponents
|
||||
QML_IMPORT_MAJOR_VERSION = 1
|
||||
|
||||
# You can make your code fail to compile if it uses deprecated APIs.
|
||||
# In order to do so, uncomment the following line.
|
||||
@@ -20,9 +23,9 @@ HEADERS += \
|
||||
items/xqitemtype.h \
|
||||
items/xqitemdelegate.h \
|
||||
model/xqcommand.h \
|
||||
model/xqmodelsectionlist.h \
|
||||
model/xqnode.h \
|
||||
model/xqnodewriter.h \
|
||||
model/xqsectionmanager.h \
|
||||
model/xqselectionmodel.h \
|
||||
model/xqsimpleclipboard.h \
|
||||
model/xqviewmodel.h \
|
||||
@@ -58,9 +61,9 @@ SOURCES += \
|
||||
items/xqitemdelegate.cpp \
|
||||
main.cpp \
|
||||
model/xqcommand.cpp \
|
||||
model/xqmodelsectionlist.cpp \
|
||||
model/xqnode.cpp \
|
||||
model/xqnodewriter.cpp \
|
||||
model/xqsectionmanager.cpp \
|
||||
model/xqselectionmodel.cpp \
|
||||
model/xqsimpleclipboard.cpp \
|
||||
model/xqviewmodel.cpp \
|
||||
|
@@ -1,10 +1,14 @@
|
||||
<RCC>
|
||||
<qresource prefix="/">
|
||||
<file alias="modeldata1.xtr">../xml/modeldata1.xtr</file>
|
||||
<file alias="modeldata2.xtr">../xml/modeldata2.xtr</file>
|
||||
<file alias="modeldata3.xtr">../xml/modeldata3.xtr</file>
|
||||
<file alias="modelsheet.xml">../xml/modelsheets.xml</file>
|
||||
<file alias="quickview.qml">../quick/quickview.qml</file>
|
||||
|
||||
</qresource>
|
||||
</RCC>
|
||||
<qresource prefix="/">
|
||||
<file alias="modeldata1.xtr">../xml/modeldata1.xtr</file>
|
||||
<file alias="modeldata2.xtr">../xml/modeldata2.xtr</file>
|
||||
<file alias="modeldata3.xtr">../xml/modeldata3.xtr</file>
|
||||
<file alias="modelsheet.xml">../xml/modelsheets.xml</file>
|
||||
<file alias="xqtableview.qml">../qml/xqtableview.qml</file>
|
||||
<file alias="HorizontalHeaderViewDelegate.qml">../qml/HorizontalHeaderViewDelegate.qml</file>
|
||||
<file alias="XMain.qml">../qml/XMain.qml</file>
|
||||
<file alias="VerticalHeaderViewDelegate.qml">../qml/VerticalHeaderViewDelegate.qml</file>
|
||||
<file alias="dummyview.qml">../qml/dummyview.qml</file>
|
||||
<file alias="xqtreeview.qml">../qml/xqtreeview.qml</file>
|
||||
</qresource>
|
||||
</RCC>
|
@@ -7,18 +7,18 @@
|
||||
-->
|
||||
|
||||
<ItemTypes>
|
||||
<TreeParentType RenderStyle="PlainStyle" ItemFlags="IsEnabled|IsDropEnabled" Icon="DirIcon" />
|
||||
<TreeSectionType RenderStyle="PlainStyle" ItemFlags="IsEnabled" Icon="DesktopIcon"/>
|
||||
<TreeChildType RenderStyle="PlainStyle" ItemFlags="IsUserCheckable|IsEnabled" Icon="MediaPlay"/>
|
||||
<HeaderType RenderStyle="HeaderStyle" ItemFlags="IsEnabled"/>
|
||||
<TreeParentType RenderStyle="PlainStyle" EditorType="LineEditType" ItemFlags="IsEnabled|IsDropEnabled" Icon="DirIcon" />
|
||||
<TreeChildType RenderStyle="PlainStyle" EditorType="LineEditType" ItemFlags="IsEnabled" Icon="MediaPlay"/>
|
||||
<TreeSectionType RenderStyle="PlainStyle" EditorType="LineEditType" ItemFlags="IsUserCheckable|IsEnabled" Icon="DesktopIcon"/>
|
||||
<HeaderType RenderStyle="HeaderStyle" EditorType="LineEditType" ItemFlags="IsEnabled"/>
|
||||
<HiddenType RenderStyle="HiddenStyle"/>
|
||||
<StaticType RenderStyle="PlainStyle"/>
|
||||
<PlainType RenderStyle="PlainStyle" ItemFlags="IsEnabled|IsEditable|IsSelectable"/>
|
||||
<ValueType RenderStyle="FormattedStyle" ItemFlags="IsEnabled|IsEditable|IsSelectable" UnitType="Coulomb"/>
|
||||
<CheckableType RenderStyle="FormattedStyle" ItemFlags="IsEnabled|IsEditable|IsSelectable" UnitType="###"/>
|
||||
<PercentageType RenderStyle="ProgressBarStyle" ItemFlags="IsEnabled|IsSelectable"/>
|
||||
<ChoiceType RenderStyle="ComboBoxStyle" ItemFlags="IsEnabled|IsSelectable|IsEditable" FixedChoices="la|le|lo|lu"/>
|
||||
<IntValueType RenderStyle="SpinBoxStyle" ItemFlags="IsEnabled|IsSelectable"/>
|
||||
<PlainType RenderStyle="PlainStyle" EditorType="LineEditType" ItemFlags="IsEnabled|IsEditable|IsSelectable"/>
|
||||
<ValueType RenderStyle="FormattedStyle" EditorType="LineEditType" ItemFlags="IsEnabled|IsEditable|IsSelectable" UnitType="Coulomb"/>
|
||||
<CheckableType RenderStyle="FormattedStyle" EditorType="LineEditType" ItemFlags="IsEnabled|IsEditable|IsSelectable" UnitType="###"/>
|
||||
<PercentageType RenderStyle="ProgressBarStyle" EditorType="LineEditType" ItemFlags="IsEnabled|IsSelectable"/>
|
||||
<ChoiceType RenderStyle="ComboBoxStyle" EditorType="ComboBoxType" ItemFlags="IsEnabled|IsSelectable|IsEditable" FixedChoices="la|le|lo|lu"/>
|
||||
<IntValueType RenderStyle="SpinBoxStyle" EditorType="SpinBoxType" ItemFlags="IsEnabled|IsSelectable"/>
|
||||
</ItemTypes>
|
||||
|
||||
|
||||
@@ -75,7 +75,7 @@
|
||||
<!-- 'Icon' überschreibt den default wert im ItemType und erzeugt damit einen neuen ItemType-->
|
||||
<PanelID ItemType="PlainType" Icon="DesktopIcon"/>
|
||||
<PanelName ItemType="PlainType" Icon="BrowserStop"/>
|
||||
<Manufacturer ItemType="ValueType"/>
|
||||
<Manufacturer ItemType="PlainType"/>
|
||||
<!-- 'UnitType' überschreibt den default wert im ItemType und erzeugt damit einen neuen ItemType-->
|
||||
<WattPeak ItemType="ValueType" UnitType="Wp"/>
|
||||
<Width ItemType="CheckableType" Icon="VistaShield" UnitType="m"/>
|
||||
@@ -98,20 +98,20 @@
|
||||
<Weight Caption="Weight" ItemType="HeaderType" />
|
||||
</Header>
|
||||
<ModelSheet>
|
||||
<InverterID Caption="Inverter" ItemType="ValueType" />
|
||||
<InverterName Caption="Name" ItemType="ValueType" />
|
||||
<Manufacturer Caption="Manufacturer" ItemType="ValueType" />
|
||||
<InverterID Caption="Inverter" ItemType="PlainType" />
|
||||
<InverterName Caption="Name" ItemType="PlainType" />
|
||||
<Manufacturer Caption="Manufacturer" ItemType="PlainType" />
|
||||
<MaxPowerInput Caption="max. Input" ItemType="ValueType" ItemType="ChoiceType" ChoiceModelSheetSource="MaxPowerInputChoice" UnitType="W"/>
|
||||
<MaxPowerOutput Caption="max Output" ItemType="ValueType" UnitType="W"/>
|
||||
<NumStrings Caption="Strings" ItemType="ValueType" />
|
||||
<NumStrings Caption="Strings" ItemType="PlainType" />
|
||||
<Weight Caption="Weight" ItemType="ValueType" UnitType="kg"/>
|
||||
</ModelSheet>
|
||||
</Section>
|
||||
|
||||
<Section ContentType="Battery" >
|
||||
<Header>
|
||||
<BatteryID Caption="Name" ItemType="HeaderType" />
|
||||
<BatteryName Caption="Battery" ItemType="HeaderType" />
|
||||
<BatteryID Caption="Battery" ItemType="HeaderType" />
|
||||
<BatteryName Caption="Name" ItemType="HeaderType" />
|
||||
<Manufacturer Caption="Manufacturer" ItemType="HeaderType" />
|
||||
<Capacity Caption="Capacity" ItemType="HeaderType"/>
|
||||
<Yield Caption="Yield" ItemType="HeaderType" />
|
||||
@@ -119,9 +119,9 @@
|
||||
<MaxVolt Caption="max. Volt" ItemType="HeaderType" />
|
||||
</Header>
|
||||
<ModelSheet>
|
||||
<BatteryID Caption="Battery" ItemType="ValueType" />
|
||||
<BatteryName Caption="Name" ItemType="ValueType" />
|
||||
<Manufacturer Caption="Manufacturer" ItemType="ValueType" />
|
||||
<BatteryID Caption="Battery" ItemType="PlainType" />
|
||||
<BatteryName Caption="Name" ItemType="PlainType" />
|
||||
<Manufacturer Caption="Manufacturer" ItemType="PlainType" />
|
||||
<Capacity Caption="Capacity" ItemType="ValueType" UnitType="Wh"/>
|
||||
<Yield Caption="Yield" ItemType="ValueType" ItemType="PercentageType" UnitType="%"/>
|
||||
<MaxCurrent Caption="max. Current" ItemType="ValueType" UnitType="A"/>
|
||||
|
@@ -1,27 +1,24 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Project Established="2006" FriendlyName="@ProjectName" ProjectID="HA01" ProjectName="Wiebelbach West" State="runnning" WattPeak="84000">
|
||||
<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="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="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 6" MaxAmpere="11" MaxVolt="42" PanelID="#6 JA 06" PanelName="JA 06 Solar X58C" WattPeak="440" Weight="12" Width="1,10"/>
|
||||
<Inverter FriendlyName="@InverterName" InverterID="#1 HM600 01" InverterName="01 HM600 S2 TMax" Manufacturer="HoyMiles" MaxPowerInput="2000" MaxPowerInputChoice="2000;4000;6000" MaxPowerOutput="600" NumStrings="2" Weight="28"/>
|
||||
<Inverter FriendlyName="@InverterName" InverterID="#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="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="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">
|
||||
<AdditionalData DataItem="Image" DataValue="image.png"/>
|
||||
<AdditionalData DataItem="Manual" DataValue="manual.docx"/>
|
||||
<AdditionalData DataItem="Certificate" DataValue="certificate.pdf"/>
|
||||
</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="#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="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="#6 GroWatt 06 G4K" BatteryName="06 BYD T02 Stackable" Capacity="9000" FriendlyName="@BatteryName" Manufacturer="GroWatt" MaxCurrent="120" MaxVolt="48" Yield="49"/>
|
||||
<Battery BatteryID="#7 Pyne 07 G4K" BatteryName="07 Pyne K7 Stackable" Capacity="9000" FriendlyName="@BatteryName" Manufacturer="PyNe" MaxCurrent="120" MaxVolt="48" Yield="49"/>
|
||||
</Components>
|
||||
<IrgendWasAnderes/>
|
||||
</Project>
|
||||
<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="1,70" Manufacturer="JA Solar 2" MaxAmpere="11" MaxVolt="42" PanelID="#2 JA 02" PanelName="maa" WattPeak="440" Weight="12" Width="1,10"/>
|
||||
<Panel FriendlyName="@PanelName" Height="2,70" Manufacturer="JA Solar 3" MaxAmpere="11" MaxVolt="67" PanelID="#3 JA 03" PanelName="JA 03 Solar T62B" WattPeak="620" Weight="12" Width="1,10"/>
|
||||
<Panel FriendlyName="@PanelName" Height="1,70" Manufacturer="JA Solar 4" MaxAmpere="11" MaxVolt="42" PanelID="#4 JA 04" PanelName="moo" WattPeak="440" Weight="12" Width="1,10"/>
|
||||
<Panel FriendlyName="@PanelName" Height="1,70" Manufacturer="JA Solar 5" MaxAmpere="11" MaxVolt="42" PanelID="#5 JA 05" PanelName="JA 05 Solar X58C" WattPeak="440" Weight="12" Width="1,10"/>
|
||||
<Panel FriendlyName="@PanelName" Height="1,70" Manufacturer="JA Solar 6" MaxAmpere="11" MaxVolt="42" PanelID="#6 JA 06" PanelName="JA 06 Solar X58C" WattPeak="440" Weight="12" Width="1,10"/>
|
||||
<Inverter FriendlyName="@InverterName" InverterID="#1 HM600 01" InverterName="01 HM600 S2 TMax" Manufacturer="HoyMiles" MaxPowerInput="2000" MaxPowerInputChoice="2000;4000;6000" MaxPowerOutput="600" NumStrings="2" Weight="28"/>
|
||||
<Inverter FriendlyName="@InverterName" InverterID="#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="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="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">
|
||||
<AdditionalData DataItem="Image" DataValue="image.png"/>
|
||||
<AdditionalData DataItem="Manual" DataValue="manual.docx"/>
|
||||
<AdditionalData DataItem="Certificate" DataValue="certificate.pdf"/>
|
||||
</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="#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="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="#6 GroWatt 06 G4K" BatteryName="06 BYD T02 Stackable" Capacity="9000" FriendlyName="@BatteryName" Manufacturer="GroWatt" MaxCurrent="120" MaxVolt="48" Yield="49"/>
|
||||
<Battery BatteryID="#7 Pyne 07 G4K" BatteryName="07 Pyne K7 Stackable" Capacity="9000" FriendlyName="@BatteryName" Manufacturer="PyNe" MaxCurrent="120" MaxVolt="48" Yield="49"/>
|
||||
</Components>
|
||||
|
Reference in New Issue
Block a user