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

322 lines
8.8 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 <xqmainwindow.h>
#include <xqcommand.h>
#include <xqexception.h>
#include <xqitemfactory.h>
#include <xqnodewriter.h>
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-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!";
// 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)) );
2025-08-09 21:33:03 +02:00
2025-08-07 03:11:56 +02:00
connect( &_mainModelView, &XQViewModel::xqItemCreated, 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
} );
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
2025-08-12 23:41:36 +02:00
//_mainModelView.initModel( c_MainModelName );
_mainModelView.initModel( "ModelX" );
2025-08-05 22:39:41 +02:00
// #2. load demo data
2025-08-12 23:41:36 +02:00
//loadDocument( c_DocumentFileName1 );
2025-08-05 22:39:41 +02:00
//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-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-08 21:39:33 +02:00
// gibts die Datei?
2025-08-05 22:39:41 +02:00
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.
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);
// die Modelstruktur anlegen
childModel->initModel( c_ChildModelName );
// Den globalen undo-stack ...
childModel->setUndoStack(&_undoStack);
// und die TreeView übergeben
2025-08-07 10:39:42 +02:00
childModel->setTreeTable(childTreeView);
2025-08-05 22:39:41 +02:00
// read the model data
childModel->setContent( contentRoot->first_child() );
2025-08-09 21:33:03 +02:00
2025-08-05 22:39:41 +02:00
// create new entry in the left side main tree view
2025-08-09 21:33:03 +02:00
XQItem* newEntry = _mainModelView.createTreeEntry( contentRoot );
2025-08-05 22:39:41 +02:00
_mainTreeView->setCurrentIndex( newEntry->index() );
_documentStore.addDocument( fileName, pTitle, newEntry, childModel );
}
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 );
}