You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
tdevelop/src/projectsession.cpp

451 lines
15 KiB

/***************************************************************************
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 <tqdom.h>
#include <tqptrlist.h>
#include <tqfile.h>
#include <tqtimer.h>
#include <tdeparts/part.h>
#include <kurl.h>
#include <tdemessagebox.h>
#include <tdelocale.h>
#include <kinstance.h>
#include <tdetexteditor/viewcursorinterface.h>
#include <tdetexteditor/document.h>
#include <tdetexteditor/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 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<KDevPlugin*>::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, TQ_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<KParts::Part> it( *PartController::getInstance()->parts() );
for ( ; it.current(); ++it )
{
KParts::ReadOnlyPart* pReadOnlyPart = dynamic_cast<KParts::ReadOnlyPart*>(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<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 ) )
{
TQString encoding = ei->encoding();
if ( !encoding.isNull() )
{
viewEl.setAttribute( "Encoding", encoding );
}
}
}
else
{
viewEl.setAttribute("Type", "Other");
}
}
/*
TQPtrListIterator<KParts::Part> it( *PartController::getInstance()->parts() );
for ( ; it.current(); ++it ) {
//// TQString partName = it.current()->name();
//// TQMessageBox::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?
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<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;
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<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
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<KDevPlugin*>::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, TQ_SLOT(loadDocument()) );
}
}