Files
xtree.old.ng/src/application/xqmainwindow.cpp

370 lines
10 KiB
C++
Raw Normal View History

2025-08-05 22:39:41 +02:00
/***************************************************************************
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>
2025-08-05 22:39:41 +02:00
#include <xqmainwindow.h>
#include <xqcommand.h>
#include <xqexception.h>
#include <xqitemfactory.h>
#include <xqnodewriter.h>
#include <xqquickwidget.h>
2025-08-05 22:39:41 +02:00
2025-08-09 21:33:03 +02:00
//! konstruktor.
2025-08-05 22:39:41 +02:00
XQMainWindow::XQMainWindow( QWidget* parent )
: QMainWindow(parent)
{
setupUi(this);
setWindowTitle( QString("XTree %1").arg(c_Version));
initMainWindow();
}
2025-08-08 21:39:33 +02:00
2025-08-14 19:13:53 +02:00
// 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;
}
}
2025-08-09 21:33:03 +02:00
//! actions & document struktur einrichten.
2025-08-08 21:39:33 +02:00
2025-08-05 22:39:41 +02:00
void XQMainWindow::initMainWindow()
{
qDebug() << " --- initMainWindow(): here we go!";
2025-08-14 19:13:53 +02:00
// das working dir setzen: 'xml' muss als unterverzeichnis vorhanden sein.
setupWorkingDir();
2025-08-05 22:39:41 +02:00
// 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)) );
2025-08-16 16:39:23 +02:00
connect( _tabWidget, SIGNAL(tabBarClicked(int)), this, SLOT(onTabClicked(int)) );
2025-08-05 22:39:41 +02:00
2025-08-16 16:39:23 +02:00
connect( _tabWidget, SIGNAL(tabBarClicked(int)), this, SLOT(onTabClicked(int)) );
2025-08-09 21:33:03 +02:00
/*
XQQuickWidget* butt = new XQQuickWidget;
butt->resize(800,600);
butt->setWindowFlags(Qt::Dialog | Qt::WindowStaysOnTopHint);
butt->move( 1200,300);
butt->show();
*/
2025-08-16 16:39:23 +02:00
/*
connect( &_mainModelView, &XQViewModel::itemCreated, this, [=, this](XQItem* item)
2025-08-05 22:39:41 +02:00
{
// 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 ) )
2025-08-07 10:39:42 +02:00
_tabWidget->setCurrentWidget( _documentStore[pID].modelView->treeTable() );
2025-08-05 22:39:41 +02:00
} );
2025-08-16 16:39:23 +02:00
*/
2025-08-05 22:39:41 +02:00
try
{
// hand over undostack
_mainModelView.setUndoStack(&_undoStack);
// hand over left side navigation tree
2025-08-07 10:39:42 +02:00
_mainModelView.setTreeTable(_mainTreeView);
2025-08-05 22:39:41 +02:00
// #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()) );
}
}
2025-08-08 21:39:33 +02:00
2025-08-09 21:33:03 +02:00
//! slot für zentrales undo
2025-08-08 21:39:33 +02:00
2025-08-05 22:39:41 +02:00
void XQMainWindow::onUndo()
{
qDebug() << " --- undo Pressed";
if(_undoStack.canUndo())
_undoStack.undo();
}
2025-08-08 21:39:33 +02:00
2025-08-09 21:33:03 +02:00
//! slot für zentrales redo
2025-08-08 21:39:33 +02:00
2025-08-05 22:39:41 +02:00
void XQMainWindow::onRedo()
{
qDebug() << " --- redo Pressed";
if(_undoStack.canRedo())
_undoStack.redo();
}
2025-08-08 21:39:33 +02:00
//! erzeugt ein document
2025-08-05 22:39:41 +02:00
void XQMainWindow::onCreateDocument()
{
qDebug() << " ---- create document Pressed!";
}
2025-08-08 21:39:33 +02:00
//! öffnet ein XML document
2025-08-05 22:39:41 +02:00
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 );
}
2025-08-08 21:39:33 +02:00
//! speichert ein XML document
2025-08-05 22:39:41 +02:00
void XQMainWindow::onSaveDocument()
{
qDebug() << " ---- save Pressed!";
saveDocument( c_ModelDummyFileName );
}
2025-08-08 21:39:33 +02:00
//! fragt nach einem datei-namen und speichert das akutelle XML
//! document unter diesem
2025-08-05 22:39:41 +02:00
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 );
}
2025-08-08 21:39:33 +02:00
//! wird aufgerufen, wenn ein XML geschlossen werden soll.
2025-08-05 22:39:41 +02:00
void XQMainWindow::onCloseDocument()
{
qDebug() << " ---- close Pressed!";
}
2025-08-08 21:39:33 +02:00
//! beendet diese application
2025-08-05 22:39:41 +02:00
void XQMainWindow::onExit()
{
qApp->exit();
}
2025-08-08 21:39:33 +02:00
//! zeigt den about-dialog
2025-08-05 22:39:41 +02:00
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();
}
2025-08-09 21:33:03 +02:00
//! wenn ein item im navigations-baum geklickt wird, soll die document
//! view rechts angepasst werden.
2025-08-05 22:39:41 +02:00
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) )
2025-08-07 10:39:42 +02:00
_tabWidget->setCurrentWidget( _documentStore[key].modelView->treeTable() );
2025-08-05 22:39:41 +02:00
}
2025-08-08 21:39:33 +02:00
2025-08-09 21:33:03 +02:00
//! beim click auf ein tab im linken fenster wird der navigationsbaum angepasst.
2025-08-05 22:39:41 +02:00
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() );
}
2025-08-16 22:03:41 +02:00
void XQMainWindow::onSectionCreated( const XQModelSection& section )
2025-08-16 16:39:23 +02:00
{
2025-08-16 22:03:41 +02:00
qDebug() << " --- XXX section created: " << section.contentType() << ":" << section.contentType();
2025-08-16 16:39:23 +02:00
}
2025-08-16 22:03:41 +02:00
void XQMainWindow::onSectionToggled( const XQModelSection& section )
2025-08-16 16:39:23 +02:00
{
2025-08-16 22:03:41 +02:00
qDebug() << " --- XXX section toggled: " << section.contentType() << ":" << section.sheetRootNode()->to_string();
2025-08-16 16:39:23 +02:00
}
2025-08-08 21:39:33 +02:00
//! liest eine XML datei namens 'fileName'
2025-08-05 22:39:41 +02:00
void XQMainWindow::loadDocument( const QString& fileName )
{
2025-08-16 22:03:41 +02:00
// gibts die Datei?
2025-08-05 22:39:41 +02:00
if( !QFile::exists( fileName) )
throw XQException( "no such file", fileName );
XQNodeFactory treeLoader;
2025-08-16 22:03:41 +02:00
// xml daten laden
2025-08-05 22:39:41 +02:00
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 )
{
2025-08-16 22:03:41 +02:00
const XQDocument& document = _documentStore.at(idx);
2025-08-05 22:39:41 +02:00
QMessageBox::warning( this, "Load Document", QString("File: %1 already loaded.").arg( fileName ) );
2025-08-16 22:03:41 +02:00
_mainTreeView->setCurrentIndex( document.treeItem->index() );
2025-08-05 22:39:41 +02:00
_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.
2025-08-07 03:11:56 +02:00
XQTreeTable* childTreeView = new XQTreeTable(_tabWidget);
2025-08-05 22:39:41 +02:00
_tabWidget->addTab( childTreeView, pTitle );
_tabWidget->setCurrentWidget( childTreeView );
setWindowTitle( pTitle );
// Ein neues Child-Model erzeugen
XQChildModel* childModel = new XQChildModel(this);
2025-08-16 16:39:23 +02:00
2025-08-16 22:03:41 +02:00
connect( childModel, SIGNAL(sectionCreated(XQModelSection)), this, SLOT(onSectionCreated(XQModelSection)) );
connect( childModel, SIGNAL(sectionToggled(XQModelSection)), this, SLOT(onSectionToggled(XQModelSection)) );
2025-08-05 22:39:41 +02:00
// Den globalen undo-stack ...
childModel->setUndoStack(&_undoStack);
2025-08-16 16:39:23 +02:00
2025-08-05 22:39:41 +02:00
// und die TreeView übergeben
2025-08-07 10:39:42 +02:00
childModel->setTreeTable(childTreeView);
2025-08-05 22:39:41 +02:00
// neuen eintrag im übsichts-baum erzeugen
XQItem* newEntry = _mainModelView.makeTreeItem( contentRoot );
2025-08-16 22:03:41 +02:00
//_mainTreeView->setCurrentIndex( newEntry->index() );
//_documentStore.addDocument( fileName, pTitle, newEntry, childModel );
2025-08-16 16:39:23 +02:00
2025-08-16 22:03:41 +02:00
// die Modelstruktur anlegen
childModel->initModel( c_ChildModelName );
2025-08-16 16:39:23 +02:00
// model inhalte laden
2025-08-05 22:39:41 +02:00
childModel->setContent( contentRoot->first_child() );
2025-08-09 21:33:03 +02:00
2025-08-16 16:39:23 +02:00
2025-08-05 22:39:41 +02:00
}
2025-08-08 21:39:33 +02:00
//! speichert ein XML unter dem 'filename'
2025-08-05 22:39:41 +02:00
void XQMainWindow::saveDocument( const QString& fileName )
{
XQNodeWriter nodeWriter;
int curIdx = _tabWidget->currentIndex();
XQNodePtr rootNode = _documentStore[curIdx].treeItem->contentNode();
nodeWriter.dumpTree( rootNode, fileName );
}