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.
451 lines
15 KiB
451 lines
15 KiB
15 years ago
|
/***************************************************************************
|
||
|
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()) );
|
||
|
}
|
||
|
}
|
||
|
|