summaryrefslogtreecommitdiffstats
path: root/src/kile/kiledocmanager.cpp
diff options
context:
space:
mode:
authortpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2010-02-10 03:05:17 +0000
committertpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2010-02-10 03:05:17 +0000
commit2c945cd914550233ed352ff195afeb4dd793f122 (patch)
tree4796bfab5733942b90b5a66bb05655be5fdcca03 /src/kile/kiledocmanager.cpp
downloadkile-2c945cd914550233ed352ff195afeb4dd793f122.tar.gz
kile-2c945cd914550233ed352ff195afeb4dd793f122.zip
Added abandoned KDE3 version of Kile
git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/applications/kile@1088055 283d02a7-25f6-0310-bc7c-ecb5cbfe19da
Diffstat (limited to 'src/kile/kiledocmanager.cpp')
-rw-r--r--src/kile/kiledocmanager.cpp2040
1 files changed, 2040 insertions, 0 deletions
diff --git a/src/kile/kiledocmanager.cpp b/src/kile/kiledocmanager.cpp
new file mode 100644
index 0000000..b94b4c4
--- /dev/null
+++ b/src/kile/kiledocmanager.cpp
@@ -0,0 +1,2040 @@
+//
+// C++ Implementation: kiledocmanager
+//
+// Description:
+//
+//
+// Author: Jeroen Wijnhout <Jeroen.Wijnhout@kdemail.net>, (C) 2004
+// Michel Ludwig <michel.ludwig@kdemail.net>, (C) 2006, 2007
+// Holger Danielsson <holger.danielsson@versanet.de>, (C) 2007
+
+/***************************************************************************
+ * *
+ * 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. *
+ * *
+ ***************************************************************************/
+
+// 2007-03-12 dani
+// - use KileDocument::Extensions
+
+#include "kiledocmanager.h"
+
+#include <qtextcodec.h>
+#include <qfile.h>
+#include <qdir.h>
+
+#include <kate/document.h>
+#include <kate/view.h>
+#include <kapplication.h>
+#include "kiledebug.h"
+#include <kencodingfiledialog.h>
+#include <klocale.h>
+#include <kmimetype.h>
+#include <kmessagebox.h>
+#include <kprogress.h>
+#include <kfile.h>
+#include <krun.h>
+#include <kstandarddirs.h>
+#include <kio/netaccess.h>
+#include <kpushbutton.h>
+#include <kurl.h>
+#include <kurldrag.h>
+#include <kfileitem.h>
+
+#include "kileeventfilter.h"
+#include "kileuntitled.h"
+#include "templates.h"
+#include "newfilewizard.h"
+#include "managetemplatesdialog.h"
+#include "kileinfo.h"
+#include "kilejscript.h"
+#include "kileproject.h"
+#include "kiledocumentinfo.h"
+#include "kileviewmanager.h"
+#include "kilefileselect.h"
+#include "kileprojectview.h"
+#include "kilestructurewidget.h"
+#include "kileprojectdlgs.h"
+#include "kiletool.h"
+#include "kiletool_enums.h"
+#include "kilestdtools.h"
+#include "kilelistselector.h"
+#include "kiletoolmanager.h"
+#include "kilekonsolewidget.h"
+#include "kileconfig.h"
+#include "kilelogwidget.h"
+#include "cleandialog.h"
+
+/*
+ * Newly created text documents have an empty URL and a non-empty document name.
+ */
+
+namespace KileDocument
+{
+
+Manager::Manager(KileInfo *info, QObject *parent, const char *name) :
+ QObject(parent, name),
+ m_ki(info)
+{
+ m_textInfoList.setAutoDelete(false);
+ m_projects.setAutoDelete(false);
+ Kate::Document::setFileChangedDialogsActivated (true);
+
+ if ( KileConfig::defaultEncoding() == "invalid" )
+ KileConfig::setDefaultEncoding(QString::fromLatin1(QTextCodec::codecForLocale()->name()));
+
+ QWidget *par = m_ki ? m_ki->parentWidget() : 0;
+ m_kpd = new KProgressDialog(par, 0, i18n("Open Project..."), QString::null, true);
+ m_kpd->showCancelButton(false);
+ m_kpd->setLabel(i18n("Scanning project files..."));
+ m_kpd->setAutoClose(true);
+ m_kpd->setMinimumDuration(2000);
+ m_kpd->cancel();
+}
+
+Manager::~Manager()
+{
+ KILE_DEBUG() << "==KileDocument::Manager::~Manager()=========" << endl;
+}
+
+void Manager::trashDoc(TextInfo *docinfo, Kate::Document *doc /*= 0L*/ )
+{
+ KILE_DEBUG() << "==void Manager::trashDoc(" << docinfo->url().path() << ")=====" << endl;
+
+ if ( m_ki->isOpen(docinfo->url()) ) return;
+
+ if ( doc == 0L ) doc = docinfo->getDoc();
+ //look for doc before we detach the docinfo
+ //if we do it the other way around, docFor will always return nil
+ if ( doc == 0L ) doc = docFor(docinfo->url());
+
+ KILE_DEBUG() << "DETACHING " << docinfo << endl;
+ docinfo->detach();
+
+ KILE_DEBUG() << "\tTRASHING " << doc << endl;
+ if ( doc == 0L ) return;
+
+ KILE_DEBUG() << "just checking: docinfo->getDoc() = " << docinfo->getDoc() << endl;
+ KILE_DEBUG() << "just checking: docFor(docinfo->url()) = " << docFor(docinfo->url()) << endl;
+
+ for ( uint i = 0; i < m_textInfoList.count(); ++i )
+ {
+ if ( (m_textInfoList.at(i) != docinfo) && (m_textInfoList.at(i)->getDoc() == doc) )
+ {
+ KMessageBox::information(0, i18n("The internal structure of Kile is corrupted (probably due to a bug in Kile). Please select Save All from the File menu and close Kile.\nThe Kile team apologizes for any inconvenience and would appreciate a bug report."));
+ kdWarning() << "docinfo " << m_textInfoList.at(i) << " url " << m_textInfoList.at(i)->url().fileName() << " has a wild pointer!!!"<< endl;
+ }
+ }
+
+ KILE_DEBUG() << "DELETING doc" << endl;
+ delete doc;
+}
+
+// update all Info's with changed user commands
+void Manager::updateInfos()
+{
+ for (uint i=0; i < m_textInfoList.count(); ++i)
+ {
+ m_textInfoList.at(i)->updateStructLevelInfo();
+ }
+}
+
+Kate::Document* Manager::docFor(const KURL & url)
+{
+ for (uint i=0; i < m_textInfoList.count(); ++i)
+ {
+ if ( m_ki->similarOrEqualURL(m_textInfoList.at(i)->url(),url) )
+ {
+ return m_textInfoList.at(i)->getDoc();
+ }
+ }
+
+ return 0L;
+}
+
+Info* Manager::getInfo() const
+{
+ Kate::Document *doc = m_ki->activeTextDocument();
+ if ( doc != 0L )
+ return textInfoFor(doc);
+ else
+ return 0L;
+}
+
+TextInfo* Manager::textInfoFor(const QString & path) const
+{
+ if( path.isEmpty() )
+ return 0L;
+
+ KILE_DEBUG() << "==KileInfo::textInfoFor(" << path << ")==========================" << endl;
+ QPtrListIterator<TextInfo> it(m_textInfoList);
+ while ( true )
+ {
+ if ( it.current()->url().path() == path)
+ return it.current();
+
+ if (it.atLast()) break;
+
+ ++it;
+ }
+
+ KILE_DEBUG() << "\tCOULD NOT find info for " << path << endl;
+ return 0L;
+}
+
+TextInfo* Manager::textInfoForURL(const KURL& url)
+{
+ if( url.isEmpty() )
+ return 0L;
+
+ KILE_DEBUG() << "==KileInfo::textInfoFor(" << url << ")==========================" << endl;
+ QPtrListIterator<TextInfo> it(m_textInfoList);
+ TextInfo *info;
+ while ( (info = it.current()) != 0L )
+ {
+ if ( info->url() == url)
+ {
+ return info;
+ }
+ ++it;
+ }
+
+ KILE_DEBUG() << "\tCOULD NOT find info for " << url << endl;
+ return 0L;
+}
+
+TextInfo* Manager::textInfoFor(Kate::Document* doc) const
+{
+ if( !doc )
+ return 0L;
+
+ QPtrListIterator<TextInfo> it(m_textInfoList);
+ while ( true )
+ {
+ if ( it.current()->getDoc() == doc)
+ return it.current();
+
+ if (it.atLast()) return 0L;
+
+ ++it;
+ }
+
+ return 0;
+}
+
+void Manager::mapItem(TextInfo *docinfo, KileProjectItem *item)
+{
+ item->setInfo(docinfo);
+}
+
+KileProject* Manager::projectFor(const KURL &projecturl)
+{
+ KileProject *project = 0;
+
+ //find project with url = projecturl
+ QPtrListIterator<KileProject> it(m_projects);
+ while ( it.current() )
+ {
+ if ((*it)->url() == projecturl)
+ {
+ return *it;
+ }
+ ++it;
+ }
+
+ return project;
+}
+
+KileProject* Manager::projectFor(const QString &name)
+{
+ KileProject *project = 0;
+
+ //find project with url = projecturl
+ QPtrListIterator<KileProject> it(m_projects);
+ while ( it.current() )
+ {
+ if ((*it)->name() == name)
+ {
+ return *it;
+ }
+ ++it;
+ }
+
+ return project;
+}
+
+KileProjectItem* Manager::itemFor(const KURL &url, KileProject *project /*=0L*/) const
+{
+ if (project == 0L)
+ {
+ QPtrListIterator<KileProject> it(m_projects);
+ while ( it.current() )
+ {
+ KILE_DEBUG() << "looking in project " << (*it)->name() << endl;
+ if ((*it)->contains(url))
+ {
+ KILE_DEBUG() << "\t\tfound!" << endl;
+ return (*it)->item(url);
+ }
+ ++it;
+ }
+ KILE_DEBUG() << "\t nothing found" << endl;
+ }
+ else
+ {
+ if ( project->contains(url) )
+ return project->item(url);
+ }
+
+ return 0L;
+}
+
+KileProjectItem* Manager::itemFor(Info *docinfo, KileProject *project /*=0*/) const
+{
+ if(docinfo)
+ return itemFor(docinfo->url(), project);
+ else
+ return 0L;
+}
+
+KileProjectItemList* Manager::itemsFor(Info *docinfo) const
+{
+ if ( docinfo == 0 ) return 0L;
+
+ KILE_DEBUG() << "==KileInfo::itemsFor(" << docinfo->url().fileName() << ")============" << endl;
+ KileProjectItemList *list = new KileProjectItemList();
+ list->setAutoDelete(false);
+
+ QPtrListIterator<KileProject> it(m_projects);
+ while ( it.current() )
+ {
+ KILE_DEBUG() << "\tproject: " << (*it)->name() << endl;
+ if ((*it)->contains(docinfo))
+ {
+ KILE_DEBUG() << "\t\tcontains" << endl;
+ list->append((*it)->item(docinfo));
+ }
+ ++it;
+ }
+
+ return list;
+}
+
+bool Manager::isProjectOpen()
+{
+ return ( m_projects.count() > 0 );
+}
+
+KileProject* Manager::activeProject()
+{
+ KileProject *curpr=0;
+ Kate::Document *doc = m_ki->activeTextDocument();
+
+ if (doc)
+ {
+ for (uint i=0; i < m_projects.count(); ++i)
+ {
+ if (m_projects.at(i)->contains(doc->url()) )
+ {
+ curpr = m_projects.at(i);
+ break;
+ }
+ }
+ }
+
+ return curpr;
+}
+
+KileProjectItem* Manager::activeProjectItem()
+{
+ KileProject *curpr = activeProject();
+ Kate::Document *doc = m_ki->activeTextDocument();
+ KileProjectItem *item = 0;
+
+ if (curpr && doc)
+ {
+ KileProjectItemList *list = curpr->items();
+
+ for (uint i=0; i < list->count(); ++i)
+ {
+ if (list->at(i)->url() == doc->url())
+ {
+ item = list->at(i);
+ break;
+ }
+ }
+ }
+
+ return item;
+}
+
+TextInfo* Manager::createTextDocumentInfo(KileDocument::Type type, const KURL & url, const KURL& baseDirectory)
+{
+ TextInfo *docinfo = 0L;
+
+ //see if this file belongs to an opened project
+ KileProjectItem *item = itemFor(url);
+ if ( item != 0L ) docinfo = item->getInfo();
+
+ if ( docinfo == 0L )
+ {
+ switch(type)
+ {
+ case Undefined: // fall through
+ case Text:
+ KILE_DEBUG() << "CREATING TextInfo for " << url.url() << endl;
+ docinfo = new TextInfo(0L,m_ki->extensions());
+ break;
+ case LaTeX:
+ KILE_DEBUG() << "CREATING LaTeXInfo for " << url.url() << endl;
+ docinfo = new LaTeXInfo(0L, m_ki->extensions(), m_ki->latexCommands(), m_ki->eventFilter());
+ break;
+ case BibTeX:
+ KILE_DEBUG() << "CREATING BibInfo for " << url.url() << endl;
+ docinfo = new BibInfo(0L, m_ki->extensions(), m_ki->latexCommands());
+ break;
+ case Script:
+ KILE_DEBUG() << "CREATING ScriptInfo for " << url.url() << endl;
+ docinfo = new ScriptInfo(0L, m_ki->extensions());
+ break;
+ }
+ docinfo->setBaseDirectory(baseDirectory);
+ emit(documentInfoCreated(docinfo));
+ m_textInfoList.append(docinfo);
+ }
+
+ KILE_DEBUG() << "DOCINFO: returning " << docinfo << " " << docinfo->url().fileName() << endl;
+ return docinfo;
+}
+
+void Manager::recreateTextDocumentInfo(TextInfo *oldinfo)
+{
+ KileProjectItemList *list = itemsFor(oldinfo);
+ KURL url = oldinfo->url();
+ TextInfo *newinfo = createTextDocumentInfo(m_ki->extensions()->determineDocumentType(url), url, oldinfo->getBaseDirectory());
+
+ newinfo->setDoc(oldinfo->getDoc());
+
+ KileProjectItem *pritem = 0L;
+ for ( pritem = list->first(); pritem; pritem = list->next() )
+ {
+ pritem->setInfo(newinfo);
+ }
+ removeTextDocumentInfo(oldinfo);
+
+ emit(updateStructure(true, newinfo));
+}
+
+bool Manager::removeTextDocumentInfo(TextInfo *docinfo, bool closingproject /* = false */)
+{
+ KILE_DEBUG() << "==Manager::removeTextDocumentInfo(Info *docinfo)=====" << endl;
+ KileProjectItemList *itms = itemsFor(docinfo);
+ bool oneItem = false;
+ if (itms->count() == 1)
+ oneItem = true;
+
+ if (itms->count() == 0 || ( closingproject && oneItem ))
+ {
+ KILE_DEBUG() << "\tremoving " << docinfo << " count = " << m_textInfoList.count() << endl;
+ m_textInfoList.remove(docinfo);
+
+ emit ( closingDocument ( docinfo ) );
+
+ cleanupDocumentInfoForProjectItems(docinfo);
+ delete docinfo;
+ delete itms;
+
+ return true;
+ }
+
+ KILE_DEBUG() << "\tnot removing " << docinfo << endl;
+ delete itms;
+ return false;
+}
+
+Kate::Document* Manager::createDocument(const QString& name, const KURL& url, TextInfo *docinfo, const QString & encoding, const QString & highlight)
+{
+ KILE_DEBUG() << "==Kate::Document* Manager::createDocument()===========" << endl;
+
+ Kate::Document *doc = (Kate::Document*) KTextEditor::createDocument ("libkatepart", this, "Kate::Document");
+ if ( docFor(url) != 0L )
+ kdWarning() << url << " already has a document!" << endl;
+ else
+ KILE_DEBUG() << "\tappending document " << doc << endl;
+
+ //set the default encoding
+ QString enc = encoding.isNull() ? KileConfig::defaultEncoding() : encoding;
+ doc->setEncoding(enc);
+
+ KILE_DEBUG() << "url is = " << docinfo->url() << endl;
+
+ if(!url.isEmpty())
+ {
+ bool r = doc->openURL(url);
+ // don't add scripts to the recent files
+ if(r && docinfo->getType() != Script)
+ {
+ emit(addToRecentFiles(url));
+ }
+ }
+ doc->setDocName(name.isEmpty() ? url.fileName() : name);
+
+ //handle changes of the document
+ connect(doc, SIGNAL(nameChanged(Kate::Document *)), m_ki->parentWidget(), SLOT(newCaption()));
+ connect(doc, SIGNAL(fileNameChanged()), m_ki->parentWidget(), SLOT(newCaption()));
+ connect(doc, SIGNAL(modStateChanged(Kate::Document*)), this, SLOT(newDocumentStatus(Kate::Document*)));
+ connect(doc, SIGNAL(modifiedOnDisc(Kate::Document*, bool, unsigned char)), this, SIGNAL(documentStatusChanged(Kate::Document*, bool, unsigned char)));
+
+ docinfo->setDoc(doc);
+ docinfo->setHighlightMode(highlight);
+ // FIXME: the whole structure updating stuff needs to be rewritten; updates should originate from
+ // the docinfo only, i.e. the structure view should just react to changes!
+ connect(docinfo, SIGNAL(completed(KileDocument::Info*)), m_ki->structureWidget(), SLOT(update(KileDocument::Info*)));
+
+ KILE_DEBUG() << "createDocument: url " << doc->url() << " name " << doc->docName() << endl;
+ KILE_DEBUG() << "createDocument: SANITY check: " << (docinfo->getDoc() == docFor(docinfo->url())) << endl;
+ return doc;
+}
+
+Kate::View* Manager::loadItem(KileDocument::Type type, KileProjectItem *item, const QString & text, bool openProjectItemViews)
+{
+ Kate::View *view = 0L;
+
+ KILE_DEBUG() << "==loadItem(" << item->url().path() << ")======" << endl;
+
+ if ( item->type() != KileProjectItem::Image )
+ {
+ view = loadText(type, QString::null, item->url(), item->encoding(), openProjectItemViews && item->isOpen(), item->highlight(), text);
+ KILE_DEBUG() << "\tloadItem: docfor = " << docFor(item->url().path()) << endl;
+
+ TextInfo *docinfo = textInfoFor(item->url().path());
+ item->setInfo(docinfo);
+
+ KILE_DEBUG() << "\tloadItem: docinfo = " << docinfo << " doc = " << docinfo->getDoc() << " docfor = " << docFor(docinfo->url().path()) << endl;
+ if ( docinfo->getDoc() != docFor(docinfo->url().path()) ) kdWarning() << "docinfo->getDoc() != docFor()" << endl;
+ }
+ else
+ {
+ KILE_DEBUG() << "\tloadItem: no document generated" << endl;
+ TextInfo *docinfo = createTextDocumentInfo(m_ki->extensions()->determineDocumentType(item->url()), item->url());
+ item->setInfo(docinfo);
+
+ if ( docFor(item->url()) == 0L)
+ {
+ docinfo->detach();
+ KILE_DEBUG() << "\t\t\tdetached" << endl;
+ }
+ }
+
+ return view;
+}
+
+Kate::View* Manager::loadText(KileDocument::Type type, const QString& name, const KURL &url , const QString & encoding /* = QString::null */, bool create /* = true */, const QString & highlight /* = QString::null */, const QString & text /* = QString::null */, int index /* = - 1 */, const KURL& baseDirectory /* = KURL() */)
+{
+ KILE_DEBUG() << "==loadText(" << url.url() << ")=================" << endl;
+ //if doc already opened, update the structure view and return the view
+ if ( !url.isEmpty() && m_ki->isOpen(url))
+ return m_ki->viewManager()->switchToTextView(url);
+
+ TextInfo *docinfo = createTextDocumentInfo(type, url, baseDirectory);
+ Kate::Document *doc = createDocument(name, url, docinfo, encoding, highlight);
+
+ m_ki->structureWidget()->clean(docinfo);
+ docinfo->updateStruct();
+
+ if ( !text.isNull() ) doc->setText(text);
+
+ //FIXME: use signal/slot
+ if (doc && create)
+ return m_ki->viewManager()->createTextView(docinfo, index);
+
+ KILE_DEBUG() << "just after createView()" << endl;
+ KILE_DEBUG() << "\tdocinfo = " << docinfo << " doc = " << docinfo->getDoc() << " docfor = " << docFor(docinfo->url().path()) << endl;
+
+ return 0L;
+}
+
+//FIXME: template stuff should be in own class
+Kate::View* Manager::loadTemplate(TemplateItem *sel)
+{
+ QString text = QString::null;
+
+ if (sel && sel->name() != DEFAULT_EMPTY_CAPTION && sel->name() != DEFAULT_EMPTY_LATEX_CAPTION && sel->name() != DEFAULT_EMPTY_BIBTEX_CAPTION)
+ {
+ //create a new document to open the template in
+ Kate::Document *tempdoc = (Kate::Document*) KTextEditor::createDocument ("libkatepart", this, "Kate::Document");
+
+ if (!tempdoc->openURL(KURL(sel->path())))
+ {
+ KMessageBox::error(m_ki->parentWidget(), i18n("Could not find template: %1").arg(sel->name()),i18n("File Not Found"));
+ }
+ else
+ {
+ //substitute templates variables
+ text = tempdoc->text();
+ delete tempdoc;
+ replaceTemplateVariables(text);
+ }
+ }
+
+ KileDocument::Type type = sel ? sel->type() : KileDocument::Undefined;
+ //always set the base directory for scripts
+ return createDocumentWithText(text, type, QString(), (type == KileDocument::Script ? m_ki->scriptManager()->getLocalJScriptDirectory() : QString()));
+}
+
+Kate::View* Manager::createDocumentWithText(const QString& text, KileDocument::Type type /* = KileDocument::Undefined */, const QString& extension, const KURL& baseDirectory)
+{
+ Kate::View *view = loadText(type, KileUntitled::next() + (extension.isEmpty() ? QString::null : '.' + extension), KURL(), QString::null, true, QString::null, text, -1, baseDirectory);
+ if (view)
+ {
+ //FIXME this shouldn't be necessary!!!
+ view->getDoc()->setModified(true);
+ newDocumentStatus(view->getDoc());
+ }
+
+ return view;
+}
+
+Kate::View* Manager::createNewJScript()
+{
+ Kate::View *view = createDocumentWithText(QString::null, Script, "js", m_ki->scriptManager()->getLocalJScriptDirectory());
+ emit(updateStructure(false, 0L));
+ emit(updateModeStatus());
+ return view;
+}
+
+Kate::View* Manager::createNewLaTeXDocument()
+{
+ Kate::View *view = createDocumentWithText(QString::null, LaTeX);
+ emit(updateStructure(false, 0L));
+ emit(updateModeStatus());
+ return view;
+}
+
+void Manager::replaceTemplateVariables(QString &line)
+{
+ line=line.replace("$$AUTHOR$$", KileConfig::author());
+ line=line.replace("$$DOCUMENTCLASSOPTIONS$$", KileConfig::documentClassOptions());
+ if (!KileConfig::templateEncoding().isEmpty()) { line=line.replace("$$INPUTENCODING$$", "\\usepackage["+ KileConfig::templateEncoding() +"]{inputenc}");}
+ else { line = line.replace("$$INPUTENCODING$$","");}
+}
+
+void Manager::createTemplate()
+{
+ Kate::View *view = m_ki->viewManager()->currentTextView();
+ if (view)
+ {
+ if (view->getDoc()->isModified() )
+ {
+ KMessageBox::information(m_ki->parentWidget(),i18n("Please save the file first."));
+ return;
+ }
+ }
+ else
+ {
+ KMessageBox::information(m_ki->parentWidget(),i18n("Open/create a document first."));
+ return;
+ }
+
+ KURL url = view->getDoc()->url();
+ KileDocument::Type type = m_ki->extensions()->determineDocumentType(url);
+
+ if(type == KileDocument::Undefined || type == KileDocument::Text)
+ {
+ KMessageBox::information(m_ki->parentWidget(),i18n("Sorry, but a template for this type of document cannot be created."));
+ return;
+ }
+
+ ManageTemplatesDialog mtd(m_ki->templateManager(), url, i18n("Create Template From Document"));
+ mtd.exec();
+}
+
+void Manager::removeTemplate()
+{
+ ManageTemplatesDialog mtd(m_ki->templateManager(), i18n("Remove Template"));
+ mtd.exec();
+}
+
+void Manager::fileNew()
+{
+ NewFileWizard *nfw = new NewFileWizard(m_ki->templateManager(), m_ki->parentWidget());
+ if (nfw->exec())
+ {
+ loadTemplate(nfw->getSelection());
+ if ( nfw->useWizard() ) emit ( startWizard() );
+ emit(updateStructure(false, 0L));
+ emit(updateModeStatus());
+ }
+ delete nfw;
+}
+
+void Manager::fileNew(const KURL & url)
+{
+ //create an empty file
+ QFile file(url.path());
+ file.open(IO_ReadWrite);
+ file.close();
+
+ fileOpen(url, QString::null);
+}
+
+void Manager::fileOpen()
+{
+ //determine the starting dir for the file dialog
+ QString compileName = m_ki->getCompileName();
+ QString currentDir;
+ if ( QFileInfo(compileName).exists() )
+ currentDir = QFileInfo(compileName).dirPath(true);
+ else
+ currentDir = m_ki->fileSelector()->dirOperator()->url().path();
+
+ // use a filter for fileOpen dialog
+ Extensions *extensions = m_ki->extensions();
+ QString filter = extensions->latexDocumentFileFilter() + '\n'
+ + extensions->latexPackageFileFilter() + '\n'
+ + extensions->bibtexFileFilter() + '\n'
+ + extensions->metapostFileFilter() + '\n'
+ + "*|" + i18n("All Files");
+
+ //get the URLs
+ KEncodingFileDialog::Result result = KEncodingFileDialog::getOpenURLsAndEncoding( KileConfig::defaultEncoding(), currentDir, filter, m_ki->parentWidget(), i18n("Open Files") );
+
+ //open them
+ KURL::List urls = result.URLs;
+ for (KURL::List::Iterator i=urls.begin(); i != urls.end(); ++i)
+ fileOpen(*i, result.encoding);
+}
+
+void Manager::fileSelected(const KFileItem *file)
+{
+ fileSelected(file->url());
+ m_ki->fileSelector()->dirOperator()->view()->setSelected(file,false);
+}
+
+void Manager::fileSelected(const KileProjectItem * item)
+{
+ fileOpen(item->url(), item->encoding());
+}
+
+void Manager::fileSelected(const KURL & url)
+{
+ fileOpen(url, m_ki->fileSelector()->comboEncoding()->lineEdit()->text());
+}
+
+void Manager::saveURL(const KURL & url)
+{
+ Kate::Document *doc = docFor(url);
+ if (doc) doc->save();
+}
+
+void Manager::newDocumentStatus(Kate::Document *doc)
+{
+ KILE_DEBUG() << "void Manager::newDocumentStatus(Kate::Document)" << endl;
+ if (doc == 0L) return;
+
+ //sync terminal
+ m_ki->texKonsole()->sync();
+
+ emit(documentStatusChanged(doc, doc->isModified(), 0));
+
+ //updatestructure if active document changed from modified to unmodified (typically after a save)
+ if (!doc->isModified())
+ emit(updateStructure(true, textInfoFor(doc)));
+}
+
+void Manager::fileSaveAll(bool amAutoSaving, bool disUntitled )
+{
+ Kate::View *view= 0L;
+ QFileInfo fi;
+ int saveResult = Kate::View::SAVE_ERROR;
+ KURL url, backupUrl;
+
+ KILE_DEBUG() << "===Kile::fileSaveAll(amAutoSaving = " << amAutoSaving << ",disUntitled = " << disUntitled <<")" << endl;
+
+ for (uint i = 0; i < m_ki->viewManager()->textViews().count(); ++i)
+ {
+ view = m_ki->viewManager()->textView(i);
+
+ if ( view && view->getDoc()->isModified() )
+ {
+ url = view->getDoc()->url();
+ fi.setFile(url.path());
+
+ if ( ( !amAutoSaving && !(disUntitled && url.isEmpty() ) ) // DisregardUntitled is true and we have an untitled doc and don't autosave
+ || ( amAutoSaving && !url.isEmpty() ) //don't save untitled documents when autosaving
+ || ( !amAutoSaving && !disUntitled ) // both false, so we want to save everything
+ )
+ {
+
+ KILE_DEBUG() << "The files _" << autosaveWarnings.join(", ") << "_ have autosaveWarnings" <<endl;
+
+ if ( amAutoSaving)
+ {
+ if( !fi.isWritable() )
+ {
+ if ( autosaveWarnings.contains(url.path()) )
+ {
+ KILE_DEBUG() << "File " << url.prettyURL() << " is not writeable (again), trying next file" << endl;
+ continue;
+ }
+ else
+ {
+ autosaveWarnings.append(url.path());
+ KILE_DEBUG() << "File " << url.prettyURL() << " is not writeable (first time)" << endl;
+ }
+ }
+ else
+ {
+ autosaveWarnings.remove(url.path());
+ }
+ }
+ if (amAutoSaving && fi.size() > 0) // the size check ensures that we don't save empty files (to prevent something like #125809 in the future).
+ {
+ KURL backupUrl = KURL::fromPathOrURL(url.path()+ ".backup");
+
+ // patch for secure permissions, slightly modified for kile by Thomas Braun, taken from #103331
+
+ // get the right permissions, start with safe default
+ mode_t perms = 0600;
+ KIO::UDSEntry fentry;
+ if (KIO::NetAccess::stat (url, fentry, kapp->mainWidget()))
+ {
+ KILE_DEBUG () << "stating successful: " << url.prettyURL() << endl;
+ KFileItem item (fentry, url);
+ perms = item.permissions();
+ }
+
+ // first del existing file if any, than copy over the file we have
+ // failure if a: the existing file could not be deleted, b: the file could not be copied
+ if ( (!KIO::NetAccess::exists( backupUrl, false, kapp->mainWidget() )
+ || KIO::NetAccess::del( backupUrl, kapp->mainWidget() ) )
+ && KIO::NetAccess::file_copy( url, backupUrl, perms, true, false, kapp->mainWidget() ) )
+ {
+ KILE_DEBUG()<<"backing up successful ("<<url.prettyURL()<<" -> "<<backupUrl.prettyURL()<<")"<<endl;
+ }
+ else
+ {
+ KILE_DEBUG()<<"backing up failed ("<<url.prettyURL()<<" -> "<<backupUrl.prettyURL()<<")"<<endl;
+ emit printMsg(KileTool::Error,i18n("The file %1 could not be saved, check the permissions and the free disk space!").arg(backupUrl.prettyURL()),i18n("Autosave"));
+ }
+ }
+
+ KILE_DEBUG() << "trying to save: " << url.path() << endl;
+ saveResult = view->save();
+ fi.refresh();
+
+ if(saveResult == Kate::View::SAVE_ERROR && fi.size() == 0 && !url.isEmpty()) // we probably hit bug #125809, inform the user of the possible consequences
+ emit printMsg(KileTool::Error,i18n("Kile encountered problems while saving the file %1. Do you have enough free disk space left?").arg(url.url()),i18n("Saving"));
+ }
+ }
+ }
+ /*
+ This may look superfluos but actually it is not, in the case of multiple modified docs it ensures that the structure view keeps synchronized with the currentTextView
+ And if we only have one masterdoc or none nothing goes wrong.
+ */
+ emit(updateStructure(false,NULL));
+}
+
+void Manager::fileOpen(const KURL & url, const QString & encoding, int index)
+{
+ KILE_DEBUG() << "==Kile::fileOpen==========================" << endl;
+
+ //don't want to receive signals from the fileselector since
+ //that would allow the user to open a single file twice by double-clicking on it
+ m_ki->fileSelector()->blockSignals(true);
+
+ KILE_DEBUG() << "url is " << url.url() << endl;
+ const KURL realurl = symlinkFreeURL(url);
+ KILE_DEBUG() << "symlink free url is " << realurl.url() << endl;
+
+ bool isopen = m_ki->isOpen(realurl);
+
+ Kate::View *view = loadText(m_ki->extensions()->determineDocumentType(realurl), QString::null, realurl, encoding, true, QString::null, QString::null, index);
+ KileProjectItem *item = itemFor(realurl);
+
+ if(!isopen)
+ {
+ if(!item)
+ emit addToProjectView(realurl);
+ else if(view)
+ view->setCursorPosition(item->lineNumber(),item->columnNumber());
+ }
+
+ emit(updateStructure(true, 0L));
+ emit(updateModeStatus());
+ // update undefined references in this file
+ emit(updateReferences(textInfoFor(realurl.path())) );
+ m_ki->fileSelector()->blockSignals(false);
+}
+
+void Manager::fileSave()
+{
+ Kate::View* view = m_ki->viewManager()->currentTextView();
+ if(!view)
+ {
+ return;
+ }
+ KURL url = view->getDoc()->url();
+ if(url.isEmpty()) // newly created document
+ {
+ fileSaveAs();
+ return;
+ }
+ else
+ {
+ view->save();
+ }
+}
+
+void Manager::fileSaveAs(Kate::View* view)
+{
+
+ if(!view)
+ view = m_ki->viewManager()->currentTextView();
+ if(!view)
+ return;
+
+ Kate::Document* doc = view->getDoc();
+ Q_ASSERT(doc);
+ KileDocument::TextInfo* info = textInfoFor(doc);
+ Q_ASSERT(info);
+ KURL startURL = info->url();
+ KURL oldURL = startURL;
+ if(startURL.isEmpty())
+ {
+ if((info->getBaseDirectory()).isEmpty())
+ {
+ startURL = ":KILE_LATEX_SAVE_DIR";
+ }
+ else
+ {
+ startURL = info->getBaseDirectory();
+ startURL.setFileName(doc->docName());
+ }
+ }
+
+ KILE_DEBUG() << "startURL is " << startURL.path() << endl;
+
+ KEncodingFileDialog::Result result;
+ KURL saveURL;
+ while(true)
+ {
+ QString filter = info->getFileFilter() + "\n* |" + i18n("All Files");
+ result = KEncodingFileDialog::getSaveURLAndEncoding(KileConfig::defaultEncoding(), startURL.url(), filter, m_ki->parentWidget(), i18n("Save File"));
+ if(result.URLs.isEmpty() || result.URLs.first().isEmpty())
+ {
+ return;
+ }
+ saveURL = result.URLs.first();
+ if(info->getType() == KileDocument::LaTeX) {
+ saveURL = Info::makeValidTeXURL(saveURL, m_ki->extensions()->isTexFile(saveURL), false); // don't check for file existence
+ }
+ if(KIO::NetAccess::exists(saveURL, true, kapp->mainWidget())) // check for writing possibility
+ {
+ int r = KMessageBox::warningContinueCancel(m_ki->parentWidget(), i18n("A file with the name \"%1\" exists already. Do you want to overwrite it ?").arg(saveURL.fileName()), i18n("Overwrite File ?"), KGuiItem(i18n("&Overwrite")), QString::null);
+ if(r != KMessageBox::Continue)
+ {
+ continue;
+ }
+ }
+ break;
+ }
+ doc->setEncoding(result.encoding);
+ if(!doc->saveAs(saveURL))
+ {
+ return;
+ }
+ if(oldURL != saveURL)
+ {
+ if(info->isDocumentTypePromotionAllowed())
+ {
+ recreateTextDocumentInfo(info);
+ info = textInfoFor(doc);
+ }
+ m_ki->structureWidget()->updateUrl(info);
+ emit addToRecentFiles(saveURL);
+ emit addToProjectView(doc->url());
+ }
+}
+
+void Manager::fileSaveCopyAs()
+{
+ Kate::Document *doc= m_ki->activeTextDocument();
+ Kate::View *view = 0L;
+ if(doc)
+ {
+ KileDocument::TextInfo *originalInfo = textInfoFor(doc);
+
+ if(!originalInfo)
+ return;
+
+ view = createDocumentWithText(doc->text(),originalInfo->getType());
+
+ KileDocument::TextInfo *newInfo = textInfoFor(view->getDoc());
+
+ if(originalInfo->url().isEmpty()) // untitled doc
+ newInfo->setBaseDirectory(m_ki->fileSelector()->dirOperator()->url().path());
+ else
+ newInfo->setBaseDirectory(originalInfo->url().path());
+
+ fileSaveAs(view);
+
+ doc = view->getDoc();
+ if(doc && !doc->isModified()) // fileSaveAs was successful
+ fileClose(doc);
+ }
+}
+
+bool Manager::fileCloseAllOthers()
+{
+ Kate::View * currentview = m_ki->viewManager()->currentTextView();
+ while ( m_ki->viewManager()->textViews().count() > 1 )
+ {
+ Kate::View *view = m_ki->viewManager()->textViews().first();
+ if ( view == currentview )
+ view = m_ki->viewManager()->textViews().next();
+ if ( ! fileClose(view->getDoc()) )
+ return false;
+ }
+
+ return true;
+}
+
+bool Manager::fileCloseAll()
+{
+ Kate::View * view = m_ki->viewManager()->currentTextView();
+
+ //assumes one view per doc here
+ while( ! m_ki->viewManager()->textViews().isEmpty() )
+ {
+ view = m_ki->viewManager()->textView(0);
+ if (! fileClose(view->getDoc())) return false;
+ }
+
+ return true;
+}
+
+bool Manager::fileClose(const KURL & url)
+{
+ Kate::Document *doc = docFor(url);
+ if ( doc == 0L )
+ return true;
+ else
+ return fileClose(doc);
+}
+
+bool Manager::fileClose(Kate::Document *doc /* = 0L*/, bool closingproject /*= false*/)
+{
+ KILE_DEBUG() << "==Kile::fileClose==========================" << endl;
+
+ if (doc == 0L)
+ doc = m_ki->activeTextDocument();
+
+ if (doc == 0L)
+ return true;
+ else
+ //FIXME: remove from docinfo map, remove from dirwatch
+ {
+ KILE_DEBUG() << "doc->url().path()=" << doc->url().path() << endl;
+
+ const KURL url = doc->url();
+
+ TextInfo *docinfo= textInfoFor(doc);
+ if (docinfo == 0L)
+ {
+ kdWarning() << "no DOCINFO for " << url.url() << endl;
+ return true;
+ }
+ KileProjectItemList *items = itemsFor(docinfo);
+
+ while ( items->current() )
+ {
+ //FIXME: refactor here
+ if (items->current() && doc) storeProjectItem(items->current(),doc);
+ items->next();
+ }
+
+ delete items;
+
+ if ( doc->closeURL() )
+ {
+ // docinfo may have been recreated from 'Untitled' doc to a named doc
+ if ( url.isEmpty() )
+ docinfo= textInfoFor(doc);
+
+ if ( KileConfig::cleanUpAfterClose() )
+ cleanUpTempFiles(url, true); // yes we pass here url and not docinfo->url()
+
+ //FIXME: use signal/slot
+ m_ki->viewManager()->removeView(static_cast<Kate::View*>(doc->views().first()));
+ //remove the decorations
+
+ trashDoc(docinfo, doc);
+ m_ki->structureWidget()->clean(docinfo);
+ removeTextDocumentInfo(docinfo, closingproject);
+
+ emit removeFromProjectView(url);
+ emit updateModeStatus();
+ }
+ else
+ return false;
+ }
+
+ return true;
+}
+
+void Manager::buildProjectTree(const KURL & url)
+{
+ KileProject * project = projectFor(url);
+
+ if (project)
+ buildProjectTree(project);
+}
+
+void Manager::buildProjectTree(KileProject *project)
+{
+ if (project == 0)
+ project = activeProject();
+
+ if (project == 0 )
+ project = selectProject(i18n("Refresh Project Tree"));
+
+ if (project)
+ {
+ //TODO: update structure for all docs
+ project->buildProjectTree();
+ }
+ else if (m_projects.count() == 0)
+ KMessageBox::error(m_ki->parentWidget(), i18n("The current document is not associated to a project. Please activate a document that is associated to the project you want to build the tree for, then choose Refresh Project Tree again."),i18n( "Could Not Refresh Project Tree"));
+}
+
+void Manager::projectNew()
+{
+ KILE_DEBUG() << "==Kile::projectNew==========================" << endl;
+ KileNewProjectDlg *dlg = new KileNewProjectDlg(m_ki->templateManager(), m_ki->extensions(), m_ki->parentWidget());
+ KILE_DEBUG()<< "\tdialog created" << endl;
+
+ if (dlg->exec())
+ {
+ KILE_DEBUG()<< "\tdialog executed" << endl;
+ KILE_DEBUG() << "\t" << dlg->name() << " " << dlg->location() << endl;
+
+ KileProject *project = dlg->project();
+
+ //add the project file to the project
+ //TODO: shell expand the filename
+ KileProjectItem *item = new KileProjectItem(project, project->url());
+ item->setOpenState(false);
+ projectOpenItem(item);
+
+ if (dlg->createNewFile())
+ {
+ QString filename = dlg->file();
+
+ //create the new document and fill it with the template
+ //TODO: shell expand the filename
+ Kate::View *view = loadTemplate(dlg->getSelection());
+
+ //derive the URL from the base url of the project
+ KURL url = project->baseURL();
+ url.addPath(filename);
+
+ TextInfo *docinfo = textInfoFor(view->getDoc());
+
+ //save the new file
+ view->getDoc()->saveAs(url);
+ emit documentStatusChanged(view->getDoc(), false, 0);
+
+ //add this file to the project
+ item = new KileProjectItem(project, url);
+ //project->add(item);
+ mapItem(docinfo, item);
+
+ //docinfo->updateStruct(m_kwStructure->level());
+ emit(updateStructure(true, docinfo));
+ }
+
+ project->buildProjectTree();
+ //project->save();
+ addProject(project);
+ emit(updateModeStatus());
+ emit(addToRecentProjects(project->url()));
+ }
+}
+
+void Manager::addProject(const KileProject *project)
+{
+ KILE_DEBUG() << "==void Manager::addProject(const KileProject *project)==========" << endl;
+ m_projects.append(project);
+ KILE_DEBUG() << "\tnow " << m_projects.count() << " projects" << endl;
+ emit addToProjectView(project);
+ connect(project, SIGNAL(projectTreeChanged(const KileProject *)), this, SIGNAL(projectTreeChanged(const KileProject *)));
+}
+
+KileProject* Manager::selectProject(const QString& caption)
+{
+ QStringList list;
+ QPtrListIterator<KileProject> it(m_projects);
+ while (it.current())
+ {
+ list.append((*it)->name());
+ ++it;
+ }
+
+ KileProject *project = 0;
+ QString name = QString::null;
+ if (list.count() > 1)
+ {
+ KileListSelector *dlg = new KileListSelector(list, caption, i18n("Select Project"), m_ki->parentWidget());
+ if (dlg->exec())
+ {
+ name = list[dlg->currentItem()];
+ }
+ delete dlg;
+ }
+ else if (list.count() == 0)
+ {
+ return 0;
+ }
+ else
+ name = m_projects.first()->name();
+
+ project = projectFor(name);
+
+ return project;
+}
+
+void Manager::addToProject(const KURL & url)
+{
+ KILE_DEBUG() << "===Kile::addToProject(const KURL & url =" << url.url() << ")" << endl;
+
+ KileProject *project = selectProject(i18n("Add to Project"));
+
+ if (project)
+ addToProject(project, url);
+}
+
+void Manager::addToProject(KileProject* project, const KURL & url)
+{
+ const KURL realurl = symlinkFreeURL(url);
+ QFileInfo fi(realurl.path());
+
+ if (project->contains(realurl))
+ {
+ emit printMsg(KileTool::Info,i18n("The file %1 is already member of the project %2").arg(realurl.filename()).arg(project->name()),i18n("Add to Project"));
+ return;
+ }
+ else if(!fi.exists() || !fi.isReadable())
+ {
+ emit printMsg( KileTool::Info,i18n("The file %1 can not be added because it does not exist or is not readable").arg(realurl.filename()),i18n("Add to Project"));
+ return;
+ }
+
+ KileProjectItem *item = new KileProjectItem(project, realurl);
+ item->setOpenState(m_ki->isOpen(realurl));
+ projectOpenItem(item);
+ emit addToProjectView(item);
+ buildProjectTree(project);
+}
+
+void Manager::removeFromProject(const KileProjectItem *item)
+{
+ if (item && item->project())
+ {
+ KILE_DEBUG() << "\tprojecturl = " << item->project()->url().path() << ", url = " << item->url().path() << endl;
+
+ if (item->project()->url() == item->url())
+ {
+ KMessageBox::error(m_ki->parentWidget(), i18n("This file is the project file, it holds all the information about your project. Therefore it is not allowed to remove this file from its project."), i18n("Cannot Remove File From Project"));
+ return;
+ }
+
+ emit removeItemFromProjectView(item, m_ki->isOpen(item->url()));
+
+ KileProject *project = item->project();
+ item->project()->remove(item);
+
+ // update undefined references in all project files
+ updateProjectReferences(project);
+ project->buildProjectTree();
+ }
+}
+
+void Manager::projectOpenItem(KileProjectItem *item, bool openProjectItemViews)
+{
+ KILE_DEBUG() << "==Kile::projectOpenItem==========================" << endl;
+ KILE_DEBUG() << "\titem:" << item->url().path() << endl;
+
+ if (m_ki->isOpen(item->url())) //remove item from projectview (this file was opened before as a normal file)
+ emit removeFromProjectView(item->url());
+
+ Kate::View *view = loadItem(m_ki->extensions()->determineDocumentType(item->url()), item, QString::null, openProjectItemViews);
+
+ if ( (!item->isOpen()) && (view == 0L) && (item->getInfo()) ) //doc shouldn't be displayed, trash the doc
+ trashDoc(item->getInfo());
+ else if (view != 0L)
+ view->setCursorPosition(item->lineNumber(), item->columnNumber());
+
+ //oops, doc apparently was open while the project settings wants it closed, don't trash it the doc, update openstate instead
+ if ((!item->isOpen()) && (view != 0L))
+ item->setOpenState(true);
+}
+
+KileProject* Manager::projectOpen(const KURL & url, int step, int max, bool openProjectItemViews)
+{
+ KILE_DEBUG() << "==Kile::projectOpen==========================" << endl;
+ KILE_DEBUG() << "\tfilename: " << url.fileName() << endl;
+
+ const KURL realurl = symlinkFreeURL(url);
+
+ if (m_ki->projectIsOpen(realurl))
+ {
+ m_kpd->cancel();
+
+ KMessageBox::information(m_ki->parentWidget(), i18n("The project you tried to open is already opened. If you wanted to reload the project, close the project before you re-open it."),i18n("Project Already Open"));
+ return 0L;
+ }
+
+ QFileInfo fi(realurl.path());
+ if ( ! fi.isReadable() )
+ {
+ m_kpd->cancel();
+
+ if (KMessageBox::warningYesNo(m_ki->parentWidget(), i18n("The project file for this project does not exists or is not readable. Remove this project from the recent projects list?"),i18n("Could Not Load Project File")) == KMessageBox::Yes)
+ emit(removeFromRecentProjects(realurl));
+
+ return 0L;
+ }
+
+ m_kpd->show();
+
+ KileProject *kp = new KileProject(realurl,m_ki->extensions());
+
+ if(kp->isInvalid())
+ {
+ m_kpd->cancel();
+ delete kp;
+ return 0L;
+ }
+
+ emit(addToRecentProjects(realurl));
+
+ KileProjectItemList *list = kp->items();
+
+ int project_steps = list->count() + 1;
+ m_kpd->progressBar()->setTotalSteps(project_steps * max);
+ project_steps *= step;
+ m_kpd->progressBar()->setValue(project_steps);
+
+ // open the project files in the correct order
+ QValueVector<KileProjectItem*> givenPositionVector(list->count(), NULL);
+ QValueList<KileProjectItem*> notCorrectlyOrderedList;
+ for(KileProjectItem *item = list->first(); item; item = list->next())
+ {
+ int order = item->order();
+ if(order >= 0 && static_cast<unsigned int>(order) >= list->count())
+ {
+ order = -1;
+ }
+ if(!item->isOpen() || order < 0 || givenPositionVector[order] != NULL)
+ {
+ notCorrectlyOrderedList.push_back(item);
+ }
+ else
+ {
+ givenPositionVector[order] = item;
+ }
+ }
+
+ QValueList<KileProjectItem*> orderedList;
+ for(unsigned int i = 0; i < givenPositionVector.size(); ++i)
+ {
+ KileProjectItem *item = givenPositionVector[i];
+ if(item)
+ {
+ orderedList.push_back(item);
+ }
+ }
+ for(QValueList<KileProjectItem*>::iterator i = notCorrectlyOrderedList.begin(); i != notCorrectlyOrderedList.end(); ++i)
+ {
+ orderedList.push_back(*i);
+ }
+
+ unsigned int counter = 0;
+ for (QValueList<KileProjectItem*>::iterator i = orderedList.begin(); i != orderedList.end(); ++i)
+ {
+ projectOpenItem(*i, openProjectItemViews);
+ m_kpd->progressBar()->setValue(counter + project_steps);
+ kapp->processEvents();
+ ++counter;
+ }
+
+ kp->buildProjectTree();
+ addProject(kp);
+
+ emit(updateStructure(false, 0L));
+ emit(updateModeStatus());
+ // update undefined references in all project files
+ updateProjectReferences(kp);
+
+ if (step == (max - 1))
+ m_kpd->cancel();
+
+ m_ki->viewManager()->switchToTextView(kp->lastDocument());
+
+ return kp;
+}
+
+// as all labels are gathered in the project, we can check for unsolved references
+void Manager::updateProjectReferences(KileProject *project)
+{
+ KileProjectItemList *list = project->items();
+ for ( uint i=0; i < list->count(); ++i)
+ {
+ emit(updateReferences(list->at(i)->getInfo()));
+ }
+}
+
+KileProject* Manager::projectOpen()
+{
+ KILE_DEBUG() << "==Kile::projectOpen==========================" << endl;
+ KURL url = KFileDialog::getOpenURL( KileConfig::defaultProjectLocation(), i18n("*.kilepr|Kile Project Files\n*|All Files"), m_ki->parentWidget(), i18n("Open Project") );
+
+ if (!url.isEmpty())
+ return projectOpen(url);
+ else
+ return 0L;
+}
+
+
+void Manager::projectSave(KileProject *project /* = 0 */)
+{
+ KILE_DEBUG() << "==Kile::projectSave==========================" << endl;
+ if (project == 0)
+ {
+ //find the project that corresponds to the active doc
+ project= activeProject();
+ }
+
+ if (project == 0 )
+ project = selectProject(i18n("Save Project"));
+
+ if (project)
+ {
+ KileProjectItemList *list = project->items();
+ Kate::Document *doc = NULL;
+ KileProjectItem *item = NULL;
+ TextInfo *docinfo = NULL;
+
+ // determine the order in which the project items are opened
+ QValueVector<KileProjectItem*> viewPositionVector(m_ki->viewManager()->getTabCount(), NULL);
+ for (KileProjectItemList::iterator i = list->begin(); i != list->end(); ++i)
+ {
+ docinfo = (*i)->getInfo();
+ if(docinfo)
+ {
+ Kate::View *view = m_ki->viewManager()->textView(docinfo);
+ if(view)
+ {
+ int position = m_ki->viewManager()->getIndexOf(view);
+ if(position >= 0 && static_cast<unsigned int>(position) < viewPositionVector.size())
+ {
+ viewPositionVector[position] = *i;
+ }
+ }
+ }
+ }
+ int position = 0;
+ for(unsigned int i = 0; i < viewPositionVector.size(); ++i)
+ {
+ if(viewPositionVector[i] != NULL)
+ {
+ viewPositionVector[i]->setOrder(position);
+ ++position;
+ }
+ }
+
+ //update the open-state of the items
+ for (KileProjectItemList::iterator i = list->begin(); i != list->end(); ++i)
+ {
+ item = *i;
+ KILE_DEBUG() << "\tsetOpenState(" << (*i)->url().path() << ") to " << m_ki->isOpen(item->url()) << endl;
+ item->setOpenState(m_ki->isOpen(item->url()));
+ docinfo = item->getInfo();
+
+ if (docinfo != 0L)
+ doc = docinfo->getDoc();
+ if (doc != 0L)
+ storeProjectItem(item, doc);
+
+ doc = 0L;
+ docinfo = 0L;
+ }
+
+ project->save();
+ }
+ else
+ KMessageBox::error(m_ki->parentWidget(), i18n("The current document is not associated to a project. Please activate a document that is associated to the project you want to save, then choose Save Project again."),i18n( "Could Determine Active Project"));
+}
+
+void Manager::projectAddFiles(const KURL & url)
+{
+ KileProject *project = projectFor(url);
+
+ if (project)
+ projectAddFiles(project,url);
+}
+
+void Manager::projectAddFiles(KileProject *project,const KURL & fileUrl)
+{
+ KILE_DEBUG() << "==Kile::projectAddFiles()==========================" << endl;
+ if (project == 0 )
+ project = activeProject();
+
+ if (project == 0 )
+ project = selectProject(i18n("Add Files to Project"));
+
+ if (project)
+ {
+ QString currentDir;
+ if(fileUrl.isEmpty())
+ currentDir=project->url().directory();
+ else
+ currentDir=fileUrl.directory();
+
+ KILE_DEBUG() << "currentDir is " << currentDir << endl;
+ KFileDialog *dlg = new KFileDialog(currentDir, i18n("*|All Files"),m_ki->parentWidget(), 0, true );
+ KPushButton* okButton = dlg->okButton();
+ okButton->setText(i18n("Add"));
+ dlg->setCaption(i18n("Add Files"));
+ KFile::Mode mode = static_cast<KFile::Mode>( KFile::Files | KFile::ExistingOnly);
+ dlg->setMode(mode);
+
+ if(dlg->exec())
+ {
+ KURL::List urls = dlg->selectedURLs();
+ for (uint i=0; i < urls.count(); ++i)
+ {
+ addToProject(project, urls[i]);
+ }
+ // update undefined references in all project files
+ updateProjectReferences(project);
+ }
+ delete dlg;
+
+ //open them
+ }
+ else if (m_projects.count() == 0)
+ KMessageBox::error(m_ki->parentWidget(), i18n("There are no projects opened. Please open the project you want to add files to, then choose Add Files again."),i18n( "Could Not Determine Active Project"));
+}
+
+void Manager::toggleArchive(KileProjectItem *item)
+{
+ item->setArchive(!item->archive());
+}
+
+void Manager::projectOptions(const KURL & url)
+{
+ KileProject *project = projectFor(url);
+
+ if (project)
+ projectOptions(project);
+}
+
+void Manager::projectOptions(KileProject *project /* = 0*/)
+{
+ KILE_DEBUG() << "==Kile::projectOptions==========================" << endl;
+ if (project ==0 )
+ project = activeProject();
+
+ if (project == 0 )
+ project = selectProject(i18n("Project Options For"));
+
+ if (project)
+ {
+ KILE_DEBUG() << "\t" << project->name() << endl;
+ KileProjectOptionsDlg *dlg = new KileProjectOptionsDlg(project, m_ki->extensions(), m_ki->parentWidget());
+ dlg->exec();
+ }
+ else if (m_projects.count() == 0)
+ KMessageBox::error(m_ki->parentWidget(), i18n("The current document is not associated to a project. Please activate a document that is associated to the project you want to modify, then choose Project Options again."),i18n( "Could Not Determine Active Project"));
+}
+
+bool Manager::projectCloseAll()
+{
+ KILE_DEBUG() << "==Kile::projectCloseAll==========================" << endl;
+ bool close = true;
+
+ QPtrListIterator<KileProject> it(m_projects);
+ int i = m_projects.count() + 1;
+ while ( it.current() && close && (i > 0))
+ {
+ close = close && projectClose(it.current()->url());
+ --i;
+ }
+
+ return close;
+}
+
+bool Manager::projectClose(const KURL & url)
+{
+ KILE_DEBUG() << "==Kile::projectClose==========================" << endl;
+ KileProject *project = 0;
+
+ if (url.isEmpty())
+ {
+ project = activeProject();
+
+ if (project == 0 )
+ project = selectProject(i18n("Close Project"));
+ }
+ else
+ {
+ project = projectFor(url);
+ }
+
+ if (project)
+ {
+ KILE_DEBUG() << "\tclosing:" << project->name() << endl;
+ project->setLastDocument(m_ki->getName());
+
+ projectSave(project);
+
+ KileProjectItemList *list = project->items();
+
+ bool close = true;
+ Kate::Document *doc = 0L;
+ TextInfo *docinfo = 0L;
+ for (uint i =0; i < list->count(); ++i)
+ {
+ doc = 0L;
+ docinfo = list->at(i)->getInfo();
+ if (docinfo)
+ {
+ doc = docinfo->getDoc();
+ }
+ else
+ {
+ continue;
+ }
+ if (doc)
+ {
+ KILE_DEBUG() << "\t\tclosing item " << doc->url().path() << endl;
+ bool r = fileClose(doc, true);
+ close = close && r;
+ if (!close)
+ break;
+ }
+ else
+ {
+ // we still need to delete the TextInfo object
+ removeTextDocumentInfo(docinfo, true);
+ }
+ }
+
+ if (close)
+ {
+ m_projects.remove(project);
+ emit removeFromProjectView(project);
+ delete project;
+ emit(updateModeStatus());
+ return true;
+ }
+ else
+ return false;
+ }
+ else if (m_projects.count() == 0)
+ KMessageBox::error(m_ki->parentWidget(), i18n("The current document is not associated to a project. Please activate a document that is associated to the project you want to close, then choose Close Project again."),i18n( "Could Not Close Project"));
+
+ return true;
+}
+
+void Manager::storeProjectItem(KileProjectItem *item, Kate::Document *doc)
+{
+ KILE_DEBUG() << "===Kile::storeProjectItem==============" << endl;
+ KILE_DEBUG() << "\titem = " << item << ", doc = " << doc << endl;
+ item->setEncoding(doc->encoding());
+ item->setHighlight(doc->hlModeName(doc->hlMode()));
+ uint l = 0, c = 0;
+ QPtrList<KTextEditor::View> viewList = doc->views();
+ if(!viewList.isEmpty()) {
+ Kate::View *view = static_cast<Kate::View*>(viewList.first());
+
+ if(view) {
+ view->cursorPosition(&l,&c);
+ }
+ }
+ item->setLineNumber(l);
+ item->setColumnNumber(c);
+
+ KILE_DEBUG() << "\t" << item->encoding() << " " << item->highlight() << " should be " << doc->hlModeName(doc->hlMode()) << endl;
+}
+
+void Manager::cleanUpTempFiles(const KURL &url, bool silent)
+{
+ KILE_DEBUG() << "===void Manager::cleanUpTempFiles(const KURL " << url.path() << ", bool " << silent << ")===" << endl;
+
+ if( url.isEmpty() )
+ return;
+
+ QStringList extlist;
+ QFileInfo fi(url.path());
+ const QStringList templist = QStringList::split(" ", KileConfig::cleanUpFileExtensions());
+ const QString fileName = fi.fileName();
+ const QString dirPath = fi.dirPath(true);
+ const QString baseName = fi.baseName(true);
+
+ for (uint i=0; i < templist.count(); ++i)
+ {
+ fi.setFile( dirPath + '/' + baseName + templist[i] );
+ if ( fi.exists() )
+ extlist.append(templist[i]);
+ }
+
+ if (!silent && ( KileUntitled::isUntitled(fileName) || fileName.isEmpty() ) )
+ return;
+
+ if (!silent && extlist.count() > 0 )
+ {
+ KILE_DEBUG() << "not silent" << endl;
+ KileDialog::Clean *dialog = new KileDialog::Clean(m_ki->parentWidget(), fileName, extlist);
+ if ( dialog->exec() )
+ extlist = dialog->getCleanlist();
+ else
+ {
+ delete dialog;
+ return;
+ }
+
+ delete dialog;
+ }
+
+ if ( extlist.count() == 0 )
+ emit printMsg(KileTool::Warning, i18n("Nothing to clean for %1").arg(fileName), i18n("Clean"));
+ else
+ {
+ for ( uint i = 0 ; i < extlist.count() ; ++i )
+ {
+ QFile file( dirPath + '/' + baseName + extlist[i] );
+ KILE_DEBUG() << "About to remove file = " << file.name() << endl;
+ file.remove();
+ }
+ emit printMsg(KileTool::Info, i18n("Cleaning %1 : %2").arg(fileName).arg(extlist.join(" ")), i18n("Clean"));
+ }
+}
+
+void Manager::openDroppedURLs(QDropEvent *e) {
+ KURL::List urls;
+ Extensions *extensions = m_ki->extensions();
+ if(KURLDrag::decode(e, urls)) {
+ for(KURL::List::iterator i = urls.begin(); i != urls.end(); ++i) {
+ KURL url = *i;
+ if(extensions->isProjectFile(url))
+ {
+ projectOpen(url);
+ }
+ else
+ {
+ fileOpen(url);
+ }
+ }
+ }
+}
+
+// Show all opened projects and switch to another one, if you want
+
+void Manager::projectShow()
+{
+ if ( m_projects.count() <= 1 )
+ return;
+
+ // select the new project
+ KileProject *project = selectProject(i18n("Switch Project"));
+ if ( !project || project==activeProject() )
+ return;
+
+ // get last opened document
+ const KURL lastdoc = project->lastDocument();
+ KileProjectItem *docitem = ( !lastdoc.isEmpty() ) ? itemFor(lastdoc,project) : 0L;
+
+ // if not, we search for the first opened tex file of this project
+ // if no file is opened, we take the first tex file mentioned in the list
+ KileProjectItem *first_texitem = 0L;
+ if ( ! docitem )
+ {
+ KileProjectItemList *list = project->items();
+ for ( KileProjectItem *item=list->first(); item; item=list->next() )
+ {
+ QString itempath = item->path();
+
+ // called from KAction 'Show projects...': find the first opened
+ // LaTeX document or, if that fails, any other opened file
+ QStringList extlist = QStringList::split(" ",m_ki->extensions()->latexDocuments() + ' ' + m_ki->extensions()->latexPackages());
+ for ( QStringList::Iterator it=extlist.begin(); it!=extlist.end(); ++it )
+ {
+ if ( itempath.find( (*it), -(*it).length() ) >= 0 )
+ {
+ if ( m_ki->isOpen(item->url()) )
+ {
+ docitem = item;
+ break;
+ }
+ else if ( ! first_texitem )
+ first_texitem = item;
+ }
+ }
+ if ( docitem )
+ break;
+ }
+ }
+
+ // did we find one opened file or must we take the first entry
+ if ( ! docitem )
+ {
+ if ( ! first_texitem )
+ return;
+ docitem = first_texitem;
+ }
+
+ // ok, we can switch to another project now
+ if ( m_ki->isOpen(docitem->url()) )
+ m_ki->viewManager()->switchToTextView(docitem->url());
+ else
+ fileOpen( docitem->url(),docitem->encoding() );
+}
+
+void Manager::projectRemoveFiles()
+{
+ KileProjectItemList* items = selectProjectFileItems( i18n("Select Files to Remove") );
+ if ( items && items->count() > 0 )
+ for ( KileProjectItemList::Iterator it = items->begin(); it != items->end(); ++it )
+ removeFromProject(*it);
+ delete items;
+}
+
+void Manager::projectShowFiles()
+{
+ KileProjectItem *item = selectProjectFileItem( i18n("Select File") );
+ if ( item )
+ {
+ if ( item->type() == KileProjectItem::ProjectFile )
+ dontOpenWarning( item, i18n("Show Project Files"), i18n("project configuration file") );
+ else if ( item->type() == KileProjectItem::Image )
+ dontOpenWarning( item, i18n("Show Project Files"), i18n("graphics file") );
+ else
+ {
+ // ok, we can switch to another file
+ if ( m_ki->isOpen(item->url()) )
+ m_ki->viewManager()->switchToTextView(item->url());
+ else
+ fileOpen( item->url(),item->encoding() );
+ }
+ }
+}
+
+void Manager::projectOpenAllFiles()
+{
+ KileProject *project = selectProject(i18n("Select Project"));
+ if (project != 0L)
+ {
+ projectOpenAllFiles(project->url());
+ }
+}
+
+void Manager::projectOpenAllFiles(const KURL & url)
+{
+ KileProject* project;
+ Kate::Document* doc = 0L;
+
+ if(!url.isValid())
+ return;
+ project = projectFor(url);
+
+ if(!project)
+ return;
+
+
+ if(m_ki->viewManager()->currentTextView())
+ doc = m_ki->viewManager()->currentTextView()->getDoc();
+ // we remember the actual view, so the user gets the same view back after opening
+
+ KileProjectItemList *list = project->items();
+ for ( KileProjectItem *item=list->first(); item; item = list->next() )
+ {
+ if ( item->type()==KileProjectItem::ProjectFile )
+ dontOpenWarning( item, i18n("Open All Project Files"), i18n("project configuration file") );
+ else if ( item->type()==KileProjectItem::Image )
+ dontOpenWarning( item, i18n("Open All Project Files"), i18n("graphics file") );
+ else if ( ! m_ki->isOpen(item->url()) )
+ fileOpen( item->url(),item->encoding() );
+ }
+
+ if(doc) // we have a doc so switch back to original view
+ m_ki->viewManager()->switchToTextView(doc->url());
+}
+
+QStringList Manager::getProjectFiles()
+{
+ QStringList filelist;
+
+ KileProject *project = activeProject();
+ if ( project )
+ {
+ KileProjectItemList *list = project->items();
+ for ( KileProjectItem *item=list->first(); item; item = list->next() )
+ {
+ if ( item->type()!=KileProjectItem::ProjectFile && item->type()!=KileProjectItem::Image )
+ filelist << item->url().path();
+ }
+ }
+ return filelist;
+}
+
+void Manager::dontOpenWarning(KileProjectItem *item, const QString &action, const QString &filetype)
+{
+ emit printMsg(KileTool::Info, i18n("not opened: %1 (%2)").arg(item->url().path()).arg(filetype), action);
+}
+
+KileProjectItem* Manager::selectProjectFileItem(const QString &label)
+{
+ // select a project
+ KileProject *project = selectProject(i18n("Select Project"));
+ if ( ! project )
+ return 0L;
+
+ // get a list of files
+ QStringList filelist;
+ QMap<QString,KileProjectItem *> map;
+ KileProjectItemList *list = project->items();
+ for ( KileProjectItem *item=list->first(); item; item = list->next() ) {
+ filelist << item->path();
+ map[item->path()] = item;
+ }
+
+ // select one of these files
+ KileProjectItem *item = 0L;
+ KileListSelector *dlg = new KileListSelector(filelist,i18n("Project Files"),label, m_ki->parentWidget());
+ if ( dlg->exec() ) {
+ if ( dlg->currentItem() >= 0 ) {
+ QString name = filelist[dlg->currentItem()];
+ if ( map.contains(name) )
+ item = map[name];
+ else
+ KMessageBox::error(m_ki->parentWidget(), i18n("Could not determine the selected file."),i18n( "Project Error"));
+ }
+ }
+ delete dlg;
+
+ return item;
+}
+
+KileProjectItemList* Manager::selectProjectFileItems(const QString &label)
+{
+ KileProject *project = selectProject(i18n("Select Project"));
+ if ( ! project )
+ return 0L;
+
+ QStringList filelist, selectedfiles;
+ QMap<QString,KileProjectItem *> map;
+
+ KileProjectItemList *list = project->items();
+ for ( KileProjectItem *item=list->first(); item; item = list->next() ) {
+ filelist << item->path();
+ map[item->path()] = item;
+ }
+
+ KileProjectItemList *items = new KileProjectItemList();
+ items->setAutoDelete(false);
+
+ KileListSelectorMultiple *dlg = new KileListSelectorMultiple(filelist,i18n("Project Files"),label, m_ki->parentWidget());
+ if ( dlg->exec() ) {
+ if ( dlg->currentItem() >= 0 ) {
+ selectedfiles = dlg->selected();
+ for ( QStringList::Iterator it = selectedfiles.begin(); it != selectedfiles.end(); ++it ){
+ if ( map.contains(*it) )
+ items->append( map[(*it)] );
+ else
+ KMessageBox::error(m_ki->parentWidget(), i18n("Could not determine the selected file."),i18n( "Project Error"));
+ }
+ }
+ }
+ delete dlg;
+
+ return items;
+}
+
+// add a new file to the project
+// - only when there is an active project
+// - if the file doesn't already belong to it (checked by addToProject)
+
+void Manager::projectAddFile(QString filename, bool graphics)
+{
+ KILE_DEBUG() << "===Kile::projectAddFile==============" << endl;
+ KileProject *project = activeProject();
+ if ( ! project )
+ return;
+
+ QFileInfo fi(filename);
+ if ( ! fi.exists() )
+ {
+ if ( graphics )
+ return;
+
+ // called from InputDialog after a \input- or \include command:
+ // - if the chosen file has an extension: accept
+ // - if not we add the default TeX extension: accept if it exists else reject
+ QString ext = fi.extension();
+ if ( ! ext.isEmpty() )
+ return;
+
+ filename += m_ki->extensions()->latexDocumentDefault();
+ if ( QFileInfo(filename).exists() )
+ return;
+ }
+
+ //ok, we have a project and an existing file
+ KILE_DEBUG() << "\tadd file: " << filename << endl;
+ m_ki->viewManager()->updateStructure(true);
+
+ KURL url;
+ url.setPath(filename);
+ addToProject(project, url);
+}
+
+const KURL Manager::symlinkFreeURL(const KURL& url)
+{
+ KILE_DEBUG() << "===symlinkFreeURL==" << endl;
+
+ if( !url.isLocalFile() )
+ return url;
+
+ QDir dir(url.directory());
+ QString filename=url.path(); // if the directory does not exist we return the old url (just to be sure)
+
+ if(dir.exists())
+ filename= dir.canonicalPath() + '/' + url.filename();
+ else
+ KILE_DEBUG() << "directory " << url.directory() << "does not exist" << endl;
+
+ return KURL::fromPathOrURL(filename);
+}
+
+void Manager::cleanupDocumentInfoForProjectItems(KileDocument::Info *info)
+{
+ KileProjectItemList *itms = itemsFor(info);
+ QPtrListIterator<KileProjectItem> it(*itms);
+ KileProjectItem *current;
+ while((current = it.current()) != 0)
+ {
+ ++it;
+ current->setInfo(0);
+ }
+ delete itms;
+}
+
+}
+
+#include "kiledocmanager.moc"