/*************************************************************************** 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 #include #include #include #include #include #include #include //! 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( &_mainModelView, &XQViewModel::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->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 = "xtree concept
"; text += "2024 c.holzheuer

"; text += "sourceworx.org/xtree"; 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() << " --- 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->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() ); } //! 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 ); // 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. XQTreeTable* childTreeView = new XQTreeTable(_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->setTreeTable(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 ); */ } //! 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 ); }