diff options
Diffstat (limited to 'src/projectsession.cpp')
-rw-r--r-- | src/projectsession.cpp | 450 |
1 files changed, 450 insertions, 0 deletions
diff --git a/src/projectsession.cpp b/src/projectsession.cpp new file mode 100644 index 00000000..be3ec4a1 --- /dev/null +++ b/src/projectsession.cpp @@ -0,0 +1,450 @@ +/*************************************************************************** + projectsession.cpp - description + ------------------- + begin : 30 Nov 2002 + copyright : (C) 2002 by Falk Brettschneider + email : falk@kdevelop.org + ***************************************************************************/ + +/*************************************************************************** + * * + * 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 <qdom.h> +#include <qptrlist.h> +#include <qfile.h> +#include <qtimer.h> + +#include <kparts/part.h> +#include <kurl.h> +#include <kmessagebox.h> +#include <klocale.h> +#include <kinstance.h> +#include <ktexteditor/viewcursorinterface.h> +#include <ktexteditor/document.h> +#include <ktexteditor/encodinginterface.h> + +#include "api.h" +#include "partcontroller.h" +#include "domutil.h" +#include "documentationpart.h" +#include "toplevel.h" +#include "kdevplugin.h" + +#include "projectsession.h" +#include "projectsession.moc" +//--------------------------------------------------------------------------- +ProjectSession::ProjectSession() +{ + initXMLTree(); +} + +//--------------------------------------------------------------------------- +ProjectSession::~ProjectSession() +{ +} + +//--------------------------------------------------------------------------- +void ProjectSession::initXMLTree() +{ + // initializes the XML tree on startup of kdevelop and when a project + // has been closed to ensure that the XML tree exists already including + // doctype when a project gets opened that doesn't have a kdevses file + // or a new project gets generated (which doesn't have a kdevses file + // either as the project has never been closed before opening it). + domdoc.clear(); + QDomDocument doc("KDevPrjSession"); + domdoc=doc; + domdoc.appendChild( domdoc.createProcessingInstruction( "xml", "version=\"1.0\" encoding=\"UTF-8\"" ) ); + // KDevPrjSession is the root element of the XML file + QDomElement session = domdoc.documentElement(); + session = domdoc.createElement("KDevPrjSession"); + domdoc.appendChild( session); +} + +//--------------------------------------------------------------------------- +bool ProjectSession::restoreFromFile( const QString & sessionFileName, const QValueList< KDevPlugin * > plugins ) +{ + bool bFileOpenOK = true; + + QFile f(sessionFileName); + if ( f.open(IO_ReadOnly) ) { // file opened successfully + bool ok = domdoc.setContent( &f); + f.close(); + if (!ok) { + KMessageBox::sorry(0L, + i18n("The file %1 does not contain valid XML.\n" + "The loading of the session failed.").arg(sessionFileName)); + initXMLTree(); // because it was now broken after failed setContent() + return false; + } + } + else { + bFileOpenOK = false; + } + + // Check for proper document type. + if (domdoc.doctype().name() != "KDevPrjSession") { + KMessageBox::sorry(0L, + i18n("The file %1 does not contain a valid KDevelop project session ('KDevPrjSession').\n").arg(sessionFileName) + + i18n("The document type seems to be: '%1'.").arg(domdoc.doctype().name())); + return false; + } + + QDomElement session = domdoc.documentElement(); + + // read the information about the mainframe widget + if (bFileOpenOK) { + recreateDocs(session); + } + + // now also let the plugins load their session stuff + QDomElement pluginListEl = session.namedItem("pluginList").toElement(); + QValueList<KDevPlugin*>::ConstIterator it = plugins.begin(); + while( it != plugins.end() ) + { + KDevPlugin* pPlugin = (*it); + QString pluginName = pPlugin->instance()->instanceName(); + QDomElement pluginEl = pluginListEl.namedItem(pluginName).toElement(); + if (!pluginEl.isNull()) { + // now plugin, load what you find! + pPlugin->restorePartialProjectSession(&pluginEl); + } + ++it; + } + + QTimer::singleShot( 0, this, SLOT(loadDocument()) ); + + return true; +} + +//--------------------------------------------------------------------------- +void ProjectSession::recreateDocs(QDomElement& el) +{ +//// QDomElement mainframeEl = el.namedItem("Mainframe").toElement(); +//// bool bMaxMode =initXMLTree() (bool) mainframeEl.attribute("MaximizeMode", "0").toInt(); +//// QextMdiMainFrm* pMainWidget = (QextMdiMainFrm*) qApp->mainWidget(); +//// pMainWidget->setEnableMaximizedChildFrmMode(bMaxMode); +//// bool bTaskBarWasOn = pMainWidget->isViewTaskBarOn(); +//// pMainWidget->hideViewTaskBar(); + + // read the information about the documents + QDomElement docsAndViewsEl = el.namedItem("DocsAndViews").toElement(); + int nNrOfDocs = docsAndViewsEl.attribute("NumberOfDocuments", "0").toInt(); + // loop over all docs + int nDoc = 0; + QDomElement docEl; + for (docEl = docsAndViewsEl.firstChild().toElement(), nDoc = 0; + nDoc < nNrOfDocs; + nDoc++, docEl = docEl.nextSibling().toElement()) + { + // read the document name and type + QString docName = docEl.attribute( "URL", ""); + if (!docName.isEmpty() /* && URL::exists(docName)*/) { + KURL url(docName); + // create the views of this document, the first view creation will also create the document + kdDebug() << k_funcinfo << "Doc to be activated? " << (nDoc == nNrOfDocs - 1) << endl; + recreateViews(url, docEl, (nDoc == nNrOfDocs - 1)); + } + } + + //FIXME: God, I hate KMDI. What the hell is this? +/* if (nNrOfDocs > 0) { + API::getInstance()->mainWindow()->callCommand("qextmdi-UI: do hack on session loading finished"); + }*/ +//// if (bTaskBarWasOn) { +//// pMainWidget->showViewTaskBar(); +//// } +} + +//--------------------------------------------------------------------------- +void ProjectSession::recreateViews(KURL& url, QDomElement docEl, bool activate) +{ + // read information about the views + int nNrOfViews = docEl.attribute( "NumberOfViews", "0").toInt(); + + // we should restore every view, but right now we only support a single view per document + // so use this simple method for now + + if ( nNrOfViews > 0 ) + { + QDomElement viewEl = docEl.firstChild().toElement(); + DocumentData dd; + dd.type = viewEl.attribute("Type"); + dd.line = viewEl.attribute("line", "0").toInt(); + dd.url = url; + dd.activate = activate; + dd.encoding = viewEl.attribute( "Encoding" ); + + _docDataList << dd; + } + +/* + // loop over all views of this document + int nView = 0; + + QDomElement viewEl; + QString viewType; + QString context; + if (docEl.hasAttribute("context")) { + context = docEl.attribute("context"); + } + + for (viewEl = docEl.firstChild().toElement(), nView = 0; nView < nNrOfViews; nView++, viewEl = viewEl.nextSibling().toElement()) { + +//// // is it the focused view? (XXX well, this only refers to the module instance) +//// if (viewEl.attribute( "Focus", "0").toInt()) { +//// // yes, memorize for later use +//// pFocusedView = pView; +//// } + + if (context.isEmpty()) { + int line = 0; + if (viewEl.hasAttribute("line")) { + line = viewEl.attribute("line", "0").toInt(); + } + PartController::getInstance()->editDocument(url, line); + } + else { + PartController::getInstance()->showDocument(url); + } + QDomElement viewPropertiesEl = viewEl.namedItem("AdditionalSettings").toElement(); + if (!viewPropertiesEl.isNull()) { + emit sig_restoreAdditionalViewProperties(url.url(), &viewPropertiesEl); + } + + } +//// // restore focus +//// if (pFocusedView != 0L) { +//// if (pFocusedView->parentWidget()->inherits("QextMdiChildView")) { +//// ((QextMdiChildView*)pFocusedView->parentWidget())->activate(); +//// } +//// pFocusedView->setFocus(); +//// } +*/ +} + +//--------------------------------------------------------------------------- +bool ProjectSession::saveToFile( const QString & sessionFileName, const QValueList< KDevPlugin * > plugins ) +{ + QString section, keyword; + QDomElement session = domdoc.documentElement(); + + int nDocs = 0; + QString docIdStr; + +//// // read the information about the mainframe widget +//// QDomElement mainframeEl = session.namedItem("Mainframe").toElement(); +//// if(mainframeEl.isNull()){ +//// mainframeEl=domdoc.createElement("Mainframe"); +//// session.appendChild( mainframeEl); +//// } +//// bool bMaxMode = ((QextMdiMainFrm*)m_pDocViewMan->parent())->isInMaximizedChildFrmMode(); +//// mainframeEl.setAttribute("MaximizeMode", bMaxMode); + + + // read the information about the documents + QDomElement docsAndViewsEl = session.namedItem("DocsAndViews").toElement(); + if (docsAndViewsEl.isNull()) { + docsAndViewsEl = domdoc.createElement("DocsAndViews"); + session.appendChild( docsAndViewsEl); + } + else { + // we need to remove the old ones before memorizing the current ones (to avoid merging) + QDomNode n = docsAndViewsEl.firstChild(); + while ( !n.isNull() ) { + QDomNode toBeRemoved = n; + n = n.nextSibling(); + docsAndViewsEl.removeChild(toBeRemoved); + } + } + + QPtrListIterator<KParts::Part> it( *PartController::getInstance()->parts() ); + for ( ; it.current(); ++it ) + { + + KParts::ReadOnlyPart* pReadOnlyPart = dynamic_cast<KParts::ReadOnlyPart*>(it.current()); + if (!pReadOnlyPart) + continue; + + QString url = pReadOnlyPart->url().url(); + + docIdStr.setNum(nDocs); + QDomElement docEl = domdoc.createElement("Doc" + docIdStr); + docEl.setAttribute( "URL", url); + docsAndViewsEl.appendChild( docEl); + nDocs++; + docEl.setAttribute( "NumberOfViews", 1); + + QDomElement viewEl = domdoc.createElement( "View0"); + docEl.appendChild( viewEl); + + if ( dynamic_cast<HTMLDocumentationPart*>(pReadOnlyPart) ) + { + viewEl.setAttribute("Type", "Documentation"); + } + else if ( pReadOnlyPart->inherits("KTextEditor::Document") ) + { + viewEl.setAttribute("Type", "Source"); + KTextEditor::ViewCursorInterface *iface = dynamic_cast<KTextEditor::ViewCursorInterface*>(pReadOnlyPart->widget()); + if (iface) { + unsigned int line, col; + iface->cursorPosition(&line, &col); + viewEl.setAttribute( "line", line ); + } + if ( KTextEditor::EncodingInterface * ei = dynamic_cast<KTextEditor::EncodingInterface*>( pReadOnlyPart ) ) + { + QString encoding = ei->encoding(); + if ( !encoding.isNull() ) + { + viewEl.setAttribute( "Encoding", encoding ); + } + } + } + else + { + viewEl.setAttribute("Type", "Other"); + } + } + +/* + QPtrListIterator<KParts::Part> it( *PartController::getInstance()->parts() ); + for ( ; it.current(); ++it ) { +//// QString partName = it.current()->name(); +//// QMessageBox::information(0L,"",partName); + + KParts::ReadOnlyPart* pReadOnlyPart = dynamic_cast<KParts::ReadOnlyPart*>(it.current()); + if (!pReadOnlyPart) + continue; // note: read-write parts are also a read-only part, they inherit from it + + HTMLDocumentationPart* pDocuPart = dynamic_cast<HTMLDocumentationPart*>(pReadOnlyPart); + + /// @todo Save relative path for project sharing? + QString url = pReadOnlyPart->url().url(); + + docIdStr.setNum(nDocs); + QDomElement docEl = domdoc.createElement("Doc" + docIdStr); + docEl.setAttribute( "URL", url); + docsAndViewsEl.appendChild( docEl); + nDocs++; +//// docEl.setAttribute( "Type", "???"); +//// // get the view list +//// QPtrList<KWpEditorPartriteView> viewList = pDoc->viewList(); +//// // write the number of views +//// docEl.setAttribute( "NumberOfViews", viewList.count()); + docEl.setAttribute( "NumberOfViews", 1); + // loop over all views of this document + int nView = 0; +//// KWriteView* pView = 0L; + QString viewIdStr; +//// for (viewList.first(), nView = 0; viewList.current() != 0; viewList.next(), nView++) { +//// pView = viewList.current(); +//// if (pView != 0L) { + viewIdStr.setNum( nView); + QDomElement viewEl = domdoc.createElement( "View"+viewIdStr); + docEl.appendChild( viewEl); + // focus? +//// viewEl.setAttribute("Focus", (((CEditWidget*)pView->parentWidget()) == m_pDocViewMan->currentEditView())); + viewEl.setAttribute("Type", "???"); + + QDomElement viewPropertiesEl = domdoc.createElement("AdditionalSettings"); + viewEl.appendChild(viewPropertiesEl); + emit sig_saveAdditionalViewProperties(url, &viewPropertiesEl); + + if (pReadOnlyPart->inherits("KTextEditor::Document")) { + KTextEditor::ViewCursorInterface *iface = dynamic_cast<KTextEditor::ViewCursorInterface*>(pReadOnlyPart->widget()); + if (iface) { + unsigned int line, col; + iface->cursorPosition(&line, &col); + viewEl.setAttribute( "line", line ); + } + } + + if (pDocuPart) { + docEl.setAttribute( "context", pDocuPart->context() ); + } + } +*/ + docsAndViewsEl.setAttribute("NumberOfDocuments", nDocs); + + + // now also let the project-related plugins save their session stuff + // read the information about the documents + QDomElement pluginListEl = session.namedItem("pluginList").toElement(); + if (pluginListEl.isNull()) { + pluginListEl = domdoc.createElement("pluginList"); + session.appendChild( pluginListEl); + } + else { + // we need to remove the old ones before memorizing the current ones (to avoid merging) + QDomNode n = pluginListEl.firstChild(); + while ( !n.isNull() ) { + QDomNode toBeRemoved = n; + n = n.nextSibling(); + pluginListEl.removeChild(toBeRemoved); + } + } + + QValueList<KDevPlugin*>::ConstIterator itt = plugins.begin(); + while( itt != plugins.end() ) + { + KDevPlugin* pPlugin = (*itt); + QString pluginName = pPlugin->instance()->instanceName(); + QDomElement pluginEl = domdoc.createElement(pluginName); + + // now plugin, save what you have! + pPlugin->savePartialProjectSession(&pluginEl); + + // if the plugin wrote anything, accept itt for the session, otherwise forget itt + if (pluginEl.hasChildNodes() || pluginEl.hasAttributes()) + { + pluginListEl.appendChild(pluginEl); + } + ++itt; + } + + // Write it out to the session file on disc + QFile f(sessionFileName); + if ( f.open(IO_WriteOnly) ) { // file opened successfully + QTextStream t( &f ); // use a text stream + t << domdoc.toCString(); + f.close(); + } + initXMLTree(); // clear and initialize the tree again + + return true; +} + + +void ProjectSession::loadDocument( ) +{ + while ( !_docDataList.isEmpty() ) + { + DocumentData & dd = _docDataList.first(); + if ( dd.type == "Source" ) + { + PartController::getInstance()->setEncoding( dd.encoding ); + PartController::getInstance()->editDocumentInternal( dd.url, dd.line, -1, dd.activate ); + } + else if ( dd.type == "Documentation" ) + { + // FIXME needs to be deferred if !activate ? + PartController::getInstance()->showDocument( dd.url, true ); + } + else + { + // FIXME needs to be deferred if !activate ? + PartController::getInstance()->editDocument( dd.url ); + } + _docDataList.pop_front(); + + loadDocument(); + //QTimer::singleShot( 0, this, SLOT(loadDocument()) ); + } +} + |