first re-commit.

This commit is contained in:
2025-08-05 22:39:41 +02:00
commit 87de9c1f33
73 changed files with 23249 additions and 0 deletions

14
.gitignore vendored Normal file
View File

@@ -0,0 +1,14 @@
x64*
Userschris*
xtree.pro.user*
.vs
debug/
release/
enc_temp_folder/
ui_*
*autosave
doc/~$ree_thoughts.docx
doc/~WRL0004.tmp
UsersC998D~1.HOLAppDataLocalTemptmpj0mbo3rd
xml/fitzefatz.xml
build*

58
README.md Normal file
View File

@@ -0,0 +1,58 @@
# XTree
## Also, noch mal von vorn:
- Es geht um das Editieren von XML Daten in einer baumartigen Darstellung am Bildschirm.
- Es handelt sich vorwiegend um technische Daten: Strom, Spannung, unterschiedliche Betriebsparameter und sowas.
- Die Qt Viewerklassen arbeiten feldbasiert, die Datenfelder heissen 'Items', die Basisklasse zu einem Datenfeld heisst bei uns ```XQItem```
- Unser Darstellung der Datenfelder ist im Prinzip erstmal tabellenartig, bla blu
- Die QtLib unterscheidet zwischen 'rendering' und 'editing'
- bla blub
Also: itemtypes werden einfach beschrieben, mit properties, wie die properties intern implementiert werden, ist erstmal
egal: ein type sheet
pattern: model-view-controller
qt: model-view
wir: modelhub _only_
--
ein ItemType aggregiert gemeinsame Eigenschaften von Items, z.b. UnitType, EditorType, RenderTypezusammen, die ein Gruppe von Items gemeinsam
# Old stuff:
## Getting started
Das working directory muss aufs source directory zeigen, da liegen unter xml/
die Testfiles.
## Wo ich hinwill
- [ ] Alle models, menus etc. sollen in XML beschrieben werden, siehe xml/modelsheet.xml
- [ ] Es gibt nur eine Modelklasse: XQModel (ist ein QStandardItemModel)
- [ ] Datenlogik und Anwendungslogik sollen getrennt sein
- [ ] Dazu werden die Datenknoten (composites) in einen Wrapper verpackt und in den Items 'versteckt'
- [ ] Für jede Editorklasse XyzEditor.cpp gibt es eine Klasse XyzHub.cpp
- [ ] Im XyzHub wird die Anwendungslogik implementiert, d.h. die SIGNALs der UI werden mit Operationen auf das Model verbunden
- [ ] Operationen auf Datenknoten werden für die Anwendung transparent von der Datenschicht ausgeführt
- [ ] Die genaue Implementierung dafür ist mir noch unklar:
- [ ] ```ZQNode::nodeManager.applyCommand( ZQCommand( ZQ::PasteNode, ZQNode& ) )``` ???
## Basisklassen
- [ ] ```znode::zbasic_node<string_type>``` Knotenabstraction, vgl. ```std::basic_string<char_t>```
- [ ] ```ZQNode``` template-Instanziierung von zbasic_node mit QString
- [ ] ```XQModel``` ein QStandardItemModel mit ZQItems
- [ ] ```XQItem``` ein QStandardItem mit einem XQNodeWrapper
- [ ] (Sauberer wäre ein eigenes Model aus einem QAbstractItemModel, aber das ist dann wirklich Arbeit ...)
- [ ] ```XQNodeWrapper``` verpackt einen ZQNode* und vermittelt dessen Attributes an die ViewItems
- [ ] ```XQNodeManager``` operations on nodes, gibts noch nicht.
- [ ] Eigentlich ```znode::znode_manager<zbasic_node<string_type>...> ...``` für alle Anwendungsfälle
- [ ] ```XQModelReader``` erzeugt QModels aus XML, siehe XML/modelsheet.xml
- [ ] ```XQModelHub``` Datenmanager-Klasse, hier läuft alles zusammen
- [ ] ```class XQModelHub : public XQModel, public XQModelReader```: etwas fragwürdig, spart aber leidige Verpointerungen

153
application/xqappdata.cpp Normal file
View File

@@ -0,0 +1,153 @@
/***************************************************************************
source::worx xtree
Copyright © 2024-2025 c.holzheuer
christoph.holzheuer@gmail.com
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
***************************************************************************/
#include <xqappdata.h>
#include <QDebug>
#include <QApplication>
#include <QStyle>
#include <QIcon>
#include <QMap>
#include <QMetaEnum>
#include <QPushButton>
namespace XQAppData
{
template<typename E>
constexpr auto to_underlying(E e) noexcept
{
return static_cast<std::underlying_type_t<E>>(e);
}
class XQAppIconMap : public QMap<QString,QIcon>
{
public:
void init()
{
auto from = to_underlying(QIcon::ThemeIcon::AddressBookNew);
auto to = to_underlying(QIcon::ThemeIcon::NThemeIcons);
for (auto i = from; i < to; ++i)
{
QIcon::ThemeIcon f = static_cast<QIcon::ThemeIcon>(i);
QIcon icon = QIcon::fromTheme(f);
// Nur hinzufügen, wenn das Icon existiert
if (!icon.isNull())
insert(icon.name(), icon);
}
}
};
static XQAppIconMap s_IconMap;
bool hasTypeIcon(const QString& key )
{
if(s_IconMap.isEmpty())
s_IconMap.init();
return !key.isEmpty() && s_IconMap.contains(key);
}
QIcon typeIcon(const QString& key )
{
if( hasTypeIcon(key) )
return s_IconMap[key];
return QApplication::style()->standardIcon(QStyle::SP_TrashIcon);
}
/*
{ "icnFolder" , QApplication::style()->standardIcon(QStyle::SP_DirIcon) },
{ "icnFolder" , QApplication::style()->standardIcon(QStyle::SP_DirIcon)},
{ "icn02Dummy", QApplication::style()->standardIcon(QStyle::SP_FileDialogBack)},
{ "icn03Dummy", QApplication::style()->standardIcon(QStyle::SP_FileDialogContentsView)},
{ "icn04Dummy", QApplication::style()->standardIcon(QStyle::SP_FileDialogDetailedView)},
{ "icn05Dummy", QApplication::style()->standardIcon(QStyle::SP_FileDialogEnd)},
{ "icn06Dummy", QApplication::style()->standardIcon(QStyle::SP_FileDialogInfoView)},
{ "icn07Dummy", QApplication::style()->standardIcon(QStyle::SP_FileDialogListView)},
{ "icn08Dummy", QApplication::style()->standardIcon(QStyle::SP_FileDialogNewFolder)},
{ "icn09Dummy", QApplication::style()->standardIcon(QStyle::SP_FileDialogStart)},
{ "icn10Dummy", QApplication::style()->standardIcon(QStyle::SP_FileDialogToParent)},
{ "icn11Dummy", QApplication::style()->standardIcon(QStyle::SP_ArrowBack)},
{ "icn12Dummy", QApplication::style()->standardIcon(QStyle::SP_DirIcon)},
{ "icn13Dummy", QApplication::style()->standardIcon(QStyle::SP_MediaSkipBackward)},
{ "icn14Dummy", QApplication::style()->standardIcon(QStyle::SP_ArrowDown)},
{ "icn15Dummy", QApplication::style()->standardIcon(QStyle::SP_DirLinkIcon)},
{ "icn16Dummy", QApplication::style()->standardIcon(QStyle::SP_MediaSkipForward)},
{ "icn17Dummy", QApplication::style()->standardIcon(QStyle::SP_ArrowForward)},
{ "icn18Dummy", QApplication::style()->standardIcon(QStyle::SP_DirOpenIcon)},
{ "icn19Dummy", QApplication::style()->standardIcon(QStyle::SP_MediaStop)},
{ "icn20Dummy", QApplication::style()->standardIcon(QStyle::SP_ArrowLeft)},
{ "icn21Dummy", QApplication::style()->standardIcon(QStyle::SP_DockWidgetCloseButton)},
{ "icn22Dummy", QApplication::style()->standardIcon(QStyle::SP_MediaVolume)},
{ "icn23Dummy", QApplication::style()->standardIcon(QStyle::SP_ArrowRight)},
{ "icn24Dummy", QApplication::style()->standardIcon(QStyle::SP_DriveCDIcon)},
{ "icn25Dummy", QApplication::style()->standardIcon(QStyle::SP_MediaVolumeMuted)},
{ "icn26Dummy", QApplication::style()->standardIcon(QStyle::SP_ArrowUp)},
{ "icn27Dummy", QApplication::style()->standardIcon(QStyle::SP_DriveDVDIcon)},
{ "icn28Dummy", QApplication::style()->standardIcon(QStyle::SP_MessageBoxCritical)},
{ "icn29Dummy", QApplication::style()->standardIcon(QStyle::SP_BrowserReload)},
{ "icn30Dummy", QApplication::style()->standardIcon(QStyle::SP_DriveFDIcon)},
{ "icn31Dummy", QApplication::style()->standardIcon(QStyle::SP_MessageBoxInformation)},
{ "icn32Dummy", QApplication::style()->standardIcon(QStyle::SP_BrowserStop)},
{ "icn33Dummy", QApplication::style()->standardIcon(QStyle::SP_DriveHDIcon)},
{ "icn34Dummy", QApplication::style()->standardIcon(QStyle::SP_MessageBoxQuestion)},
{ "icn35Dummy", QApplication::style()->standardIcon(QStyle::SP_CommandLink)},
{ "icn36Dummy", QApplication::style()->standardIcon(QStyle::SP_DriveNetIcon)},
{ "icn37Dummy", QApplication::style()->standardIcon(QStyle::SP_MessageBoxWarning)},
{ "icn38Dummy", QApplication::style()->standardIcon(QStyle::SP_ComputerIcon)},
{ "icn39Dummy", QApplication::style()->standardIcon(QStyle::SP_FileDialogBack)},
{ "icn40Dummy", QApplication::style()->standardIcon(QStyle::SP_TitleBarCloseButton)},
{ "icn41Dummy", QApplication::style()->standardIcon(QStyle::SP_CustomBase)},
{ "icn42Dummy", QApplication::style()->standardIcon(QStyle::SP_FileDialogContentsView)},
{ "icn43Dummy", QApplication::style()->standardIcon(QStyle::SP_TitleBarContextHelpButton)},
{ "icn44Dummy", QApplication::style()->standardIcon(QStyle::SP_DesktopIcon)},
{ "icn45Dummy", QApplication::style()->standardIcon(QStyle::SP_FileDialogDetailedView)},
{ "icn46Dummy", QApplication::style()->standardIcon(QStyle::SP_TitleBarMaxButton)},
{ "icn47Dummy", QApplication::style()->standardIcon(QStyle::SP_DialogApplyButton)},
{ "icn48Dummy", QApplication::style()->standardIcon(QStyle::SP_FileDialogEnd)},
{ "icn49Dummy", QApplication::style()->standardIcon(QStyle::SP_TitleBarMenuButton)},
{ "icn50Dummy", QApplication::style()->standardIcon(QStyle::SP_DialogCancelButton)},
{ "icn51Dummy", QApplication::style()->standardIcon(QStyle::SP_FileDialogInfoView)},
{ "icn52Dummy", QApplication::style()->standardIcon(QStyle::SP_TitleBarMinButton)},
{ "icn53Dummy", QApplication::style()->standardIcon(QStyle::SP_DialogCloseButton)},
{ "icn54Dummy", QApplication::style()->standardIcon(QStyle::SP_FileDialogListView)},
{ "icn55Dummy", QApplication::style()->standardIcon(QStyle::SP_TitleBarNormalButton)},
{ "icn56Dummy", QApplication::style()->standardIcon(QStyle::SP_DialogDiscardButton)},
{ "icn57Dummy", QApplication::style()->standardIcon(QStyle::SP_FileDialogNewFolder)},
{ "icn58Dummy", QApplication::style()->standardIcon(QStyle::SP_TitleBarShadeButton)},
{ "icn59Dummy", QApplication::style()->standardIcon(QStyle::SP_DialogHelpButton)},
{ "icn60Dummy", QApplication::style()->standardIcon(QStyle::SP_FileDialogStart)},
{ "icn61Dummy", QApplication::style()->standardIcon(QStyle::SP_TitleBarUnshadeButton)},
{ "icn62Dummy", QApplication::style()->standardIcon(QStyle::SP_DialogNoButton)},
{ "icn63Dummy", QApplication::style()->standardIcon(QStyle::SP_FileDialogToParent)},
{ "icn64Dummy", QApplication::style()->standardIcon(QStyle::SP_ToolBarHorizontalExtensionButton)},
{ "icn65Dummy", QApplication::style()->standardIcon(QStyle::SP_DialogOkButton)},
{ "icn66Dummy", QApplication::style()->standardIcon(QStyle::SP_FileIcon)},
{ "icn67Dummy", QApplication::style()->standardIcon(QStyle::SP_ToolBarVerticalExtensionButton)},
{ "icn68Dummy", QApplication::style()->standardIcon(QStyle::SP_DialogResetButton)},
{ "icn70Dummy", QApplication::style()->standardIcon(QStyle::SP_FileLinkIcon)},
{ "icn71Dummy", QApplication::style()->standardIcon(QStyle::SP_TrashIcon)},
{ "icn72Dummy", QApplication::style()->standardIcon(QStyle::SP_DialogSaveButton)},
{ "icn73Dummy", QApplication::style()->standardIcon(QStyle::SP_MediaPause)},
{ "icn74Dummy", QApplication::style()->standardIcon(QStyle::SP_VistaShield)},
{ "icn75Dummy", QApplication::style()->standardIcon(QStyle::SP_DialogYesButton)},
{ "icn76Dummy", QApplication::style()->standardIcon(QStyle::SP_MediaPlay)},
{ "icn77Dummy", QApplication::style()->standardIcon(QStyle::SP_DirClosedIcon)},
{ "icn79Dummy", QApplication::style()->standardIcon(QStyle::SP_MediaSeekBackward)},
{ "icn80Dummy", QApplication::style()->standardIcon(QStyle::SP_DirHomeIcon)},
{ "icn81Dummy", QApplication::style()->standardIcon(QStyle::SP_MediaSeekForward)}
}
*/
}; // namespace XQAppData

49
application/xqappdata.h Normal file
View File

@@ -0,0 +1,49 @@
/***************************************************************************
source::worx xtree
Copyright © 2024-2025 c.holzheuer
christoph.holzheuer@gmail.com
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
***************************************************************************/
#ifndef XQAPPDATA_H
#define XQAPPDATA_H
#include <qnamespace.h>
#include <QVariant>
#include <QMap>
#include <QStringView>
#include <QIcon>
#include <pugixml.hpp>
const QString c_Version = "0.1.1 04.09.2024";
const QString c_MainModelName = "DocumentTreeModel";
const QString c_ChildModelName = "DocumentDetailsModel";
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";
const QString c_FriendlyName = "FriendlyName";
namespace XQAppData
{
class XQAppIconMap;
bool hasTypeIcon(const QString& key );
QIcon typeIcon(const QString& key );
}
#endif // XQAPPDATA_H

View File

@@ -0,0 +1,150 @@
/***************************************************************************
source::worx xtree
Copyright © 2024-2025 c.holzheuer
christoph.holzheuer@gmail.com
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
***************************************************************************/
#include <znode_factory.h>
#include <xqchildmodel.h>
#include <xqselectionmodel.h>
#include <xqitemdelegate.h>
#include <xqappdata.h>
#include <xqtreeview.h>
#include <xqitemfactory.h>
XQChildModel::XQChildModel( QObject *parent )
: XQModel{parent}
{
}
XQChildModel::~XQChildModel()
{
}
/**
* @brief XQChildModel::initModel: Create the own modelstructure
* using subtree 'Components'
*/
void XQChildModel::initModel(const QString& modelName)
{
// #0: Wir suchen die Model-Beschreibung
XQNodePtr modelSheet = _itemFactory.findModelSheet( modelName ); // throws
// #1: Wie erzeugen die Model-Struktur: Jedes Kind beschreibt einen
// XML-Datentyp, z.B. <Panel atr1="..." />, <Battery .../>
// Jeder XML-Knoten entspricht einer Zeile im späteren Model, jedes
// Attribut wird einem eigenen Feld (XQItem) abgebildet.
for( auto& sheetNode : modelSheet->children() )
{
XQItemList list = _itemFactory.makeHeaderRow( sheetNode );
// für jeden XML-Knotentyp in der Modelbeschreibung erzeugen wir eine section
addSection(list, sheetNode );
/*
// empty row
XQNodePtr contentNode = XQNode::make_node( sheetNode->tag_name() );
XQItemList emptyRow = _itemFactory.makeEmptyRow( contentNode, sheetNode );
appendRow( emptyRow );
*/
} // for
}
void XQChildModel::setContent( const XQNodePtr& contentRoot )
{
// __fix: set object name ??
qDebug() << " --- create Model Data: " << contentRoot->to_string();
// Die Datenbasis als shared_ptr sichern
_contentRoot = contentRoot;
// Wir gehen über alle Einträge, die verschiedenen Typen
// haben, hier: <Panel>. <Battery> ...
for (const auto& contentEntry : _contentRoot->children())
{
// Das ist hier der Typ des Eintrags: Panel, Battery ...
QString key = contentEntry->tag_name();
// 'silent failure' hier der Datenbaum kann auch Knoten enthalten
// die nicht für uns gedacht sind.
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
section.contentRootNode = contentEntry->parent();
int newRow = _sections.lastRow(section);
qDebug() << " --- AHJA: " << key << " -- last Row dazu: " << newRow;
XQItemList list = _itemFactory.makeContentRow( contentEntry, section.sheetRootNode );
// als Baum?
//section.headerItem().appendRow( list );
insertRow( newRow, list);
} // for
}
void XQChildModel::createModelContentChildRow( QStandardItem* parent, XQNodePtr contentNode )
{
/*
parent->appendRow( { new XQItem("Optionals", XQItemType::HeaderStyle ), new XQItem( "Value", XQItemType::HeaderStyle )} );
for( auto& child : contentNode->children() )
{
XQItemList list;
list.append( new XQItem( child->attribute("DataItem"), XQItemType::StaticStyle ) );
list.append( new XQItem( child->attribute("DataValue"), XQItemType::StaticStyle ) );
parent->appendRow( list );
}
*/
}
void XQChildModel::initContextMenu()
{
// __fixme! add a menu title
_contextMenu->clear();
const QModelIndex& curIdx = _treeView->currentIndex();
bool hasSel = curIdx.isValid() && _treeView->selectionModel()->hasSelection();
bool canPaste = _clipBoard.canPaste( curIdx );
_contextMenu->addAction( "icn11Dummy", "Undo", XQCommand::cmdUndo, _undoStack->canUndo() );
_contextMenu->addAction( "icn17Dummy", "Redo", XQCommand::cmdRedo, _undoStack->canRedo() );
_contextMenu->addAction( "icn58Dummy", "Cut", XQCommand::cmdCut, hasSel );
_contextMenu->addAction( "icn61Dummy", "Paste", XQCommand::cmdPaste, canPaste );
_contextMenu->addAction( "icn55Dummy", "Copy", XQCommand::cmdCopy, hasSel );
//_contextMenu->addAction( "icn35Dummy", "Move", XQCommand::cmdMove, hasSel );
_contextMenu->addAction( "icn70Dummy", "New", XQCommand::cmdNew, hasSel );
_contextMenu->addAction( "icn50Dummy", "Delete", XQCommand::cmdDelete, hasSel );
// __fixme! set 'toggle section <name>' entry
//contextMenu.actions().first()->setText("<name>");
_contextMenu->addAction( "icn29Dummy", "Toggle Section", XQCommand::cmdToggleSection, hasSel);
}

View File

@@ -0,0 +1,44 @@
/***************************************************************************
source::worx xtree
Copyright © 2024-2025 c.holzheuer
christoph.holzheuer@gmail.com
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
***************************************************************************/
#ifndef XQCHILDMODEL_H
#define XQCHILDMODEL_H
#include <xqmodel.h>
class XQChildModel : public XQModel
{
Q_OBJECT
public:
explicit XQChildModel(QObject *parent = nullptr);
virtual ~XQChildModel();
void initModel(const QString& modelName) override;
void setContent(const XQNodePtr& contentRoot );
protected:
virtual void createModelContentChildRow(QStandardItem* parent, XQNodePtr contentNode );
//void setupViewProperties() override;
void initContextMenu() override;
};
#endif // XQCHILDMODEL_H

View File

@@ -0,0 +1,58 @@
/***************************************************************************
source::worx xtree
Copyright © 2024-2025 c.holzheuer
christoph.holzheuer@gmail.com
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
***************************************************************************/
#include <xqdocumentstore.h>
#include <xqitem.h>
#include <QFile>
XQDocument::XQDocument(const QString& aFileName, const QString& aFriendlyName, XQItem* aTreeItem, XQModel* aModelView )
: fileName{ aFileName }, friendlyName{ aFriendlyName }, treeItem{ aTreeItem }, modelView{ aModelView }
{
}
XQDocument::~XQDocument()
{
//delete _documentRoot;
}
///
/// ---
///
XQDocumentStore::~XQDocumentStore()
{
//for (auto entry : *this)
// delete entry;
//for( int i=0; i<size();++i)
// delete at(i);
}
void XQDocumentStore::addDocument( const QString& aFileName, const QString& aFriendlyName, XQItem* aTreeItem, XQModel* aModelView )
{
XQDocument newDocument( aFileName, aFriendlyName, aTreeItem,aModelView );
addAtKey( aFileName, newDocument );
// attention: this assumes the presence of the 'ProjectID' value
//addAlias( aFileName, aTreeItem->attribute(c_ProjectID) );
//addAlias( aFileName, "fitze!" );
}

View File

@@ -0,0 +1,57 @@
/***************************************************************************
source::worx xtree
Copyright © 2024-2025 c.holzheuer
christoph.holzheuer@gmail.com
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
***************************************************************************/
#ifndef XQDOCUMENTSTORE_H
#define XQDOCUMENTSTORE_H
#include <xqmaptor.h>
#include <xqnode.h>
class XQModel;
class XQItem;
// should this be internal??
struct XQDocument
{
XQDocument() = default;
XQDocument( const QString& aFileName, const QString& aFriendlyName, XQItem* aTreeItem, XQModel* aModelView );
virtual ~XQDocument();
QString fileName; // also used as key
QString friendlyName;
XQItem* treeItem{};
XQModel* modelView{};
};
class XQDocumentStore : public XQMaptor<XQDocument>
{
public:
XQDocumentStore() = default;
virtual ~ XQDocumentStore();
void addDocument( const QString& aFileName, const QString& aFriendlyName, XQItem* aTreeItem, XQModel* aModelView );
protected:
XQNode _treeRootNode{ "treeRootNode" };
};
#endif // XQDOCUMENTSTORE_H

View File

@@ -0,0 +1,83 @@
/***************************************************************************
source::worx xtree
Copyright © 2024-2025 c.holzheuer
christoph.holzheuer@gmail.com
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
***************************************************************************/
#include <QPersistentModelIndex>
#include <QClipboard>
#include <xqmainmodel.h>
#include <xqexception.h>
#include <xqtreeview.h>
#include <xqitemdelegate.h>
#include <xqitem.h>
#include <xqappdata.h>
#include <xqselectionmodel.h>
#include <xqitemfactory.h>
XQMainModel::XQMainModel(QObject *parent )
: XQModel{parent}
{
}
XQMainModel::~XQMainModel()
{
// delete
}
void XQMainModel::initModel(const QString& modelName)
{
XQNodePtr modelSheet = _itemFactory.findModelSheet( modelName );
// #1: create structure: create static sections for this model
for( auto& sheetNode : modelSheet->children() )
{
qDebug() << " create main model: " << sheetNode->tag_name();
XQItemList list = { _itemFactory.makeHeaderItem( sheetNode ) };
Q_ASSERT(!list.isEmpty());
addSection(list, sheetNode );
//appendRow( list );
}
}
XQItem* XQMainModel::createTreeEntry( XQNodePtr contentNode )
{
for(const auto& section : _sections )
{
if( contentNode->attribute("State") == section.sheetRootNode->attribute("State") )
{
XQItem* newTreeentry = _itemFactory.makeContentItem( contentNode, section.sheetRootNode );
section.headerItem().appendRow( newTreeentry );
_treeView->expand( section.modelIndex );
// ??
_treeView->setCurrentIndex( section.modelIndex );
newTreeentry->setContentNode(contentNode);
emit xqItemCreated( newTreeentry );
return newTreeentry;
}
}
throw XQException( "createTreeEntry: main model should not be emtpy!" );
}
void XQMainModel::initContextMenu()
{
}

47
application/xqmainmodel.h Normal file
View File

@@ -0,0 +1,47 @@
/***************************************************************************
source::worx xtree
Copyright © 2024-2025 c.holzheuer
christoph.holzheuer@gmail.com
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
***************************************************************************/
#ifndef XQMAINMODEL_H
#define XQMAINMODEL_H
//#include <QItemSelectionModel>
#include <xqmodel.h>
//#include <xqmodelsections.h>
class XQTreeView;
class XQMainModel : public XQModel
{
Q_OBJECT
public:
explicit XQMainModel(QObject *parent = nullptr);
virtual ~XQMainModel();
void initModel(const QString& modelName) override;
XQItem* createTreeEntry( XQNodePtr contentNode );
public slots:
protected:
void initContextMenu() override;
};
#endif // XQMAINMODEL_H

View File

@@ -0,0 +1,285 @@
/***************************************************************************
source::worx xtree
Copyright © 2024-2025 c.holzheuer
christoph.holzheuer@gmail.com
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
***************************************************************************/
#include <QDebug>
#include <QFileDialog>
#include <QMessageBox>
#include <xqmainwindow.h>
#include <xqcommand.h>
#include <xqexception.h>
#include <xqitemfactory.h>
#include <xqnodewriter.h>
XQMainWindow::XQMainWindow( QWidget* parent )
: QMainWindow(parent)
{
setupUi(this);
setWindowTitle( QString("XTree %1").arg(c_Version));
initMainWindow();
}
void XQMainWindow::initMainWindow()
{
qDebug() << " --- initMainWindow(): here we go!";
// als allererstes laden wir die Modelschreibungen
XQItemFactory::instance().initItemFactory( c_ModelSheetFileName );
_undoView->setStack( &_undoStack );
_actionUndo->setData( XQCommand::cmdUndo);
_actionRedo->setData( XQCommand::cmdRedo);
_actionCut->setData( XQCommand::cmdCut);
_actionCopy->setData( XQCommand::cmdCopy);
_actionPaste->setData( XQCommand::cmdPaste);
_actionNew->setData( XQCommand::cmdNew);
_actionDelete->setData( XQCommand::cmdDelete);
connect( _actionUndo, &QAction::triggered, this, &XQMainWindow::onUndo );
connect( _actionRedo, &QAction::triggered, this, &XQMainWindow::onRedo );
connect( _actionOpen, &QAction::triggered, this, &XQMainWindow::onOpenDocument );
connect( _actionSave, &QAction::triggered, this, &XQMainWindow::onSaveDocument );
connect( _actionSaveAs, &QAction::triggered, this, &XQMainWindow::onSaveDocumentAs );
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( &_mainModelView, &XQModel::xqItemCreated, this, [=, this](XQItem* item)
{
// when a new main tree item has been created ...
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->treeView() );
} );
try
{
// hand over undostack
_mainModelView.setUndoStack(&_undoStack);
// hand over left side navigation tree
_mainModelView.setTreeView(_mainTreeView);
// #1. init the left side main tree view
_mainModelView.initModel( c_MainModelName );
// #2. load demo data
loadDocument( c_DocumentFileName1 );
//loadDocument( c_DocumentFileName2 );
qDebug() << " --- all here: " << XQNode::s_Count;
}
catch( XQException& exception )
{
qDebug() << exception.what();
QMessageBox::critical( this, "Failure", QString("Failure: %1").arg(exception.what()) );
}
}
void XQMainWindow::onUndo()
{
qDebug() << " --- undo Pressed";
if(_undoStack.canUndo())
_undoStack.undo();
}
void XQMainWindow::onRedo()
{
qDebug() << " --- redo Pressed";
if(_undoStack.canRedo())
_undoStack.redo();
}
void XQMainWindow::onCreateDocument()
{
qDebug() << " ---- create document Pressed!";
}
void XQMainWindow::onOpenDocument()
{
QString fileName = QFileDialog::getOpenFileName(this, tr("Open Project"), c_DocumentDirectory, tr("project data(*.xtr)") );
QFile file(fileName);
if (!file.open(QFile::ReadOnly | QFile::Text))
{
QMessageBox::warning(this, "Warning", "Cannot load file: " + file.errorString());
return;
}
// close dummy file ...
file.close();
loadDocument( fileName );
}
void XQMainWindow::onSaveDocument()
{
qDebug() << " ---- save Pressed!";
saveDocument( c_ModelDummyFileName );
}
void XQMainWindow::onSaveDocumentAs()
{
QString fileName = QFileDialog::getSaveFileName(this, "Save as", c_DocumentDirectory, tr("project data(*.xtr)") );
QFile file(fileName);
// open dummy file
if (!file.open(QFile::WriteOnly | QFile::Text))
{
QMessageBox::warning(this, "Warning", "Cannot save file: " + file.errorString());
return;
}
// close dummy file ...
file.close();
// and create a xml stream
saveDocument( fileName );
}
void XQMainWindow::onCloseDocument()
{
qDebug() << " ---- close Pressed!";
}
void XQMainWindow::onExit()
{
qApp->exit();
}
void XQMainWindow::onAbout()
{
QMessageBox msgBox(QMessageBox::NoIcon, "About", "", QMessageBox::Ok);
QString text = "<b>xtree concept</b><br>";
text += "2024 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
msgBox.setText( text );
msgBox.exec();
}
// when item in the left tree is clicked, switch view on the right side
void XQMainWindow::onTreeItemClicked(const QModelIndex& index )
{
XQItem& entry = XQItem::xqItemFromIndex(index);
qDebug() << " --- mainWindow onTreeItemClicked:" << entry.text();
return;
//_mainTreeView->selectionModel()->select(index, QItemSelectionModel::Select);
//entry->setBackground( QBrush( Qt::green ) );
QString key = entry.attribute(c_ProjectID);
if( _documentStore.contains(key) )
_tabWidget->setCurrentWidget( _documentStore[key].modelView->treeView() );
}
// when item in the left tree is clicked, switch view on the right side
void XQMainWindow::onTabClicked( int index )
{
const QString& key = _documentStore[index].treeItem->attribute( c_ProjectID );
qDebug() << " ---- tab clicked: " << index << " : " << _documentStore[index].friendlyName << ": " << key;
_mainTreeView->setCurrentIndex( _documentStore[index].treeItem->index() );
}
void XQMainWindow::loadDocument( const QString& fileName )
{
//ntThrowIfNullPtr
// gibts die Datei?
if( !QFile::exists( fileName) )
throw XQException( "no such file", fileName );
// load data tree from xml file
XQNodeFactory treeLoader;
XQNodePtr rawTree = treeLoader.load_tree( qPrintable(fileName) );
// versteckten root node ignorieren
XQNodePtr contentRoot = rawTree->first_child();
// Project-ID behandeln
const QString& pID = contentRoot->attribute(c_ProjectID);
int idx = _documentStore.indexOf( pID );
if( idx > -1 )
{
const XQDocument& doc = _documentStore.at(idx);
QMessageBox::warning( this, "Load Document", QString("File: %1 already loaded.").arg( fileName ) );
_mainTreeView->setCurrentIndex( doc.treeItem->index() );
_tabWidget->setCurrentIndex( idx );
return;
}
// '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 );
// Eine neue TreeView erzeugn und im TabWidget parken.
XQTreeView* childTreeView = new XQTreeView(_tabWidget);
_tabWidget->addTab( childTreeView, pTitle );
_tabWidget->setCurrentWidget( childTreeView );
setWindowTitle( pTitle );
// Ein neues Child-Model erzeugen
XQChildModel* childModel = new XQChildModel(this);
// die Modelstruktur anlegen
childModel->initModel( c_ChildModelName );
// Den globalen undo-stack ...
childModel->setUndoStack(&_undoStack);
// und die TreeView übergeben
childModel->setTreeView(childTreeView);
// read the model data
childModel->setContent( contentRoot->first_child() );
// create new entry in the left side main tree view
XQItem* newEntry = _mainModelView.createTreeEntry( contentRoot );
_mainTreeView->setCurrentIndex( newEntry->index() );
_documentStore.addDocument( fileName, pTitle, newEntry, childModel );
}
void XQMainWindow::saveDocument( const QString& fileName )
{
XQNodeWriter nodeWriter;
int curIdx = _tabWidget->currentIndex();
XQNodePtr rootNode = _documentStore[curIdx].treeItem->contentNode();
nodeWriter.dumpTree( rootNode, fileName );
}

View File

@@ -0,0 +1,67 @@
/***************************************************************************
source::worx xtree
Copyright © 2024-2025 c.holzheuer
christoph.holzheuer@gmail.com
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
***************************************************************************/
#ifndef XQMAINWINDOW_H
#define XQMAINWINDOW_H
#include <QMainWindow>
#include <ui_xqmainwindow.h>
#include <xqdocumentstore.h>
#include <xqmainmodel.h>
#include <xqchildmodel.h>
#include <xqappdata.h>
class XQMainWindow : public QMainWindow, public Ui_XQMainWindow
{
Q_OBJECT
public:
XQMainWindow( QWidget* parent = nullptr );
virtual ~XQMainWindow() = default;
void initMainWindow();
public slots:
void onUndo();
void onRedo();
void onCreateDocument();
void onOpenDocument();
void onSaveDocument();
void onSaveDocumentAs();
void onCloseDocument();
void onAbout();
void onExit();
void onTreeItemClicked(const QModelIndex& index );
void onTabClicked( int index );
protected:
// fixme implement
void showDocumnet( const QString& key ){}
void loadDocument( const QString& fileName );
void saveDocument( const QString& fileName );
QUndoStack _undoStack;
XQDocumentStore _documentStore;
XQMainModel _mainModelView;
};
#endif // XQMAINWINDOW_H

290
application/xqmainwindow.ui Normal file
View File

@@ -0,0 +1,290 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>XQMainWindow</class>
<widget class="QMainWindow" name="XQMainWindow">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>800</width>
<height>600</height>
</rect>
</property>
<property name="windowTitle">
<string>XTree</string>
</property>
<widget class="QWidget" name="_centralWidget">
<layout class="QVBoxLayout" name="verticalLayout_4">
<property name="spacing">
<number>0</number>
</property>
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>2</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QTabWidget" name="_tabWidget"/>
</item>
</layout>
</widget>
<widget class="QMenuBar" name="_menuBar">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>800</width>
<height>26</height>
</rect>
</property>
<widget class="QMenu" name="_fileMenu">
<property name="title">
<string>&amp;File</string>
</property>
<addaction name="separator"/>
<addaction name="_actionOpen"/>
<addaction name="_actionSave"/>
<addaction name="_actionSaveAs"/>
<addaction name="_actionExit"/>
</widget>
<widget class="QMenu" name="menuHelp">
<property name="title">
<string>Help</string>
</property>
<addaction name="_actionAbout"/>
</widget>
<widget class="QMenu" name="_menuEdit">
<property name="title">
<string>Edit</string>
</property>
<addaction name="_actionUndo"/>
<addaction name="_actionRedo"/>
<addaction name="separator"/>
<addaction name="_actionCut"/>
<addaction name="_actionPaste"/>
<addaction name="_actionCopy"/>
</widget>
<addaction name="_fileMenu"/>
<addaction name="_menuEdit"/>
<addaction name="menuHelp"/>
</widget>
<widget class="QStatusBar" name="_statusBar"/>
<widget class="QDockWidget" name="_treeDockWidget">
<property name="windowTitle">
<string>MainDocument</string>
</property>
<attribute name="dockWidgetArea">
<number>1</number>
</attribute>
<widget class="QWidget" name="_treeDockLayout">
<layout class="QVBoxLayout" name="verticalLayout">
<property name="spacing">
<number>0</number>
</property>
<property name="leftMargin">
<number>4</number>
</property>
<property name="topMargin">
<number>2</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="XQTreeView" name="_mainTreeView">
<property name="styleSheet">
<string notr="true"/>
</property>
<property name="frameShape">
<enum>QFrame::Shape::NoFrame</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Shadow::Plain</enum>
</property>
<property name="lineWidth">
<number>0</number>
</property>
</widget>
</item>
</layout>
</widget>
</widget>
<widget class="QDockWidget" name="_statusDock">
<property name="toolTipDuration">
<number>7</number>
</property>
<property name="windowTitle">
<string>Status</string>
</property>
<attribute name="dockWidgetArea">
<number>8</number>
</attribute>
<widget class="QWidget" name="_statusContent">
<layout class="QVBoxLayout" name="verticalLayout_2">
<property name="leftMargin">
<number>2</number>
</property>
<property name="topMargin">
<number>2</number>
</property>
<property name="rightMargin">
<number>2</number>
</property>
<property name="bottomMargin">
<number>2</number>
</property>
<item>
<widget class="QUndoView" name="_undoView">
<property name="frameShape">
<enum>QFrame::Shape::NoFrame</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Shadow::Plain</enum>
</property>
<property name="lineWidth">
<number>0</number>
</property>
</widget>
</item>
</layout>
</widget>
</widget>
<action name="_actionExit">
<property name="text">
<string>E&amp;xit</string>
</property>
<property name="shortcut">
<string>Ctrl+Q</string>
</property>
</action>
<action name="_actionCopy">
<property name="text">
<string>Copy</string>
</property>
<property name="shortcut">
<string>Ctrl+C</string>
</property>
</action>
<action name="_actionCut">
<property name="text">
<string>Cu&amp;t</string>
</property>
<property name="shortcut">
<string>Ctrl+X</string>
</property>
</action>
<action name="_actionNew">
<property name="text">
<string>New</string>
</property>
<property name="shortcut">
<string>Ctrl+N</string>
</property>
</action>
<action name="_actionPaste">
<property name="icon">
<iconset theme="audio-volume-high"/>
</property>
<property name="text">
<string>Paste</string>
</property>
<property name="shortcut">
<string>Ctrl+V</string>
</property>
</action>
<action name="_actionUndo">
<property name="text">
<string>Undo</string>
</property>
<property name="shortcut">
<string>Ctrl+Z</string>
</property>
</action>
<action name="_actionRedo">
<property name="text">
<string>Redo</string>
</property>
<property name="shortcut">
<string>Ctrl+Y</string>
</property>
</action>
<action name="_actionOpen">
<property name="text">
<string>Open</string>
</property>
<property name="shortcut">
<string>Ctrl+O</string>
</property>
</action>
<action name="actionCopyAsText">
<property name="text">
<string>Copy As Text</string>
</property>
<property name="menuRole">
<enum>QAction::MenuRole::NoRole</enum>
</property>
</action>
<action name="_actionDelete">
<property name="text">
<string>Delete</string>
</property>
<property name="menuRole">
<enum>QAction::MenuRole::NoRole</enum>
</property>
</action>
<action name="_actionFind">
<property name="text">
<string>Find</string>
</property>
<property name="menuRole">
<enum>QAction::MenuRole::NoRole</enum>
</property>
</action>
<action name="_actionSave">
<property name="text">
<string>Save</string>
</property>
<property name="toolTip">
<string>Save</string>
</property>
<property name="shortcut">
<string>Ctrl+S</string>
</property>
</action>
<action name="_actionSaveAs">
<property name="text">
<string>Save as ...</string>
</property>
<property name="toolTip">
<string>Save as ...</string>
</property>
<property name="shortcut">
<string>Ctrl+Alt+S</string>
</property>
</action>
<action name="_actionAbout">
<property name="text">
<string>About</string>
</property>
</action>
</widget>
<customwidgets>
<customwidget>
<class>XQTreeView</class>
<extends>QTreeView</extends>
<header location="global">xqtreeview.h</header>
</customwidget>
</customwidgets>
<resources/>
<connections/>
</ui>

BIN
doc/xtree_basics.docx Normal file

Binary file not shown.

15
items/xqgenericitem.cpp Normal file
View File

@@ -0,0 +1,15 @@
/***************************************************************************
source::worx xtree
Copyright © 2024-2025 c.holzheuer
christoph.holzheuer@gmail.com
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
***************************************************************************/
#include <xqgenericitem.h>

33
items/xqgenericitem.h Normal file
View File

@@ -0,0 +1,33 @@
/***************************************************************************
source::worx xtree
Copyright © 2024-2025 c.holzheuer
christoph.holzheuer@gmail.com
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
***************************************************************************/
#ifndef XQGENERICITEM_H
#define XQGENERICITEM_H
#include <xqitem.h>
//
// Was sollte das mal werden?
//
template<class T, class U>
class XQGenericItem : public XQItem, public T, public U
{
public:
XQGenericItem() = default;
};
#endif // XQGENERICITEM_H

595
items/xqitem.cpp Normal file
View File

@@ -0,0 +1,595 @@
/***************************************************************************
source::worx xtree
Copyright © 2024-2025 c.holzheuer
christoph.holzheuer@gmail.com
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
***************************************************************************/
#include <xqitem.h>
#include <xqmodel.h>
#include <xqmaptor.h>
#include <QDateTime>
#include <xqitemtype.h>
#include <QDebug>
XQItem::XQItemFlagMap XQItem::s_ItemFlagMap
{
{ "NoItemFlags", Qt::NoItemFlags },
{ "IsSelectable", Qt::ItemIsSelectable },
{ "IsEditable", Qt::ItemIsEditable },
{ "IsDragEnabled", Qt::ItemIsDragEnabled },
{ "IsDropEnabled", Qt::ItemIsDropEnabled },
{ "IsUserCheckable", Qt::ItemIsUserCheckable },
{ "IsEnabled", Qt::ItemIsEnabled },
{ "IsAutoTristate", Qt::ItemIsAutoTristate },
{ "ItemNeverHasChildren", Qt::ItemNeverHasChildren },
{ "IsUserTristate", Qt::ItemIsUserTristate }
};
XQItem::XQItemDataRoleMap XQItem::s_ItemDataRoleMap
{
{"ItemType", ItemTypeRole},
{"Content", ContentRole},
{"RenderStyle", RenderStyleRole},
{"EditorType", EditorTypeRole},
{"ItemFlags", FlagsRole},
{"UnitType", UnitTypeRole},
{"ContentFormat", ContentFormatRole},
{"FlagsRole", FlagsRole},
{"Icon", IconRole},
{"FixedChoices", FixedChoicesRole},
{"DataNode", ContentNodeRole},
{"SheetNode", SheetNodeRole}
};
// No bi-map needed here, qmap.key() is sufficient for the job
XQItem::XQRenderStyleMap XQItem::s_RenderStyleMap
{
{ "NoRenderStyle", NoRenderStyle },
{ "HiddenStyle", HiddenStyle },
{ "HeaderStyle", HeaderStyle },
{ "PlainStyle", PlainStyle },
{ "CheckBoxStyle", CheckBoxStyle },
{ "ComboBoxStyle", ComboBoxStyle },
{ "TreeHeaderStyle", TreeHeaderStyle },
{ "CustomRenderStyle", CustomRenderStyle },
{ "PickerStyle", PickerStyle },
{ "SpinBoxStyle", SpinBoxStyle },
{ "ProgressBarStyle", ProgressBarStyle},
{ "FormattedStyle", FormattedStyle},
};
XQItem::XQEditorTypeMap XQItem::s_EditorTypeMap
{
{ "NoEditorType", NoEditorType },
{ "LineEditType", LineEditType },
{ "ComboBoxType", ComboBoxType },
{ "PickerType", PickerType },
{ "ProgressBarType", ProgressBarType },
{ "SpinBoxType", SpinBoxType},
{ "CustomEditorType", CustomEditorType}
};
XQItem::XQUnitTypeMap XQItem::s_UnitTypeMap
{
{ NoUnitType, "NoUnitType" },
{ Ampere, "A" },
{ Volt, "V" },
{ Ohm, "Ohm" },
{ Farad, "C" },
{ Watt, "W" },
{ WattPeak, "Wp" },
{ WattHour, "Wh" },
{ Second, "s" },
{ Percent, "%" },
{ Hertz, "Hz" },
{ Meter, "m" },
{ Kg, "kg" },
{ ISODate, "ISODate" }, // fixme: ISO-Date is present, but has no Unit ?!?
};
XQItem::XQPrefixExponentMap XQItem::s_PrefixExponentMap
{
{ "p", -12 }, // pico
{ "n", -9 }, // nano
{ "µ", -6 }, // micro
{ "m", -3 }, // Milli
{ "" , 0 }, // No prefix means multiplier of 1
//{ " ", 0 }, // No prefix means multiplier of 1
{ "k", 3 }, // Kilo
{ "M", 6 }, // Mega
{ "G", 9 }, // Giga
{ "T", 12 }, // Tera
{ "P", 15 }, // Peta
{ "E", 18 }, // Exa
{ "Z", 21 }, // Zetta
{ "Y", 24}, // Yotta
};
XQItem::XQItem()
: XQItem{XQItemType::staticItemType()}
{
setFlags(Qt::NoItemFlags);
//setText("[dummy]");
//XQItemType::setStaticType( this );
//setItemType(NTItemType::defaultItemType());
}
XQItem::XQItem( XQItemType* itemType )
: QStandardItem{}
{
setItemType( itemType );
}
XQItem::XQItem(XQItemType* itemType, const QString *content )
: XQItem{ itemType }
{
setContent(content);
}
// Warum beides?
XQItem::XQItem(XQItemType* itemType, const QString *content, const XQNodePtr& contentNode )
: XQItem{ itemType, content }
{
setContentNode(contentNode);
}
/// ------------------ forbidden fruits ------------------
XQItem::XQItem(const XQItem& other)
: QStandardItem( other )
{
// QStandardItem( other ) koopiert bereits
// die data() struktur
}
XQItem::~XQItem()
{
// fixed choices lebt im item type, also
// im parent
//QAbstractItemModel* model = fixedChoices();
//if( model )
// delete model;
}
XQItem* XQItem::clone() const
{
//return new XQItem( *this );
// this is used as invisible filling material
//return new XQItem( "", XQItemType::StaticStyle );
// __fix!
return new XQItem();
}
bool XQItem::isValid() const
{
// fragwürdig
return QStandardItem::data( XQItem::ItemTypeRole ).value<XQItemType*>() != nullptr;
}
XQNodePtr XQItem::contentNode() const
{
return data( ContentNodeRole ).value<XQNodePtr>();
}
void XQItem::setContentNode( const XQNodePtr& contentNode )
{
QStandardItem::setData( QVariant::fromValue(contentNode), ContentNodeRole);
}
XQNodePtr XQItem::sheetNode() const
{
//
return data( SheetNodeRole ).value<XQNodePtr>();
}
void XQItem::setSheetNode(const XQNodePtr& sheetNode )
{
QStandardItem::setData( QVariant::fromValue(sheetNode), SheetNodeRole);
}
bool XQItem::hasAttribute( const QString& attribKey ) const
{
return contentNode()->has_attribute( attribKey );
}
const QString& XQItem::attribute( const QString& attribKey, const QString& defaultValue ) const
{
if( !hasAttribute(attribKey ) )
return defaultValue;
return contentNode()->attribute( attribKey );
}
bool XQItem::testAttribute( const QString& attribKey, const QString& attribValue ) const
{
return contentNode()->test_attribute( attribKey, attribValue );
}
XQItemType& XQItem::itemType() const
{
XQItemType* itemTypePtr = QStandardItem::data( XQItem::ItemTypeRole ).value<XQItemType*>();
return *itemTypePtr;
}
void XQItem::setItemType( XQItemType* itemTypePtr )
{
// der ItemType wird direkt hier gespeichert
QStandardItem::setData( QVariant::fromValue(itemTypePtr), XQItem::ItemTypeRole );
}
void XQItem::addFlag( Qt::ItemFlag newFlag )
{
setFlags( flags() | newFlag );
}
void XQItem::clearFlag( Qt::ItemFlag newFlag )
{
setFlags( flags() & ~newFlag);
}
///
/// data() access shortcuts
///
XQItem::RenderStyle XQItem::renderStyle() const
{
return data( RenderStyleRole ).value<RenderStyle>();
}
QString XQItem::renderStyleToString() const
{
return XQItem::fetchRenderStyleToString( renderStyle() );
}
void XQItem::setRenderStyle(RenderStyle renderStyle )
{
setData( QVariant::fromValue(renderStyle), XQItem::RenderStyleRole );
// Der RenderStyle wohnt im ItemType
//itemType().replaceAttribute( this, RenderStyleRole, renderStyle );
}
XQItem::EditorType XQItem::editorType() const
{
return data( EditorTypeRole ).value<EditorType>();
}
QString XQItem::editorTypeToString() const
{
return XQItem::fetchEditorTypeToString( editorType() );
}
void XQItem::setEditorType(EditorType editorType)
{
setData( QVariant::fromValue(editorType), XQItem::EditorTypeRole);
// Der EditorType wohnt im ItemType
//itemType().replaceAttribute( this, EditorTypeRole, editorType );
}
XQItem::UnitType XQItem::unitType() const
{
return data( XQItem::UnitTypeRole ).value<UnitType>();
}
QString XQItem::unitTypeToString() const
{
return XQItem::fetchUnitTypeToString( unitType() );
}
void XQItem::setUnitType(UnitType unitType)
{
setData( QVariant::fromValue(unitType), XQItem::UnitTypeRole);
}
const QString& XQItem::content() const
{
const QString* contentPtr = QStandardItem::data( XQItem::ContentRole ).value<const QString*>();
if(contentPtr)
return *contentPtr;
static const QString s_dummyContent("-");
return s_dummyContent;
}
void XQItem::setContent( const QString* content )
{
setData( QVariant::fromValue<const QString*>(content), XQItem::ContentRole );
}
const QString& XQItem::contentKey() const
{
return contentNode()->attributes().key_of( content() );
}
QString XQItem::contentFormat() const
{
return data( XQItem::ContentFormatRole ).toString();
}
void XQItem::setContentFormat(const QString& contentFormat)
{
setData( QVariant::fromValue(contentFormat), XQItem::ContentFormatRole);
}
QStandardItemModel* XQItem::fixedChoices() const
{
return data( XQItem::FixedChoicesRole ).value<QStandardItemModel*>();
}
QString XQItem::fixedChoicesToString() const
{
QStandardItemModel* model = fixedChoices();
if( !model || model->rowCount() == 0)
return QString("()");
QString result = "(";
int rc = model->rowCount();
for (int row = 0; row < rc; ++row)
{
const QString text = model->item(row)->text();
result += text;
if(row < rc-1)
result += "|";
}
result += ")";
return result;
}
void XQItem::setfixedChoices( QStandardItemModel* newModel )
{
// Der RenderStyle wohnt im ItemType
setData( QVariant::fromValue(newModel), XQItem::FixedChoicesRole);
}
bool XQItem::isHeaderStyle()
{
return renderStyle() == XQItem::HeaderStyle;
}
QVariant XQItem::data(int role ) const
{
//emitDataChanged()
switch(role)
{
//
// Die im ItemType ausgelagerten Daten werden
// von da geholt.
//
case FlagsRole: // aka Qt::ItemDataRole(Qt::UserRole - 1),
case IconRole: // aka Qt::DecorationRole,
case RenderStyleRole:
case EditorTypeRole:
case UnitTypeRole:
case ContentFormatRole:
case FixedChoicesRole:
{
return itemType().data(role);
}
// Das ist der Sonderfall, hier dereferenzieren wir den
// Zeiger auf den QString* aus unserem XQNodePtr
case Qt::DisplayRole :
case Qt::EditRole :
case XQItem::ContentRole:
{
return content();
}
case Qt::ToolTipRole:
{
return content() + ":" + itemType().text() + ":" + renderStyleToString();
}
//
// Die lokal verwalteten Resourcen werden über QStandardItem::data(role)
// abgewickelt.
//
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 );
// sonst: delegieren an den node-Besitzer
QModelIndex pIndex = model()->index( row(), 0 );
XQItem& firstItem = xqItemFromIndex( pIndex );
return firstItem.data( XQItem::ContentNodeRole );
}
case Qt::StatusTipRole:
case Qt::WhatsThisRole:
case Qt::SizeHintRole:
case Qt::FontRole:
case Qt::TextAlignmentRole:
case Qt::BackgroundRole:
case Qt::ForegroundRole:
case Qt::CheckStateRole:
case Qt::InitialSortOrderRole:
default:
break;
}
return QStandardItem::data(role);
}
void XQItem::setData(const QVariant& value, int role )
{
//replaceAttribute( XQItem* item, XQItem::ItemDataRole role, const QVariant& newValue)
//emitDataChanged()
switch(role)
{
// das ist ein pointer auf den original-string aus dem XML
// ContentRole :
// ItemTypeRole :
case RenderStyleRole :
case EditorTypeRole :
case UnitTypeRole:
case ContentFormatRole:
case FlagsRole:
case IconRole:
case FixedChoicesRole:
//qDebug() << " ---call type set Data: " << role << ": " << XQItem::fetchItemDataRoleName(role) << ":" << value.toString();
itemType().replaceAttribute( this, value, role );
break;
case ContentNodeRole:
case SheetNodeRole:
case TypeKeyRole:
case Qt::DisplayRole :
case Qt::EditRole :
// return the raw, unformatted data
case ContentRole:
default:
QStandardItem::setData( value,role);
}
}
XQItem& XQItem::fallBackDummyItem()
{
static XQItem s_fallBackDummyItem;
return s_fallBackDummyItem;
}
XQItem& XQItem::xqItemFromIndex(const QModelIndex& index)
{
if (index.isValid())
{
const XQModel* mdl = dynamic_cast<const XQModel*>(index.model());
if (mdl)
return mdl->xqItemFromIndex(index);
}
return fallBackDummyItem();
}
int XQItem::fetchItemDataRole( const QString& dataRoleKey )
{
if(!dataRoleKey.isEmpty() && s_ItemDataRoleMap.contains(dataRoleKey) )
return s_ItemDataRoleMap[ dataRoleKey ];
return NoRole;
}
QString XQItem::fetchItemDataRoleName( int dataRole )
{
return s_ItemDataRoleMap.key(dataRole);
}
Qt::ItemFlag XQItem::fetchItemFlag( const QString& flagKey )
{
if(!flagKey.isEmpty() && s_ItemFlagMap.contains(flagKey) )
return Qt::ItemFlag( s_ItemFlagMap[ flagKey ] );
return Qt::NoItemFlags;
}
QString XQItem::fetchItemFlagName( int flag )
{
return s_ItemFlagMap.key(flag);
}
XQItem::RenderStyle XQItem::fetchRenderStyle(const QString& styleKey )
{
if(!styleKey.isEmpty() && s_RenderStyleMap.contains(styleKey) )
return s_RenderStyleMap[styleKey];
return NoRenderStyle;
}
QString XQItem::fetchRenderStyleToString(XQItem::RenderStyle renderStyle )
{
return s_RenderStyleMap.key(renderStyle);
}
XQItem::EditorType XQItem::fetchEditorType( const QString& editorTypeKey )
{
if(!editorTypeKey.isEmpty() && s_EditorTypeMap.contains(editorTypeKey) )
return s_EditorTypeMap[editorTypeKey];
return NoEditorType;
}
QString XQItem::fetchEditorTypeToString( EditorType editorType )
{
return s_EditorTypeMap.key(editorType);
}
XQItem::UnitType XQItem::fetchUnitType(const QString& unitTypeKey)
{
return s_UnitTypeMap.key(unitTypeKey);
}
QString XQItem::fetchUnitTypeToString( UnitType unitType)
{
return s_UnitTypeMap[unitType];
}

297
items/xqitem.h Normal file
View File

@@ -0,0 +1,297 @@
/***************************************************************************
source::worx xtree
Copyright © 2024-2025 c.holzheuer
christoph.holzheuer@gmail.com
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
***************************************************************************/
#ifndef XQITEM_H
#define XQITEM_H
#include <QVariant>
#include <QVector>
#include <QStandardItem>
#include <xqnode.h>
using XQItemList = QList<QStandardItem*>;
//class QStyleOptionViewItem;
class XQItemFactory;
class XQItemType;
/**
* @brief Extends QStandardItem to hold additional
* settings.
*/
class XQItem : public QStandardItem
{
public:
//friend class XQItemType;
//friend class XQItemFactory;
/// Die data(enum role) Infrastruktur wird sowohl für XQItem als auch
/// für den XQItemType verwendet, deshalb definieren wir hier _alle_
/// notwendigen Roles
enum ItemDataRole
{
NoRole = Qt::UserRole + 1,
// das ist ein pointer auf den original-string aus dem XML
ContentRole,
ItemTypeRole,
RenderStyleRole,
EditorTypeRole,
UnitTypeRole,
ContentFormatRole,
// @see qstandarditemmodel.cpp, stolen from there
FlagsRole = Qt::ItemDataRole(Qt::UserRole - 1),
IconRole = Qt::DecorationRole,
// re-start count
FixedChoicesRole = ContentFormatRole+1,
ContentNodeRole,
//?? werden beide gebraucht?
SheetNodeRole,
// das ist der Schlüssel um den content string aus dem contentNode zu holen
//ContentKeyRole,
// weitere, weniger gebräuchlichen Rollen für XQItemType::data()
TypeKeyRole,
//TypeNameRole, nicht so wichtig
/*
renderStyleToStringRole,
editorTypeToStringRole,
unitTypeToStringRole,
*/
RoleEnd
};
// wie wirds gemalt
enum RenderStyle
{
NoRenderStyle,
HiddenStyle,
HeaderStyle,
PlainStyle,
CheckBoxStyle,
ComboBoxStyle,
PickerStyle,
SpinBoxStyle,
ProgressBarStyle,
FormattedStyle,
TreeHeaderStyle,
CustomRenderStyle,
RenderStyleEnd //!< Not a special editor. Keep at end of this enumeration!
// ...
/*
PickerStyle
LineEditStyle ,
UserDefStyle ,
*/
};
// wie wirds editiert
enum EditorType
{
NoEditorType,
LineEditType,
ComboBoxType,
PickerType,
ProgressBarType,
SpinBoxType,
CustomEditorType,
EditorTypeEnd
};
// typische Einheiten
enum UnitType
{
NoUnitType,
Ampere,
Volt,
Ohm,
Watt,
WattPeak,
WattHour,
Farad,
Tesla,
Henry,
Hertz,
Coulomb,
Kelvin,
Percent,
Second,
Meter,
Kg,
ISODate,
UnitTypeEnd
};
//XQItem(int rows, int columns = 1);
XQItem();
XQItem( XQItemType* itemType );
XQItem( XQItemType* itemType, const QString* content );
XQItem( XQItemType* itemType, const QString* content, const XQNodePtr& contentNode );
/*
XQItem(const QString& text);
XQItem(const QIcon& icon, const QString& text);
XQItem(int rows, int columns);
*/
XQItem(const XQItem& other);
XQItem(const QStandardItem& other);
virtual ~XQItem();
//! creates not a clone but a new default item, \see QStandardItemModel::setItemPrototype()
//! -- not used at the moment --
XQItem* clone() const override;
bool isValid() const;
// shortcuts auf XQNodePtr
virtual XQNodePtr contentNode() const;
virtual void setContentNode(const XQNodePtr& contentNode );
virtual XQNodePtr sheetNode() const;
virtual void setSheetNode( const XQNodePtr& sheetNode );
bool hasAttribute( const QString& attribKey ) const;
const QString& attribute( const QString& attribKey, const QString& defaultValue="" ) const;
bool testAttribute( const QString& attribKey, const QString& attribValue ) const;
XQItemType& itemType() const;
void setItemType( XQItemType* itemTypePtr );
// shortcuts für die itemFlags
// __fix! das können die selber !?
void addFlag( Qt::ItemFlag newFlag );
void clearFlag( Qt::ItemFlag newFlag );
//das ist ein Sonderfall: Ein ist ein dereferenzierter Zeiger auf 'unser' Atrribut in
// XQNodePtr, also unserem contentNode(). Das wird hier direkt aufgelöst und nicht auf
// data() umgeleitet.
const QString& content() const;
const QString& contentKey() const;
void setContent( const QString* content );
//
// Convenience-Funktionen zum Memberzugriff, die Implementierung
// läuft über die data()-Methode wie in den QStandardItems. So
// ist sie für XQItem und auch für XQItemType als Deirvat von XQItem gültig.
//
RenderStyle renderStyle() const;
QString renderStyleToString() const;
void setRenderStyle(RenderStyle renderStyle );
EditorType editorType() const;
QString editorTypeToString() const;
void setEditorType(EditorType editorType);
UnitType unitType() const;
QString unitTypeToString() const;
void setUnitType(UnitType unitType);
QString contentFormat() const;
void setContentFormat(const QString& contentFormat);
QStandardItemModel* fixedChoices() const;
QString fixedChoicesToString() const;
void setfixedChoices( QStandardItemModel* newModel );
//
//shortCuts
//
bool isHeaderStyle();
// ...
QVariant data(int role = Qt::DisplayRole ) const override;
void setData(const QVariant &value, int role ) override;
// Das sind die die items im tree links: icon,text, node pointer
//XQItem( const QString& text, XQNodePtr contentNode );
//XQItem( const QString& text, XQItemType::RenderStyle renderStyle );
/*
template<class T>
void setToVariant(T entry, QtExtUserRoles::NTDataRoles role)
{
setData(QVariant::fromValue<T>(entry), role);
}
template<class T>
T getFromVariant(QtExtUserRoles::NTDataRoles role)
{
return data(role).value<T>();
}
*/
///
/// Static convenience methods
///
static XQItem& xqItemFromIndex( const QModelIndex& index );
static XQItem& fallBackDummyItem();
static int fetchItemDataRole( const QString& dataRoleKey );
static QString fetchItemDataRoleName( int dataRole );
static Qt::ItemFlag fetchItemFlag( const QString& flagKey );
static QString fetchItemFlagName( int flag );
static RenderStyle fetchRenderStyle( const QString& styleKey );
static QString fetchRenderStyleToString( RenderStyle renderStyle );
static EditorType fetchEditorType( const QString& editorTypeKey );
static QString fetchEditorTypeToString( EditorType editorType );
static UnitType fetchUnitType( const QString& typeKey );
static QString fetchUnitTypeToString( UnitType );
protected:
using XQItemFlagMap = QMap<QString,int>;
using XQItemDataRoleMap = QMap<QString,int>;
using XQRenderStyleMap = QMap<QString,RenderStyle>;
using XQEditorTypeMap = QMap<QString,EditorType>;
using XQUnitTypeMap = QMap<UnitType, QString>;
using XQPrefixExponentMap = QMap<QString, int>;
static XQItemFlagMap s_ItemFlagMap;
static XQItemDataRoleMap s_ItemDataRoleMap;
static XQRenderStyleMap s_RenderStyleMap;
static XQEditorTypeMap s_EditorTypeMap;
static XQUnitTypeMap s_UnitTypeMap;
static XQPrefixExponentMap s_PrefixExponentMap;
};
Q_DECLARE_METATYPE(XQItem::RenderStyle);
Q_DECLARE_METATYPE(XQItem::EditorType);
Q_DECLARE_METATYPE(XQItem::UnitType);
Q_DECLARE_METATYPE(const QString*);
#endif // XQITEM_H

291
items/xqitemdelegate.cpp Normal file
View File

@@ -0,0 +1,291 @@
/***************************************************************************
source::worx xtree
Copyright © 2024-2025 c.holzheuer
christoph.holzheuer@gmail.com
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
***************************************************************************/
#include <QApplication>
#include <QItemEditorFactory>
#include <QLineEdit>
#include <QComboBox>
#include <QDoubleSpinBox>
#include <QProgressBar>
#include <QPainter>
#include <QHeaderView>
#include <QCommonStyle>
#include <xqitemdelegate.h>
#include <xqtreeview.h>
#include <xqitemtype.h>
#include <xqmodel.h>
class XQItemEditorFactory : public QItemEditorFactory
{
public:
XQItemEditorFactory()
{
registerEditor(XQItem::LineEditType, new QStandardItemEditorCreator<QLineEdit>());
registerEditor(XQItem::ComboBoxType, new QStandardItemEditorCreator<QLineEdit>());
registerEditor(XQItem::PickerType, new QStandardItemEditorCreator<QLineEdit>());
registerEditor(XQItem::ProgressBarType, new QStandardItemEditorCreator<QLineEdit>());
registerEditor(XQItem::SpinBoxType, new QStandardItemEditorCreator<QLineEdit>());
registerEditor(XQItem::CustomEditorType, new QStandardItemEditorCreator<QLineEdit>());
/*
registerEditor(XQItem::LineEditStyle, new QStandardItemEditorCreator<QLineEdit>());
registerEditor(XQItemType::ComboBoxStyle, new QStandardItemEditorCreator<QComboBox>());
//registerEditor(XQItemType::ProgressBarStyle, new QStandardItemEditorCreator<QProgressBar>());
registerEditor(XQItemType::SpinBoxStyle, new QStandardItemEditorCreator<QSpinBox>());
*/
/*
registerEditor(XQItem::etDoubleSpinType, new QStandardItemEditorCreator<QDoubleSpinBox>());
registerEditor(XQItemItemTypes::etDoubleSpinType, new QStandardItemEditorCreator<QDoubleSpinBox>());
registerEditor(XQItemItemTypes::etIPAddressType, new QStandardItemEditorCreator<NTIpAddressEdit>());
registerEditor(XQItemItemTypes::etLineEditBrowser, new QStandardItemEditorCreator<NTFileSelectLine>());
*/
}
};
XQItemDelegate::XQItemDelegate( XQModel& modelView)
: _modelView{modelView}
{
static XQItemEditorFactory s_EditorFactory;
setItemEditorFactory(&s_EditorFactory);
}
XQTreeView* XQItemDelegate::treeView() const
{
return _modelView.treeView();
}
XQItem& XQItemDelegate::xqItemFromIndex( const QModelIndex& index ) const
{
return _modelView.xqItemFromIndex( index );
}
QWidget* XQItemDelegate::prepareHeaderOption(const QStyleOptionViewItem& option, const QModelIndex& index, QStyleOptionHeader& headerOption) const
{
// use the header as "parent" for style init
QWidget* srcWidget = treeView()->header();
headerOption.initFrom(srcWidget);
headerOption.text = index.data(Qt::DisplayRole).toString();
headerOption.rect = option.rect;
headerOption.styleObject = option.styleObject;
// __ch: reduce inner offset when painting
headerOption.textAlignment |= Qt::AlignVCenter;
return srcWidget;
}
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 );
case XQItem::ComboBoxStyle :
return drawComboBoxStyle( painter, option, index );
case XQItem::HiddenStyle :
return;
//case XQItem::ProgressBarStyle :
// return drawProgressBarStyle( painter, option, index );
default:
break;
} // switch
}
QStyledItemDelegate::paint(painter, option, index);
}
void XQItemDelegate::drawHeaderStyle(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const
{
QStyleOptionHeader headerOption;
QWidget* srcWidget = prepareHeaderOption(option, index, headerOption);
if (srcWidget != nullptr)
{
// save painter
painter->save();
//value = index.data(Qt::ForegroundRole);
//if (value.canConvert<QBrush>())
//headerOption.palette.setBrush(QPalette::Text, Qt::red );
//headerOption.palette.setBrush(QPalette::Window, Qt::red );
QCommonStyle itemStyle;
//headerOption.backgroundBrush()
//srcWidget->style()->drawControl(QStyle::CE_Header, &headerOption, painter, srcWidget);
itemStyle.drawControl(QStyle::CE_Header, &headerOption, painter, srcWidget);
// restore painter
painter->restore();
}
}
void XQItemDelegate::drawProgressBarStyle(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
int progress = index.data(XQItem::ContentRole ).toInt();
QStyleOptionProgressBar progressBarOption;
progressBarOption.rect = option.rect;
progressBarOption.minimum = 0;
progressBarOption.maximum = 100;
progressBarOption.progress = progress;
progressBarOption.text = QString::number(progress) + "%";
progressBarOption.textAlignment = Qt::AlignCenter;
progressBarOption.textVisible = true;
QApplication::style()->drawControl(QStyle::CE_ProgressBar,&progressBarOption, painter);
}
void XQItemDelegate::drawComboBoxStyle(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
QWidget* srcWidget = qobject_cast<QWidget*>(option.styleObject);
QStyleOptionComboBox comboOption;
QStyle* comboStyle = srcWidget->style();
comboOption.initFrom(srcWidget);
// set options
comboOption.rect = option.rect;
comboOption.state = option.state | QStyle::State_Selected | QStyle::State_Enabled;
// not editable => only visual, but painter needs to know it
comboOption.editable = false;
comboOption.currentText = index.data(Qt::DisplayRole).toString();
// decoration (if any)
comboOption.currentIcon = qvariant_cast<QIcon>(index.data(Qt::DecorationRole));
comboOption.iconSize = comboOption.currentIcon.actualSize(QSize(option.rect.height() - 3, option.rect.height() - 3));
// save painter
painter->save();
// draw combo
comboStyle->drawComplexControl(QStyle::CC_ComboBox, &comboOption, painter, srcWidget);
// and combobox label
comboStyle->drawControl(QStyle::CE_ComboBoxLabel, &comboOption, painter, srcWidget);
// restore painter
painter->restore();
}
void XQItemDelegate::drawSpinBoxStyle(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const
{
// xx_fix!
//int value = index.data(XQItem::ContentRole ).toInt();
QStyleOptionSpinBox spinBoxOption;
spinBoxOption.rect = option.rect;
/*
spinBoxOption.text = QString::number(value);
spinBoxOption.textAlignment = Qt::AlignCenter;
spinBoxOption.textVisible = true;
*/
QApplication::style()->drawComplexControl(QStyle::CC_SpinBox,&spinBoxOption, painter);
}
QSize XQItemDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const
{
return QStyledItemDelegate::sizeHint(option, index);
}
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 )
{
return editor;
}
}
void XQItemDelegate::setEditorData(QWidget* editor, const QModelIndex& index) const
{
XQItem& item = xqItemFromIndex( index );
qDebug() << " --- ZZZ: setEditorData: " << item.text();
switch( item.editorType() )
{
case XQItemType::ComboBoxType :
{
QComboBox* comboBox = qobject_cast<QComboBox*>(editor);
comboBox->setModel( item.fixedChoices());
comboBox->setCurrentText( item.data().toString() );
comboBox->showPopup();
return;
}
default:
break;
}
QStyledItemDelegate::setEditorData(editor, index);
}
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);
return;
}
default:
break;
}
QStyledItemDelegate::setModelData(editor, model, index);
}
void XQItemDelegate::updateEditorGeometry(QWidget* editor, const QStyleOptionViewItem& option, const QModelIndex& index) const
{
//qDebug() << " --- update Editor Geometry";
QStyledItemDelegate::updateEditorGeometry(editor, option, index);
}

60
items/xqitemdelegate.h Normal file
View File

@@ -0,0 +1,60 @@
/***************************************************************************
source::worx xtree
Copyright © 2024-2025 c.holzheuer
christoph.holzheuer@gmail.com
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
***************************************************************************/
#ifndef XQITEMDELEGATE_H
#define XQITEMDELEGATE_H
#include <QStyledItemDelegate>
#include <xqappdata.h>
class XQItem;
class XQTreeView;
class XQModel;
/**
* @brief A specialized QItemDelegate class to draw different XQItem styles.
*/
class XQItemDelegate : public QStyledItemDelegate
{
Q_OBJECT
public:
explicit XQItemDelegate(XQModel& modelView);
XQTreeView* treeView() 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;
protected:
QWidget* prepareHeaderOption(const QStyleOptionViewItem& option, const QModelIndex& index, QStyleOptionHeader& headerOption) 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;
XQModel& _modelView;
};
#endif // XQITEMDELEGATE_H

347
items/xqitemfactory.cpp Normal file
View File

@@ -0,0 +1,347 @@
/***************************************************************************
source::worx xtree
Copyright © 2024-2025 c.holzheuer
christoph.holzheuer@gmail.com
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
***************************************************************************/
#include <xqitemfactory.h>
#include <xqexception.h>
#include <xqdocumentstore.h>
#include <xqmodel.h>
#include <xqitemtype.h>
#include <znode_factory.h>
void XQItemFactory::initItemFactory( const QString& modelSheetFileName )
{
auto configureItemType = [&, this](XQItemType* itemType, const XQNodePtr& sheetNode )
{
// über alle attribute
for( const auto& [key,value] : sheetNode->attributes() )
{
setItemDataFromString( *itemType, key, value );
}
};
// schritt #1: modelbeschreibung laden
XQNodeFactory treeLoader;
_modelSheet = treeLoader.load_tree( qPrintable(modelSheetFileName) );
// schritt #2: model root testen
if (!_modelSheet)
throw XQException("modelSheet load failed. ", modelSheetFileName);
// schritt #3: itemtype beschreibungen laden ...
_typesSheet = _modelSheet->find_child_by_tag_name( "ItemTypes" );
// ... und testen
if( !_typesSheet )
throw XQException( "initItemFactory typeSheetRoot is null" );
// alle itemtype vorlagen erzeugen
for( const XQNodePtr& typeSheetNode : _typesSheet->children())
{
XQItemType* itemType = new XQItemType;
//const QString& typeName = typeSheetNode->tag_name();
const QString& typeName = typeSheetNode->tag_name();
configureItemType(itemType, typeSheetNode);
itemType->setText( typeName);
s_ItemTypeCache[typeName] = itemType;
}
}
bool XQItemFactory::isValid()
{
return _modelSheet && _typesSheet;
}
XQItemType* XQItemFactory::findItemType(const QString& key ) const
{
if( !key.isEmpty() && s_ItemTypeCache.contains(key))
return s_ItemTypeCache[key];
throw XQException( "itemfactory: findItemType: not found:", key );
}
XQNodePtr XQItemFactory::findModelSheet( const QString& modelName ) const
{
XQNodePtr modelSheet = _modelSheet->find_child_by_tag_name( modelName );
if( !modelSheet )
throw XQException( "model sheet not found: ", modelName );
return modelSheet;
}
XQItem* XQItemFactory::makeContentItem( const XQNodePtr& contentNode, const XQNodePtr& sheetEntry ) const
{
// den itemtype des neuen items rausfinden
QString typeKey = sheetEntry->attribute("ItemType");
XQItemType* itemType = findItemType(typeKey); // throws
const QString* contentPtr = contentNode->attribute_ptr( sheetEntry->tag_name() );
XQItem* newItem = new XQItem( itemType, contentPtr );
return newItem;
}
XQItem* XQItemFactory::makeHeaderItem( const XQNodePtr& sheetEntry ) const
{
// header items are all non-data items:
// - section header row items
// - main tree header items
// - main tree child items
// - also: static items, hidden items
// den itemtype des neuen items rausfinden
QString typeKey = sheetEntry->attribute("HeaderItemType");
XQItemType* itemType = findItemType(typeKey); // throws
// das ist Unterschied zum normalen Item: Der Titel kommt aus der Modelbeschreibung
const QString* contentPtr = sheetEntry->attribute_ptr("HeaderCaption");
XQItem* newHeaderItem = new XQItem( itemType, contentPtr );
return newHeaderItem;
}
void XQItemFactory::setItemDataFromString( XQItem& item, const QString& roleKey, const QString& source ) const
{
int dataRole = XQItem::fetchItemDataRole( roleKey );
if( dataRole != XQItem::NoRole)
{
QVariant variant = makeVariant( dataRole, source );
if( !variant.isNull() && variant.isValid() )
item.setData( variant, dataRole );
}
}
QVariant XQItemFactory::makeVariant( int dataRole, const QString& source ) const
{
QVariant value;
switch(dataRole)
{
// das ist ein pointer auf den original-string aus dem XML
case XQItem::ContentRole:
{
// content() -> QString*
value = QVariant::fromValue(&source);
break;
}
case XQItem::ItemTypeRole:
{
// itemType() -> XQItemType*
XQItemType* itemType = findItemType( source );
value = QVariant::fromValue(itemType);
break;
}
case XQItem::RenderStyleRole:
{
XQItem::RenderStyle renderStyle = XQItem::fetchRenderStyle( source );
value = QVariant::fromValue(renderStyle);
break;
}
case XQItem::EditorTypeRole:
{
XQItem::EditorType editorType = XQItem::fetchEditorType( source );
value = QVariant::fromValue(editorType);
break;
}
case XQItem::UnitTypeRole:
{
XQItem::UnitType unitType = XQItem::fetchUnitType( source );
value = QVariant::fromValue(unitType);
break;
}
case XQItem::ContentFormatRole:
{
// contentFormat() -> QString
value = QVariant::fromValue(source);
break;
}
case XQItem::FlagsRole:
{
QFlags itemFlags = Qt::NoItemFlags;
const QStringList flagKeys = source.split( '|' );
for( const QString& flagKey : flagKeys )
{
Qt::ItemFlag flag = XQItem::fetchItemFlag( flagKey );
itemFlags.setFlag( flag );
}
value = QVariant::fromValue(itemFlags);
break;
}
case XQItem::IconRole:
{
QIcon typeIcon;
if(XQAppData::hasTypeIcon(source))
typeIcon = XQAppData::typeIcon(source);
value = QVariant::fromValue(typeIcon);
break;
}
case XQItem::FixedChoicesRole:
{
const QStringList choices = source.split( '|' );
QStandardItemModel* fixedChoices = new QStandardItemModel();
for( const QString& entry : choices )
fixedChoices->appendRow( new QStandardItem( entry ) );
value = QVariant::fromValue(fixedChoices);
break;
}
/*
case XQItem::ContentNodeRole:
{
value = QVariant::fromValue(&source);
break;
}
case XQItem::XQItem::SheetNodeRole:
{
value = QVariant::fromValue(&source);
break;
}
*/
default:
case XQItem::XQItem::NoRole:
{
break;
}
};
//if( !value.toString().isEmpty())
// setData( value, dataRole);
return value;
}
///
/// ------------------------------------------------
///
XQItemList XQItemFactory::makeHeaderRow( const XQNodePtr& sheetNode )
{
XQItemList list;
// Die Kinder des Knotens beschreiben die einzelnen
// Attribute des XML-Datenknotens
for( const auto& attrNode : sheetNode->children() )
{
// ??
//if(attrNode->has_children() )
// continue;
XQItem* headerItem = makeHeaderItem( attrNode );
list.append( headerItem );
}
if( !list.empty() )
{
// wir merken uns den original content node auch, aber
// im ersten Item.
dynamic_cast<XQItem*>(list[0])->setContentNode(sheetNode);
// brauchen wir den noch?
dynamic_cast<XQItem*>(list[0])->setSheetNode(sheetNode);
}
return list;
}
// no clone here !
XQItemList XQItemFactory::makeContentRow( const XQNodePtr& contentNode, const XQNodePtr& sheetNode )
{
XQItemList list;
// - Gehe über alle Einträge der Typbeschreibung:
//
// <Battery>
// <Voltage .../>
// -> <Capacity ../>
//
// - Nimm das dazugehörige Attribut aus dem contentNode
// value = contentNode->attributes["Capacity"];
//
for( const auto& sheetEntry : sheetNode->children() )
{
list.append( makeContentItem( contentNode, sheetEntry ) );
}
if( !list.empty() )
{
// wir merken uns den original content node auch, aber
// im ersten Item.
dynamic_cast<XQItem*>(list[0])->setContentNode(contentNode);
}
return list;
}
XQItemList XQItemFactory::makeEmptyRow( const XQNodePtr& contentNode, const XQNodePtr& sheetNode )
{
Q_UNUSED(contentNode)
XQItemList list;
// create a data node for each sheet entry
size_t max = sheetNode->children().size();
for( size_t i=0; i<max; ++i )
{
// __fix
//list.append( new XQItem( "", XQItemType::EmptyStyle ) );
}
return list;
}
XQItemList XQItemFactory::createGenericRow( const XQNodePtr& contentNode, const XQNodePtr& sheetNode )
{
// we have a new empty contentNode, so we add attributes first.
for( const auto& sheetEntry : sheetNode->children() )
{
QString value = "[" + sheetEntry->tag_name() + "]";
if( sheetEntry->has_attribute("Unit") )
value = "0";
contentNode->set_attribute( sheetEntry->tag_name(), value );
}
if( sheetNode->has_attribute( c_FriendlyName ) )
contentNode->set_attribute( c_FriendlyName, sheetNode->friendly_name() );
// now, we can create a normal entry row
return makeContentRow(contentNode, sheetNode );
}

68
items/xqitemfactory.h Normal file
View File

@@ -0,0 +1,68 @@
/* **************************************************************************
source::worx xtree
Copyright © 2024-2025 c.holzheuer
christoph.holzheuer@gmail.com
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
***************************************************************************/
#ifndef XQITEMFACTORY_H
#define XQITEMFACTORY_H
#include <xqitem.h>
#include <xqitemtype.h>
#include <functional>
class XQModel;
// erzeugt items aus XQNodes
class XQItemFactory : public xsingleton<XQItemFactory>
{
public:
void initItemFactory(const QString& modelSheetFileName );
XQNodePtr findModelSheet( const QString& modelName ) const;
XQItem* makeHeaderItem(const XQNodePtr& typeSheetNode ) const;
XQItem* makeContentItem( const XQNodePtr& contentNode, const XQNodePtr& sheetEntry ) const;
virtual XQItemList makeHeaderRow( const XQNodePtr& sheetNode );
virtual XQItemList makeContentRow( const XQNodePtr& contentNode, const XQNodePtr& sheetNode );
virtual XQItemList makeEmptyRow( const XQNodePtr& contentNode, const XQNodePtr& sheetNode );
// wozu ist das gut?
virtual XQItemList createGenericRow( const XQNodePtr& contentNode, const XQNodePtr& sheetNode );
void setItemDataFromString( XQItem& item, const QString& roleKey, const QString& source ) const;
// __fix! unsinn!
XQItemType* findItemType(const QString& key ) const;
QVariant makeVariant(int dataRole, const QString &value ) const;
protected:
bool isValid();
// shortcuts
using ItemConfigFunc = std::function<void( XQItem* item, const QString& attrValue, XQNodePtr contentNode, XQNodePtr sheetNode )>;
using ItemConfigMap = QMap<QString,ItemConfigFunc>;
XQItemTypeMap s_ItemTypeCache;
// Beschreibung des XQModels
XQNodePtr _modelSheet{};
// Beschreibung der ItemTypes
XQNodePtr _typesSheet{};
};
#endif // XQITEMFACTORY_H

259
items/xqitemtype.cpp Normal file
View File

@@ -0,0 +1,259 @@
/***************************************************************************
source::worx xtree
Copyright © 2024-2025 c.holzheuer
christoph.holzheuer@gmail.com
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
***************************************************************************/
//#include <cmath>
#include <xqitemtype.h>
#include <QDateTime>
#include <QDebug>
XQItemTypeMap XQItemType::s_ItemTypeMap;
size_t XQItemType::s_ItemTypeCount = 0;
///
/// XQItemType
///
XQItemType::XQItemType()
: XQItem(nullptr) // vermeide rekursion
{
}
XQItemType::XQItemType( const XQItemType& other)
: XQItem( other )
{
}
XQItemType::~XQItemType()
{
}
QVariant XQItemType::data( int role ) const
{
return QStandardItem::data(role);
}
void XQItemType::setData(const QVariant &value, int role )
{
return QStandardItem::setData(value,role);
}
void XQItemType::replaceAttribute( XQItem* item, const QVariant& newValue, int role )
{
// hat sich überhaupt was geändert?
QVariant oldValue = data(role);
// ja, es hat
if( oldValue != newValue )
{
XQItemType* myClone = new XQItemType(*this);
// Änderungen übernehmen
myClone->setData( newValue, role );
// Gibt es den geänderten ItemType schon?
QString newKey = myClone->makeItemTypeKey();
// jawoll
if( s_ItemTypeMap.contains( newKey ) )
{
// nur abräumen, sonst nix
delete myClone;
}
else
{
// speichern
s_ItemTypeMap.insert( newKey, myClone );
// und ins item übernehmen
item->setItemType( myClone );
/// Obacht! Der alte, geänderte itemType bleibt erhaltent
/// und verrottet ggf. ohne Daseinszweck
}
}
}
QString XQItemType::formatToSI( const QString& valueTxt ) const
{
/*
if( valueTxt.isEmpty() )
return valueTxt;
if( XQItem::ISODate == _unitType )
{
// format iso date
QDateTime dateTime = QDateTime::fromString(valueTxt, Qt::ISODate);
// fixme! make this configurable!
QString format = "dd.MM.yyyy HH:mm:ss"; // You can customize this format
// Format the QDateTime object into a human-readable string
return dateTime.toString(format);
}
QLocale sysLocale = QLocale::system();
sysLocale.setNumberOptions(sysLocale.numberOptions() | QLocale::OmitGroupSeparator);
double dVal = sysLocale.toDouble(valueTxt);
QString strVal, strPrefix;
int exp = (int)::log10f(dVal);
exp = (exp/3)*3;
double nVal = dVal;
if( !s_PrefixExponentMap.key(exp).isEmpty() )
nVal /= ::pow( 10,exp);
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() );
*/
return "fitze!";
}
QString XQItemType::unFormatFromSI(const QString& formText ) const
{
/*
QString input = formText.simplified();
// #1: strip numeric part
if( input.isEmpty() )
return input;
int idx = 0;
for( auto c : input )
{
if( c.isNumber() || c.toLower() == 'e' || c == '.' || c == ',' ||c == '-' || c == '+' )
idx++;
else
break;
}
if(!idx)
return QString("0");
QString numPart = formText.left(idx);
QString unitPart;
//if(idx + 1 < formText.size() )
unitPart = formText.right(idx - 1).simplified();
QLocale sysLocale = QLocale::system();
double dVal = sysLocale.toDouble(numPart);
if( unitPart.size() > 0 )
{
QString prefix = QString(unitPart[0]);
if( s_PrefixExponentMap.contains(prefix) )
dVal *= std::pow( 10.0, s_PrefixExponentMap[prefix] );
}
sysLocale.setNumberOptions(sysLocale.numberOptions() | QLocale::OmitGroupSeparator);
QString result = sysLocale.toString(dVal, 'f', 2);
//qDebug() << " convert: " << numPart << " : " << unitPart << " : " << dVal << " : " << result;
return result;
*/
return "fitze!";
}
///
/// --- statics --------------------------------------------------------------------------
///
XQItemType* XQItemType::staticItemType()
{
static XQItemType s_DummyItemType;
return &s_DummyItemType;
}
//
// Das ist eigentlich Blödsinn, KISS baby KISS!
// Die ItemTypes sollten statisch bleiben, zusätzliche
// oder geänderte Attribute eines Items landen dann
// halt in G.N. in QStadardItem::data Vector!
//
/*
XQItemType* XQItemType::storeItemType(XQItemType* protoType)
{
// haben wir den prototype schon?
QString itemTypeKey = protoType->makeItemTypeKey();
if(s_ItemTypeMap.contains( itemTypeKey ) )
{
// dann weg damit ...
delete protoType;
// ... und die alte Version zurückgeben
return s_ItemTypeMap[itemTypeKey];
}
// sonst: wir speichern den prototype
s_ItemTypeMap.insert( itemTypeKey, protoType);
s_ItemTypeCount++;
qDebug() << " --- ItemTypes: " << s_ItemTypeCount;
return protoType;
}
*/
QString XQItemType::makeItemTypeKey()
{
QString key("%1:%2:%3:%4:%5:%6:%7");
key = key.arg( renderStyleToString() );
key = key.arg( editorTypeToString() );
key = key.arg( unitTypeToString() );
key = key.arg( contentFormat() );
key = key.arg( data(XQItem::FlagsRole).toString() );
key = key.arg( icon().name() );
key = key.arg( fixedChoicesToString() );
/*
static const QList<XQItem::ItemDataRole> roleList
{
XQItem::RenderStyleRole,
XQItem::EditorTypeRole,
XQItem::UnitTypeRole,
XQItem::ContentFormatRole,
XQItem::FlagsRole,
XQItem::IconRole,
XQItem::FixedChoicesRole
};
QString key;
for( const auto role : roleList )
{
qDebug() << " --- YYY trying: " << XQItem::fetchItemDataRoleName( role );
QVariant entry = data(role);
if( !entry.isNull() && entry.isValid())
{
// fckin' sonderlocke:
key += role == XQItem::IconRole ? entry.value<QIcon>().name() : entry.toString();
}
key += ":";
}
*/
//qDebug() << " --- YES: KEY: " << key;
return key;
}

86
items/xqitemtype.h Normal file
View File

@@ -0,0 +1,86 @@
/***************************************************************************
source::worx xtree
Copyright © 2024-2025 c.holzheuer
christoph.holzheuer@gmail.com
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
***************************************************************************/
#ifndef XQITEMTYPE_H
#define XQITEMTYPE_H
#include <QDebug>
#include <QMap>
#include <xqitem.h>
///
/// Ist das Unsinn!? Einfach ein QStandardItem mit data() nehmen?
/// Ok, das erspart die die attribs, aber wo ist der fette gewinn?
/// statt _editorType = x hast Du dann halt setData( QVariant::fromValue<>(x) );
/// Aber: Du kannst T abbilden auf QString ... und dann
///
using XQItemTypeMap = QMap<QString, XQItemType*>;
//class XQItemType : public QObject
class XQItemType : public XQItem// public QObject
{
//
//Q_OBJECT
// wäre auch eine möglichkeit !?
//Q_PROPERTY(XQItem::RenderStyle renderStyle renderStyle getDate WRITE setrenderStyle )
public:
XQItemType();
XQItemType( const XQItemType& other);
virtual ~XQItemType();
QVariant data( int role ) const override;
void setData(const QVariant& value, int role ) override;
// FIX! Das gehört hier nicht her!
QString formatToSI(const QString& rawText ) const;
QString unFormatFromSI(const QString& valueText ) const;
void replaceAttribute( XQItem* item, const QVariant& newValue, int role );
QString makeItemTypeKey();
//static XQItemType* storeItemType( XQItemType* protoType );
static XQItemType* staticItemType();
protected:
static XQItemTypeMap s_ItemTypeMap;
static size_t s_ItemTypeCount;
/*
static void setItemType( XQItem* item, RenderStyle renderStyle, Qt::ItemFlags flags, UnitType unitType, const QString& format );
static void setStaticType( XQItem* item );
*/
// fix __ch
// static void setItemType( XQItem* item, const QString& renderStyle, const QString& unitType, const QString& itemTypeID );
//static XQItemType* addItemType( const QString& key, RenderStyle renderStyle, UnitType unitType);
//static XQItemType* makeItemType( RenderStyle renderStyle, UnitType unitType);
};
Q_DECLARE_METATYPE(XQItemType*);
#endif // XQITEMTYPE_H

70
main.cpp Normal file
View File

@@ -0,0 +1,70 @@
/***************************************************************************
source::worx xtree
Copyright © 2024-2025 c.holzheuer
christoph.holzheuer@gmail.com
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
***************************************************************************/
#include <QDebug>
#include <QApplication>
#include <xqmainwindow.h>
/*
TODO:
- kann ich die Enums auto generieren?
- entries einfach abzählen,
- einen enum als type
- auf diesen type drauf-casten, siehe qtglobal.h
- FIX! in reality, we have nested types, also.
- done: reference style
- done: shared_ptr
- try QML
- try 'model->readMore'
doc:
- vorhandenes xnode konzept soll am qt angebunden werden
- datensparsam: flyweight pattern & pointer auf orig
who is who:
- item
-itemtype
- factory
- model
- section
*/
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
//qDebug() << " lebt";
//app.setStyle("fusion");
XQMainWindow window;
window.show();
return app.exec();
}

116
model/xqcommand.cpp Normal file
View File

@@ -0,0 +1,116 @@
/***************************************************************************
source::worx xtree
Copyright © 2024-2025 c.holzheuer
christoph.holzheuer@gmail.com
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
***************************************************************************/
#include <xqcommand.h>
#include <xqmodel.h>
#include <xqtreeview.h>
void XQNodeStore::dumpList( const QString& title ) const
{
if( !title.isEmpty() )
qDebug() << " --- " << title;
for( const auto& entry : *this )
qDebug() << " -- dumpList: itemPos: " << entry.itemPos << " nodePos: " << entry.nodePos << " id: " << ( entry.contentNode ? entry.contentNode->_id : 0 ) << " used: " << ( entry.contentNode ? entry.contentNode.use_count() : 0 );
}
XQCommand::XQCommand(CmdType cmdType, XQModel* modelView )
: _cmdType{ cmdType }, _modelView(modelView)
{
}
XQCommand::~XQCommand()
{
qDebug() << " --- command destructor: " << toString();
}
XQCommand::CmdType XQCommand::commandType() const
{
return _cmdType;
}
void XQCommand::setCommandType( XQCommand::CmdType cmdType )
{
_cmdType = cmdType;
}
void XQCommand::redo()
{
_modelView->onCommandRedo( *this );
}
void XQCommand::undo()
{
_modelView->onCommandUndo( *this );
}
const QModelIndex& XQCommand::originIndex() const
{
return _originIndex;
}
void XQCommand::setOriginIndex( const QModelIndex& origin )
{
QString cmdText("%1: %2 (%3)");
QString name = origin.data().toString();
QString items("%1 item%2");
int mySize = size();
items = items.arg(mySize).arg(mySize > 1 ? "s" : "");
cmdText = cmdText.arg( toString(), name, items );
_originIndex = origin;
setText(cmdText);
}
void XQCommand::saveNodes( const QModelIndexList& list )
{
clear();
for( auto entry : list )
{
XQNodePtr contentNode = XQItem::xqItemFromIndex( entry ).contentNode();
// im command speichern wir den original knoten, nicht eine kopie, wie im clipboard.
push_back( {entry.row(), contentNode->own_pos(), contentNode } );
}
}
QString XQCommand::toString()
{
static QMap<CmdType,QString> s_CmdTypeMap
{
{ cmdTextEdit, "cmdTextEdit" },
{ cmdInvalid, "cmdInvalid" },
{ cmdCut, "cmdCut" },
{ cmdPaste, "cmdPaste" },
{ cmdPasteSelf, "cmdPasteSelf" },
{ cmdNew, "cmdNew" },
{ cmdUndo, "cmdUndo" },
{ cmdRedo, "cmdRedo" },
{ cmdCopy, "cmdCopy" },
{ cmdMove, "cmdMove" },
{ cmdDelete, "cmdDelete" },
{ cmdToggleSection, "cmdToggleSection" },
{ cmdExtern, "cmdExtern" }
};
if( !s_CmdTypeMap.contains( _cmdType ))
return QString(" cmdType missmatch");
return s_CmdTypeMap[_cmdType];
}

107
model/xqcommand.h Normal file
View File

@@ -0,0 +1,107 @@
/***************************************************************************
source::worx xtree
Copyright © 2024-2025 c.holzheuer
christoph.holzheuer@gmail.com
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
***************************************************************************/
#ifndef XQCOMMAND_H
#define XQCOMMAND_H
#include <QUndoCommand>
#include <xqitem.h>
class XQModel;
struct XQNodeBackup
{
int itemPos{-1};
int nodePos{-1};
XQNodePtr contentNode;
};
class XQNodeStore : public QVector<XQNodeBackup>
{
public:
void dumpList( const QString& title="" ) const;
virtual void saveNodes( const QModelIndexList& list ) = 0;
};
// Das command enthält immer auch die betroffenen items
// ist also auch eine SavedNodeList
class XQCommand : public QUndoCommand, public XQNodeStore
{
public:
enum CmdType
{
cmdInvalid,
cmdUndo,
cmdRedo,
cmdTextEdit,
cmdCut,
cmdPaste,
cmdPasteSelf,
cmdCopy,
cmdMove,
cmdNew,
cmdDelete,
cmdToggleSection,
cmdExtern //??
};
XQCommand(CmdType cmdType, XQModel* modelView );
virtual ~XQCommand();
CmdType commandType() const;
void setCommandType( CmdType cmdType );
const QModelIndex& originIndex() const;
void setOriginIndex( const QModelIndex& origin );
void saveNodes( const QModelIndexList& list ) override;
void redo() override;
void undo() override;
QString toString();
protected:
CmdType _cmdType{cmdInvalid};
XQModel* _modelView{}; // needed for redo() / undo()
QModelIndex _originIndex;
/*
Du hast den item editor vergessen, Du Honk!
NTCompositeModel* m_pModel;
QModelIndex m_index;
QVariant m_value;
QVariant m_oldValue;
bool m_updateIndex;
*/
};
Q_DECLARE_METATYPE(XQCommand::CmdType);
#endif // XQCOMMAND_H

522
model/xqmodel.cpp Normal file
View File

@@ -0,0 +1,522 @@
/***************************************************************************
source::worx xtree
Copyright © 2024-2025 c.holzheuer
christoph.holzheuer@gmail.com
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
***************************************************************************/
#include <QMessageBox>
#include <QUndoStack>
#include <xqexception.h>
#include <xqmodel.h>
#include <xqselectionmodel.h>
#include <xqtreeview.h>
#include <xqcommand.h>
#include <xqitemdelegate.h>
#include <xqitemfactory.h>
#include <znode_factory.h>
// create global dummy item as
// fallback return value (klappt nicht)
//Q_GLOBAL_STATIC(XQItem,s_dummyItem)
void showItemList( const XQItemList& list)
{
for(const auto& entry : list )
qDebug() << " --- itemList: " << ((XQItem*)entry)->content();
qDebug();
}
XQModel::~XQModel()
{
}
XQModel::XQModel( QObject* parent )
: QStandardItemModel{ parent }, _itemFactory{ XQItemFactory::instance() }
{
invisibleRootItem()->setData( "[rootItem]", Qt::DisplayRole );
setItemPrototype( new XQItem );
}
const XQItem& XQModel::xqRootItem()
{
// das ist ein hack, denn 'invisibleRootItem()' ist und bleibt ein
// QStandardItem. Trick: keine eigenen members in XQItem, alles
// dynamisch über den ItemData Mechanismus wie in QStandardItem
return *static_cast<XQItem*>(invisibleRootItem());
}
XQItem& XQModel::xqItemFromIndex(const QModelIndex& index) const
{
if( index.isValid() )
{
QStandardItem* xqItem = QStandardItemModel::itemFromIndex(index);
if( xqItem )
return *static_cast<XQItem*>(xqItem);
}
return XQItem::fallBackDummyItem();
}
XQItem& XQModel::xqFirstItem(int row) const
{
return *static_cast<XQItem*>( QStandardItemModel::item(row) );
}
QString XQModel::fetchNodeAttribute(int row, const QString& key )
{
/*
__fix
XQItem* item = fromRow(row);
if( item && item->hasNode() )
return item->contentNode()->attribute( key );
*/
return "";
}
/**
* @brief XQModel::fetchNodeTagName get the tag_name of the contentNode
* in a row
* @param row the row
* @return
*/
QString XQModel::fetchNodeTagName( int row )
{
// __fix
/*
XQItem* item = fromRow(row);
if( item && item->hasNode() )
return item->contentNode()->tag_name();
*/
return "";
}
void XQModel::onActionTriggered(QAction* action)
{
qDebug() << " --- onActionTriggered: count:" << XQNode::s_Count;
// all selected indices
QModelIndexList selectionList = treeView()->selectionModel()->selectedRows();
// extract command type
XQCommand::CmdType cmdType = action->data().value<XQCommand::CmdType>();
switch( cmdType )
{
// just handle undo ...
case XQCommand::cmdUndo :
return _undoStack->undo();
// ... or do/redo
case XQCommand::cmdRedo :
return _undoStack->redo();
// for copy & cut, we create a clone of the dataNodes in the clipboard
case XQCommand::cmdCopy :
case XQCommand::cmdCut :
// don't 'copy' empty selections
if( !selectionList.isEmpty() )
_clipBoard.saveNodes( selectionList );
// for copy, we are done, since copy cannot be undone
if( cmdType == XQCommand::cmdCopy )
return;
default:
break;
}
// we create a command
XQCommand* command = new XQCommand( cmdType, this );
// store the row positions of the selected indices
command->saveNodes( selectionList );
command->setOriginIndex( treeView()->currentIndex() );
// execute command
_undoStack->push( command );
}
/**
* @brief XQModel::onCommandRedo called to execute a command ('do').
* @param command the current command
*/
void XQModel::onCommandRedo( XQCommand& command )
{
try
{
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();
}
}
catch( XQException& exception )
{
qDebug() << exception.what();
QMessageBox::critical( nullptr, "Failure", QString("Failure: %1").arg(exception.what()) );
}
}
/**
* @brief XQModel::onCommandUndo: called to 'undo' a command.
* @param command the command to be undone.
*/
void XQModel::onCommandUndo( XQCommand& command )
{
qDebug() << " --- onCommandUndo: count: " << XQNode::s_Count;
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();
}
}
catch( XQException& exception )
{
qDebug() << exception.what();
QMessageBox::critical( nullptr, "Failure", QString("Failure: %1").arg(exception.what()) );
}
}
// undo-/redo-able stuff
/**
* @brief XQModel::cmdCutRows Cut the rows whose positions have been store in the command.
* @param command
*/
void XQModel::cmdCut( XQCommand& command )
{
// wir gehen rückwärts über alle gemerkten knoten ...
for (auto it = command.rbegin(); it != command.rend(); ++it)
{
// ... holen das erste item, das auch den content node enthält
const XQNodeBackup& entry = *it;
XQItem& firstItem = xqFirstItem( (*it).itemPos );
qDebug() << " --- Cut: " << firstItem.text() << " " << firstItem.row() << " id#" << entry.contentNode->_id;
// jetzt löschen, dabei wird die parent-verbindung entfernt
entry.contentNode->unlink_self();
removeRow(entry.itemPos );
}
}
// clone to clipboard, remove items
void XQModel::cmdCutUndo( XQCommand& command )
{
command.dumpList("UNDO Cut");
_sections.dump();
int xx = command.first().itemPos;
const XQModelSection& section = _sections.sectionFromRow( xx );
for (auto& entry : command )
{
XQNodePtr savedNode = entry.contentNode;
// __fix! should not bee _contentRoot!
savedNode->add_me_at( entry.nodePos, _contentRoot );
XQItemList list = _itemFactory.makeContentRow( savedNode, section.sheetRootNode );
XQItem& firstItem = *((XQItem*)list[0]);
qDebug() << " --- Cut Undo: " << firstItem.text() << " " << firstItem.row() << " id#" << entry.contentNode->_id;
insertRow( entry.itemPos, list );
}
}
void XQModel::cmdPaste( XQCommand& command )
{
// selection holen ...
QItemSelectionModel* selectionModel = treeView()->selectionModel();
// ... und löschen
selectionModel->clearSelection();
// aktuelles item finden
const XQItem& item = xqItemFromIndex( command.originIndex() );
// die neue item position ist unter dem akutellen item
int insRow = item.row()+1;
int nodePos = item.contentNode()->own_pos()+1;
// die zugehörige section finden
const XQModelSection& section = _sections.sectionFromRow( insRow-1 );
// wir pasten das clipboard
for (auto& entry : _clipBoard )
{
XQNodePtr savedNode = entry.contentNode;
XQItemList list = _itemFactory.makeContentRow( savedNode, section.sheetRootNode );
// wir klonen den knoten aus dem clipbord
savedNode->clone(section.contentRootNode )->add_me_at( nodePos );
insertRow( insRow, list );
const QModelIndex& selIdx = list[0]->index();
_treeView->selectionModel()->select(selIdx, QItemSelectionModel::Select | QItemSelectionModel::Rows);
// zur nächsten zeile
insRow++;
nodePos++;
}
// unsere änderungen merken fürs 'undo'
command.saveNodes( selectionModel->selectedRows() );
}
void XQModel::cmdPasteUndo( XQCommand& command )
{
command.dumpList("Paste UNDO");
// wir gehen rückwärts über alle markieren knoten ...
for (auto it = command.rbegin(); it != command.rend(); ++it)
{
// ... holen das erste item, das auch den content node enthält
const XQNodeBackup& entry = *it;
XQItem& firstItem = xqFirstItem( (*it).itemPos );
qDebug() << " --- Cut: " << firstItem.text() << " " << firstItem.row();
// jetzt löschen
entry.contentNode->unlink_self();
removeRow(entry.itemPos );
}
}
// don't clone into clipboard, remove items
void XQModel::cmdDelete( XQCommand& command )
{
// wir gehen rückwärts über alle markieren knoten ...
for (auto it = command.rbegin(); it != command.rend(); ++it)
{
// ... holen das erste item, das auch den content node enthält
const XQNodeBackup& entry = *it;
XQItem& firstItem = xqFirstItem( (*it).itemPos );
qDebug() << " --- Cut: " << firstItem.text() << " " << firstItem.row();
// jetzt löschen
entry.contentNode->unlink_self();
removeRow(entry.itemPos );
}
}
void XQModel::cmdDeleteUndo( XQCommand& command )
{
}
/**
* @brief XQModel::cmdNewRow create one new item row
* @param command the command
*/
void XQModel::cmdNew( XQCommand& command )
{
// __fix
/*
const QModelIndex& origin = command.originIndex();
if( !origin.isValid() )
throw XQException("cmdNewRow failed: index not valid ");
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() );
// store node in node->parent()
//node->add_before_me( newNode );
// store node also in 'command' to enable undo
const XQModelSection& section = _sections.sectionxqItemFromIndex( origin );
// create new item row
XQItemList list = _itemFactory.createGenericRow( newNode, section.sheetRootNode );
// add it to the treeview ...
insertRow( origin.row(), list );
// ... and make it ...
treeView()->setCurrentIndex( list[0]->index() );
// ... editable
treeView()->edit( list[0]->index() );
*/
}
void XQModel::cmdNewUndo( XQCommand& command )
{
}
void XQModel::cmdToggleSection( const QModelIndex& index )
{
Q_ASSERT(index.isValid());
int fstRow = _sections.firstRow( index );
int lstRow = _sections.lastRow( index );
bool hidden =_treeView->isRowHidden( fstRow, _treeView->rootIndex() );
for (int row = fstRow; row < lstRow; ++row )
_treeView->setRowHidden( row, _treeView->rootIndex(), !hidden );
}
XQTreeView* XQModel::treeView()
{
return _treeView;
}
void XQModel::setTreeView(XQTreeView* mainView )
{
// store view for direct access: the maintree
_treeView = mainView;
// connect myself as model to the mainview
_treeView->setModel(this);
XQItemDelegate* delegate = new XQItemDelegate( *this );
_treeView->setItemDelegate( delegate );
_contextMenu = new XQContextMenu( mainView );
connect( _treeView, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(onShowContextMenu(QPoint)));
//connect( _treeView, SIGNAL(doubleClicked(QModelIndex)), this, SLOT(onDoubleClicked(QModelIndex)) );
connect(_contextMenu, SIGNAL(triggered(QAction*)), this, SLOT(onActionTriggered(QAction*)));
// __fixme, die view soll über das modelsheet konfiguriert werden!
setupViewProperties();
}
/**
* @brief XQModel::setupViewProperties set the tree views' properties: context menu policy,
* edit triggers and so on.
*/
void XQModel::setupViewProperties()
{
_treeView->setContextMenuPolicy(Qt::CustomContextMenu);
_treeView->setEditTriggers(QAbstractItemView::DoubleClicked | QAbstractItemView::EditKeyPressed);
_treeView->setSelectionBehavior(QAbstractItemView::SelectRows);
_treeView->setSelectionMode(QAbstractItemView::ExtendedSelection);
//_treeView->setSelectionMode(QAbstractItemView::ContiguousSelection);
_treeView->setSelectionModel( new XQSelectionModel(this) );
}
void XQModel::addSection( const XQItemList& list, const XQNodePtr& sheetNode )
{
appendRow(list);
_sections.addSectionEntry( list[0]->index(), sheetNode );
}
QUndoStack* XQModel::undoStack()
{
return _undoStack;
}
void XQModel::setUndoStack( QUndoStack* undoStack )
{
_undoStack = undoStack;
}
void XQModel::onShowContextMenu(const QPoint& point)
{
initContextMenu();
_contextMenu->popup(_treeView->mapToGlobal(point));
}
QHash<int, QByteArray> XQModel::roleNames() const
{
QHash<int, QByteArray> roles;
roles[XQItem::ContentRole] = "content";
roles[XQItem::ItemTypeRole] = "itemType";
roles[XQItem::RenderStyleRole] = "renderStyle";
roles[XQItem::EditorTypeRole] = "editorType";
roles[XQItem::UnitTypeRole] = "unitType";
roles[XQItem::FixedChoicesRole] = "fixedChoices";
roles[XQItem::ContentNodeRole] = "contentNode";
roles[XQItem::SheetNodeRole] = "sheetNode";
roles[XQItem::TypeKeyRole] = "typeKey";
return roles;
}

142
model/xqmodel.h Normal file
View File

@@ -0,0 +1,142 @@
/***************************************************************************
source::worx xtree
Copyright © 2024-2025 c.holzheuer
christoph.holzheuer@gmail.com
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
***************************************************************************/
#ifndef XQMODEL_H
#define XQMODEL_H
#include <QUndoStack>
#include <QMenu>
#include <QStandardItemModel>
#include <xqsimpleclipboard.h>
#include <xqmodelsections.h>
#include <xqitemfactory.h>
#include <xqcontextmenu.h>
class XQTreeView;
class XQItem;
class XQCommand;
/**
* @brief Abstract baseclass of all modelviews: Extends QStandardItemModel with a treeview.
*/
// might be own implementation of QAbstractItemModel, not done yet.
//using QStandardItemModel = XQSimpleItemModel;
using QStandardItemModel = QStandardItemModel;
/**
* @brief The XQModel class: An extendend QStandardItem model
* containing its own view.
*/
class XQModel : public QStandardItemModel
{
Q_OBJECT
public:
XQModel(QObject* parent = nullptr);
virtual ~XQModel();
XQTreeView* treeView();
virtual void setTreeView( XQTreeView* mainView );
QUndoStack* undoStack();
void setUndoStack( QUndoStack* undoStack );
QHash<int, QByteArray> roleNames() const override;
//! create the own model structure
virtual void initModel( const QString& modelName) = 0;
//little helpers
const XQItem& xqRootItem();
XQItem& xqItemFromIndex(const QModelIndex& index) const;
XQItem& xqFirstItem(int row) const;
// was ist das?
QString fetchNodeAttribute(int row, const QString& key );
QString fetchNodeTagName(int row );
// undo-/redo-able stuff
virtual void cmdToggleSection( const QModelIndex& index );
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 );
// wtf!?
bool setData(const QModelIndex& index, const QVariant& value, int role = Qt::EditRole) override
{
qDebug() << " --- setData: " << value.toString();
return QStandardItemModel::setData( index, value, role );
}
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override
{
return QStandardItemModel::data( index, role );
}
public slots:
virtual void onShowContextMenu(const QPoint& point);
virtual void onActionTriggered(QAction* action);
// handle XQCommands ( == UndoCommand )
virtual void onCommandRedo( XQCommand& command );
virtual void onCommandUndo( XQCommand& command );
signals:
void xqItemCreated( XQItem* newItem );
protected:
void addSection(const XQItemList& list, const XQNodePtr& sheetNode );
protected:
virtual void initContextMenu() = 0;
// __fixme: should be created from xml
virtual void setupViewProperties();
protected:
// das eine reference auf ein globales singleton
XQItemFactory& _itemFactory;
XQSimpleClipBoard _clipBoard;
XQModelSections _sections;
XQTreeView* _treeView{};
QUndoStack* _undoStack{};
XQContextMenu* _contextMenu{};
//! Die Modelbeschreibung
XQNodePtr _modelSheet{};
//! Der eigentliche Inhalt
XQNodePtr _contentRoot{};
};
#endif // XQMODEL_H

146
model/xqmodelsections.cpp Normal file
View File

@@ -0,0 +1,146 @@
/***************************************************************************
source::worx xtree
Copyright © 2024-2025 c.holzheuer
christoph.holzheuer@gmail.com
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
***************************************************************************/
#include <xqmodelsections.h>
#include <xqitem.h>
XQModelSection::XQModelSection(const QModelIndex& aModelIndex, XQNodePtr aSheetNode)
: modelIndex{ aModelIndex }, sheetRootNode{ aSheetNode }
{
}
bool XQModelSection::operator==(const XQModelSection& other) const
{
return modelIndex == other.modelIndex && sheetRootNode == other.sheetRootNode;
}
bool XQModelSection::isValid() const
{
return modelIndex.isValid() && sheetRootNode;
}
int XQModelSection::XQModelSection::row() const
{
return modelIndex.row();
}
XQItem& XQModelSection::XQModelSection::headerItem() const
{
return XQItem::xqItemFromIndex( modelIndex );
}
//
//
// -------------------------------------------------------------------------------------------------------------------------------------------------------
//
//
void XQModelSections::addSectionEntry(const QModelIndex& idx, XQNodePtr sheetNode)
{
XQModelSection section(idx, sheetNode);
addAtKey(sheetNode->tag_name(), section);
}
bool XQModelSections::hasValidSection(const QString& sectionKey) const
{
if (!contains(sectionKey) )
return false;
return at(sectionKey).isValid();
}
const XQModelSection& XQModelSections::sectionxqItemFromIndex( const QModelIndex& index ) const
{
return sectionFromRow( index.row() );
}
const XQModelSection& XQModelSections::sectionFromRow(int itemRow ) const
{
int i = size() - 1;
for (; i >= 0; --i)
{
if ( at(i).modelIndex.row() < itemRow )
return at(i);
}
static XQModelSection s_DummySection;
return s_DummySection;
}
int XQModelSections::firstRow(const QModelIndex& idx) const
{
return sectionFromRow(idx.row() ).row();
}
int XQModelSections::lastRow(const QModelIndex& idx) const
{
return lastRow(sectionFromRow(idx.row()));
}
int XQModelSections::lastRow(const XQModelSection& section ) const
{
//qDebug() << " -- last row in section: " << section.modelIndex.data().toString() << " --> " << section.modelIndex.row();
// row() der section unterhalb dieser
// __fix? index mit speichern?
int index = indexOf(section);
if (index > -1)
{
// last section? return last row of model
if (index == size() - 1)
return section.modelIndex.model()->rowCount();// - 1;
// return row above the row of the next section -> last row of given section
return at(index+1).row();
}
return -1;
}
void XQModelSections::dump() const
{
qDebug() << " --- sections dump(): " <<size() << " entries.";
for( int i = 0; i<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();
}
}

71
model/xqmodelsections.h Normal file
View File

@@ -0,0 +1,71 @@
/***************************************************************************
source::worx xtree
Copyright © 2024-2025 c.holzheuer
christoph.holzheuer@gmail.com
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
***************************************************************************/
#ifndef XQMODELSECTIONS_H
#define XQMODELSECTIONS_H
#include <QPersistentModelIndex>
#include <xqnode.h>
#include <xqmaptor.h>
class XQItem;
/**
* @brief Struct containing data for a header section
*/
struct XQModelSection
{
QPersistentModelIndex modelIndex;
XQNodePtr sheetRootNode{};
XQNodePtr contentRootNode{};
XQModelSection() = default;
XQModelSection(const QModelIndex& aModelIndex, XQNodePtr aSheetNode);
bool operator==(const XQModelSection& other) const;
bool isValid() const;
int row() const;
XQItem& headerItem() const;
};
/**
* @brief Maptor containing all header sections.
*/
class XQModelSections : public XQMaptor<XQModelSection>
{
public:
XQModelSections() = default;
virtual ~XQModelSections() = default;
void addSectionEntry(const QModelIndex& idx, XQNodePtr sheetNode );
bool hasValidSection(const QString& sectionKey) const;
const XQModelSection& sectionFromRow( int row ) const;
const XQModelSection& sectionxqItemFromIndex( const QModelIndex& index ) const;
int firstRow(const QModelIndex& idx) const;
int lastRow(const QModelIndex& idx) const;
int lastRow(const XQModelSection& section) const;
void dump()const override;
};
#endif // XQMODELSECTIONS_H

79
model/xqnode.cpp Normal file
View File

@@ -0,0 +1,79 @@
/***************************************************************************
source::worx xtree
Copyright © 2024-2025 c.holzheuer
christoph.holzheuer@gmail.com
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
***************************************************************************/
#include <xqnode.h>
#include <xqitem.h>
void inspect( const XQNodePtr& node, int indent )
{
qDebug() << std::string(indent * 2, ' ').c_str() << node.use_count() << ": " << node->to_string();
if (node->has_children())
{
for (const auto& child : node->children())
{
inspect( child, indent + 1 );
}
}
}
// Overload the operator<< for MyClass and std::ostream
std::ostream& operator<<(std::ostream& os, const QString& obj)
{
// Simply call the getter and insert the string into the stream
os << obj.toStdString();
return os; // Return the stream for chaining
}
template<>
bool znode::zpayload<QString>::xstr_split_by(const QString& entry, const QString& sep, QString& key, QString& value )
{
int index = entry.indexOf(sep);
if(index < 0)
return false;
key = entry.left(index);
value = entry.mid( index+sep.length() );
return true;
}
template<>
QString znode::zpayload<QString>::xstr_sub_str( const QString& entry, int pos ) const
{
return entry.mid(pos);
}
template<>
bool znode::zpayload<QString>::xstr_is_empty(const QString& entry ) const
{
return entry.isEmpty();
}
template<>
const QString znode::zpayload<QString>::cType = "Type";
template<>
const QString znode::zpayload<QString>::cName = "Name";
template<>
const QString znode::zpayload<QString>::cValue = "Value";
template<>
const QString znode::zpayload<QString>::cFriendlyName = "FriendlyName";

172
model/xqnode.h Normal file
View File

@@ -0,0 +1,172 @@
/***************************************************************************
source::worx xtree
Copyright © 2024-2025 c.holzheuer
christoph.holzheuer@gmail.com
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
***************************************************************************/
#ifndef XQNODE_H
#define XQNODE_H
#include <iostream>
#include <memory>
#include <stack>
#include <iterator>
#include <QDebug>
#include <QModelIndex>
#include <znode.h>
#include <xqappdata.h>
#include <znode_factory.h>
// Overload the operator<< for QString and std::ostream
std::ostream& operator<<(std::ostream& os, const QString& obj);
// raw node
using XQNode = znode::zbasic_node<QString>;
// default shared node
using XQNodePtr = std::shared_ptr<znode::zbasic_node<QString>>;
// const ref on XQNodePtr, ok but what its good for?
//using const XQNodePtr& = const XQNodePtr&;
/*
class XQBasicSheetNode : public znode::zbasic_node<QString>
{
public:
//...
};
using XQSheetNode = std::shared_ptr<const XQBasicSheetNode>;
using XQSheetNodeCRef = const XQSheetNode&;
*/
///
/// __fix
/// sollte man einen XQNodePtr einführen, um 'setAttr<XQNodePtr>()' von
/// setAttr<XQNodePtr>() unterscheiden zu können?
///
/// nice try. (siehe oben). Haut aber so nicht hin, node.children() gibt wieder
/// Pointer auf die Basisklasse zurück, ( vgl. XQItemList -> QList<QStandardItem*>.
/// Erst dass behandeln!
///
// weak pointer to znode, used for parent()
using XQWeakNode = std::weak_ptr<znode::zbasic_node<QString>>;
// the node factory
using XQNodeFactory = znode::znode_factory<QString>;
class XQNodeList : public znode::zbasic_node<QString>::znode_list
{
friend class XQSimpleClipBoard;
public:
XQNodeList() = default;
virtual ~XQNodeList() = default;
};
class XNodeIterator
{
public:
using iterator_category = std::forward_iterator_tag;
using value_type = XQNode;
using difference_type = std::ptrdiff_t;
using pointer = XQNode*;
using reference = XQNode&;
XNodeIterator() = default;
XNodeIterator(XQNodePtr root)
{
if (root) {
_stack.push(root);
}
}
reference operator*() const {
return *_stack.top();
}
pointer operator->() const {
return _stack.top().get();
}
XNodeIterator& operator++() {
auto node = _stack.top();
_stack.pop();
for (auto it = node->children().rbegin(); it != node->children().rend(); ++it)
{
_stack.push(*it);
}
return *this;
}
XNodeIterator operator++(int) {
XNodeIterator tmp = *this;
++(*this);
return tmp;
}
bool operator==(const XNodeIterator& other) const {
return _stack == other._stack;
}
bool operator!=(const XNodeIterator& other) const {
return !(*this == other);
}
private:
std::stack<XQNodePtr> _stack;
};
// Define the tree class with begin and end methods
class XTree
{
public:
XTree(XQNodePtr root)
: _root(root)
{}
XNodeIterator begin()
{
return XNodeIterator(_root);
}
XNodeIterator end()
{
return XNodeIterator();
}
private:
XQNodePtr _root;
};
//void inspect( XQNodePtr node, int offSet=0 );
void inspect( const XQNodePtr& node, int indent=0 );
Q_DECLARE_METATYPE(XQNodePtr);
#endif // XQNODE_H

59
model/xqnodewriter.cpp Normal file
View File

@@ -0,0 +1,59 @@
/***************************************************************************
source::worx xtree
Copyright © 2024-2025 c.holzheuer
christoph.holzheuer@gmail.com
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
***************************************************************************/
#include <xqnodewriter.h>
#include <QFile>
#include <QXmlStreamWriter>
#include <xqnode.h>
void XQNodeWriter::dumpTree( XQNodePtr rootNode, const QString& fileName ) const
{
QFile treeFile( fileName );
if (!treeFile.open(QIODevice::WriteOnly | QIODevice::Text))
throw XQException("can't open", fileName);
QXmlStreamWriter writer(&treeFile);
writer.setAutoFormatting(true); // Makes the output more readable
writer.writeStartDocument();
dumpNode( writer, rootNode );
writer.writeEndDocument();
treeFile.close();
}
void XQNodeWriter::dumpNode( QXmlStreamWriter& writer, XQNodePtr node ) const
{
//qDebug() << " --- dumpNode: id:" << node._id;
writer.writeStartElement(node->tag_name() );
if( !node->attributes().empty() )
{
for( const auto& attrEntry : node->attributes() )
writer.writeAttribute( attrEntry.first , attrEntry.second );
}
if( node->has_children() )
{
for (auto& child : node->children())
dumpNode( writer, child );
}
writer.writeEndElement();
}

42
model/xqnodewriter.h Normal file
View File

@@ -0,0 +1,42 @@
/***************************************************************************
source::worx xtree
Copyright © 2024-2025 c.holzheuer
christoph.holzheuer@gmail.com
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
***************************************************************************/
#ifndef XQNODEWRITER_H
#define XQNODEWRITER_H
#include <Qt>
#include "qxmlstream.h"
#include <xqnode.h>
class QString;
class XQNodeWriter
{
public:
XQNodeWriter() = default;
virtual ~XQNodeWriter() = default;
void dumpTree( XQNodePtr rootNode, const QString& fileName ) const;
protected:
void dumpNode( QXmlStreamWriter& writer, XQNodePtr node ) const;
};
#endif // XQNODEWRITER_H

View File

@@ -0,0 +1,65 @@
/***************************************************************************
source::worx xtree
Copyright © 2024-2025 c.holzheuer
christoph.holzheuer@gmail.com
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
***************************************************************************/
#include <xqselectionmodel.h>
#include <xqitem.h>
XQSelectionModel::XQSelectionModel(QAbstractItemModel* model)
: QItemSelectionModel(model)
{
}
XQSelectionModel::XQSelectionModel(QAbstractItemModel* model, QObject* parent)
: QItemSelectionModel(model, parent)
{
}
void XQSelectionModel::select(const QItemSelection& selection, QItemSelectionModel::SelectionFlags command)
{
// step #0: fetch selected indices.
QModelIndexList list = selection.indexes();
if (list.isEmpty() || selectedRows().isEmpty() )
return QItemSelectionModel::select(selection, command);
// fetch first index
QModelIndex firstValid = list.first();
if (hasSelection() )
firstValid = selectedRows().first();
//XQItem& firstItem = XQItem::xqItemFromIndex(firstValid);
//if( firstItem.isValid() )
{
XQNodePtr firstNode = XQItem::xqItemFromIndex(firstValid).contentNode();
QItemSelection newSelection;
// __fixme! das crasht!
for (const QModelIndex& idx : list)
{
XQNodePtr nextNode = XQItem::xqItemFromIndex(idx).contentNode();
if (!nextNode || idx.data().toString().isEmpty() || nextNode->tag_name() != firstNode->tag_name() )
break;
newSelection.select(idx, idx);
}
return QItemSelectionModel::select(newSelection, command);
}
QItemSelectionModel::select(selection, command);
}

41
model/xqselectionmodel.h Normal file
View File

@@ -0,0 +1,41 @@
/***************************************************************************
source::worx xtree
Copyright © 2024-2025 c.holzheuer
christoph.holzheuer@gmail.com
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
***************************************************************************/
#ifndef XQSELECTIONMODEL_H
#define XQSELECTIONMODEL_H
#include <QItemSelectionModel>
#include <QObject>
/**
* @brief Extends QItemSelectionModel so that the selection is limited to a single section entry.
*/
class XQSelectionModel : public QItemSelectionModel
{
Q_OBJECT
public:
XQSelectionModel(QAbstractItemModel* model = nullptr);
XQSelectionModel(QAbstractItemModel* model, QObject* parent);
virtual ~XQSelectionModel() = default;
public slots:
void select(const QItemSelection& selection, QItemSelectionModel::SelectionFlags command) override;
};
#endif // XQSELECTIONMODEL_H

View File

@@ -0,0 +1,49 @@
/***************************************************************************
source::worx xtree
Copyright © 2024-2025 c.holzheuer
christoph.holzheuer@gmail.com
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
***************************************************************************/
#include <xqsimpleclipboard.h>
#include <xqmodel.h>
bool XQSimpleClipBoard::canPaste( const QModelIndex& curIdx ) const
{
bool pasteOk = false;
if( !isEmpty() )
{
XQItem& item = XQItem::xqItemFromIndex(curIdx);
// __fixme! header items haben keinen ZNode!
qDebug() << " --- can paste: " << item.contentNode()->tag_name() << " nodelist: " << front().contentNode->tag_name();
// paste is only allowed for the same component.type, which
// is coded in the tag_type
pasteOk = item.contentNode()->tag_name() == front().contentNode->tag_name();
}
else
{
qDebug() << " -- ClipBoard: nodelist empty!";
}
return pasteOk;
}
void XQSimpleClipBoard::saveNodes( const QModelIndexList& list )
{
clear();
for( auto entry : list )
{
XQNodePtr contentNode = XQItem::xqItemFromIndex( entry ).contentNode();
// im clipboard brauchen wir eine eltern-lose kopie des knotens
push_back( {entry.row(), contentNode->own_pos(), contentNode->clone() } );
}
}

36
model/xqsimpleclipboard.h Normal file
View File

@@ -0,0 +1,36 @@
/***************************************************************************
source::worx xtree
Copyright © 2024-2025 c.holzheuer
christoph.holzheuer@gmail.com
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
***************************************************************************/
#ifndef XQSIMPLECLIPBOARD_H
#define XQSIMPLECLIPBOARD_H
#include <xqitem.h>
#include <xqcommand.h>
class XQSimpleClipBoard : public XQNodeStore
{
public:
XQSimpleClipBoard() = default;
virtual ~XQSimpleClipBoard() = default;
bool canPaste( const QModelIndex& curIdx ) const;
void saveNodes( const QModelIndexList& list ) override;
};
#endif // XQSIMPLECLIPBOARD_H

22
nodes/znode.cpp Normal file
View File

@@ -0,0 +1,22 @@
/***************************************************************************
source::worx xtree
Copyright © 2024-2025 c.holzheuer
christoph.holzheuer@gmail.com
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
***************************************************************************/
#include <znode.h>
namespace znode
{
int zid::s_Count{0};
} // namespace znode

389
nodes/znode.h Normal file
View File

@@ -0,0 +1,389 @@
/***************************************************************************
source::worx xtree
Copyright © 2024-2025 c.holzheuer
christoph.holzheuer@gmail.com
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
***************************************************************************/
#ifndef ZNODE_H
#define ZNODE_H
#include <vector>
#include <string>
#include <memory>
//#include <typeinfo>
#include <QString>
#include <QDebug>
#include <xqmaptor.h>
#include <xsingleton.h>
#include <znode_iterator.h>
//#include <znode_vector.h>
#include <znode_id.h>
#include <znode_payload.h>
namespace znode
{
/// ----------------- snip 8< -----------------------------------------------------------------------------------------------------------------------------
// forward declaration of base class zbasic_node ...
//template<class str_t>
//class zbasic_node;
// ... used here for conveniance typedef
//template<class str_t>
//using zshared_node = std::shared_ptr<zbasic_node<str_t>>;
// main class
template<class str_t>
class zbasic_node : public zid, public zpayload<str_t>, public std::enable_shared_from_this<zbasic_node<str_t>>
{
public:
using str_cref = const str_t&;
using str_list = std::vector<str_t>;
//using zshared_node = std::shared_ptr<zbasic_node>;
//using znode_list = znode_vector<zbasic_node>;
//using znode_list = znode_vector<zshared_node<str_t>>;
//using znode_list = std::vector<zshared_node<str_t>>;
using zweak_node = std::weak_ptr<zbasic_node>;
using zshared_node = std::shared_ptr<zbasic_node>;
using znode_list = std::vector<zshared_node>;
using zshared_cref = const std::shared_ptr<zbasic_node>&;
using ziterator = znode_iterator<zbasic_node>;
protected:
zweak_node _parent;
znode_list _children;
struct match_node
{
match_node( zbasic_node* match )
: _match{match}
{}
bool operator()( const zshared_node& node )
{
return _match == node.get();
}
zbasic_node* _match{};
};
public:
static zshared_node make_node( str_cref arg1, str_cref arg2 = "" , zshared_cref parent = nullptr )
{
return std::make_shared<zbasic_node>( arg1, arg2, parent );
}
zbasic_node() = default;
// ...
zbasic_node( str_cref tag_name, zshared_cref parent = nullptr )
: zpayload<str_t>{tag_name}, _parent{parent}
{
}
// ...
zbasic_node( str_cref tag_name, str_cref value, zshared_cref parent = nullptr )
: zpayload<str_t>{tag_name,value}, _parent{parent}
{
}
zbasic_node( str_cref tag_name, const str_list& attributes, zshared_cref parent = nullptr )
: zbasic_node{tag_name, parent}
{
for( str_cref entry : attributes )
{
str_t key_value, data_value;
if( xstr_split_by( entry, "=", key_value, data_value) )
set_attribute( key_value, data_value );
}
}
virtual ~zbasic_node() = default;
// Kopieren ist hier nicht sinnvoll (Child-Pointer müssen konsistent bleiben)
zbasic_node(const zbasic_node&) = delete;
zbasic_node& operator=(const zbasic_node&) = delete;
// Bewegen geht (shared_from_this bleibt gültig)
zbasic_node(zbasic_node&&) noexcept = default;
zbasic_node& operator=(zbasic_node&&) noexcept = default;
virtual zshared_node clone(const zshared_node& parent = nullptr ) const
{
// copy als shared ptr erzeugen
zshared_node new_me = std::make_shared<zbasic_node>(this->_tag_name, this->_value );
// auch die attribute kopieren ...
new_me->_attributes = this->_attributes;
// ... und, so vorhanden, den parent-node.
new_me->_parent = parent;
// kinder kopieren
for (const zshared_node& child : _children)
new_me->_children.push_back( child->clone( new_me ) );
return new_me;
}
// STL-ish traverse iterators
auto begin()
{
return ziterator(this);
}
auto end()
{
return ziterator(nullptr);
}
// ... set_int
// ... as_int
//zweak_node parent()
zshared_node parent() const
{
return _parent.lock();
}
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())
return *(it);
//return zshared_node( make_node("WTF?") );
return zshared_node();
}
inline const znode_list& children() const
{
return _children;
}
bool has_children() const
{
return !children().empty();
}
zshared_node first_child()
{
if(!children().empty())
return children().front();
return nullptr;
}
zshared_node last_child()
{
if(!children().empty())
return children().back();
return nullptr;
}
zshared_node child( int idx )
{
if(idx>-1 && idx<children().size())
return _children[idx];
return nullptr;
}
int add_child( const zshared_node& node )
{
_children.push_back( node );
node->_parent = this->shared_from_this();
return int(children().size() - 1);
}
int add_child_at( int idx, const zshared_node& node )
{
_children.insert(children().begin() + idx, node );
node->_parent = this->shared_from_this();
return int(children().size() - 1);
}
void add_me_at( int offset )
{
if( parent() )
parent()->add_child_at( offset, this->shared_from_this() );
else
qDebug() << " -- fick2"; // shold throw?
}
void add_me_at( int offset, const zshared_node& parent_node )
{
if( parent_node )
{
_parent = parent_node;
parent_node->add_child_at( offset, this->shared_from_this() );
}
else
qDebug() << " -- fick4"; // shold throw?
}
int own_pos()
{
if( parent())
return parent()->child_pos( this->shared_from_this() );
return -1;
}
//int child_pos(zbasic_node* child)
int child_pos(const zshared_node& child)
{
//auto pos = std::find_if(children().begin(), children().end(), match_node(child) );
auto pos = std::find(children().begin(), children().end(), child );
if ( pos != children().end() )
return std::distance( children().begin(), pos );
return -1;
}
//zshared_node unlink_child( zbasic_node* node )
zshared_node unlink_child( const zshared_node& node )
{
auto it = std::find(_children.begin(), _children.end(), node);
if (it == _children.end())
return nullptr;
zshared_node removed = *it;
// Parent-Zeiger im Kind zurücksetzen
removed->_parent.reset();
_children.erase(it);
return removed;
}
void unlink_self()
{
if(parent())
parent()->unlink_child( this->shared_from_this() );
else
qDebug() << " -- fuck: ";
}
zshared_node find_child_by_attribute(str_cref attrkey, str_cref attrvalue )
{
for( auto child : _children )
{
qDebug() << " --#- " << child->name() << " : " << child->has_attribute( attrkey, attrvalue );
if( child->has_attribute( attrkey, attrvalue ))
return child;
}
return zshared_node();
}
zshared_node find_child_by_tag_name(str_cref tagname )
{
for( auto child : _children )
{
if( child->tag_name() == tagname )
return child;
}
return zshared_node();
}
zshared_node find_child_by_id( int id )
{
for (auto child : _children )
{
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;
}
// find ...
// depth first ...
// by attr
// by child
// by value
// by find( auto xxx )
// ...
};
class zbasic_node_walker
{
public:
virtual void begin()
{}
template<class str_t>
void for_each_node( zbasic_node<str_t>* node );
virtual void end()
{}
};
} //namespace znode
#endif // znode_H

123
nodes/znode_factory.h Normal file
View File

@@ -0,0 +1,123 @@
/***************************************************************************
source::worx xtree
Copyright © 2024-2025 c.holzheuer
christoph.holzheuer@gmail.com
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
***************************************************************************/
#ifndef ZNODE_FACTORY_H
#define ZNODE_FACTORY_H
#include <pugixml.hpp>
#include <znode.h>
class xtree;
/*
nodes: nackt also ungekaspselt?
-> children()
-> attributes()
attributes: ja was seid ihr denn? als string gelesen, als string geschrieben, aber dazwischen?
-> std::variant<bool...> mit enum type{t_bool = 0 ...};
-> conversion mit boost::lexical_cast<> bzw. std::to_string() und std::stoi(), std::stod()
-> beim parsen konvertieren? contains '.'? is_number?
-> betrifft tag_values und tag_attributes
-> vorher definieren? attribute 'voltage' == double, oder gar mehr: unit V, double, range
-> über xs:double?
model: muss ich wirklich jeden attibute node einzeln angeben?
*/
namespace znode
{
template<class str_t>
class znode_factory
{
public:
using str_cref = const str_t&;
using zshared_node = std::shared_ptr<zbasic_node<str_t>>;
znode_factory() = default;
virtual ~znode_factory() = default;
zshared_node load_tree( const std::string& filename )
{
pugi::xml_document tree_document;
// load document
pugi::xml_parse_result result = tree_document.load_file( filename.c_str() );
if( !result )
{
throw XQException( "znode_factory::load_tree: parse error: ", result.description() );
}
//MemberFunc func = &znode_factory::process_node;
//xtreewalker<znode_factory, MemberFunc> parser(this,func);
//_current_depth = -1;
//tree_document.traverse(parser);
//zbasic_node<str_t>* root_node = new zbasic_node<str_t>*("root!");
zshared_node root_node = zbasic_node<str_t>::make_node("root!");
//T root_node = T::make_node( "root!" );
// prepare root == model !?
pugi::xml_node tmp_node = tree_document.first_child();
while(tmp_node)
{
//qDebug() << " --- znode_factory building: " << tmp_node.name();
create_node( tmp_node, root_node );
tmp_node = tmp_node.next_sibling();
}
//znode::zmeas_para<QString>* xxx = new znode::zmeas_para<QString>("mookoo!");
//xxx->apply_command(42);
// _root_node->apply_command(42);
//size_t idx = _root_node->add_child( xxx);
//qDebug() << " jo: " << _root_node->child(idx)->tag_name();
return root_node;
}
protected:
void create_node(const pugi::xml_node& xml_node, zshared_node parent)
{
//T* new_node = new T( node.name(), node.child_value(), parent );
//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 );
parent->add_child( new_node );
if( !xml_node.attributes().empty() )
{
for (pugi::xml_attribute attr: xml_node.attributes())
new_node->set_attribute( attr.name(), attr.value() );
}
if( !xml_node.children().empty() && std::string( xml_node.child_value() ).empty() )
{
for (pugi::xml_node child : xml_node.children())
create_node( child, new_node );
}
}
};
}
#endif // ZNODE_FACTORY_H

33
nodes/znode_id.h Normal file
View File

@@ -0,0 +1,33 @@
#ifndef ZNODE_ID_H
#define ZNODE_ID_H
namespace znode
{
struct zid
{
zid()
{
static int s_ID{0};
_id = s_ID++;
s_Count++;
//qDebug() << " --- con ID: " << _id << " count: " << s_Count;
}
virtual ~zid()
{
s_Count--;
//qDebug() << " --- del ID: " << _id << " count: " << s_Count;
}
static int s_Count;
int _id{0};
};
}
#endif // ZNODE_ID_H

124
nodes/znode_iterator.h Normal file
View File

@@ -0,0 +1,124 @@
/***************************************************************************
source::worx xtree
Copyright © 2024-2025 c.holzheuer
christoph.holzheuer@gmail.com
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
***************************************************************************/
#ifndef znode_iterator_H
#define znode_iterator_H
#include <iterator>
namespace znode
{
template<class T>
struct znode_iterator
{
using iterator_category = std::forward_iterator_tag;
using difference_type = std::ptrdiff_t;
using value_type = T;
using pointer = T*; // or also value_type*
using reference = T&; // or also value_type&
znode_iterator()
: _root{},_node{}
{}
znode_iterator(pointer node)
: _root{node},_node{node}
{}
void set_node(pointer node)
{
_root = node;
_node = node;
}
pointer get() // const
{
return _node;
}
int level() // const
{
return _level;
}
pointer operator->()
{
return _node;
}
reference operator*()
{
return *(operator->());
}
operator bool() const
{
return _node != nullptr;
}
// Prefix increment
znode_iterator& operator++()
{
if( !_node )
return *this;
// depth first: do we have children?
if( _node->has_children() )
{
_node = _node->first_child().get();
_level++;
return *this;
}
// no children, so we take siblings
pointer tmp = _node->sibling().get();
pointer nxt = _node->parent().get();
while( !tmp && nxt )
{
tmp = nxt->sibling().get();
if( nxt == _root )
{
//qDebug() << " ouch ";
_node = nullptr;
return *this;
}
_level--;
nxt = nxt->parent().get();
}
_node = tmp;
return *this;
}
// Postfix increment
znode_iterator operator++(int) { znode_iterator tmp = *this; ++(*this); return tmp; }
friend bool operator== (const znode_iterator& a, const znode_iterator& b) { return a._node == b._node; };
friend bool operator!= (const znode_iterator& a, const znode_iterator& b) { return a._node != b._node; };
protected:
pointer _root{};
pointer _node{};
int _level{0};
};
}
#endif // znode_iterator_H

264
nodes/znode_payload.h Normal file
View File

@@ -0,0 +1,264 @@
#ifndef ZNODE_PAYLOAD_H
#define ZNODE_PAYLOAD_H
#include <vector>
#include <map>
//#include <znode_stringmap.h>
//#include <znode_attributes.h>
namespace znode
{
template<class str_t>
class zstringmap : public std::map<str_t,str_t>
{
public:
using str_cref = const str_t&;
using str_ptr = str_t*;
using str_list = std::vector<str_t>;
using zvalue = str_t; // could be any or variant
// __fixme: should this be a vector? or a maptor?
//using zattributes = std::map<str_t, zvalue>;
using zattributes = zstringmap<str_t>;
str_cref key_of(str_cref value) const
{
for( const auto& pair : *this )
{
if (pair.second == value)
return pair.first;
}
static str_t s_dummy;
return s_dummy;
}
};
template<class str_t>
class zpayload
{
public:
using str_cref = const str_t&;
using str_ptr = str_t*;
using str_list = std::vector<str_t>;
using zvalue = str_t; // could be any or variant
// __fixme: should this be a vector? or a maptor?
//using zattributes = std::map<str_t, zvalue>;
using zattributes = zstringmap<str_t>;
static const str_t cType;// = "Type";
static const str_t cName;// = "Name";
static const str_t cValue;// = "Value";
static const str_t cFriendlyName;
protected:
str_t _tag_name;
str_t _value;
zattributes _attributes;
static zvalue s_dummy_value;
public:
zpayload( str_cref tag_name )
: _tag_name{tag_name}
{}
// ...
zpayload( str_cref tag_name, str_cref value )
: _tag_name{tag_name}, _value{value}
{}
zpayload( str_cref tag_name, const str_list& attriblist )
: zpayload(tag_name)
{
for( str_cref entry : attriblist )
{
str_t key_value, data_value;
if( xstr_split_by( entry, "=", key_value, data_value) )
set_attribute( key_value, data_value );
}
}
str_cref tag_name() const
{
return _tag_name;
}
str_ptr tag_name_ptr()
{
return &_tag_name;
}
void set_tag_name( str_cref tag_name )
{
_tag_name = tag_name;
}
str_cref tag_value() const
{
return _value;
}
str_ptr tag_value_ptr()
{
return &_value;
}
void set_tag_value( str_cref value )
{
_value = value;
}
str_cref friendly_name() const
{
return attribute(cFriendlyName);
}
str_ptr friendly_name_ptr()
{
return &attribute(cFriendlyName);
}
str_cref type() const
{
return attribute(cType);
}
str_ptr type_ptr() const
{
return &attribute(cType);
}
void set_type( str_cref type )
{
set_attribute( cType, type);
}
str_cref name() const
{
return attribute(cName);
}
str_ptr name_ptr()
{
return &attribute(cName);
}
void set_name( str_cref name )
{
set_attribute( cType, name);
}
const zattributes& attributes() const
{
return _attributes;
}
bool has_attribute(str_cref key ) const
{
if( xstr_is_empty( key ) )
return false;
typename zattributes::const_iterator pos = _attributes.find(key);
if( pos == _attributes.end() )
return false;
return true;
}
bool test_attribute(str_cref key, str_cref value ) const
{
if( xstr_is_empty( key ) )
return false;
typename zattributes::const_iterator pos = _attributes.find(key);
if( pos == _attributes.end() )
return false;
if( !xstr_is_empty( value ) )
return (*pos).second == value;
return true;
}
const zvalue& attribute(str_cref key ) const
{
if( !xstr_is_empty( key ) )
{
typename zattributes::const_iterator pos = _attributes.find(key);
if (pos != _attributes.end())
{
const zvalue& result = (*pos).second;
if (!xstr_is_empty(result) && result[0] == '@')
return attribute( xstr_sub_str(result, 1) );
return result;
}
}
return s_dummy_value;
}
const zvalue* attribute_ptr(str_cref key ) const
{
if( !xstr_is_empty( key ) )
{
typename zattributes::const_iterator pos = _attributes.find(key);
if (pos != _attributes.end())
{
const zvalue& result = (*pos).second;
if (!xstr_is_empty(result) && result[0] == '@')
return attribute_ptr( xstr_sub_str(result, 1) );
return &result;
}
}
return &s_dummy_value;
}
void set_attribute(str_cref key, zvalue value )
{
if( !xstr_is_empty( key ) )
_attributes[key] = value;
}
// dumper
str_t to_string() const
{
str_t result = '<' +_tag_name +'>';
if( !xstr_is_empty(_value) )
result += ": " + _value;
if( !_attributes.empty() )
{
result += " [";
bool first = true;
for (const auto& entry : _attributes)
{
if(first)
{
result += entry.first + "=" + entry.second;
first = false;
continue;
}
result += ", " + entry.first + "=" + entry.second;
}
result += "]";
}
return result;
}
// forward helpers
bool xstr_split_by(str_cref entry, str_cref sep, str_t& key, str_t& value );
str_t xstr_sub_str(str_cref entry, int pos) const;
bool xstr_is_empty(str_cref key ) const;
};
// init statics
template<class str_t>
str_t zpayload<str_t>::s_dummy_value;
}
#endif // ZNODE_PAYLOAD_H

50
nodes/znode_vector.h Normal file
View File

@@ -0,0 +1,50 @@
#ifndef ZNODE_VECTOR_H
#define ZNODE_VECTOR_H
#include <vector>
//using znode_vector = std::vector<zplain_node*>;
template<class T>
class znode_vector : public std::vector<T*>
{
public:
// FIX! implement this!
// why delete??
znode_vector() = default;
znode_vector(const znode_vector&) = delete;
znode_vector& operator=(const znode_vector&) = delete;
virtual ~znode_vector()
{
}
znode_vector* clone() const
{
znode_vector* new_list = new znode_vector;
clone_into( *new_list );
return new_list;
}
void clone_into( znode_vector& new_list ) const
{
new_list.clear();
for(const auto entry : *this )
new_list.push_back( entry->clone() );
}
void clone_from( const znode_vector& src_list )
{
this->clear();
for(const auto entry : src_list )
this->push_back( entry->clone() );
}
};
#endif // ZNODE_VECTOR_H

77
pugixml/pugiconfig.hpp Normal file
View File

@@ -0,0 +1,77 @@
/**
* pugixml parser - version 1.14
* --------------------------------------------------------
* Copyright (C) 2006-2023, by Arseny Kapoulkine (arseny.kapoulkine@gmail.com)
* Report bugs and download new versions at https://pugixml.org/
*
* This library is distributed under the MIT License. See notice at the end
* of this file.
*
* This work is based on the pugxml parser, which is:
* Copyright (C) 2003, by Kristen Wegner (kristen@tima.net)
*/
#ifndef HEADER_PUGICONFIG_HPP
#define HEADER_PUGICONFIG_HPP
// Uncomment this to enable wchar_t mode
// #define PUGIXML_WCHAR_MODE
// Uncomment this to enable compact mode
// #define PUGIXML_COMPACT
// Uncomment this to disable XPath
// #define PUGIXML_NO_XPATH
// Uncomment this to disable STL
// #define PUGIXML_NO_STL
// Uncomment this to disable exceptions
// #define PUGIXML_NO_EXCEPTIONS
// Set this to control attributes for public classes/functions, i.e.:
// #define PUGIXML_API __declspec(dllexport) // to export all public symbols from DLL
// #define PUGIXML_CLASS __declspec(dllimport) // to import all classes from DLL
// #define PUGIXML_FUNCTION __fastcall // to set calling conventions to all public functions to fastcall
// In absence of PUGIXML_CLASS/PUGIXML_FUNCTION definitions PUGIXML_API is used instead
// Tune these constants to adjust memory-related behavior
// #define PUGIXML_MEMORY_PAGE_SIZE 32768
// #define PUGIXML_MEMORY_OUTPUT_STACK 10240
// #define PUGIXML_MEMORY_XPATH_PAGE_SIZE 4096
// Tune this constant to adjust max nesting for XPath queries
// #define PUGIXML_XPATH_DEPTH_LIMIT 1024
// Uncomment this to switch to header-only version
// #define PUGIXML_HEADER_ONLY
// Uncomment this to enable long long support
// #define PUGIXML_HAS_LONG_LONG
#endif
/**
* Copyright (c) 2006-2023 Arseny Kapoulkine
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/

13237
pugixml/pugixml.cpp Normal file

File diff suppressed because it is too large Load Diff

1516
pugixml/pugixml.hpp Normal file

File diff suppressed because it is too large Load Diff

290
trash/xqitemtype.cpp Normal file
View File

@@ -0,0 +1,290 @@
/***************************************************************************
source::worx xtree
Copyright © 2024 c.holzheuer
christoph.holzheuer@gmail.com
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
***************************************************************************/
//#include <cmath>
#include <xqitemtype.h>
#include <QDateTime>
#include <QDebug>
XQItemTypeMap XQItemType::s_ItemTypeMap;
///
/// XQItemType
///
XQItemType::XQItemType()
{
}
XQItemType::XQItemType( const XQItemType& other)
{
_renderStyle = other._renderStyle;
_editorType = other._editorType;
_itemFlags = other._itemFlags;
_unitType = other._unitType;
_contentFormat = other._contentFormat;
// wem gehören die dann? leck?
_fixedChoices = other._fixedChoices;
_typeIcon = other._typeIcon;
}
XQItemType::~XQItemType()
{
}
/*
XQItemType::XQItemType( RenderStyle aRenderStyle, EditorType aEditorType, Qt::ItemFlags aItemFlags, UnitType aUnitType, const QString& aContentFormat )
: renderStyle{aRenderStyle},
editorType{aEditorType},
itemFlags{aItemFlags},
unitType{aUnitType},
contentFormat{aContentFormat}
{
itemtypeKey = makeItemTypeKey(renderStyle,editorType,itemFlags,unitType,contentFormat);
};
*/
///
/// create attributes for from factory
///
void XQItemType::setAttribute(XQItem::RenderStyle renderStyle )
{
_renderStyle = renderStyle;
}
void XQItemType::setAttribute(XQItem::EditorType editorType )
{
_editorType = editorType;
}
void XQItemType::setAttribute(Qt::ItemFlags itemFlags )
{
_itemFlags = itemFlags;
}
void XQItemType::setAttribute(XQItem::UnitType unitType)
{
_unitType = unitType;
}
void XQItemType::setAttribute(const QString& contentFormat)
{
_contentFormat = contentFormat;
}
void XQItemType::setAttribute(QStandardItemModel *fixedChoices)
{
_fixedChoices = fixedChoices;
}
void XQItemType::setAttribute(const QIcon& typeIcon )
{
_typeIcon = typeIcon;
}
///
/// data() access for property sytem
///
XQItem::RenderStyle XQItemType::renderStyle() const
{
return _renderStyle;
}
XQItem::EditorType XQItemType::editorType() const
{
return _editorType;
}
XQItem::UnitType XQItemType::unitType() const
{
return _unitType;
}
const QString& XQItemType::contentFormat() const
{
return _contentFormat;
}
QStandardItemModel* XQItemType::fixedChoices() const
{
return _fixedChoices;
}
QString XQItemType::unitTypeStr() const
{
return XQItem::fetchUnitTypeStr( _unitType );
}
QString XQItemType::formatToSI( const QString& valueTxt ) const
{
/*
if( valueTxt.isEmpty() )
return valueTxt;
if( XQItem::ISODate == _unitType )
{
// format iso date
QDateTime dateTime = QDateTime::fromString(valueTxt, Qt::ISODate);
// fixme! make this configurable!
QString format = "dd.MM.yyyy HH:mm:ss"; // You can customize this format
// Format the QDateTime object into a human-readable string
return dateTime.toString(format);
}
QLocale sysLocale = QLocale::system();
sysLocale.setNumberOptions(sysLocale.numberOptions() | QLocale::OmitGroupSeparator);
double dVal = sysLocale.toDouble(valueTxt);
QString strVal, strPrefix;
int exp = (int)::log10f(dVal);
exp = (exp/3)*3;
double nVal = dVal;
if( !s_PrefixExponentMap.key(exp).isEmpty() )
nVal /= ::pow( 10,exp);
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, unitTypeStr() );
*/
return "fitze!";
}
QString XQItemType::unFormatFromSI(const QString& formText ) const
{
/*
QString input = formText.simplified();
// #1: strip numeric part
if( input.isEmpty() )
return input;
int idx = 0;
for( auto c : input )
{
if( c.isNumber() || c.toLower() == 'e' || c == '.' || c == ',' ||c == '-' || c == '+' )
idx++;
else
break;
}
if(!idx)
return QString("0");
QString numPart = formText.left(idx);
QString unitPart;
//if(idx + 1 < formText.size() )
unitPart = formText.right(idx - 1).simplified();
QLocale sysLocale = QLocale::system();
double dVal = sysLocale.toDouble(numPart);
if( unitPart.size() > 0 )
{
QString prefix = QString(unitPart[0]);
if( s_PrefixExponentMap.contains(prefix) )
dVal *= std::pow( 10.0, s_PrefixExponentMap[prefix] );
}
sysLocale.setNumberOptions(sysLocale.numberOptions() | QLocale::OmitGroupSeparator);
QString result = sysLocale.toString(dVal, 'f', 2);
//qDebug() << " convert: " << numPart << " : " << unitPart << " : " << dVal << " : " << result;
return result;
*/
return "fitze!";
}
///
/// --- statics --------------------------------------------------------------------------
///
QString XQItemType::makeItemTypeKey()
{
return makeItemTypeKey(
_renderStyle,
_editorType,
_itemFlags,
_unitType,
_contentFormat,
_fixedChoices,
_typeIcon
);
}
QString XQItemType::makeItemTypeKey(
XQItem::RenderStyle aRenderStyle,
XQItem::EditorType aEditorType,
Qt::ItemFlags aItemFlags,
XQItem::UnitType aUnitType,
const QString& aContentFormat,
QStandardItemModel* aFixedChoices,
const QIcon aIcon
)
{
auto combinedHash = [](const QStandardItemModel* model)
{
const quint32 prime = 0x9e3779b1; // große Zufallszahl
quint32 seed = 0;
for (int row = 0; row < model->rowCount(); ++row) {
const QString text = model->item(row)->text();
quint32 h = qHash(text);
// Verschmelzung nach Boost-Hash-Combine:
seed ^= h + prime + (seed << 6) + (seed >> 2);
}
return QString::number(seed);
};
return QString("%1:%2:%3:%4:%5:%7:%8").arg(
XQItem::fetchRenderStyleStr(aRenderStyle),
XQItem::fetchEditorTypeStr(aEditorType),
QString::number( aItemFlags.toInt() ),
XQItem::fetchUnitTypeStr(aUnitType),
aContentFormat,
combinedHash(aFixedChoices),
aIcon.name()
);
}
/*
void XQItemType::setItemType( XQItem* item, RenderStyle renderStyle, UnitType unitType )
{
XQItemType* itemType = XQItemType::makeItemType( renderStyle, unitType );
item->setItemType( itemType );
}
*/

149
trash/xqitemtype.h Normal file
View File

@@ -0,0 +1,149 @@
/***************************************************************************
source::worx xtree
Copyright © 2024 c.holzheuer
christoph.holzheuer@gmail.com
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
***************************************************************************/
#ifndef XQITEMTYPE_H
#define XQITEMTYPE_H
#include <QDebug>
#include <QMap>
#include <xqitem.h>
///
/// Ist das Unsinn!? Einfach ein QStandardItem mit data() nehmen?
/// Ok, das erspart die die attribs, aber wo ist der fette gewinn?
/// statt _editorType = x hast Du dann halt setData( QVariant::fromValue<>(x) );
/// Aber: Du kannst T abbilden auf QString ... und dann
///
using XQItemTypeMap = QMap<QString, XQItemType*>;
class XQItemType : public QObject
{
//?? needed?
Q_OBJECT
//das haut so nicht hin
//Q_PROPERTY(XQItem::RenderStyle renderStyle renderStyle getDate WRITE setrenderStyle )
public:
XQItemType();
XQItemType( const XQItemType& other);
virtual ~XQItemType();
//XQItemType( RenderStyle aRenderStyle, EditorType aEditorType, Qt::ItemFlags aItemFlags, UnitType aUnitType, const QString& aContentFormat );
// ContentFormat als enum?? Warum, für predefined types: int, double ?
// key for custom edit?
// key for custom format?
///
/// Setter für die XQItemFactory. Setzen das Attribute
/// _ohne_ den itemTypeCache zu beeinflussen
///
void setAttribute(XQItem::RenderStyle renderStyle );
void setAttribute(XQItem::EditorType editorType );
void setAttribute(Qt::ItemFlags itemFlags );
void setAttribute(XQItem::UnitType unitType);
void setAttribute(const QString& contentFormat);
void setAttribute(QStandardItemModel* fixedChoices);
void setAttribute(const QIcon& typeIcon);
QString unitTypeStr() const;
// FIX! Das gehört hier nicht her!
QString formatToSI(const QString& rawText ) const;
QString unFormatFromSI(const QString& valueText ) const;
/// data() access for property system
XQItem::RenderStyle renderStyle() const;
XQItem::EditorType editorType() const;
Qt::ItemFlags itemFlags() const;
XQItem::UnitType unitType() const;
const QString& contentFormat() const;
QStandardItemModel* fixedChoices() const;
template<typename T>
XQItemType* replaceAttribute(T attribute)
{
// eine kopie meiner selbst erzeugen
XQItemType* myClone = new XQItemType(*this);
return myClone;
}
XQItemType* replaceRenderStyle(XQItem::RenderStyle renderStyle );
XQItemType* replaceEditorType(XQItem::EditorType editorType);
XQItemType* replaceItemFlags(Qt::ItemFlags itemFlags);
XQItemType* replaceUnitType(XQItem::UnitType unitType);
XQItemType* replaceContentFormat(const QString& contentFormat);
XQItemType* replaceFixedChoices( QStandardItemModel* fixedChoices);
QString makeItemTypeKey();
static QString makeItemTypeKey(
XQItem::RenderStyle aRenderStyle,
XQItem::EditorType aEditorType,
Qt::ItemFlags aItemFlags,
XQItem::UnitType aUnitType,
const QString& aContentFormat,
QStandardItemModel* aFixedChoices,
const QIcon aIcon
);
protected:
static XQItemTypeMap s_ItemTypeMap;
XQItem::RenderStyle _renderStyle{XQItem::NoRenderStyle};
XQItem::EditorType _editorType{XQItem::NoEditorType};
Qt::ItemFlags _itemFlags;
XQItem::UnitType _unitType{XQItem::NoUnitType};
QString _contentFormat;
QStandardItemModel* _fixedChoices{};
QIcon _typeIcon;
QString _itemTypeKey;
/*
static void setItemType( XQItem* item, RenderStyle renderStyle, Qt::ItemFlags flags, UnitType unitType, const QString& format );
static void setStaticType( XQItem* item );
*/
// fix __ch
// static void setItemType( XQItem* item, const QString& renderStyle, const QString& unitType, const QString& itemTypeID );
//static XQItemType* addItemType( const QString& key, RenderStyle renderStyle, UnitType unitType);
//static XQItemType* makeItemType( RenderStyle renderStyle, UnitType unitType);
};
Q_DECLARE_METATYPE(XQItemType*);
/*
//??
done by Q_ENUM
Q_DECLARE_METATYPE(XQItemType::RenderStyle);
Q_DECLARE_METATYPE(XQItemType::UnitType);
Q_DECLARE_METATYPE(XQItemType);
*/
#endif // XQITEMTYPE_H

20
util/xqexception.cpp Normal file
View File

@@ -0,0 +1,20 @@
/***************************************************************************
source::worx xtree
Copyright © 2024-2025 c.holzheuer
christoph.holzheuer@gmail.com
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
***************************************************************************/
#include <xqexception.h>
XQException::XQException(const QString& what, const QString& param )
: std::runtime_error( param.isEmpty() ? what.toStdString() : QString( "%1: %2" ).arg(what,param).toStdString( ) )
{}

34
util/xqexception.h Normal file
View File

@@ -0,0 +1,34 @@
/***************************************************************************
source::worx xtree
Copyright © 2024-2025 c.holzheuer
christoph.holzheuer@gmail.com
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
***************************************************************************/
#ifndef XQEXCEPTION_H
#define XQEXCEPTION_H
#include <QString>
#include <stdexcept>
/**
* @brief Simple exception class
*/
class XQException : public std::runtime_error
{
public:
XQException( const QString& what, const QString& param="" );
};
#endif // XQEXCEPTION_H

76
util/xqmapindex.h Normal file
View File

@@ -0,0 +1,76 @@
/***************************************************************************
source::worx xtree
Copyright © 2024-2025 c.holzheuer
christoph.holzheuer@gmail.com
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
***************************************************************************/
#ifndef XQMAPINDEX_H
#define XQMAPINDEX_H
#include <QMap>
/**
* @brief Holds the string to index mapping for the QXMaptor classes
*/
class XQMapIndex : public QMap<QString, int>
{
public:
virtual ~XQMapIndex() = default;
void addKey(const QString& key, int index)
{
(*this)[key] = index;
}
int indexOf(const QString& key) const
{
if (contains(key))
return (*this)[key];
return -1;
}
void update(int index)
{
XQMapIndex newindex;
QMapIterator<QString, int> iter(*this);
while (iter.hasNext())
{
iter.next();
// item idx == kill-index: continue
// item idx < kill-index: store item
// item idx > kill-index: decrement & store item
int idx = iter.value();
if (idx == index)
continue;
if (idx > index)
idx--;
// schlüssel auch sichern
newindex[(iter.key())] = idx;
}
swap(newindex);
}
};
#endif // XQMAPINDEX_H

305
util/xqmaptor.h Normal file
View File

@@ -0,0 +1,305 @@
/***************************************************************************
source::worx xtree
Copyright © 2024-2025 c.holzheuer
christoph.holzheuer@gmail.com
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
***************************************************************************/
#ifndef XQMAPTOR_H
#define XQMAPTOR_H
#include <xqmapindex.h>
#include <xqexception.h>
/**
* @brief map + vector = XQMaptor, a template storage class whose data
* items can be accessed via string keys and int indices.
*/
template<class T>
class XQMaptor
{
public:
XQMaptor()
{
}
XQMaptor( int itemsize )
{
if( itemsize )
_data.resize( itemsize );
}
XQMaptor( const XQMaptor& src )
{
*this=src;
}
virtual ~XQMaptor()
{
}
XQMaptor& operator=( const XQMaptor& src )
{
if( this == &src )
return *this;
_data = src._data;
_index = src._index;
return *this;
}
// STL-like iterators
auto begin()
{
return _data.begin();
}
auto end()
{
return _data.end();
}
inline int size() const
{
return (int) _data.size();
}
inline bool isEmpty() const
{
return (_data.size()==0);
}
inline bool contains( int index ) const
{
return index < size() && index > -1;
}
inline bool contains( const QString& key ) const
{
return mapIndex().contains(key);
}
inline const XQMapIndex& mapIndex() const
{
return _index;
}
int indexOf( const QString& key ) const
{
return mapIndex().indexOf(key);
}
int indexOf(const T& entry) const
{
for (int i=0; i<_data.size(); ++i)
{
if (_data[i] == entry)
return i;
}
return -1;
}
virtual QString keyOf( int index ) const
{
return mapIndex().key( index );
}
T& operator[]( int index )
{
if( contains(index) )
return _data[index];
throw XQException("XQMaptor operator[ int index ]: out of range");
}
const T& operator[]( int index ) const
{
if ( contains(index) )
return _data[index];
throw XQException("XQMaptor const operator[ int index ]: out of range");
}
T& at( int index )
{
return (*this)[index];
}
const T& at( int index ) const
{
return (*this)[index];
}
T& operator[]( const QString& key )
{
if( key.isEmpty() || !contains(key) )
throw XQException("maprow operator[]: key empty || not found: " + key);
return _data[ _index[key] ];
}
const T& operator[]( const QString& key ) const
{
if (key.isEmpty() || !contains(key))
throw XQException("maprow operator[]: key empty || not found: " + key);
return _data[_index[key]];
}
T& at( const QString& key )
{
return (*this)[key];
}
const T& at( const QString& key ) const
{
return (*this)[key];
}
virtual int add( const T& item )
{
_data.push_back( item );
return _data.size()-1;
}
virtual void addAtIndex( int index, const T& item )
{
if(contains(index))
throw XQException( "QStringrow::add: index out of range!" );
_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 );
if( pos == _index.end() )
{
_data.push_back( item );
_index[key] = _data.size()-1;
}
else
{
_data[pos.value()] = item;
}
}
bool addAlias( const QString& key, const QString& alias )
{
// look for 'original' key
int key_idx = indexOf(key);
// quit if not found
if( key_idx < 0 )
return false;
// look for alias
int alias_idx = indexOf(alias);
// quit if found: don't overwrite anything
if( alias_idx > -1 )
return false;
// store alias
_index[ alias ] = key_idx;
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 );
if( idx<0 )
return false;
return killEntry( (int) idx );
}
virtual bool killEntry( int index )
{
if( index >= this->_data.size() )
return false;
// eintrag lschen
this->_data.erase( this->_data.begin()+index );
// index updaten
_index.update( index );
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)
Q_UNUSED(from)
Q_UNUSED(to)
throw XQException("XQMaptor: join not implemented!" );
return "--";
}
int replaceKey( const QString& oldkey, const QString& newkey )
{
int idx = indexOf( oldkey );
if( idx<0 || oldkey == newkey )
return idx;
_index.remove( oldkey );
_index[ newkey ] = idx;
return idx;
}
protected:
QVector<T> _data;
XQMapIndex _index;
};
#endif // XQMAPTOR_H

128
util/xqptrmaptor.h Normal file
View File

@@ -0,0 +1,128 @@
/***************************************************************************
source::worx xtree
Copyright © 2024-2025 c.holzheuer
christoph.holzheuer@gmail.com
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
***************************************************************************/
#ifndef XQPTRMAPTOR_H
#define XQPTRMAPTOR_H
#include <xqmaptor.h>
/**
* @brief A XQMaptor implementation for pointers to to data entries.
*/
template<class T>
class XQPtrMaptor : public XQMaptor<T*>
{
public:
virtual ~XQPtrMaptor()
{
for (int i = 0; i < this->_data.size(); ++i)
delete this->_data[i];
}
T& entry(const QString& key)
{
int i = this->indexOf(key);
if (i < 0)
throw XQException("XQPtrMaptor: entry: not found: " + key);
return *(this->_data[i]);
}
const T& entry(const QString& key) const
{
int i = this->indexOf(key);
if (i < 0)
throw XQException("XQPtrMaptor: entry: not found: " + key);
return *(this->_data[i]);
}
T& entry(int index)
{
if ((int)index < this->_data.size())
return *(this->_data[index]);
throw XQException("ddmapptr entry( int index ): out of range");
}
const T& entry(int index) const
{
if (index > 0 && index < this->_data.size())
return *(this->_data[index]);
throw XQException("ddmapptr const entry( int index ): out of range");
}
bool killEntry(const QString& key) override
{
int idx = this->indexOf(key);
// warum keine exception?
if (idx < 0)
return false;
return killEntry((int)idx);
}
bool killEntry(int index) override
{
T* item = this->_data[index];
if (XQMaptor<T*>::killEntry(index))
{
delete item;
return true;
}
return false;
}
bool removeEntry(const QString& key)
{
int idx = this->indexOf(key);
// warum keine exception?
if (idx < 0)
return false;
return removeEntry((int)idx);
}
bool removeEntry(int index)
{
if (index >= this->_data.size())
return false;
// eintrag löschen
this->_data.erase(this->_data.begin() + index);
// index updaten
this->_index.update(index);
return true;
}
void replace(int index, T* entry)
{
if ((int)index >= this->_data.size())
throw XQException("ddmapptr replace( int index ): out of range");
delete(this->_data[index]);
this->_data[index] = entry;
}
void replace(const QString& key, T* entry)
{
replace(this->indexOf(key), entry);
}
};
ö
#endif // XQPTRMAPTOR_H

48
util/xsingleton.h Normal file
View File

@@ -0,0 +1,48 @@
/***************************************************************************
source::worx xtree
Copyright © 2024-2025 c.holzheuer
christoph.holzheuer@gmail.com
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
***************************************************************************/
#ifndef XSINGLETON_H
#define XSINGLETON_H
/**
* @brief The classic singleton template interface.
*/
template <typename T>
class xsingleton
{
public:
//! Get the singleton instance.
static T& instance()
{
static T Instance;
return Instance;
}
protected:
xsingleton() {}
virtual ~xsingleton() {}
private:
xsingleton(xsingleton const &) = delete;
xsingleton& operator=(xsingleton const &) = delete;
};
#endif // XSINGLETON_H

47
util/xtreewalker.h Normal file
View File

@@ -0,0 +1,47 @@
/***************************************************************************
source::worx xtree
Copyright © 2024-2025 c.holzheuer
christoph.holzheuer@gmail.com
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
***************************************************************************/
#ifndef XTREEWALKER_H
#define XTREEWALKER_H
#include <pugixml.hpp>
#include <functional>
/**
* @brief A implentation of the pugi::xml treewalker class.
*/
template <typename O,typename M>
class xtreewalker : public pugi::xml_tree_walker
{
public:
xtreewalker( O* object, M member )
{
_call = std::bind(member, object, std::placeholders::_1, std::placeholders::_2);
}
virtual bool for_each(pugi::xml_node& node) override
{
return _call(node,depth());
}
protected:
std::function<bool(pugi::xml_node& node,int)> _call;
};
#endif // XTREEWALKER_H

68
widgets/xqcontextmenu.cpp Normal file
View File

@@ -0,0 +1,68 @@
/***************************************************************************
source::worx xtree
Copyright © 2024-2025 c.holzheuer
christoph.holzheuer@gmail.com
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
***************************************************************************/
#include <xqcontextmenu.h>
XQContextMenu::XQContextMenu(const QString& title, QWidget* parent )
: QMenu( title, parent )
{
/*
QAction* titleDummy = new QAction(title,this);
QWidget::addAction(titleDummy);
addSeparator();
titleDummy->setEnabled(false);
*/
}
XQContextMenu::XQContextMenu(QWidget* parent)
: QMenu( parent )
{
}
void XQContextMenu::addAction(const QString& text, XQCommand::CmdType commandType, bool enabled)
{
QAction* newAction = new QAction(text, this);
newAction->setData(commandType);
_actionMap[commandType] = newAction;
QWidget::addAction(newAction);
setActionEnabled( commandType, enabled );
}
void XQContextMenu::addAction(const QString& iconKey, const QString& name, XQCommand::CmdType commandType, bool enabled)
{
addAction(XQAppData::typeIcon( iconKey), name, commandType, enabled );
}
void XQContextMenu::addAction(const QIcon& icon, const QString& text, XQCommand::CmdType commandType, bool enabled)
{
QAction* newAction = new QAction(icon, text, this);
newAction->setData(commandType);
_actionMap[commandType] = newAction;
QWidget::addAction(newAction);
setActionEnabled( commandType, enabled );
}
void XQContextMenu::setActionEnabled(XQCommand::CmdType commandType, bool enabled)
{
if( _actionMap.contains(commandType) )
_actionMap[commandType]->setEnabled( enabled );
}

51
widgets/xqcontextmenu.h Normal file
View File

@@ -0,0 +1,51 @@
/***************************************************************************
source::worx xtree
Copyright © 2024-2025 c.holzheuer
christoph.holzheuer@gmail.com
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
***************************************************************************/
#ifndef XQCONTEXTMENU_H
#define XQCONTEXTMENU_H
#include <QMenu>
#include <QMap>
#include <xqcommand.h>
/**
* @brief A specialized QMenu for @see XQCommands
*/
class XQContextMenu : public QMenu
{
Q_OBJECT
public:
XQContextMenu(const QString& title, QWidget* parent = nullptr );
XQContextMenu(QWidget* parent = nullptr );
virtual ~XQContextMenu() = default;
void addAction(const QString& name, XQCommand::CmdType commandType, bool enabled );
void addAction(const QString& iconKey, const QString& name, XQCommand::CmdType commandType, bool enabled );
void addAction(const QIcon& icon, const QString& name, XQCommand::CmdType commandType, bool enabled );
void setActionEnabled(XQCommand::CmdType commandType, bool enabled);
protected:
QMap<int, QAction*> _actionMap;
};
#endif //; XQContextMenu_H

196
widgets/xqtreeview.cpp Normal file
View File

@@ -0,0 +1,196 @@
/***************************************************************************
source::worx xtree
Copyright © 2024-2025 c.holzheuer
christoph.holzheuer@gmail.com
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
***************************************************************************/
#include <QPainter>
#include <QTime>
#include "qheaderview.h"
#include <xqtreeview.h>
#include <xqmodel.h>
#define DB_TIMESTAMP QTime::currentTime().toString(" -- HH:mm:ss.zzz")
XQTreeView::XQTreeView(QWidget* parent)
: QTreeView(parent)
{
/*
setDragEnabled(true);
setAcceptDrops(true);
setDragDropOverwriteMode(true);
setDropIndicatorShown(false);
*/
setHeaderHidden(true);
setMouseTracking(true);
}
XQTreeView::~XQTreeView()
{
}
XQModel* XQTreeView::modelView()
{
return static_cast<XQModel*>(model());
}
// __fixme: necessary?
XQItem& XQTreeView::xqItemFromIndex(const QModelIndex& index )
{
return modelView()->xqItemFromIndex( index );
}
void XQTreeView::currentChanged(const QModelIndex& current, const QModelIndex& previous)
{
QTreeView::currentChanged(current, previous);
// edit comboboxes directly
//XQItem& currentItem = xqItemFromIndex(current);
// xx_fix!
/*
if (curreXQItem && curreXQItem->renderStyle() == XQItem::ComboBoxStyle )
{
QTreeView::edit(current);
}
*/
}
void XQTreeView::mouseResizeHeaderEntry(int xpos)
{
// resize colummn: minimal vertical margin in pixels
static const int s_MinimalMargin = 50;
QRect itemRect = visualRect(_indexToResize);
// new position different to item rect outer right position
int newPos = xpos - itemRect.right();
// current section size from header
int column = _indexToResize.column();
int sectionSize = columnWidth( column );
int maxPos = s_MinimalMargin + xpos;
// resize header and update view
if (maxPos <= width())
{
header()->resizeSection(column, sectionSize + newPos);
}
}
void XQTreeView::mouseMoveEvent(QMouseEvent* event)
{
// pixel Grenzwert zur Anzeige des Splitcursors
static const int s_CatchOffset = 5;
bool leftBtn = (event->buttons() & Qt::LeftButton);
QPoint eventPos = event->pos();
// splitcursor ist active
bool splitCursor = (cursor().shape() == Qt::SplitHCursor);
// sind wir schon am 'draggen'?
if (_indexToResize.isValid() && splitCursor && leftBtn)
{
return mouseResizeHeaderEntry(eventPos.x());
}
// nein, nocht nicht
QModelIndex idxFromPos = indexAt(eventPos);
// mousepointer is inside a header section
if ( xqItemFromIndex(idxFromPos).isHeaderStyle() )
{
QRect itemRect = visualRect(idxFromPos);
int crX = itemRect.topRight().x() - s_CatchOffset;
QRect catchRect = QRect(crX, itemRect.y(), s_CatchOffset, itemRect.height());
if (catchRect.contains(eventPos))
{
return setCursor(QCursor(Qt::SplitHCursor));
}
}
setCursor(QCursor(Qt::ArrowCursor));
QTreeView::mouseMoveEvent(event);
}
void XQTreeView::mouseDoubleClickEvent(QMouseEvent* event)
{
/*
QModelIndex idxFromPos = indexAt(event->pos());
if (idxFromPos.isValid())
{
if ( NTItem::isHeaderType(idxFromPos) && cursor().shape() == Qt::SplitHCursor)
{
return resizeColumnToContents(idxFromPos.column());
}
}
*/
QTreeView::mouseDoubleClickEvent(event);
}
void XQTreeView::mousePressEvent(QMouseEvent* event)
{
// case #1:
// Handle header resiszing
QPoint pos = event->pos();
QModelIndex index = indexAt(pos);
// set index for resize column if cursor for split is active
if (cursor().shape() == Qt::SplitHCursor)
{
_indexToResize = index;
}
QTreeView::mousePressEvent(event);
}
void XQTreeView::mouseReleaseEvent(QMouseEvent* event)
{
// reset index for resize column
_indexToResize = QModelIndex();
setCursor(QCursor(Qt::ArrowCursor));
QTreeView::mouseReleaseEvent(event);
}
void XQTreeView::wheelEvent(QWheelEvent* event)
{
// Ctrl-key down?
if (!event->modifiers().testFlag(Qt::ControlModifier))
// default processing
return QTreeView::wheelEvent(event);
// current size
int curSize = fontInfo().pointSize();
// increase?
if (event->angleDelta().y() > 0)
{
// "zoom in"
curSize += (curSize < 40) ? (1) : (0);
}
else
{
// "zoom out"
curSize -= (curSize > 8) ? (1) : (0);
}
// adjust size via stylesheet
setStyleSheet(QString("font: %1pt;").arg(curSize));
}

62
widgets/xqtreeview.h Normal file
View File

@@ -0,0 +1,62 @@
/***************************************************************************
source::worx xtree
Copyright © 2024-2025 c.holzheuer
christoph.holzheuer@gmail.com
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
***************************************************************************/
#ifndef XQTREEVIEW_H
#define XQTREEVIEW_H
#include <QTreeView>
#include <QMouseEvent>
#include <QDebug>
class XQItem;
class XQModel;
/**
* @brief A specialized QTreeView that will handle the drawing of
* empty or non-existing items in the future.
*/
class XQTreeView : public QTreeView
{
Q_OBJECT
Q_DECLARE_PRIVATE(QTreeView)
public:
XQTreeView(QWidget* parent = nullptr );
virtual ~XQTreeView();
XQModel* modelView();
XQItem& xqItemFromIndex(const QModelIndex& index );
protected:
void currentChanged(const QModelIndex& current, const QModelIndex& previous) override;
void mouseMoveEvent(QMouseEvent* event) override;
//! Mouse press event.used to emulate the behavior of a QHeaderView in the first line of the view
void mouseDoubleClickEvent(QMouseEvent* event) override;
//! Mouse release event.used to emulate the behavior of a QHeaderView in the first line of the view
void mouseReleaseEvent(QMouseEvent* event) override;
//! Mouse press event.used to emulate the behavior of a QHeaderView in the first line of the view
void mousePressEvent(QMouseEvent* event) override;
void mouseResizeHeaderEntry(int xpos);
//! Mouse wheel event.
void wheelEvent(QWheelEvent* event) override;
//! used by the mouse events
QModelIndex _indexToResize;
};
#endif // XQTREEVIEW_H

35
xml/modeldata1.xtr Normal file
View File

@@ -0,0 +1,35 @@
<?xml version='1.0' encoding='UTF-8'?>
<Project ProjectID="HA01" FriendlyName="@ProjectName" ProjectName="Wiebelbach West" Established="2006" WattPeak="84000" State="runnning">
<Components>
<Panel PanelID="#1 JA 01" FriendlyName="@PanelName" PanelName="JA 01 Solar T62B" Manufacturer="JA Solar 1 XX" WattPeak="620" Height="2,70" Width="1,10" Weight="12" MaxVolt="67" MaxAmpere="11">
</Panel>
<Panel PanelID="#2 JA 02" FriendlyName="@PanelName" PanelName="JA 02 Solar X58C" Manufacturer="JA Solar 2" WattPeak="440" Height="1,70" Width="1,10" Weight="12" MaxVolt="42" MaxAmpere="11"/>
<Panel PanelID="#3 JA 03" FriendlyName="@PanelName" PanelName="JA 03 Solar T62B" Manufacturer="JA Solar 3" WattPeak="620" Height="2,70" Width="1,10" Weight="12" MaxVolt="67" MaxAmpere="11"/>
<Panel PanelID="#4 JA 04" FriendlyName="@PanelName" PanelName="JA 04 Solar X58C" Manufacturer="JA Solar 4" WattPeak="440" Height="1,70" Width="1,10" Weight="12" MaxVolt="42" MaxAmpere="11"/>
<Panel PanelID="#5 JA 05" FriendlyName="@PanelName" PanelName="JA 05 Solar X58C" Manufacturer="JA Solar 5" WattPeak="440" Height="1,70" Width="1,10" Weight="12" MaxVolt="42" MaxAmpere="11"/>
<Panel PanelID="#6 JA 06" FriendlyName="@PanelName" PanelName="JA 06 Solar X58C" Manufacturer="JA Solar 6" WattPeak="440" Height="1,70" Width="1,10" Weight="12" MaxVolt="42" MaxAmpere="11"/>
<Inverter InverterID="#1 HM600 01" FriendlyName="@InverterName" InverterName="01 HM600 S2 TMax" Manufacturer="HoyMiles" MaxPowerInput="2000" MaxPowerInputChoice="2000;4000;6000" MaxPowerOutput="600" NumStrings="2" Weight="28"/>
<Inverter InverterID="#2 HM800 02" FriendlyName="@InverterName" InverterName="02 HM800 S2 TMax" Manufacturer="HoyMiles" MaxPowerInput="4000" MaxPowerInputChoice="2000;4000;6000" MaxPowerOutput="800" NumStrings="2" Weight="29"/>
<Inverter InverterID="#3 HM1600 03" FriendlyName="@InverterName" InverterName="03 HM1600 S4 TMax" Manufacturer="HoyMiles" MaxPowerInput="6000" MaxPowerInputChoice="2000;4000;6000" MaxPowerOutput="1600" NumStrings="4" Weight="32"/>
<Inverter InverterID="#4 D12K 04" FriendlyName="@InverterName" InverterName="04 HM600 S2 TMax" Manufacturer="Deye" MaxPowerInput="12000,33" MaxPowerInputChoice="6000;8000;12000" MaxPowerOutput="600" NumStrings="2" Weight="28"/>
<Battery BatteryID="#1 BYD 01" FriendlyName="@BatteryName" BatteryName="01 BYD T01 Stackable" Manufacturer="BYD" Capacity="4500" Yield="90" MaxCurrent="120" MaxVolt="48">
<AdditionalData DataItem="Image" DataValue="image.png"/>
<AdditionalData DataItem="Manual" DataValue="manual.docx"/>
<AdditionalData DataItem="Certificate" DataValue="certificate.pdf"/>
</Battery>
<Battery BatteryID="#2 BYD 02" FriendlyName="@BatteryName" BatteryName="02 BYD T02 Stackable" Manufacturer="BYD" Capacity="9000" Yield="94" MaxCurrent="120" MaxVolt="48"/>
<Battery BatteryID="#3 BYD 03" FriendlyName="@BatteryName" BatteryName="03 BYD T01 Stackable" Manufacturer="BYD" Capacity="4500" Yield="86" MaxCurrent="120" MaxVolt="48"/>
<Battery BatteryID="#4 BYD 04" FriendlyName="@BatteryName" BatteryName="04 BYD T02 Stackable" Manufacturer="BYD" Capacity="9000" Yield="98" MaxCurrent="120" MaxVolt="48"/>
<Battery BatteryID="#5 GroWatt 05 G2K" FriendlyName="@BatteryName" BatteryName="05 BYD T01 Stackable" Manufacturer="GroWatt" Capacity="4500" Yield="94" MaxCurrent="120" MaxVolt="48"/>
<Battery BatteryID="#6 GroWatt 06 G4K" FriendlyName="@BatteryName" BatteryName="06 BYD T02 Stackable" Manufacturer="GroWatt" Capacity="9000" Yield="49" MaxCurrent="120" MaxVolt="48"/>
<Battery BatteryID="#7 Pyne 07 G4K" FriendlyName="@BatteryName" BatteryName="07 Pyne K7 Stackable" Manufacturer="PyNe" Capacity="9000" Yield="49" MaxCurrent="120" MaxVolt="48"/>
</Components>
<IrgendWasAnderes>
</IrgendWasAnderes>
</Project>

31
xml/modeldata2.xtr Normal file
View File

@@ -0,0 +1,31 @@
<?xml version='1.0' encoding='UTF-8'?>
<Project ProjectID="HA02" FriendlyName="@ProjectName" ProjectName="Gerbrunn Ost" Established="2006" WattPeak="9840" State="planned">
<Components>
<Panel PanelID="Jingli 01" FriendlyName="@PanelName" PanelName="Jingli 01 Solar T62B" Manufacturer="Jingli Solar" WattPeak="620" Height="2,70" Width="1,10" Weight="12" MaxVolt="67" MaxAmpere="11">
<AdditionalData DataItem="Image" DataValue="image,png"/>
<AdditionalData DataItem="Manual" DataValue="manual,docx"/>
<AdditionalData DataItem="Certificate" DataValue="certificate,pdf"/>
</Panel>
<Panel PanelID="Jingli 02" FriendlyName="@PanelName" PanelName="Jingli 02 Solar X58C" Manufacturer="Jingli Solar" WattPeak="440" Height="1,70" Width="1,10" Weight="12" MaxVolt="42" MaxAmpere="11"/>
<Panel PanelID="Jingli 03" FriendlyName="@PanelName" PanelName="Jingli 03 Solar T62B" Manufacturer="Jingli Solar" WattPeak="620" Height="2,70" Width="1,10" Weight="12" MaxVolt="67" MaxAmpere="11"/>
<Inverter InverterID="HM600 01" FriendlyName="@InverterName" InverterName="01 HM600 S2 TMax" Manufacturer="HoyMiles" MaxPowerInput="4000" MaxPowerInputChoice="2000;4000;6000" MaxPowerOutput="600" NumStrings="2" Weight="28"/>
<Inverter InverterID="HM800 02" FriendlyName="@InverterName" InverterName="02 HM800 S2 TMax" Manufacturer="HoyMiles" MaxPowerInput="4000" MaxPowerInputChoice="2000;4000;6000" MaxPowerOutput="800" NumStrings="2" Weight="29"/>
<Inverter InverterID="HM1600 03" FriendlyName="@InverterName" InverterName="03 HM1600 S4 TMax" Manufacturer="HoyMiles" MaxPowerInput="4000" MaxPowerInputChoice="2000;4000;6000" MaxPowerOutput="1600" NumStrings="4" Weight="32"/>
<Inverter InverterID="D12K 04" FriendlyName="@InverterName" InverterName="04 HM600 S2 TMax" Manufacturer="Deye" MaxPowerInput="4000" MaxPowerInputChoice="2000;4000;6000" MaxPowerOutput="600" NumStrings="2" Weight="28"/>
<Battery BatteryID="BYD 01" FriendlyName="@BatteryName" BatteryName="01 BYD T01 Stackable" Manufacturer="BYD" Capacity="4500" Yield="88" MaxCurrent="120" MaxVolt="48">
<AdditionalData DataItem="Image" DataValue="image.png"/>
<AdditionalData DataItem="Manual" DataValue="manual.docx"/>
<AdditionalData DataItem="Certificate" DataValue="certificate.pdf"/>
</Battery>
<Battery BatteryID="BYD 04" FriendlyName="@BatteryName" BatteryName="04 BYD T02 Stackable" Manufacturer="BYD" Capacity="9000" Yield="32" MaxCurrent="120" MaxVolt="48"/>
<Battery BatteryID="GroWatt 05 G2K" FriendlyName="@BatteryName" BatteryName="05 BYD T01 Stackable" Manufacturer="PylonTech" Capacity="4500" Yield="46" MaxCurrent="120" MaxVolt="48"/>
<Battery BatteryID="GroWatt 06 G4K" FriendlyName="@BatteryName" BatteryName="06 BYD T02 Stackable" Manufacturer="PylonTech" Capacity="9000" Yield="94" MaxCurrent="120" MaxVolt="48">
</Battery>
</Components>
</Project>

26
xml/modeldata3.xtr Normal file
View File

@@ -0,0 +1,26 @@
<?xml version='1.0' encoding='UTF-8'?>
<Project ProjectID="HA03" FriendlyName="@ProjectName" ProjectName="Neubrunn Süd" Established="2006" WattPeak="9840" State="runnning">
<Components>
<Panel PanelID="AIKO 01" FriendlyName="@PanelName" PanelName="AIKO 01 Solar T62B" Manufacturer="AIKO Solar" WattPeak="620" Height="2,70" Width="1,10" Weight="12" MaxVolt="67" MaxAmpere="11">
<AdditionalData DataItem="Image" DataValue="image.png"/>
<AdditionalData DataItem="Manual" DataValue="manual.docx"/>
<AdditionalData DataItem="Certificate" DataValue="certificate.pdf"/>
</Panel>
<Panel PanelID="AIKO 02" FriendlyName="@PanelName" PanelName="AIKO 02 Solar X58C" Manufacturer="AIKO Solar" WattPeak="440" Height="1,70" Width="1,10" Weight="12" MaxVolt="42" MaxAmpere="11"/>
<Panel PanelID="AIKO 03" FriendlyName="@PanelName" PanelName="AIKO 03 Solar T62B" Manufacturer="AIKO Solar" WattPeak="620" Height="2,70" Width="1,10" Weight="12" MaxVolt="67" MaxAmpere="11"/>
<Panel PanelID="AIKO 04" FriendlyName="@PanelName" PanelName="AIKO 04 Solar X58C" Manufacturer="AIKO Solar" WattPeak="440" Height="1,70" Width="1,10" Weight="12" MaxVolt="42" MaxAmpere="11"/>
<Panel PanelID="AIKO 06" FriendlyName="@PanelName" PanelName="AIKO 06 Solar X58C" Manufacturer="AIKO Solar" WattPeak="440" Height="1,70" Width="1,10" Weight="12" MaxVolt="42" MaxAmpere="11"/>
<Inverter InverterID="HM600 01" FriendlyName="@InverterName" InverterName="01 HM600 S2 TMax" Manufacturer="HoyMiles" MaxPowerInput="4000" MaxPowerInputChoice="2000;4000;6000" MaxPowerOutput="600" NumStrings="2" Weight="28"/>
<Inverter InverterID="HM800 02" FriendlyName="@InverterName" InverterName="02 HM800 S2 TMax" Manufacturer="HoyMiles" MaxPowerInput="4000" MaxPowerInputChoice="2000;4000;6000" MaxPowerOutput="800" NumStrings="2" Weight="29"/>
<Battery BatteryID="BYD 01" FriendlyName="@BatteryName" BatteryName="01 BYD T01 Stackable" Manufacturer="BYD" Capacity="4500" Yield="94" MaxCurrent="120" MaxVolt="48">
<AdditionalData DataItem="Image" DataValue="image.png"/>
<AdditionalData DataItem="Manual" DataValue="manual.docx"/>
<AdditionalData DataItem="Certificate" DataValue="certificate.pdf"/>
</Battery>
<Battery BatteryID="BYD 02" FriendlyName="@BatteryName" BatteryName="02 BYD T02 Stackable" Manufacturer="BYD" Capacity="9000" Yield="94" MaxCurrent="120" MaxVolt="48"/>
<Battery BatteryID="BYD 03" FriendlyName="@BatteryName" BatteryName="03 BYD T01 Stackable" Manufacturer="BYD" Capacity="4500" Yield="94" MaxCurrent="120" MaxVolt="48"/>
</Components>
</Project>

103
xml/modelsheets.xml Normal file
View File

@@ -0,0 +1,103 @@
<?xml version='1.0' encoding='UTF-8'?>
<!--
Der ItemType beschreibt die Eigenschaften eines Items.
-->
<ItemTypesX>
<HiddenType RenderStyle="HiddenStyle"/>
<StaticType RenderStyle="StaticStyle"/>
<HeaderType RenderStyle="HeaderStyle"/>
<TreeParentType RenderStyle="StaticStyle" ItemFlags="IsEnabled|IsDropEnabled"/>
<TreeChildType RenderStyle="StaticStyle" ItemFlags="IsEnabled|IsDragEnabled|IsSelectable|IsDropEnabled"/>
<ValueType RenderStyle="LineEditStyle" ItemFlags="IsEnabled|IsEditable|IsSelectable"/>
<PercentageType RenderStyle="ProgressBarStyle" ItemFlags="IsEnabled|IsSelectable"/>
<ChoiceType RenderStyle="ComboBoxStyle" ItemFlags="IsEnabled|IsSelectable|IsEditable" FixedChoices="la|le|lo|lu"/>
<IntValueType RenderStyle="SpinBoxStyle" ItemFlags="IsEnabled|IsSelectable"/>
</ItemTypesX>
<!--
MainModel
-->
<MainModelX>
<ActiveProjects HeaderCaption="Active Projects" HeaderItemType="TreeParentType" Icon="icn08Dummy" State="runnning">
<Project HeaderCaption="#-Project" HeaderItemType="TreeChildType" Icon="icn74Dummy"/>
</ActiveProjects>
<PlannedProjects HeaderCaption="Planned Projects" HeaderItemType="TreeParentType" Icon="icn08Dummy" State="planned">
<Project HeaderCaption="#Project" HeaderItemType="TreeChildType" Icon="icn74Dummy"/>
</PlannedProjects>
</MainModelX>
<!--
Der ItemType beschreibt die Eigenschaften eines Items.
-->
<ItemTypes>
<HiddenType RenderStyle="HiddenStyle"/>
<StaticType RenderStyle="PlainStyle"/>
<TreeChildType RenderStyle="PlainStyle" ItemFlags="IsEnabled|IsDragEnabled|IsSelectable|IsDropEnabled"/>
<ValueType RenderStyle="FormattedStyle" ItemFlags="IsEnabled|IsEditable|IsSelectable"/>
<PercentageType RenderStyle="ProgressBarStyle" ItemFlags="IsEnabled|IsSelectable"/>
<ChoiceType RenderStyle="ComboBoxStyle" ItemFlags="IsEnabled|IsSelectable|IsEditable" FixedChoices="la|le|lo|lu"/>
<IntValueType RenderStyle="SpinBoxStyle" ItemFlags="IsEnabled|IsSelectable"/>
<TreeParentType RenderStyle="PlainStyle" ItemFlags="IsEnabled|IsDropEnabled" Icon="battery" />
<HeaderType RenderStyle="HeaderStyle" ItemFlags="IsEnabled" Icon="battery"/>
</ItemTypes>
<!--
DocumentTreeModel
-->
<DocumentTreeModel>
<ActiveProjects HeaderItemType="TreeParentType" HeaderCaption="Active Projects" ItemType="ValueType" ItemFlags="IsEnabled|IsDropEnabled" RenderStyle="HeaderStyle" State="runnning"/>
<PlannedProjects HeaderItemType="TreeParentType" HeaderCaption="Planned Projects" ItemType="ValueType" ItemFlags="IsEnabled|IsDropEnabled" RenderStyle="HeaderStyle" State="planned"/>
<FinishedProjectss HeaderItemType="TreeParentType" HeaderCaption="Finished Projects" ItemType="ValueType" ItemFlags="IsEnabled|IsDropEnabled" RenderStyle="HeaderStyle" State="finished"/>
</DocumentTreeModel>
<!--
DocumentDetailsModel: moo
-->
<DocumentDetailsModel>
<Panel FriendlyName="@PanelName">
<PanelID HeaderCaption="Panel" HeaderItemType="HeaderType" ItemType="ValueType" Icon="icn74Dummy"/>
<PanelName HeaderCaption="Name" HeaderItemType="HeaderType" ItemType="ValueType"/>
<Manufacturer HeaderCaption="Manufacturer" HeaderItemType="HeaderType" ItemType="ValueType"/>
<WattPeak HeaderCaption="Watt Peak" HeaderItemType="HeaderType" ItemType="ValueType" Unit="Wp"/>
<Width HeaderCaption="Width" HeaderItemType="HeaderType" ItemType="ValueType" Unit="m"/>
<Height HeaderCaption="Height" HeaderItemType="HeaderType" ItemType="ValueType" Unit="m"/>
<Weight HeaderCaption="Weight" HeaderItemType="HeaderType" ItemType="ValueType" Unit="kg"/>
<MaxVolt HeaderCaption="max. Volt" HeaderItemType="HeaderType" ItemType="ValueType" Unit="V"/>
<MaxAmpere HeaderCaption="max. Ampere" HeaderItemType="HeaderType" ItemType="ValueType" Unit="A"/>
</Panel>
<Inverter FriendlyName="@InverterName">
<InverterID HeaderCaption="Inverter" HeaderItemType="HeaderType" ItemType="ValueType"/>
<InverterName HeaderCaption="Name" HeaderItemType="HeaderType" ItemType="ValueType"/>
<Manufacturer HeaderCaption="Manufacturer" HeaderItemType="HeaderType" ItemType="ValueType"/>
<MaxPowerInput HeaderCaption="max. Input" HeaderItemType="HeaderType" ItemType="ChoiceType" ChoiceDataSource="MaxPowerInputChoice" Unit="W"/>
<MaxPowerOutput HeaderCaption="max Output" HeaderItemType="HeaderType" ItemType="ValueType" Unit="W"/>
<NumStrings HeaderCaption="Strings" HeaderItemType="HeaderType" ItemType="ValueType"/>
<Weight HeaderCaption="Weight" HeaderItemType="HeaderType" ItemType="ValueType" Unit="kg"/>
</Inverter>
<Battery FriendlyName="@BatteryName">
<BatteryID HeaderCaption="Battery" HeaderItemType="HeaderType" ItemType="ValueType"/>
<BatteryName HeaderCaption="Name" HeaderItemType="HeaderType" ItemType="ValueType"/>
<Manufacturer HeaderCaption="Manufacturer" HeaderItemType="HeaderType" ItemType="ValueType"/>
<Capacity HeaderCaption="Capacity" HeaderItemType="HeaderType" ItemType="ValueType" Unit="Wh"/>
<Yield HeaderCaption="Yield" HeaderItemType="HeaderType" ItemType="PercentageType" Unit="%"/>
<MaxCurrent HeaderCaption="max. Current" HeaderItemType="HeaderType" ItemType="ValueType" Unit="A"/>
<MaxVolt HeaderCaption="max. Volt" HeaderItemType="HeaderType" ItemType="ValueType" Unit="V"/>
</Battery>
</DocumentDetailsModel>

27
xml/saved_testfile.xtr Normal file
View File

@@ -0,0 +1,27 @@
<?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>

97
xtree.pro Normal file
View File

@@ -0,0 +1,97 @@
QT += core gui widgets
# widgets-private
CONFIG += c++20
# You can make your code fail to compile if it uses deprecated APIs.
# In order to do so, uncomment the following line.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
INCLUDEPATH += pugixml widgets nodes model application datatypes util items
HEADERS += \
application/xqchildmodel.h \
application/xqdocumentstore.h \
application/xqmainmodel.h \
application/xqmainwindow.h \
application/xqappdata.h \
items/xqgenericitem.h \
items/xqitem.h \
items/xqitemfactory.h \
items/xqitemtype.h \
items/xqitemdelegate.h \
model/xqcommand.h \
model/xqmodel.h \
model/xqmodelsections.h \
model/xqnode.h \
model/xqnodewriter.h \
model/xqselectionmodel.h \
model/xqsimpleclipboard.h \
nodes/znode.h \
nodes/znode_factory.h \
nodes/znode_id.h \
nodes/znode_iterator.h \
nodes/znode_payload.h \
#nodes/znode_stringmap.h \
#nodes/znode_attributes.h \
nodes/znode_vector.h \
pugixml/pugiconfig.hpp \
pugixml/pugixml.hpp \
util/xqexception.h \
util/xqmapindex.h \
util/xqmaptor.h \
util/xqptrmaptor.h \
util/xsingleton.h \
util/xtreewalker.h \
widgets/xqcontextmenu.h \
widgets/xqtreeview.h
SOURCES += \
application/xqchildmodel.cpp \
application/xqdocumentstore.cpp \
application/xqmainmodel.cpp \
application/xqmainwindow.cpp \
application/xqappdata.cpp \
items/xqgenericitem.cpp \
items/xqitem.cpp \
items/xqitemfactory.cpp \
items/xqitemtype.cpp \
items/xqitemdelegate.cpp \
main.cpp \
model/xqcommand.cpp \
model/xqmodel.cpp \
model/xqmodelsections.cpp \
model/xqnode.cpp \
model/xqnodewriter.cpp \
model/xqselectionmodel.cpp \
model/xqsimpleclipboard.cpp \
nodes/znode.cpp \
pugixml/pugixml.cpp \
util/xqexception.cpp \
widgets/xqcontextmenu.cpp \
widgets/xqtreeview.cpp
FORMS += \
application/xqmainwindow.ui
RESOURCES = xtree.qrc
# Default rules for deployment.
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += target
DISTFILES += \
README.md \
xml/modelsheets.xml \
xml/modeldata1.xtr \
xml/modeldata2.xtr \
xml/modeldata3.xtr

8
xtree.qrc Normal file
View File

@@ -0,0 +1,8 @@
<RCC>
<qresource prefix="/">
<file>xml/modeldata1.xtr</file>
<file>xml/modeldata2.xtr</file>
<file>xml/modeldata3.xtr</file>
<file>xml/modelsheets.xml</file>
</qresource>
</RCC>

25
xtree.sln Normal file
View File

@@ -0,0 +1,25 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.9.34728.123
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "xtree", "xtree.vcxproj", "{D9E56CB4-F99F-4F88-B721-1443A0AFD5D0}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x86 = Debug|x86
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{D9E56CB4-F99F-4F88-B721-1443A0AFD5D0}.Debug|x86.ActiveCfg = Debug|Win32
{D9E56CB4-F99F-4F88-B721-1443A0AFD5D0}.Debug|x86.Build.0 = Debug|Win32
{D9E56CB4-F99F-4F88-B721-1443A0AFD5D0}.Release|x86.ActiveCfg = Release|Win32
{D9E56CB4-F99F-4F88-B721-1443A0AFD5D0}.Release|x86.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {22F98E65-DA6B-44B7-989E-45B612815CD0}
EndGlobalSection
EndGlobal

181
xtree.vcxproj Normal file
View File

@@ -0,0 +1,181 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="17.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{D9E56CB4-F99F-4F88-B721-1443A0AFD5D0}</ProjectGuid>
<Keyword>QtVS_v304</Keyword>
<WindowsTargetPlatformVersion Condition="'$(Configuration)|$(Platform)' == 'Debug|Win32'">10.0</WindowsTargetPlatformVersion>
<WindowsTargetPlatformVersion Condition="'$(Configuration)|$(Platform)' == 'Release|Win32'">10.0</WindowsTargetPlatformVersion>
<QtMsBuild Condition="'$(QtMsBuild)'=='' OR !Exists('$(QtMsBuild)\qt.targets')">$(MSBuildProjectDirectory)\QtMsBuild</QtMsBuild>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<PlatformToolset>v143</PlatformToolset>
<UseDebugLibraries>true</UseDebugLibraries>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<PlatformToolset>v143</PlatformToolset>
<UseDebugLibraries>false</UseDebugLibraries>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Condition="Exists('$(QtMsBuild)\qt_defaults.props')">
<Import Project="$(QtMsBuild)\qt_defaults.props" />
</ImportGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|Win32'" Label="QtSettings">
<QtInstall>qt691</QtInstall>
<QtModules>core;gui;widgets</QtModules>
<QtBuildConfig>debug</QtBuildConfig>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|Win32'" Label="QtSettings">
<QtInstall>VS2017x86Default</QtInstall>
<QtModules>core;gui;widgets</QtModules>
<QtBuildConfig>release</QtBuildConfig>
</PropertyGroup>
<Target Name="QtMsBuildNotFound" BeforeTargets="CustomBuild;ClCompile" Condition="!Exists('$(QtMsBuild)\qt.targets') or !Exists('$(QtMsBuild)\qt.props')">
<Message Importance="High" Text="QtMsBuild: could not locate qt.targets, qt.props; project may not build correctly." />
</Target>
<ImportGroup Label="ExtensionSettings" />
<ImportGroup Label="Shared" />
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)' == 'Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="$(QtMsBuild)\Qt.props" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)' == 'Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="$(QtMsBuild)\Qt.props" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|Win32'">
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|Win32'">
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<AdditionalIncludeDirectories>items;model;application;widgets;util;nodes;pugixml;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<LanguageStandard>stdcpp17</LanguageStandard>
</ClCompile>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|Win32'" Label="Configuration">
<ClCompile>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<WarningLevel>Level3</WarningLevel>
<SDLCheck>true</SDLCheck>
<ConformanceMode>true</ConformanceMode>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)' == 'Release|Win32'" Label="Configuration">
<ClCompile>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<WarningLevel>Level3</WarningLevel>
<SDLCheck>true</SDLCheck>
<ConformanceMode>true</ConformanceMode>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>false</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<QtRcc Include="xtree.qrc" />
<QtUic Include="application\xqmainwindow.ui" />
<ClCompile Include="application\xqappdata.cpp" />
<ClCompile Include="application\xqchildmodelview.cpp" />
<ClCompile Include="application\xqdocumentstore.cpp" />
<ClCompile Include="application\xqmainmodelview.cpp" />
<ClCompile Include="application\xqmainwindow.cpp" />
<ClCompile Include="items\xqgenericitem.cpp" />
<ClCompile Include="items\xqitem.cpp" />
<ClCompile Include="items\xqitemdelegate.cpp" />
<ClCompile Include="items\xqitemfactory.cpp" />
<ClCompile Include="items\xqitemtype.cpp" />
<ClCompile Include="model\xqcommand.cpp" />
<ClCompile Include="model\xqitemtype.cpp" />
<ClCompile Include="model\xqitemtypefactory.cpp" />
<ClCompile Include="model\xqnodewriter.cpp" />
<ClCompile Include="model\xqselectionmodel.cpp" />
<ClCompile Include="model\xqitem.cpp" />
<ClCompile Include="model\xqmodelview.cpp" />
<ClCompile Include="model\xqmodelsections.cpp" />
<ClCompile Include="model\xqsimpleclipboard.cpp" />
<ClCompile Include="model\xqitemfactory.cpp" />
<ClCompile Include="model\xqnode.cpp" />
<ClCompile Include="nodes\znode.cpp" />
<ClCompile Include="pugixml\pugixml.cpp" />
<ClCompile Include="util\xqexception.cpp" />
<ClCompile Include="widgets\xqitemdelegate.cpp" />
<ClCompile Include="widgets\xqcontextmenu.cpp" />
<ClCompile Include="widgets\xqtreeview.cpp" />
<ClCompile Include="main.cpp" />
</ItemGroup>
<ItemGroup>
<QtMoc Include="application\xqchildmodelview.h" />
</ItemGroup>
<ItemGroup>
<QtMoc Include="application\xqmainmodelview.h" />
</ItemGroup>
<ItemGroup>
<QtMoc Include="application\xqmainwindow.h" />
</ItemGroup>
<ItemGroup>
<QtMoc Include="application\xqdocumentstore.h" />
<ClInclude Include="application\xqappdata.h" />
<ClInclude Include="items\xqgenericitem.h" />
<ClInclude Include="items\xqitem.h" />
<ClInclude Include="items\xqitemdelegate.h" />
<ClInclude Include="items\xqitemfactory.h" />
<ClInclude Include="items\xqitemtype.h" />
<ClInclude Include="model\xqcommand.h" />
<ClInclude Include="model\xqmodelsections.h" />
<ClInclude Include="model\xqnodewriter.h" />
<ClInclude Include="model\xqsimpleclipboard.h" />
<ClInclude Include="model\xqnode.h" />
<ClInclude Include="nodes\znode.h" />
<ClInclude Include="nodes\znode_attributes.h" />
<ClInclude Include="nodes\znode_factory.h" />
<ClInclude Include="nodes\znode_id.h" />
<ClInclude Include="nodes\znode_iterator.h" />
<ClInclude Include="nodes\znode_payload.h" />
<ClInclude Include="nodes\znode_vector.h" />
<ClInclude Include="pugixml\pugiconfig.hpp" />
<ClInclude Include="pugixml\pugixml.hpp" />
<ClInclude Include="util\xqexception.h" />
<ClInclude Include="util\xqmapindex.h" />
<ClInclude Include="util\xqmaptor.h" />
<ClInclude Include="util\xqptrmaptor.h" />
<ClInclude Include="util\xsingleton.h" />
<ClInclude Include="util\xtreewalker.h" />
<QtMoc Include="widgets\xqtreeview.h" />
<QtMoc Include="widgets\xqcontextmenu.h" />
<QtMoc Include="widgets\xqitemdelegate.h" />
<QtMoc Include="model\xqmodelview.h" />
<QtMoc Include="model\xqselectionmodel.h" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Condition="Exists('$(QtMsBuild)\qt.targets')">
<Import Project="$(QtMsBuild)\qt.targets" />
</ImportGroup>
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

272
xtree.vcxproj.filters Normal file
View File

@@ -0,0 +1,272 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Source Files">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>qml;cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="Header Files">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hh;hpp;hxx;hm;inl;inc;xsd</Extensions>
</Filter>
<Filter Include="Resource Files">
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
<Extensions>qrc;rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
</Filter>
<Filter Include="Form Files">
<UniqueIdentifier>{99349809-55BA-4b9d-BF79-8FDBB0286EB3}</UniqueIdentifier>
<Extensions>ui</Extensions>
</Filter>
<Filter Include="Translation Files">
<UniqueIdentifier>{639EADAA-A684-42e4-A9AD-28FC9BCB8F7C}</UniqueIdentifier>
<Extensions>ts</Extensions>
</Filter>
<Filter Include="Header Files\pugixml">
<UniqueIdentifier>{c1cbeda0-491a-46fe-9d15-5b21860ea498}</UniqueIdentifier>
</Filter>
<Filter Include="Header Files\widgets">
<UniqueIdentifier>{63294d99-ad90-46cf-ba38-14f7edc6be6f}</UniqueIdentifier>
</Filter>
<Filter Include="Header Files\nodes">
<UniqueIdentifier>{298ce403-da4f-40a7-84ac-f6e9bfd730cf}</UniqueIdentifier>
</Filter>
<Filter Include="Header Files\model">
<UniqueIdentifier>{97b0d146-c114-43de-b9d7-297c147cbe29}</UniqueIdentifier>
</Filter>
<Filter Include="Header Files\application">
<UniqueIdentifier>{8a32e1fe-2e12-47df-b2c9-792983588c4b}</UniqueIdentifier>
</Filter>
<Filter Include="Header Files\util">
<UniqueIdentifier>{b9c72284-5bbd-45c5-9494-955aa9f19e60}</UniqueIdentifier>
</Filter>
<Filter Include="Source Files\model">
<UniqueIdentifier>{435db408-f6b8-4323-b878-1adce636c1ae}</UniqueIdentifier>
</Filter>
<Filter Include="Source Files\pugixml">
<UniqueIdentifier>{5ce48ab8-bef4-4a72-a91d-e8c90ae21387}</UniqueIdentifier>
</Filter>
<Filter Include="Source Files\widgets">
<UniqueIdentifier>{55c5c9bb-0d76-4941-88d7-79742698b4c7}</UniqueIdentifier>
</Filter>
<Filter Include="Source Files\nodes">
<UniqueIdentifier>{2ba2298d-4869-4816-925f-57f3f344b1c8}</UniqueIdentifier>
</Filter>
<Filter Include="Source Files\application">
<UniqueIdentifier>{c6422570-27c7-4803-b36f-fc69ce71e9a0}</UniqueIdentifier>
</Filter>
<Filter Include="Source Files\util">
<UniqueIdentifier>{59ebd050-7d3b-4c7f-a29d-e8e85c29a1f9}</UniqueIdentifier>
</Filter>
<Filter Include="Header Files\items">
<UniqueIdentifier>{8b3093d8-ce13-429c-8489-698995039f55}</UniqueIdentifier>
</Filter>
<Filter Include="Source Files\Items">
<UniqueIdentifier>{9c2a5017-1219-4efc-a661-f0d08d70dba9}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<QtRcc Include="xtree.qrc">
<Filter>Resource Files</Filter>
</QtRcc>
</ItemGroup>
<ItemGroup>
<ClCompile Include="main.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="model\xqcommand.cpp">
<Filter>Source Files\model</Filter>
</ClCompile>
<ClCompile Include="model\xqitem.cpp">
<Filter>Source Files\model</Filter>
</ClCompile>
<ClCompile Include="model\xqmodelview.cpp">
<Filter>Source Files\model</Filter>
</ClCompile>
<ClCompile Include="model\xqnode.cpp">
<Filter>Source Files\model</Filter>
</ClCompile>
<ClCompile Include="application\xqmainmodelview.cpp">
<Filter>Source Files\application</Filter>
</ClCompile>
<ClCompile Include="application\xqmainwindow.cpp">
<Filter>Source Files\application</Filter>
</ClCompile>
<ClCompile Include="nodes\znode.cpp">
<Filter>Source Files\nodes</Filter>
</ClCompile>
<ClCompile Include="widgets\xqitemdelegate.cpp">
<Filter>Source Files\widgets</Filter>
</ClCompile>
<ClCompile Include="widgets\xqtreeview.cpp">
<Filter>Source Files\widgets</Filter>
</ClCompile>
<ClCompile Include="pugixml\pugixml.cpp">
<Filter>Source Files\pugixml</Filter>
</ClCompile>
<ClCompile Include="model\xqmodelsections.cpp">
<Filter>Source Files\model</Filter>
</ClCompile>
<ClCompile Include="model\xqselectionmodel.cpp">
<Filter>Source Files\model</Filter>
</ClCompile>
<ClCompile Include="application\xqchildmodelview.cpp">
<Filter>Source Files\application</Filter>
</ClCompile>
<ClCompile Include="model\xqsimpleclipboard.cpp">
<Filter>Source Files\model</Filter>
</ClCompile>
<ClCompile Include="widgets\xqcontextmenu.cpp">
<Filter>Source Files\model</Filter>
</ClCompile>
<ClCompile Include="util\xqexception.cpp">
<Filter>Source Files\util</Filter>
</ClCompile>
<ClCompile Include="application\xqdocumentstore.cpp">
<Filter>Source Files\application</Filter>
</ClCompile>
<ClCompile Include="model\xqnodewriter.cpp">
<Filter>Source Files\model</Filter>
</ClCompile>
<ClCompile Include="model\xqitemfactory.cpp">
<Filter>Source Files\model</Filter>
</ClCompile>
<ClCompile Include="application\xqappdata.cpp">
<Filter>Source Files\application</Filter>
</ClCompile>
<ClCompile Include="model\xqitemtypefactory.cpp">
<Filter>Source Files\model</Filter>
</ClCompile>
<ClCompile Include="model\xqitemtype.cpp">
<Filter>Source Files\model</Filter>
</ClCompile>
<ClCompile Include="items\xqgenericitem.cpp">
<Filter>Source Files\Items</Filter>
</ClCompile>
<ClCompile Include="items\xqitem.cpp">
<Filter>Source Files\Items</Filter>
</ClCompile>
<ClCompile Include="items\xqitemdelegate.cpp">
<Filter>Source Files\Items</Filter>
</ClCompile>
<ClCompile Include="items\xqitemfactory.cpp">
<Filter>Source Files\Items</Filter>
</ClCompile>
<ClCompile Include="items\xqitemtype.cpp">
<Filter>Source Files\Items</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="model\xqcommand.h">
<Filter>Header Files\model</Filter>
</ClInclude>
<ClInclude Include="model\xqnode.h">
<Filter>Header Files\model</Filter>
</ClInclude>
<ClInclude Include="util\xqmaptor.h">
<Filter>Header Files\util</Filter>
</ClInclude>
<ClInclude Include="util\xsingleton.h">
<Filter>Header Files\util</Filter>
</ClInclude>
<ClInclude Include="util\xtreewalker.h">
<Filter>Header Files\util</Filter>
</ClInclude>
<ClInclude Include="nodes\znode.h">
<Filter>Header Files\nodes</Filter>
</ClInclude>
<ClInclude Include="nodes\znode_factory.h">
<Filter>Header Files\nodes</Filter>
</ClInclude>
<ClInclude Include="pugixml\pugiconfig.hpp">
<Filter>Header Files\pugixml</Filter>
</ClInclude>
<ClInclude Include="pugixml\pugixml.hpp">
<Filter>Header Files\pugixml</Filter>
</ClInclude>
<ClInclude Include="model\xqmodelsections.h">
<Filter>Header Files\model</Filter>
</ClInclude>
<ClInclude Include="util\xqmapindex.h">
<Filter>Header Files\util</Filter>
</ClInclude>
<ClInclude Include="util\xqptrmaptor.h">
<Filter>Header Files\util</Filter>
</ClInclude>
<ClInclude Include="model\xqsimpleclipboard.h">
<Filter>Header Files\model</Filter>
</ClInclude>
<ClInclude Include="util\xqexception.h">
<Filter>Header Files\util</Filter>
</ClInclude>
<ClInclude Include="model\xqnodewriter.h">
<Filter>Header Files\model</Filter>
</ClInclude>
<ClInclude Include="application\xqappdata.h">
<Filter>Header Files\application</Filter>
</ClInclude>
<ClInclude Include="nodes\znode_iterator.h">
<Filter>Header Files\nodes</Filter>
</ClInclude>
<ClInclude Include="nodes\znode_vector.h">
<Filter>Header Files\nodes</Filter>
</ClInclude>
<ClInclude Include="nodes\znode_id.h">
<Filter>Header Files\nodes</Filter>
</ClInclude>
<ClInclude Include="nodes\znode_payload.h">
<Filter>Header Files\nodes</Filter>
</ClInclude>
<ClInclude Include="nodes\znode_attributes.h">
<Filter>Header Files\nodes</Filter>
</ClInclude>
<ClInclude Include="items\xqgenericitem.h">
<Filter>Header Files\items</Filter>
</ClInclude>
<ClInclude Include="items\xqitem.h">
<Filter>Header Files\items</Filter>
</ClInclude>
<ClInclude Include="items\xqitemdelegate.h">
<Filter>Header Files\items</Filter>
</ClInclude>
<ClInclude Include="items\xqitemfactory.h">
<Filter>Header Files\items</Filter>
</ClInclude>
<ClInclude Include="items\xqitemtype.h">
<Filter>Header Files\items</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<QtMoc Include="model\xqmodelview.h">
<Filter>Header Files\model</Filter>
</QtMoc>
<QtMoc Include="application\xqmainmodelview.h">
<Filter>Header Files\application</Filter>
</QtMoc>
<QtMoc Include="application\xqmainwindow.h">
<Filter>Header Files\application</Filter>
</QtMoc>
<QtMoc Include="widgets\xqitemdelegate.h">
<Filter>Header Files\widgets</Filter>
</QtMoc>
<QtMoc Include="widgets\xqtreeview.h">
<Filter>Header Files\widgets</Filter>
</QtMoc>
<QtMoc Include="widgets\xqcontextmenu.h">
<Filter>Header Files\widgets</Filter>
</QtMoc>
<QtMoc Include="model\xqselectionmodel.h">
<Filter>Header Files\model</Filter>
</QtMoc>
<QtMoc Include="application\xqchildmodelview.h">
<Filter>Header Files\application</Filter>
</QtMoc>
<QtMoc Include="application\xqdocumentstore.h">
<Filter>Header Files\application</Filter>
</QtMoc>
</ItemGroup>
<ItemGroup>
<QtUic Include="application\xqmainwindow.ui">
<Filter>Form Files</Filter>
</QtUic>
</ItemGroup>
</Project>

12
xtree.vcxproj.user Normal file
View File

@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup />
<PropertyGroup Label="QtSettings" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<QtTouchProperty>
</QtTouchProperty>
</PropertyGroup>
<PropertyGroup Label="QtSettings" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<QtTouchProperty>
</QtTouchProperty>
</PropertyGroup>
</Project>