kate Library API Documentation

katedocmanager.cpp

00001 /* This file is part of the KDE project
00002    Copyright (C) 2001 Christoph Cullmann <cullmann@kde.org>
00003    Copyright (C) 2002 Joseph Wenninger <jowenn@kde.org>
00004 
00005    This library is free software; you can redistribute it and/or
00006    modify it under the terms of the GNU Library General Public
00007    License version 2 as published by the Free Software Foundation.
00008 
00009    This library is distributed in the hope that it will be useful,
00010    but WITHOUT ANY WARRANTY; without even the implied warranty of
00011    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012    Library General Public License for more details.
00013 
00014    You should have received a copy of the GNU Library General Public License
00015    along with this library; see the file COPYING.LIB.  If not, write to
00016    the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
00017    Boston, MA 02111-1307, USA.
00018 */
00019 
00020 #include "katedocmanager.h"
00021 #include "katedocmanager.moc"
00022 #include "kateapp.h"
00023 #include "katemainwindow.h"
00024 #include "kateviewmanager.h"
00025 #include "katedocmanageriface.h"
00026 #include "kateexternaltools.h"
00027 #include "kateviewspacecontainer.h"
00028 
00029 #include <kate/view.h>
00030 
00031 #include <kparts/factory.h>
00032 
00033 #include <klocale.h>
00034 #include <kdebug.h>
00035 #include <kconfig.h>
00036 #include <kapplication.h>
00037 #include <klibloader.h>
00038 #include <kmdcodec.h>
00039 
00040 #include <qdatetime.h>
00041 #include <qtextcodec.h>
00042 #include <qprogressdialog.h>
00043 #include <kmessagebox.h>
00044 #include <kencodingfiledialog.h>
00045 #include <ktexteditor/encodinginterface.h>
00046 
00047 
00048 KateDocManager::KateDocManager (QObject *parent)
00049  : QObject (parent)
00050  , m_saveMetaInfos(true)
00051  , m_daysMetaInfos(0)
00052 {
00053   m_factory = (KParts::Factory *) KLibLoader::self()->factory ("libkatepart");
00054 
00055   m_documentManager = new Kate::DocumentManager (this);
00056   m_docList.setAutoDelete(true);
00057   m_docDict.setAutoDelete(false);
00058   m_docInfos.setAutoDelete(true);
00059 
00060   m_dcop = new KateDocManagerDCOPIface (this);
00061 
00062   m_metaInfos = new KConfig("metainfos", false, false, "appdata");
00063   Kate::Document::registerCommand(KateExternalToolsCommand::self());
00064 
00065   createDoc ();
00066 }
00067 
00068 KateDocManager::~KateDocManager ()
00069 {
00070   if (m_saveMetaInfos)
00071   {
00072     // saving meta-infos when file is saved is not enough, we need to do it once more at the end
00073     for (Kate::Document *doc = m_docList.first(); doc; doc = m_docList.next())
00074       saveMetaInfos(doc);
00075 
00076     // purge saved filesessions
00077     if (m_daysMetaInfos > 0)
00078     {
00079       QStringList groups = m_metaInfos->groupList();
00080       QDateTime *def = new QDateTime(QDate(1970, 1, 1));
00081       for (QStringList::Iterator it = groups.begin(); it != groups.end(); ++it)
00082       {
00083         m_metaInfos->setGroup(*it);
00084         QDateTime last = m_metaInfos->readDateTimeEntry("Time", def);
00085         if (last.daysTo(QDateTime::currentDateTime()) > m_daysMetaInfos)
00086           m_metaInfos->deleteGroup(*it);
00087       }
00088       delete def;
00089     }
00090   }
00091 
00092   delete m_dcop;
00093   delete m_metaInfos;
00094 }
00095 
00096 KateDocManager *KateDocManager::self ()
00097 {
00098   return KateApp::self()->kateDocumentManager ();
00099 }
00100 
00101 Kate::Document *KateDocManager::createDoc ()
00102 {
00103   KTextEditor::Document *doc = (KTextEditor::Document *) m_factory->createPart (0, "", this, "", "KTextEditor::Document");
00104 
00105   m_docList.append((Kate::Document *)doc);
00106   m_docDict.insert (doc->documentNumber(), (Kate::Document *)doc);
00107   m_docInfos.insert (doc, new KateDocumentInfo ());
00108 
00109   if (m_docList.count() < 2)
00110     ((Kate::Document *)doc)->readConfig(kapp->config());
00111 
00112   emit documentCreated ((Kate::Document *)doc);
00113   emit m_documentManager->documentCreated ((Kate::Document *)doc);
00114 
00115   connect(doc,SIGNAL(modifiedOnDisc(Kate::Document *, bool, unsigned char)),this,SLOT(slotModifiedOnDisc(Kate::Document *, bool, unsigned char)));
00116   return (Kate::Document *)doc;
00117 }
00118 
00119 void KateDocManager::deleteDoc (Kate::Document *doc)
00120 {
00121   uint id = doc->documentNumber();
00122   uint activeId = 0;
00123   if (m_currentDoc)
00124     activeId = m_currentDoc->documentNumber ();
00125 
00126   if (m_docList.count() < 2)
00127     doc->writeConfig(kapp->config());
00128 
00129   m_docInfos.remove (doc);
00130   m_docDict.remove (id);
00131   m_docList.remove (doc);
00132 
00133   emit documentDeleted (id);
00134   emit m_documentManager->documentDeleted (id);
00135 
00136   // ohh, current doc was deleted
00137   if (activeId == id)
00138   {
00139     // special case of documentChanged, no longer any doc here !
00140     m_currentDoc = 0;
00141 
00142     emit documentChanged ();
00143     emit m_documentManager->documentChanged ();
00144   }
00145 }
00146 
00147 Kate::Document *KateDocManager::document (uint n)
00148 {
00149   return m_docList.at(n);
00150 }
00151 
00152 Kate::Document *KateDocManager::activeDocument ()
00153 {
00154   return m_currentDoc;
00155 }
00156 
00157 void KateDocManager::setActiveDocument (Kate::Document *doc)
00158 {
00159   if (!doc)
00160     return;
00161 
00162   if (m_currentDoc && (m_currentDoc->documentNumber() == doc->documentNumber()))
00163     return;
00164 
00165   m_currentDoc = doc;
00166 
00167   emit documentChanged ();
00168   emit m_documentManager->documentChanged ();
00169 }
00170 
00171 Kate::Document *KateDocManager::firstDocument ()
00172 {
00173   return m_docList.first();
00174 }
00175 
00176 Kate::Document *KateDocManager::nextDocument ()
00177 {
00178   return m_docList.next();
00179 }
00180 
00181 Kate::Document *KateDocManager::documentWithID (uint id)
00182 {
00183   return m_docDict[id];
00184 }
00185 
00186 const KateDocumentInfo *KateDocManager::documentInfo (Kate::Document *doc)
00187 {
00188   return m_docInfos[doc];
00189 }
00190 
00191 int KateDocManager::findDocument (Kate::Document *doc)
00192 {
00193   return m_docList.find (doc);
00194 }
00195 
00196 uint KateDocManager::documents ()
00197 {
00198   return m_docList.count ();
00199 }
00200 
00201 int KateDocManager::findDocument ( KURL url )
00202 {
00203   QPtrListIterator<Kate::Document> it(m_docList);
00204 
00205   for (; it.current(); ++it)
00206   {
00207     if ( it.current()->url() == url)
00208       return it.current()->documentNumber();
00209   }
00210   return -1;
00211 }
00212 
00213 Kate::Document *KateDocManager::findDocumentByUrl( KURL url )
00214 {
00215   for (QPtrListIterator<Kate::Document> it(m_docList); it.current(); ++it)
00216   {
00217     if ( it.current()->url() == url)
00218       return it.current();
00219   }
00220 
00221   return 0L;
00222 }
00223 
00224 bool KateDocManager::isOpen(KURL url)
00225 {
00226   // return just if we found some document with this url
00227   return findDocumentByUrl (url) != 0;
00228 }
00229 
00230 Kate::Document *KateDocManager::openURL (const KURL& url,const QString &encoding, uint *id)
00231 {
00232   // special handling if still only the first initial doc is there
00233   if (!documentList().isEmpty() && (documentList().count() == 1) && (!documentList().at(0)->isModified() && documentList().at(0)->url().isEmpty()))
00234   {
00235     Kate::Document* doc = documentList().getFirst();
00236 
00237     doc->setEncoding(encoding);
00238 
00239     if (!loadMetaInfos(doc, url))
00240       doc->openURL (url);
00241 
00242     if (id)
00243       *id=doc->documentNumber();
00244 
00245     connect(doc, SIGNAL(modStateChanged(Kate::Document *)), this, SLOT(slotModChanged(Kate::Document *)));
00246 
00247     emit initialDocumentReplaced();
00248 
00249     return doc;
00250  }
00251 
00252   Kate::Document *doc = findDocumentByUrl (url);
00253   if ( !doc )
00254   {
00255     doc = (Kate::Document *)createDoc ();
00256 
00257     doc->setEncoding(encoding.isNull() ? Kate::Document::defaultEncoding() : encoding);
00258 
00259     if (!loadMetaInfos(doc, url))
00260       doc->openURL (url);
00261   }
00262 
00263   if (id)
00264     *id=doc->documentNumber();
00265 
00266   return doc;
00267 }
00268 
00269 bool KateDocManager::closeDocument(class Kate::Document *doc,bool closeURL)
00270 {
00271   if (!doc) return false;
00272 
00273   saveMetaInfos(doc);
00274   if (closeURL)
00275   if (!doc->closeURL()) return false;
00276 
00277   QPtrList<Kate::View> closeList;
00278   uint documentNumber = doc->documentNumber();
00279 
00280   for (uint i=0; i < ((KateApp *)kapp)->mainWindows (); i++ )
00281   {
00282      ((KateApp *)kapp)->kateMainWindow(i)->kateViewManager()->closeViews(documentNumber);
00283   }
00284 
00285   deleteDoc (doc);
00286 
00287   // never ever empty the whole document list
00288   if (m_docList.isEmpty())
00289     createDoc ();
00290 
00291   return true;
00292 }
00293 
00294 bool KateDocManager::closeDocument(uint n)
00295 {
00296   return closeDocument(document(n));
00297 }
00298 
00299 bool KateDocManager::closeDocumentWithID(uint id)
00300 {
00301   return closeDocument(documentWithID(id));
00302 }
00303 
00304 bool KateDocManager::closeAllDocuments(bool closeURL)
00305 {
00306   bool res = true;
00307 
00308   QPtrList<Kate::Document> docs = m_docList;
00309 
00310   for (uint i=0; i < ((KateApp *)kapp)->mainWindows (); i++ )
00311   {
00312     ((KateApp *)kapp)->kateMainWindow(i)->kateViewManager()->setViewActivationBlocked(true);
00313   }
00314 
00315   while (!docs.isEmpty() && res)
00316     if (! closeDocument(docs.at(0),closeURL) )
00317       res = false;
00318     else
00319       docs.remove ((uint)0);
00320 
00321   for (uint i=0; i < ((KateApp *)kapp)->mainWindows (); i++ )
00322   {
00323     ((KateApp *)kapp)->kateMainWindow(i)->kateViewManager()->setViewActivationBlocked(false);
00324 
00325     for (uint s=0; s < ((KateApp *)kapp)->kateMainWindow(i)->kateViewManager()->containers()->count(); s++)
00326       ((KateApp *)kapp)->kateMainWindow(i)->kateViewManager()->containers()->at(s)->activateView (m_docList.at(0)->documentNumber());
00327   }
00328 
00329   return res;
00330 }
00331 
00332 QPtrList<Kate::Document> KateDocManager::modifiedDocumentList() {
00333   QPtrList<Kate::Document> modified;
00334   for (QPtrListIterator<Kate::Document> it(m_docList); it.current(); ++it) {
00335     Kate::Document *doc = it.current();
00336     if (doc->isModified()) {
00337       modified.append(doc);
00338     }
00339   }
00340   return modified;
00341 }
00342 
00343 
00344 bool KateDocManager::queryCloseDocuments(KateMainWindow *w)
00345 {
00346   uint docCount = m_docList.count();
00347   for (QPtrListIterator<Kate::Document> it(m_docList); it.current(); ++it)
00348   {
00349     Kate::Document *doc = it.current();
00350 
00351     if (doc->url().isEmpty() && doc->isModified())
00352     {
00353       int msgres=KMessageBox::warningYesNoCancel( w,
00354                   i18n("<p>The document '%1' has been modified, but not saved."
00355                        "<p>Do you want to save your changes or discard them?").arg( doc->docName() ),
00356                     i18n("Close Document"), KStdGuiItem::save(), KStdGuiItem::discard() );
00357 
00358       if (msgres==KMessageBox::Cancel)
00359         return false;
00360 
00361       if (msgres==KMessageBox::Yes)
00362       {
00363         KEncodingFileDialog::Result r=KEncodingFileDialog::getSaveURLAndEncoding(
00364               KTextEditor::encodingInterface(doc)->encoding(),QString::null,QString::null,w,i18n("Save As"));
00365 
00366         doc->setEncoding( r.encoding );
00367 
00368         if (!r.URLs.isEmpty())
00369         {
00370           KURL tmp = r.URLs.first();
00371 
00372           if ( !doc->saveAs( tmp ) )
00373             return false;
00374         }
00375         else
00376           return false;
00377       }
00378     }
00379     else
00380     {
00381       if (!doc->queryClose())
00382         return false;
00383     }
00384   }
00385 
00386   // document count changed while queryClose, abort and notify user
00387   if (m_docList.count() > docCount)
00388   {
00389     KMessageBox::information (w,
00390                           i18n ("New file opened while trying to close Kate, closing aborted."),
00391                           i18n ("Closing Aborted"));
00392     return false;
00393   }
00394 
00395   return true;
00396 }
00397 
00398 
00399 void KateDocManager::saveAll()
00400 {
00401   for (QPtrListIterator<Kate::Document> it(m_docList); it.current(); ++it)
00402     if ( it.current()->isModified() && it.current()->views().count() )
00403       ((Kate::View*)it.current()->views().first())->save();
00404 }
00405 
00406 void KateDocManager::saveDocumentList (KConfig* config)
00407 {
00408   QString prevGrp=config->group();
00409   config->setGroup ("Open Documents");
00410   QString grp = config->group();
00411 
00412   config->writeEntry ("Count", m_docList.count());
00413 
00414   int i=0;
00415   for ( Kate::Document *doc = m_docList.first(); doc; doc = m_docList.next() )
00416   {
00417     config->setGroup(QString("Document %1").arg(i));
00418     doc->writeSessionConfig(config);
00419     config->setGroup(grp);
00420 
00421     i++;
00422   }
00423 
00424   config->setGroup(prevGrp);
00425 }
00426 
00427 void KateDocManager::restoreDocumentList (KConfig* config)
00428 {
00429   QString prevGrp=config->group();
00430   config->setGroup ("Open Documents");
00431   QString grp = config->group();
00432 
00433   int count = config->readNumEntry("Count");
00434 
00435   QProgressDialog *pd=new QProgressDialog(
00436         i18n("Reopening files from the last session..."),
00437         QString::null,
00438         count,
00439         0,
00440         "openprog");
00441 
00442   bool first = true;
00443   for (int i=0; i < count; i++)
00444   {
00445     config->setGroup(QString("Document %1").arg(i));
00446     Kate::Document *doc = 0;
00447 
00448     if (first)
00449     {
00450       first = false;
00451       doc = document (0);
00452     }
00453     else
00454       doc = createDoc ();
00455 
00456     doc->readSessionConfig(config);
00457     config->setGroup (grp);
00458 
00459     pd->setProgress(pd->progress()+1);
00460     kapp->processEvents();
00461   }
00462 
00463   delete pd;
00464 
00465   config->setGroup(prevGrp);
00466 }
00467 
00468 void KateDocManager::slotModifiedOnDisc (Kate::Document *doc, bool b, unsigned char reason)
00469 {
00470   if (m_docInfos[doc])
00471   {
00472     m_docInfos[doc]->modifiedOnDisc = b;
00473     m_docInfos[doc]->modifiedOnDiscReason = reason;
00474   }
00475 }
00476 
00477 void KateDocManager::slotModChanged(Kate::Document *doc)
00478 {
00479   saveMetaInfos(doc);
00480 }
00481 
00485 bool KateDocManager::loadMetaInfos(Kate::Document *doc, const KURL &url)
00486 {
00487   if (!m_saveMetaInfos)
00488     return false;
00489 
00490   if (!m_metaInfos->hasGroup(url.prettyURL()))
00491     return false;
00492 
00493   QCString md5;
00494   bool ok = true;
00495 
00496   if (computeUrlMD5(url, md5))
00497   {
00498     m_metaInfos->setGroup(url.prettyURL());
00499     QString old_md5 = m_metaInfos->readEntry("MD5");
00500 
00501     if ((const char *)md5 == old_md5)
00502       doc->readSessionConfig(m_metaInfos);
00503     else
00504     {
00505       m_metaInfos->deleteGroup(url.prettyURL());
00506       ok = false;
00507     }
00508 
00509     m_metaInfos->sync();
00510   }
00511 
00512   return ok && doc->url() == url;
00513 }
00514 
00518 void KateDocManager::saveMetaInfos(Kate::Document *doc)
00519 {
00520   QCString md5;
00521 
00522   if (!m_saveMetaInfos)
00523     return;
00524 
00525   if (doc->isModified())
00526   {
00527 //     kdDebug (13020) << "DOC MODIFIED: no meta data saved" << endl;
00528     return;
00529   }
00530 
00531   if (computeUrlMD5(doc->url(), md5))
00532   {
00533     m_metaInfos->setGroup(doc->url().prettyURL());
00534     doc->writeSessionConfig(m_metaInfos);
00535     m_metaInfos->writeEntry("MD5", (const char *)md5);
00536     m_metaInfos->writeEntry("Time", QDateTime::currentDateTime());
00537     m_metaInfos->sync();
00538   }
00539 }
00540 
00541 bool KateDocManager::computeUrlMD5(const KURL &url, QCString &result)
00542 {
00543   QFile f(url.path());
00544 
00545   if (f.open(IO_ReadOnly))
00546   {
00547     KMD5 md5;
00548 
00549     if (!md5.update(f))
00550       return false;
00551 
00552     md5.hexDigest(result);
00553     f.close();
00554   }
00555   else
00556     return false;
00557 
00558   return true;
00559 }
00560 // kate: space-indent on; indent-width 2; replace-tabs on;
KDE Logo
This file is part of the documentation for kate Library Version 3.4.1.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Tue Jun 13 19:27:53 2006 by doxygen 1.4.3 written by Dimitri van Heesch, © 1997-2003