• Skip to content
  • Skip to link menu
KDE 3.5 API Reference
  • KDE API Reference
  • API Reference
  • Sitemap
  • Contact Us
 

kate

katedocmanager.cpp

Go to the documentation of this file.
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., 51 Franklin Street, Fifth Floor,
00017    Boston, MA 02110-1301, 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 <ktexteditor/encodinginterface.h>
00032 
00033 #include <kparts/factory.h>
00034 
00035 #include <klocale.h>
00036 #include <kdebug.h>
00037 #include <kconfig.h>
00038 #include <klibloader.h>
00039 #include <kmdcodec.h>
00040 #include <kmessagebox.h>
00041 #include <kencodingfiledialog.h>
00042 #include <kio/job.h>
00043 #include <kwin.h>
00044 
00045 #include <qdatetime.h>
00046 #include <qtextcodec.h>
00047 #include <qprogressdialog.h>
00048 
00049 KateDocManager::KateDocManager (QObject *parent)
00050  : QObject (parent)
00051  , m_saveMetaInfos(true)
00052  , m_daysMetaInfos(0)
00053 {
00054   m_factory = (KParts::Factory *) KLibLoader::self()->factory ("libkatepart");
00055 
00056   m_documentManager = new Kate::DocumentManager (this);
00057   m_docList.setAutoDelete(true);
00058   m_docDict.setAutoDelete(false);
00059   m_docInfos.setAutoDelete(true);
00060 
00061   m_dcop = new KateDocManagerDCOPIface (this);
00062 
00063   m_metaInfos = new KConfig("metainfos", false, false, "appdata");
00064 
00065   createDoc ();
00066 }
00067 
00068 KateDocManager::~KateDocManager ()
00069 {
00070   // save config
00071   if (!m_docList.isEmpty())
00072     m_docList.at(0)->writeConfig(KateApp::self()->config());
00073 
00074   if (m_saveMetaInfos)
00075   {
00076     // saving meta-infos when file is saved is not enough, we need to do it once more at the end
00077     for (Kate::Document *doc = m_docList.first(); doc; doc = m_docList.next())
00078       saveMetaInfos(doc);
00079 
00080     // purge saved filesessions
00081     if (m_daysMetaInfos > 0)
00082     {
00083       QStringList groups = m_metaInfos->groupList();
00084       QDateTime *def = new QDateTime(QDate(1970, 1, 1));
00085       for (QStringList::Iterator it = groups.begin(); it != groups.end(); ++it)
00086       {
00087         m_metaInfos->setGroup(*it);
00088         QDateTime last = m_metaInfos->readDateTimeEntry("Time", def);
00089         if (last.daysTo(QDateTime::currentDateTime()) > m_daysMetaInfos)
00090           m_metaInfos->deleteGroup(*it);
00091       }
00092       delete def;
00093     }
00094   }
00095 
00096   delete m_dcop;
00097   delete m_metaInfos;
00098 }
00099 
00100 KateDocManager *KateDocManager::self ()
00101 {
00102   return KateApp::self()->documentManager ();
00103 }
00104 
00105 Kate::Document *KateDocManager::createDoc ()
00106 {
00107   KTextEditor::Document *doc = (KTextEditor::Document *) m_factory->createPart (0, "", this, "", "KTextEditor::Document");
00108 
00109   m_docList.append((Kate::Document *)doc);
00110   m_docDict.insert (doc->documentNumber(), (Kate::Document *)doc);
00111   m_docInfos.insert (doc, new KateDocumentInfo ());
00112 
00113   if (m_docList.count() < 2)
00114     ((Kate::Document *)doc)->readConfig(KateApp::self()->config());
00115 
00116   emit documentCreated ((Kate::Document *)doc);
00117   emit m_documentManager->documentCreated ((Kate::Document *)doc);
00118 
00119   connect(doc,SIGNAL(modifiedOnDisc(Kate::Document *, bool, unsigned char)),this,SLOT(slotModifiedOnDisc(Kate::Document *, bool, unsigned char)));
00120   return (Kate::Document *)doc;
00121 }
00122 
00123 void KateDocManager::deleteDoc (Kate::Document *doc)
00124 {
00125   uint id = doc->documentNumber();
00126   uint activeId = 0;
00127   if (m_currentDoc)
00128     activeId = m_currentDoc->documentNumber ();
00129 
00130   if (m_docList.count() < 2)
00131     doc->writeConfig(KateApp::self()->config());
00132 
00133   m_docInfos.remove (doc);
00134   m_docDict.remove (id);
00135   m_docList.remove (doc);
00136 
00137   emit documentDeleted (id);
00138   emit m_documentManager->documentDeleted (id);
00139 
00140   // ohh, current doc was deleted
00141   if (activeId == id)
00142   {
00143     // special case of documentChanged, no longer any doc here !
00144     m_currentDoc = 0;
00145 
00146     emit documentChanged ();
00147     emit m_documentManager->documentChanged ();
00148   }
00149 }
00150 
00151 Kate::Document *KateDocManager::document (uint n)
00152 {
00153   return m_docList.at(n);
00154 }
00155 
00156 Kate::Document *KateDocManager::activeDocument ()
00157 {
00158   return m_currentDoc;
00159 }
00160 
00161 void KateDocManager::setActiveDocument (Kate::Document *doc)
00162 {
00163   if (!doc)
00164     return;
00165 
00166   if (m_currentDoc && (m_currentDoc->documentNumber() == doc->documentNumber()))
00167     return;
00168 
00169   m_currentDoc = doc;
00170 
00171   emit documentChanged ();
00172   emit m_documentManager->documentChanged ();
00173 }
00174 
00175 Kate::Document *KateDocManager::firstDocument ()
00176 {
00177   return m_docList.first();
00178 }
00179 
00180 Kate::Document *KateDocManager::nextDocument ()
00181 {
00182   return m_docList.next();
00183 }
00184 
00185 Kate::Document *KateDocManager::documentWithID (uint id)
00186 {
00187   return m_docDict[id];
00188 }
00189 
00190 const KateDocumentInfo *KateDocManager::documentInfo (Kate::Document *doc)
00191 {
00192   return m_docInfos[doc];
00193 }
00194 
00195 int KateDocManager::findDocument (Kate::Document *doc)
00196 {
00197   return m_docList.find (doc);
00198 }
00199 
00200 uint KateDocManager::documents ()
00201 {
00202   return m_docList.count ();
00203 }
00204 
00205 int KateDocManager::findDocument ( KURL url )
00206 {
00207   QPtrListIterator<Kate::Document> it(m_docList);
00208 
00209   for (; it.current(); ++it)
00210   {
00211     if ( it.current()->url() == url)
00212       return it.current()->documentNumber();
00213   }
00214   return -1;
00215 }
00216 
00217 Kate::Document *KateDocManager::findDocumentByUrl( KURL url )
00218 {
00219   for (QPtrListIterator<Kate::Document> it(m_docList); it.current(); ++it)
00220   {
00221     if ( it.current()->url() == url)
00222       return it.current();
00223   }
00224 
00225   return 0L;
00226 }
00227 
00228 bool KateDocManager::isOpen(KURL url)
00229 {
00230   // return just if we found some document with this url
00231   return findDocumentByUrl (url) != 0;
00232 }
00233 
00234 Kate::Document *KateDocManager::openURL (const KURL& url,const QString &encoding, uint *id, bool isTempFile)
00235 {
00236   // special handling if still only the first initial doc is there
00237   if (!documentList().isEmpty() && (documentList().count() == 1) && (!documentList().at(0)->isModified() && documentList().at(0)->url().isEmpty()))
00238   {
00239     Kate::Document* doc = documentList().getFirst();
00240 
00241     doc->setEncoding(encoding);
00242 
00243     if (!loadMetaInfos(doc, url))
00244       doc->openURL (url);
00245 
00246     if (id)
00247       *id=doc->documentNumber();
00248 
00249     if ( isTempFile && !url.isEmpty() && url.isLocalFile() )
00250     {
00251       QFileInfo fi( url.path() );
00252       if ( fi.exists() )
00253       {
00254         m_tempFiles[ doc->documentNumber() ] = qMakePair(url, fi.lastModified());
00255         kdDebug(13001)<<"temporary file will be deleted after use unless modified: "<<url.prettyURL()<<endl;
00256       }
00257     }
00258 
00259     connect(doc, SIGNAL(modStateChanged(Kate::Document *)), this, SLOT(slotModChanged(Kate::Document *)));
00260 
00261     emit initialDocumentReplaced();
00262 
00263     return doc;
00264   }
00265 
00266   Kate::Document *doc = findDocumentByUrl (url);
00267   if ( !doc )
00268   {
00269     doc = (Kate::Document *)createDoc ();
00270 
00271     doc->setEncoding(encoding.isNull() ? Kate::Document::defaultEncoding() : encoding);
00272 
00273     if (!loadMetaInfos(doc, url))
00274       doc->openURL (url);
00275   }
00276 
00277   if (id)
00278     *id=doc->documentNumber();
00279 
00280   if ( isTempFile && !url.isEmpty() && url.isLocalFile() )
00281   {
00282     QFileInfo fi( url.path() );
00283     if ( fi.exists() )
00284     {
00285       m_tempFiles[ doc->documentNumber() ] = qMakePair(url, fi.lastModified());
00286       kdDebug(13001)<<"temporary file will be deleted after use unless modified: "<<url.prettyURL()<<endl;
00287     }
00288   }
00289 
00290   return doc;
00291 }
00292 
00293 bool KateDocManager::closeDocument(class Kate::Document *doc,bool closeURL)
00294 {
00295   if (!doc) return false;
00296 
00297   saveMetaInfos(doc);
00298   if (closeURL)
00299   if (!doc->closeURL()) return false;
00300 
00301   QPtrList<Kate::View> closeList;
00302   uint documentNumber = doc->documentNumber();
00303 
00304   for (uint i=0; i < KateApp::self()->mainWindows (); i++ )
00305   {
00306     KateApp::self()->mainWindow(i)->viewManager()->closeViews(documentNumber);
00307   }
00308 
00309   if ( closeURL && m_tempFiles.contains( documentNumber ) )
00310   {
00311     QFileInfo fi( m_tempFiles[ documentNumber ].first.path() );
00312     if ( fi.lastModified() <= m_tempFiles[ documentNumber ].second /*||
00313          KMessageBox::questionYesNo( KateApp::self()->activeMainWindow(),
00314             i18n("The supposedly temporary file %1 has been modified. "
00315                 "Do you want to delete it anyway?").arg(m_tempFiles[ documentNumber ].first.prettyURL()),
00316             i18n("Delete File?") ) == KMessageBox::Yes*/ )
00317     {
00318       KIO::del( m_tempFiles[ documentNumber ].first, false, false );
00319       kdDebug(13001)<<"Deleted temporary file "<<m_tempFiles[ documentNumber ].first<<endl;
00320       m_tempFiles.remove( documentNumber );
00321     }
00322     else
00323       kdWarning(13001)<<"The supposedly temporary file "<<m_tempFiles[ documentNumber ].first.prettyURL()<<" have been modified since loaded, and has not been deleted."<<endl;
00324   }
00325 
00326   deleteDoc (doc);
00327 
00328   // never ever empty the whole document list
00329   if (m_docList.isEmpty())
00330     createDoc ();
00331 
00332   return true;
00333 }
00334 
00335 bool KateDocManager::closeDocument(uint n)
00336 {
00337   return closeDocument(document(n));
00338 }
00339 
00340 bool KateDocManager::closeDocumentWithID(uint id)
00341 {
00342   return closeDocument(documentWithID(id));
00343 }
00344 
00345 bool KateDocManager::closeAllDocuments(bool closeURL)
00346 {
00347   bool res = true;
00348 
00349   QPtrList<Kate::Document> docs = m_docList;
00350 
00351   for (uint i=0; i < KateApp::self()->mainWindows (); i++ )
00352   {
00353     KateApp::self()->mainWindow(i)->viewManager()->setViewActivationBlocked(true);
00354   }
00355 
00356   while (!docs.isEmpty() && res)
00357     if (! closeDocument(docs.at(0),closeURL) )
00358       res = false;
00359     else
00360       docs.remove ((uint)0);
00361 
00362   for (uint i=0; i < KateApp::self()->mainWindows (); i++ )
00363   {
00364     KateApp::self()->mainWindow(i)->viewManager()->setViewActivationBlocked(false);
00365 
00366     for (uint s=0; s < KateApp::self()->mainWindow(i)->viewManager()->containers()->count(); s++)
00367       KateApp::self()->mainWindow(i)->viewManager()->containers()->at(s)->activateView (m_docList.at(0)->documentNumber());
00368   }
00369 
00370   return res;
00371 }
00372 
00373 QPtrList<Kate::Document> KateDocManager::modifiedDocumentList() {
00374   QPtrList<Kate::Document> modified;
00375   for (QPtrListIterator<Kate::Document> it(m_docList); it.current(); ++it) {
00376     Kate::Document *doc = it.current();
00377     if (doc->isModified()) {
00378       modified.append(doc);
00379     }
00380   }
00381   return modified;
00382 }
00383 
00384 
00385 bool KateDocManager::queryCloseDocuments(KateMainWindow *w)
00386 {
00387   uint docCount = m_docList.count();
00388   for (QPtrListIterator<Kate::Document> it(m_docList); it.current(); ++it)
00389   {
00390     Kate::Document *doc = it.current();
00391 
00392     if (doc->url().isEmpty() && doc->isModified())
00393     {
00394       int msgres=KMessageBox::warningYesNoCancel( w,
00395                   i18n("<p>The document '%1' has been modified, but not saved."
00396                        "<p>Do you want to save your changes or discard them?").arg( doc->docName() ),
00397                     i18n("Close Document"), KStdGuiItem::save(), KStdGuiItem::discard() );
00398 
00399       if (msgres==KMessageBox::Cancel)
00400         return false;
00401 
00402       if (msgres==KMessageBox::Yes)
00403       {
00404         KEncodingFileDialog::Result r=KEncodingFileDialog::getSaveURLAndEncoding(
00405               KTextEditor::encodingInterface(doc)->encoding(),QString::null,QString::null,w,i18n("Save As"));
00406 
00407         doc->setEncoding( r.encoding );
00408 
00409         if (!r.URLs.isEmpty())
00410         {
00411           KURL tmp = r.URLs.first();
00412 
00413           if ( !doc->saveAs( tmp ) )
00414             return false;
00415         }
00416         else
00417           return false;
00418       }
00419     }
00420     else
00421     {
00422       if (!doc->queryClose())
00423         return false;
00424     }
00425   }
00426 
00427   // document count changed while queryClose, abort and notify user
00428   if (m_docList.count() > docCount)
00429   {
00430     KMessageBox::information (w,
00431                           i18n ("New file opened while trying to close Kate, closing aborted."),
00432                           i18n ("Closing Aborted"));
00433     return false;
00434   }
00435 
00436   return true;
00437 }
00438 
00439 
00440 void KateDocManager::saveAll()
00441 {
00442   for (QPtrListIterator<Kate::Document> it(m_docList); it.current(); ++it)
00443     if ( it.current()->isModified() && it.current()->views().count() )
00444       ((Kate::View*)it.current()->views().first())->save();
00445 }
00446 
00447 void KateDocManager::saveDocumentList (KConfig* config)
00448 {
00449   QString prevGrp=config->group();
00450   config->setGroup ("Open Documents");
00451   QString grp = config->group();
00452 
00453   config->writeEntry ("Count", m_docList.count());
00454 
00455   int i=0;
00456   for ( Kate::Document *doc = m_docList.first(); doc; doc = m_docList.next() )
00457   {
00458     config->setGroup(QString("Document %1").arg(i));
00459     doc->writeSessionConfig(config);
00460     config->setGroup(grp);
00461 
00462     i++;
00463   }
00464 
00465   config->setGroup(prevGrp);
00466 }
00467 
00468 void KateDocManager::restoreDocumentList (KConfig* config)
00469 {
00470   QString prevGrp=config->group();
00471   config->setGroup ("Open Documents");
00472   QString grp = config->group();
00473 
00474   unsigned int count = config->readUnsignedNumEntry("Count", 0);
00475 
00476   if (count == 0)
00477   {
00478     config->setGroup(prevGrp);
00479     return;
00480   }
00481 
00482   QProgressDialog *pd = new QProgressDialog(
00483         i18n("Reopening files from the last session..."),
00484         QString::null,
00485         count,
00486         0,
00487         "openprog");
00488   
00489   KWin::setOnDesktop(pd->winId(), KWin::currentDesktop());
00490   pd->setCaption (KateApp::self()->makeStdCaption(i18n("Starting Up")));
00491 
00492   bool first = true;
00493   for (unsigned int i=0; i < count; i++)
00494   {
00495     config->setGroup(QString("Document %1").arg(i));
00496     Kate::Document *doc = 0;
00497 
00498     if (first)
00499     {
00500       first = false;
00501       doc = document (0);
00502     }
00503     else
00504       doc = createDoc ();
00505 
00506     doc->readSessionConfig(config);
00507     config->setGroup (grp);
00508 
00509     pd->setProgress(pd->progress()+1);
00510     KateApp::self()->processEvents();
00511   }
00512 
00513   delete pd;
00514 
00515   config->setGroup(prevGrp);
00516 }
00517 
00518 void KateDocManager::slotModifiedOnDisc (Kate::Document *doc, bool b, unsigned char reason)
00519 {
00520   if (m_docInfos[doc])
00521   {
00522     m_docInfos[doc]->modifiedOnDisc = b;
00523     m_docInfos[doc]->modifiedOnDiscReason = reason;
00524   }
00525 }
00526 
00527 void KateDocManager::slotModChanged(Kate::Document *doc)
00528 {
00529   saveMetaInfos(doc);
00530 }
00531 
00535 bool KateDocManager::loadMetaInfos(Kate::Document *doc, const KURL &url)
00536 {
00537   if (!m_saveMetaInfos)
00538     return false;
00539 
00540   if (!m_metaInfos->hasGroup(url.prettyURL()))
00541     return false;
00542 
00543   QCString md5;
00544   bool ok = true;
00545 
00546   if (computeUrlMD5(url, md5))
00547   {
00548     m_metaInfos->setGroup(url.prettyURL());
00549     QString old_md5 = m_metaInfos->readEntry("MD5");
00550 
00551     if ((const char *)md5 == old_md5)
00552       doc->readSessionConfig(m_metaInfos);
00553     else
00554     {
00555       m_metaInfos->deleteGroup(url.prettyURL());
00556       ok = false;
00557     }
00558 
00559     m_metaInfos->sync();
00560   }
00561 
00562   return ok && doc->url() == url;
00563 }
00564 
00568 void KateDocManager::saveMetaInfos(Kate::Document *doc)
00569 {
00570   QCString md5;
00571 
00572   if (!m_saveMetaInfos)
00573     return;
00574 
00575   if (doc->isModified())
00576   {
00577 //     kdDebug (13020) << "DOC MODIFIED: no meta data saved" << endl;
00578     return;
00579   }
00580 
00581   if (computeUrlMD5(doc->url(), md5))
00582   {
00583     m_metaInfos->setGroup(doc->url().prettyURL());
00584     doc->writeSessionConfig(m_metaInfos);
00585     m_metaInfos->writeEntry("MD5", (const char *)md5);
00586     m_metaInfos->writeEntry("Time", QDateTime::currentDateTime());
00587     m_metaInfos->sync();
00588   }
00589 }
00590 
00591 bool KateDocManager::computeUrlMD5(const KURL &url, QCString &result)
00592 {
00593   QFile f(url.path());
00594 
00595   if (f.open(IO_ReadOnly))
00596   {
00597     KMD5 md5;
00598 
00599     if (!md5.update(f))
00600       return false;
00601 
00602     md5.hexDigest(result);
00603     f.close();
00604   }
00605   else
00606     return false;
00607 
00608   return true;
00609 }
00610 
00611 // kate: space-indent on; indent-width 2; replace-tabs on;

kate

Skip menu "kate"
  • Main Page
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members

API Reference

Skip menu "API Reference"
  • kate
Generated for API Reference by doxygen 1.5.9
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal