/*************************************************************************** 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 #include #include #include #include #include #include #include #include #include #include #include #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 tdevelop 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(); TQDomDocument doc("KDevPrjSession"); domdoc=doc; domdoc.appendChild( domdoc.createProcessingInstruction( "xml", "version=\"1.0\" encoding=\"UTF-8\"" ) ); // KDevPrjSession is the root element of the XML file TQDomElement session = domdoc.documentElement(); session = domdoc.createElement("KDevPrjSession"); domdoc.appendChild( session); } //--------------------------------------------------------------------------- bool ProjectSession::restoreFromFile( const TQString & sessionFileName, const TQValueList< KDevPlugin * > plugins ) { bool bFileOpenOK = true; TQFile 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 TDevelop project session ('KDevPrjSession').\n").arg(sessionFileName) + i18n("The document type seems to be: '%1'.").arg(domdoc.doctype().name())); return false; } TQDomElement session = domdoc.documentElement(); // read the information about the mainframe widget if (bFileOpenOK) { recreateDocs(session); } // now also let the plugins load their session stuff TQDomElement pluginListEl = session.namedItem("pluginList").toElement(); TQValueList::ConstIterator it = plugins.begin(); while( it != plugins.end() ) { KDevPlugin* pPlugin = (*it); TQString pluginName = pPlugin->instance()->instanceName(); TQDomElement pluginEl = pluginListEl.namedItem(pluginName).toElement(); if (!pluginEl.isNull()) { // now plugin, load what you find! pPlugin->restorePartialProjectSession(&pluginEl); } ++it; } TQTimer::singleShot( 0, this, TQT_SLOT(loadDocument()) ); return true; } //--------------------------------------------------------------------------- void ProjectSession::recreateDocs(TQDomElement& el) { //// TQDomElement mainframeEl = el.namedItem("Mainframe").toElement(); //// bool bMaxMode =initXMLTree() (bool) mainframeEl.attribute("MaximizeMode", "0").toInt(); //// QextMdiMainFrm* pMainWidget = (QextMdiMainFrm*) tqApp->mainWidget(); //// pMainWidget->setEnableMaximizedChildFrmMode(bMaxMode); //// bool bTaskBarWasOn = pMainWidget->isViewTaskBarOn(); //// pMainWidget->hideViewTaskBar(); // read the information about the documents TQDomElement docsAndViewsEl = el.namedItem("DocsAndViews").toElement(); int nNrOfDocs = docsAndViewsEl.attribute("NumberOfDocuments", "0").toInt(); // loop over all docs int nDoc = 0; TQDomElement docEl; for (docEl = docsAndViewsEl.firstChild().toElement(), nDoc = 0; nDoc < nNrOfDocs; nDoc++, docEl = docEl.nextSibling().toElement()) { // read the document name and type TQString 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, TQDomElement 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 ) { TQDomElement 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; TQDomElement viewEl; TQString viewType; TQString 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); } TQDomElement 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 TQString & sessionFileName, const TQValueList< KDevPlugin * > plugins ) { TQString section, keyword; TQDomElement session = domdoc.documentElement(); int nDocs = 0; TQString docIdStr; //// // read the information about the mainframe widget //// TQDomElement 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 TQDomElement 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) TQDomNode n = docsAndViewsEl.firstChild(); while ( !n.isNull() ) { TQDomNode toBeRemoved = n; n = n.nextSibling(); docsAndViewsEl.removeChild(toBeRemoved); } } TQPtrListIterator it( *PartController::getInstance()->parts() ); for ( ; it.current(); ++it ) { KParts::ReadOnlyPart* pReadOnlyPart = dynamic_cast(it.current()); if (!pReadOnlyPart) continue; TQString url = pReadOnlyPart->url().url(); docIdStr.setNum(nDocs); TQDomElement docEl = domdoc.createElement("Doc" + docIdStr); docEl.setAttribute( "URL", url); docsAndViewsEl.appendChild( docEl); nDocs++; docEl.setAttribute( "NumberOfViews", 1); TQDomElement viewEl = domdoc.createElement( "View0"); docEl.appendChild( viewEl); if ( dynamic_cast(pReadOnlyPart) ) { viewEl.setAttribute("Type", "Documentation"); } else if ( pReadOnlyPart->inherits("KTextEditor::Document") ) { viewEl.setAttribute("Type", "Source"); KTextEditor::ViewCursorInterface *iface = dynamic_cast(pReadOnlyPart->widget()); if (iface) { unsigned int line, col; iface->cursorPosition(&line, &col); viewEl.setAttribute( "line", line ); } if ( KTextEditor::EncodingInterface * ei = dynamic_cast( pReadOnlyPart ) ) { TQString encoding = ei->encoding(); if ( !encoding.isNull() ) { viewEl.setAttribute( "Encoding", encoding ); } } } else { viewEl.setAttribute("Type", "Other"); } } /* TQPtrListIterator it( *PartController::getInstance()->parts() ); for ( ; it.current(); ++it ) { //// TQString partName = it.current()->name(); //// TQMessageBox::information(0L,"",partName); KParts::ReadOnlyPart* pReadOnlyPart = dynamic_cast(it.current()); if (!pReadOnlyPart) continue; // note: read-write parts are also a read-only part, they inherit from it HTMLDocumentationPart* pDocuPart = dynamic_cast(pReadOnlyPart); /// @todo Save relative path for project sharing? TQString url = pReadOnlyPart->url().url(); docIdStr.setNum(nDocs); TQDomElement docEl = domdoc.createElement("Doc" + docIdStr); docEl.setAttribute( "URL", url); docsAndViewsEl.appendChild( docEl); nDocs++; //// docEl.setAttribute( "Type", "???"); //// // get the view list //// TQPtrList 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; TQString viewIdStr; //// for (viewList.first(), nView = 0; viewList.current() != 0; viewList.next(), nView++) { //// pView = viewList.current(); //// if (pView != 0L) { viewIdStr.setNum( nView); TQDomElement viewEl = domdoc.createElement( "View"+viewIdStr); docEl.appendChild( viewEl); // focus? //// viewEl.setAttribute("Focus", (((CEditWidget*)pView->parentWidget()) == m_pDocViewMan->currentEditView())); viewEl.setAttribute("Type", "???"); TQDomElement viewPropertiesEl = domdoc.createElement("AdditionalSettings"); viewEl.appendChild(viewPropertiesEl); emit sig_saveAdditionalViewProperties(url, &viewPropertiesEl); if (pReadOnlyPart->inherits("KTextEditor::Document")) { KTextEditor::ViewCursorInterface *iface = dynamic_cast(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 TQDomElement 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) TQDomNode n = pluginListEl.firstChild(); while ( !n.isNull() ) { TQDomNode toBeRemoved = n; n = n.nextSibling(); pluginListEl.removeChild(toBeRemoved); } } TQValueList::ConstIterator itt = plugins.begin(); while( itt != plugins.end() ) { KDevPlugin* pPlugin = (*itt); TQString pluginName = pPlugin->instance()->instanceName(); TQDomElement 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 TQFile f(sessionFileName); if ( f.open(IO_WriteOnly) ) { // file opened successfully TQTextStream 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(); //TQTimer::singleShot( 0, this, TQT_SLOT(loadDocument()) ); } }