first commit, again.

This commit is contained in:
2025-08-22 22:57:06 +02:00
commit c8e59b10db
79 changed files with 24448 additions and 0 deletions

View File

@@ -0,0 +1,189 @@
/***************************************************************************
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:
XQAppIconMap()
{
}
void init()
{
namedInsert( "DirIcon" , QStyle::SP_DirIcon );
namedInsert( "FileDialogBack", QStyle::SP_FileDialogBack );
namedInsert( "FileDialogContentsView", QStyle::SP_FileDialogContentsView );
namedInsert( "FileDialogDetailedView", QStyle::SP_FileDialogDetailedView );
namedInsert( "icn05Dummy", QStyle::SP_FileDialogEnd );
namedInsert( "icn06Dummy", QStyle::SP_FileDialogInfoView );
namedInsert( "icn07Dummy", QStyle::SP_FileDialogListView );
namedInsert( "icn08Dummy", QStyle::SP_FileDialogNewFolder );
namedInsert( "icn09Dummy", QStyle::SP_FileDialogStart );
namedInsert( "icn10Dummy", QStyle::SP_FileDialogToParent );
namedInsert( "icn11Dummy", QStyle::SP_ArrowBack );
namedInsert( "icn12Dummy", QStyle::SP_DirIcon );
namedInsert( "icn13Dummy", QStyle::SP_MediaSkipBackward );
namedInsert( "icn14Dummy", QStyle::SP_ArrowDown );
namedInsert( "icn15Dummy", QStyle::SP_DirLinkIcon );
namedInsert( "icn16Dummy", QStyle::SP_MediaSkipForward );
namedInsert( "icn17Dummy", QStyle::SP_ArrowForward );
namedInsert( "icn18Dummy", QStyle::SP_DirOpenIcon );
namedInsert( "icn19Dummy", QStyle::SP_MediaStop );
namedInsert( "icn20Dummy", QStyle::SP_ArrowLeft );
namedInsert( "icn21Dummy", QStyle::SP_DockWidgetCloseButton );
namedInsert( "icn22Dummy", QStyle::SP_MediaVolume );
namedInsert( "icn23Dummy", QStyle::SP_ArrowRight );
namedInsert( "icn24Dummy", QStyle::SP_DriveCDIcon );
namedInsert( "icn25Dummy", QStyle::SP_MediaVolumeMuted );
namedInsert( "icn26Dummy", QStyle::SP_ArrowUp );
namedInsert( "icn27Dummy", QStyle::SP_DriveDVDIcon );
namedInsert( "icn28Dummy", QStyle::SP_MessageBoxCritical );
namedInsert( "icn29Dummy", QStyle::SP_BrowserReload );
namedInsert( "icn30Dummy", QStyle::SP_DriveFDIcon );
namedInsert( "icn31Dummy", QStyle::SP_MessageBoxInformation );
namedInsert( "BrowserStop", QStyle::SP_BrowserStop );
namedInsert( "icn33Dummy", QStyle::SP_DriveHDIcon );
namedInsert( "icn34Dummy", QStyle::SP_MessageBoxQuestion );
namedInsert( "CommandLink", QStyle::SP_CommandLink );
namedInsert( "icn36Dummy", QStyle::SP_DriveNetIcon );
namedInsert( "MessageBoxWarning", QStyle::SP_MessageBoxWarning );
namedInsert( "ComputerIcon", QStyle::SP_ComputerIcon );
namedInsert( "icn39Dummy", QStyle::SP_FileDialogBack );
namedInsert( "icn40Dummy", QStyle::SP_TitleBarCloseButton );
namedInsert( "icn42Dummy", QStyle::SP_FileDialogContentsView );
namedInsert( "icn43Dummy", QStyle::SP_TitleBarContextHelpButton );
namedInsert( "DesktopIcon", QStyle::SP_DesktopIcon );
namedInsert( "icn45Dummy", QStyle::SP_FileDialogDetailedView );
namedInsert( "icn46Dummy", QStyle::SP_TitleBarMaxButton );
namedInsert( "icn47Dummy", QStyle::SP_DialogApplyButton );
namedInsert( "icn48Dummy", QStyle::SP_FileDialogEnd );
namedInsert( "icn49Dummy", QStyle::SP_TitleBarMenuButton );
namedInsert( "icn50Dummy", QStyle::SP_DialogCancelButton );
namedInsert( "icn51Dummy", QStyle::SP_FileDialogInfoView );
namedInsert( "icn52Dummy", QStyle::SP_TitleBarMinButton );
namedInsert( "icn53Dummy", QStyle::SP_DialogCloseButton );
namedInsert( "icn54Dummy", QStyle::SP_FileDialogListView );
namedInsert( "icn55Dummy", QStyle::SP_TitleBarNormalButton );
namedInsert( "icn56Dummy", QStyle::SP_DialogDiscardButton );
namedInsert( "icn57Dummy", QStyle::SP_FileDialogNewFolder );
namedInsert( "icn58Dummy", QStyle::SP_TitleBarShadeButton );
namedInsert( "icn59Dummy", QStyle::SP_DialogHelpButton );
namedInsert( "icn60Dummy", QStyle::SP_FileDialogStart );
namedInsert( "icn61Dummy", QStyle::SP_TitleBarUnshadeButton );
namedInsert( "icn62Dummy", QStyle::SP_DialogNoButton );
namedInsert( "icn63Dummy", QStyle::SP_FileDialogToParent );
namedInsert( "icn64Dummy", QStyle::SP_ToolBarHorizontalExtensionButton );
namedInsert( "icn65Dummy", QStyle::SP_DialogOkButton );
namedInsert( "FileIcon", QStyle::SP_FileIcon );
namedInsert( "icn67Dummy", QStyle::SP_ToolBarVerticalExtensionButton );
namedInsert( "icn68Dummy", QStyle::SP_DialogResetButton );
namedInsert( "icn70Dummy", QStyle::SP_FileLinkIcon );
namedInsert( "TrashIcon", QStyle::SP_TrashIcon );
namedInsert( "icn72Dummy", QStyle::SP_DialogSaveButton );
namedInsert( "icn73Dummy", QStyle::SP_MediaPause );
namedInsert( "VistaShield", QStyle::SP_VistaShield );
namedInsert( "icn75Dummy", QStyle::SP_DialogYesButton );
namedInsert( "icn76Dummy", QStyle::SP_MediaPlay );
namedInsert( "icn77Dummy", QStyle::SP_DirClosedIcon );
namedInsert( "icn79Dummy", QStyle::SP_MediaSeekBackward );
namedInsert( "DirHomeIcon", QStyle::SP_DirHomeIcon );
namedInsert( "icn81Dummy", QStyle::SP_MediaSeekForward );
/*
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);
}
*/
}
void namedInsert( const QString& key, QStyle::StandardPixmap pixmapID )
{
QIcon icon = QApplication::style()->standardIcon( pixmapID );
insert( key, icon );
_keysToNames.insert( icon.cacheKey(), key );
}
QString iconName( const QIcon& icon )
{
return _keysToNames[icon.cacheKey()];
}
protected:
QMap<qint64,QString> _keysToNames;
};
/*
Nein, so nicht! QApplication::style() gibts hier noch nicht -> aua!
static XQAppIconMap s_IconMap
{
{ "icnFolder" , QApplication::style()->standardIcon(QStyle::SP_DirIcon) }
}
*/
static XQAppIconMap s_IconMap;
QIcon typeIcon(const QString& key )
{
if(s_IconMap.isEmpty())
s_IconMap.init();
if( s_IconMap.contains(key) )
return s_IconMap[key];
return QApplication::style()->standardIcon( QStyle::SP_TrashIcon);
}
QString iconName( const QIcon& icon )
{
if(s_IconMap.isEmpty())
s_IconMap.init();
return s_IconMap.iconName(icon);
}
}; // namespace XQAppData

View File

@@ -0,0 +1,56 @@
/***************************************************************************
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_ItemType = "ItemType";
const QString c_Caption = "Caption";
const QString c_Header = "Header";
const QString c_ContentType = "ContentType";
const QString c_ModelSheet = "ModelSheet";
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;
QIcon typeIcon(const QString& key );
QString iconName( const QIcon& icon );
}
#endif // XQAPPDATA_H

View File

@@ -0,0 +1,106 @@
/***************************************************************************
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 <xqtreetable.h>
#include <xqitemfactory.h>
//! default konstruktor.
XQChildModel::XQChildModel( QObject *parent )
: XQViewModel{parent}
{
}
//! erzegt den sichtbaren inhalt des models aus einem root-datenknoten.
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 auch unterschiedliche Typen
// haben können, 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.setContentRootNode( contentEntry->parent() );
int newRow = _sections.lastRow(section);
XQNodePtr node = section.sheetRootNode();
XQItemList list = _itemFactory.makeContentRow( node, contentEntry );
//XQItemList list = _itemFactory.makeContentRow( section.sheetRootNode, contentEntry );
// als Baum?
//section.headerItem().appendRow( list );
insertRow( newRow, list);
} // for
}
//! erzeugt ein adhoc-contextmenu, je nachdem welche aktionen gerade möflich sind.
void XQChildModel::initContextMenu()
{
// __fixme! add a menu title
_contextMenu->clear();
const QModelIndex& curIdx = _treeTable->currentIndex();
bool hasSel = curIdx.isValid() && _treeTable->selectionModel()->hasSelection();
bool canPaste = _clipBoard.canPaste( curIdx );
_contextMenu->addAction( "icn11Dummy", "Undo", XQCommand::cmdUndo, _undoStack->canUndo() );
_contextMenu->addAction( "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,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 XQCHILDMODEL_H
#define XQCHILDMODEL_H
#include <xqviewmodel.h>
class XQChildModel : public XQViewModel
{
Q_OBJECT
public:
explicit XQChildModel(QObject *parent = nullptr);
virtual ~XQChildModel() = default;
void setContent(const XQNodePtr& contentRoot );
protected:
//void setupViewProperties() override;
void initContextMenu() override;
};
#endif // XQCHILDMODEL_H

View File

@@ -0,0 +1,55 @@
/***************************************************************************
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>
//! erzeugt ein docukument
XQDocument::XQDocument(const QString& aFileName, const QString& aFriendlyName, XQItem* aTreeItem, XQViewModel* aModelView )
: fileName{ aFileName }, friendlyName{ aFriendlyName }, treeItem{ aTreeItem }, modelView{ aModelView }
{
}
///
/// ---
///
//! destruktor
XQDocumentStore::~XQDocumentStore()
{
//for (auto entry : *this)
// delete entry;
//for( int i=0; i<size();++i)
// delete at(i);
}
//! erzeugt ein document eintrag
void XQDocumentStore::addDocument( const QString& aFileName, const QString& aFriendlyName, XQItem* aTreeItem, XQViewModel* 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 XQViewModel;
class XQItem;
// should this be internal??
struct XQDocument
{
XQDocument() = default;
XQDocument( const QString& aFileName, const QString& aFriendlyName, XQItem* aTreeItem, XQViewModel* aModelView );
virtual ~XQDocument() = default;
QString fileName; // also used as key
QString friendlyName;
XQItem* treeItem{};
XQViewModel* modelView{};
};
class XQDocumentStore : public XQMaptor<XQDocument>
{
public:
XQDocumentStore() = default;
virtual ~ XQDocumentStore();
void addDocument( const QString& aFileName, const QString& aFriendlyName, XQItem* aTreeItem, XQViewModel* aModelView );
protected:
XQNode _treeRootNode{ "treeRootNode" };
};
#endif // XQDOCUMENTSTORE_H

View File

@@ -0,0 +1,91 @@
/***************************************************************************
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 <xqtreetable.h>
#include <xqitemdelegate.h>
#include <xqitem.h>
#include <xqappdata.h>
#include <xqselectionmodel.h>
#include <xqitemfactory.h>
//! default konstruktor.
XQMainModel::XQMainModel(QObject *parent )
: XQViewModel{parent}
{
}
//! leere default implementation
void XQMainModel::initContextMenu()
{
}
//! erzeugt einen eintrag in der baum-übersicht.
XQItem* XQMainModel::addProjectItem( XQNodePtr contentNode )
{
// wir durchsuchen alle unsere section nach dem passenden content-type,
// hier: content-type beschreibt die
for(const auto& section : _sections )
{
if( contentNode->attribute( c_ContentType) == section.contentType() )
{
const QString* contentPtr = contentNode->attribute_ptr( "ProjectName" );
// __fixme! das ist mist!
const XQNodePtr sheetNode = section.sheetRootNode()->first_child();
XQItemList list = _itemFactory.makeHeaderRow( sheetNode, contentPtr );
// erzeuger sheet node speichern
//newItem->setSheetNode( sheetNode );
// den neuen eintrag in die passende section der übersicht eintragen ...
section.headerItem().appendRow( list );
// ... ausklappen...
const QModelIndex index = section.headerItem().index();
_treeTable->expand( index );
// ... und markieren
_treeTable->setCurrentIndex( index );
// quellknoten auch speichern
//newItem->setContentNode( contentNode );
//emit itemCreated( newItem );
return list[0];
}
}
.
throw XQException( "addProjectItem: main model should not be empty!" );
}
void XQMainModel::addSectionItem( const XQModelSection& section, XQItem* projectItem )
{
/*
XQNodePtr sheetNode = projectItem->sheetNode()->find_child_by_tag_name("CurrentSection");
XQItem* newItem = _itemFactory.makeItem(sheetNode, &section.contentType() );
projectItem->appendRow( newItem );
_treeTable->expand( projectItem->index() );
*/
}

View File

@@ -0,0 +1,45 @@
/***************************************************************************
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 <xqviewmodel.h>
//#include <xqmodelsections.h>
class XQTreeTable;
class XQMainModel : public XQViewModel
{
Q_OBJECT
public:
explicit XQMainModel(QObject *parent = nullptr);
virtual ~XQMainModel() = default;
XQItem* addProjectItem( XQNodePtr contentNode );
void addSectionItem( const XQModelSection& section, XQItem* projectItem );
protected:
void initContextMenu() override;
};
#endif // XQMAINMODEL_H

View File

@@ -0,0 +1,377 @@
/***************************************************************************
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 <QPushButton>
#include <xqmainwindow.h>
#include <xqcommand.h>
#include <xqexception.h>
#include <xqitemfactory.h>
#include <xqnodewriter.h>
#include <xqquickwidget.h>
//! konstruktor.
XQMainWindow::XQMainWindow( QWidget* parent )
: QMainWindow(parent)
{
setupUi(this);
setWindowTitle( QString("XTree %1").arg(c_Version));
initMainWindow();
}
// setzt das working directory: dieses muss das 'xml' datenverzeichnis enthalten.
void XQMainWindow::setupWorkingDir()
{
QDir dir = QDir::current();
while (dir.exists())
{
QString xmlPath = dir.absoluteFilePath("xml");
if (QDir(xmlPath).exists())
{
qDebug() << " --- CD TO: " << dir.absolutePath();
QDir::setCurrent( dir.absolutePath() );
}
if (!dir.cdUp())
return;
}
}
//! actions & document struktur einrichten.
void XQMainWindow::initMainWindow()
{
qDebug() << " --- initMainWindow(): here we go!";
// das working dir setzen: 'xml' muss als unterverzeichnis vorhanden sein.
setupWorkingDir();
// 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( _tabWidget, SIGNAL(tabBarClicked(int)), this, SLOT(onTabClicked(int)) );
/*
XQQuickWidget* butt = new XQQuickWidget;
butt->resize(800,600);
butt->setWindowFlags(Qt::Dialog | Qt::WindowStaysOnTopHint);
butt->move( 1200,300);
butt->show();
*/
/*
connect( &_mainModelView, &XQViewModel::itemCreated, this, [=, this](XQItem* item)
{
// when a new main tree item has been created ...
QString pID = item->contentNode()->attribute(c_ProjectID);
_mainTreeView->setCurrentIndex( item->index() );
// ... we set the current view to this node
if( _documentStore.contains( pID ) )
_tabWidget->setCurrentWidget( _documentStore[pID].modelView->treeTable() );
} );
*/
try
{
// hand over undostack
_mainModelView.setUndoStack(&_undoStack);
// hand over left side navigation tree
_mainModelView.setTreeTable(_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()) );
}
}
//! slot für zentrales undo
void XQMainWindow::onUndo()
{
qDebug() << " --- undo Pressed";
if(_undoStack.canUndo())
_undoStack.undo();
}
//! slot für zentrales redo
void XQMainWindow::onRedo()
{
qDebug() << " --- redo Pressed";
if(_undoStack.canRedo())
_undoStack.redo();
}
//! erzeugt ein document
void XQMainWindow::onCreateDocument()
{
qDebug() << " ---- create document Pressed!";
}
//! öffnet ein XML document
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 );
}
//! speichert ein XML document
void XQMainWindow::onSaveDocument()
{
qDebug() << " ---- save Pressed!";
saveDocument( c_ModelDummyFileName );
}
//! fragt nach einem datei-namen und speichert das akutelle XML
//! document unter diesem
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 );
}
//! wird aufgerufen, wenn ein XML geschlossen werden soll.
void XQMainWindow::onCloseDocument()
{
qDebug() << " ---- close Pressed!";
}
//! beendet diese application
void XQMainWindow::onExit()
{
qApp->exit();
}
//! zeigt den about-dialog
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();
}
//! wenn ein item im navigations-baum geklickt wird, soll die document
//! view rechts angepasst werden.
void XQMainWindow::onTreeItemClicked(const QModelIndex& index )
{
XQItem& entry = XQItem::xqItemFromIndex(index);
qDebug() << " --- XXX mainWindow onTreeItemClicked:" << entry.text();
_mainTreeView->selectionModel()->select(index, QItemSelectionModel::Select);
if( XQNodePtr contentNode = entry.contentNode() )
{
QString key = contentNode->attribute(c_ProjectID);
qDebug() << " --- FIRZ: key: " << key;
bool isThere = _documentStore.contains(key);
if( isThere)
_tabWidget->setCurrentWidget( _documentStore[key].modelView->treeTable() );
}
}
//! beim click auf ein tab im linken fenster wird der navigationsbaum angepasst.
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::onSectionCreated( const XQModelSection& section )
{
if( _currentProjectItem )
{
_mainModelView.addSectionItem( section, _currentProjectItem );
}
}
void XQMainWindow::onSectionToggled( const XQModelSection& section )
{
//qDebug() << " --- XXX section toggled: " << section.contentType() << ":" << section.sheetRootNode()->to_string();
}
//! liest eine XML datei namens 'fileName'
void XQMainWindow::loadDocument( const QString& fileName )
{
// gibts die Datei?
if( !QFile::exists( fileName) )
throw XQException( "no such file", fileName );
XQNodeFactory treeLoader;
// xml daten laden
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& document = _documentStore.at(idx);
QMessageBox::warning( this, "Load Document", QString("File: %1 already loaded.").arg( fileName ) );
_mainTreeView->setCurrentIndex( document.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.
XQTreeTable* childTreeView = new XQTreeTable(_tabWidget);
_tabWidget->addTab( childTreeView, pTitle );
_tabWidget->setCurrentWidget( childTreeView );
setWindowTitle( pTitle );
// Ein neues Child-Model erzeugen
XQChildModel* childModel = new XQChildModel(this);
connect( childModel, SIGNAL(sectionCreated(XQModelSection)), this, SLOT(onSectionCreated(XQModelSection)) );
connect( childModel, SIGNAL(sectionToggled(XQModelSection)), this, SLOT(onSectionToggled(XQModelSection)) );
// Den globalen undo-stack ...
childModel->setUndoStack(&_undoStack);
// und die TreeView übergeben
childModel->setTreeTable(childTreeView);
// neuen eintrag im übsichts-baum erzeugen
//_currentProjectItem = _mainModelView.addProjectItem( contentRoot );
//_documentStore.addDocument( fileName, pTitle, _currentProjectItem, childModel );
qDebug() << " --- ZZZ und jetzt:";
// die Modelstruktur anlegen
childModel->initModel( c_ChildModelName );
// model inhalte laden
childModel->setContent( contentRoot->first_child() );
}
//! speichert ein XML unter dem 'filename'
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,75 @@
/***************************************************************************
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 );
//void onItemCreated( XQItem* item );
void onSectionCreated( const XQModelSection& section);
void onSectionToggled( const XQModelSection& section );
protected:
void setupWorkingDir();
// fixme implement
void showDocumnet( const QString& key ){}
void loadDocument( const QString& fileName );
void saveDocument( const QString& fileName );
QUndoStack _undoStack;
XQDocumentStore _documentStore;
XQMainModel _mainModelView;
XQItem* _currentProjectItem{};
};
#endif // XQMAINWINDOW_H

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="XQTreeTable" 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>XQTreeTable</class>
<extends>QTreeView</extends>
<header location="global">xqtreetable.h</header>
</customwidget>
</customwidgets>
<resources/>
<connections/>
</ui>