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 
00027 #include <kate/view.h>
00028 
00029 #include <kparts/factory.h>
00030 
00031 #include <klocale.h>
00032 #include <kdebug.h>
00033 #include <kconfig.h>
00034 #include <kapplication.h>
00035 #include <klibloader.h>
00036 #include <kmdcodec.h>
00037 
00038 #include <qdatetime.h>
00039 #include <qtextcodec.h>
00040 #include <qprogressdialog.h>
00041 #include <kmessagebox.h>
00042 #include <kencodingfiledialog.h>
00043 #include <ktexteditor/encodinginterface.h>
00044 
00045 KateDocManager::KateDocManager (QObject *parent)
00046  : QObject (parent)
00047  , m_saveMetaInfos(true)
00048  , m_daysMetaInfos(0)
00049 {
00050   m_factory = (KParts::Factory *) KLibLoader::self()->factory ("libkatepart");
00051 
00052   m_documentManager = new Kate::DocumentManager (this);
00053   m_docList.setAutoDelete(true);
00054   m_docDict.setAutoDelete(false);
00055   m_docInfos.setAutoDelete(true);
00056 
00057   m_dcop = new KateDocManagerDCOPIface (this);
00058 
00059   m_metaInfos = new KConfig("metainfos", false, false, "appdata");
00060 
00061   createDoc ();
00062 }
00063 
00064 KateDocManager::~KateDocManager ()
00065 {
00066   if (m_saveMetaInfos)
00067   {
00068     // saving meta-infos when file is saved is not enough, we need to do it once more at the end
00069     for (Kate::Document *doc = m_docList.first(); doc; doc = m_docList.next())
00070       saveMetaInfos(doc);
00071 
00072     // purge saved filesessions
00073     if (m_daysMetaInfos > 0)
00074     {
00075       QStringList groups = m_metaInfos->groupList();
00076       QDateTime *def = new QDateTime(QDate(1970, 1, 1));
00077       for (QStringList::Iterator it = groups.begin(); it != groups.end(); ++it)
00078       {
00079         m_metaInfos->setGroup(*it);
00080         QDateTime last = m_metaInfos->readDateTimeEntry("Time", def);
00081         if (last.daysTo(QDateTime::currentDateTime()) > m_daysMetaInfos)
00082           m_metaInfos->deleteGroup(*it);
00083       }
00084       delete def;
00085     }
00086   }
00087 
00088   delete m_dcop;
00089   delete m_metaInfos;
00090 }
00091 
00092 Kate::Document *KateDocManager::createDoc ()
00093 {
00094   KTextEditor::Document *doc = (KTextEditor::Document *) m_factory->createPart (0, "", this, "", "KTextEditor::Document");
00095 
00096   m_docList.append((Kate::Document *)doc);
00097   m_docDict.insert (doc->documentNumber(), (Kate::Document *)doc);
00098   m_docInfos.insert (doc, new KateDocumentInfo ());
00099 
00100   if (m_docList.count() < 2)
00101     ((Kate::Document *)doc)->readConfig(kapp->config());
00102 
00103   emit documentCreated ((Kate::Document *)doc);
00104   emit m_documentManager->documentCreated ((Kate::Document *)doc);
00105 
00106   connect(doc,SIGNAL(modifiedOnDisc(Kate::Document *, bool, unsigned char)),this,SLOT(slotModifiedOnDisc(Kate::Document *, bool, unsigned char)));
00107 
00108   return (Kate::Document *)doc;
00109 }
00110 
00111 void KateDocManager::deleteDoc (Kate::Document *doc)
00112 {
00113   uint id = doc->documentNumber();
00114   uint activeId = 0;
00115   if (m_currentDoc)
00116     activeId = m_currentDoc->documentNumber ();
00117 
00118   if (m_docList.count() < 2)
00119     doc->writeConfig(kapp->config());
00120 
00121   m_docInfos.remove (doc);
00122   m_docDict.remove (id);
00123   m_docList.remove (doc);
00124 
00125   emit documentDeleted (id);
00126   emit m_documentManager->documentDeleted (id);
00127 
00128   // ohh, current doc was deleted
00129   if (activeId == id)
00130   {
00131     // special case of documentChanged, no longer any doc here !
00132     m_currentDoc = 0;
00133 
00134     emit documentChanged ();
00135     emit m_documentManager->documentChanged ();
00136   }
00137 }
00138 
00139 Kate::Document *KateDocManager::document (uint n)
00140 {
00141   return m_docList.at(n);
00142 }
00143 
00144 Kate::Document *KateDocManager::activeDocument ()
00145 {
00146   return m_currentDoc;
00147 }
00148 
00149 void KateDocManager::setActiveDocument (Kate::Document *doc)
00150 {
00151   if (!doc)
00152     return;
00153 
00154   if (m_currentDoc && (m_currentDoc->documentNumber() == doc->documentNumber()))
00155     return;
00156 
00157   m_currentDoc = doc;
00158 
00159   emit documentChanged ();
00160   emit m_documentManager->documentChanged ();
00161 }
00162 
00163 Kate::Document *KateDocManager::firstDocument ()
00164 {
00165   return m_docList.first();
00166 }
00167 
00168 Kate::Document *KateDocManager::nextDocument ()
00169 {
00170   return m_docList.next();
00171 }
00172 
00173 Kate::Document *KateDocManager::documentWithID (uint id)
00174 {
00175   return m_docDict[id];
00176 }
00177 
00178 const KateDocumentInfo *KateDocManager::documentInfo (Kate::Document *doc)
00179 {
00180   return m_docInfos[doc];
00181 }
00182 
00183 int KateDocManager::findDocument (Kate::Document *doc)
00184 {
00185   return m_docList.find (doc);
00186 }
00187 
00188 uint KateDocManager::documents ()
00189 {
00190   return m_docList.count ();
00191 }
00192 
00193 int KateDocManager::findDocument ( KURL url )
00194 {
00195   QPtrListIterator<Kate::Document> it(m_docList);
00196 
00197   for (; it.current(); ++it)
00198   {
00199     if ( it.current()->url() == url)
00200       return it.current()->documentNumber();
00201   }
00202   return -1;
00203 }
00204 
00205 Kate::Document *KateDocManager::findDocumentByUrl( KURL url )
00206 {
00207   for (QPtrListIterator<Kate::Document> it(m_docList); it.current(); ++it)
00208   {
00209     if ( it.current()->url() == url)
00210       return it.current();
00211   }
00212 
00213   return 0L;
00214 }
00215 
00216 bool KateDocManager::isOpen(KURL url)
00217 {
00218   // return just if we found some document with this url
00219   return findDocumentByUrl (url) != 0;
00220 }
00221 
00222 Kate::Document *KateDocManager::openURL (const KURL& url,const QString &encoding, uint *id)
00223 {
00224   // special handling if still only the first initial doc is there
00225   if (!documentList().isEmpty() && (documentList().count() == 1) && (!documentList().at(0)->isModified() && documentList().at(0)->url().isEmpty()))
00226   {
00227     Kate::Document* doc = documentList().getFirst();
00228 
00229     doc->setEncoding(encoding.isNull() ? Kate::Document::defaultEncoding() : encoding);
00230 
00231     if (!loadMetaInfos(doc, url))
00232       doc->openURL (url);
00233 
00234     if (id)
00235       *id=doc->documentNumber();
00236 
00237     connect(doc, SIGNAL(modStateChanged(Kate::Document *)), this, SLOT(slotModChanged(Kate::Document *)));
00238 
00239     emit initialDocumentReplaced();
00240 
00241     return doc;
00242  }
00243 
00244   Kate::Document *doc = findDocumentByUrl (url);
00245   if ( !doc )
00246   {
00247     doc = (Kate::Document *)createDoc ();
00248 
00249     doc->setEncoding(encoding.isNull() ? Kate::Document::defaultEncoding() : encoding);
00250 
00251     if (!loadMetaInfos(doc, url))
00252       doc->openURL (url);
00253   }
00254 
00255   if (id)
00256     *id=doc->documentNumber();
00257 
00258   return doc;
00259 }
00260 
00261 bool KateDocManager::closeDocument(class Kate::Document *doc)
00262 {
00263   if (!doc) return false;
00264 
00265   saveMetaInfos(doc);
00266 
00267   if (!doc->closeURL()) return false;
00268 
00269   QPtrList<Kate::View> closeList;
00270   uint documentNumber = doc->documentNumber();
00271 
00272   for (uint i=0; i < ((KateApp *)kapp)->mainWindows (); i++ )
00273   {
00274      ((KateApp *)kapp)->kateMainWindow(i)->kateViewManager()->closeViews(documentNumber);
00275   }
00276 
00277   deleteDoc (doc);
00278 
00279   return true;
00280 }
00281 
00282 bool KateDocManager::closeDocument(uint n)
00283 {
00284   return closeDocument(document(n));
00285 }
00286 
00287 bool KateDocManager::closeDocumentWithID(uint id)
00288 {
00289   return closeDocument(documentWithID(id));
00290 }
00291 
00292 bool KateDocManager::closeAllDocuments()
00293 {
00294   bool res = true;
00295 
00296   while (!m_docList.isEmpty() && res)
00297     if (! closeDocument(m_docList.at(0)) )
00298       res = false;
00299 
00300   return res;
00301 }
00302 
00303 bool KateDocManager::queryCloseDocuments(KateMainWindow *w)
00304 {
00305   Kate::Document  *doc;
00306   for (QPtrListIterator<Kate::Document> it(m_docList); (doc=it.current())!=0; ++it)
00307   {
00308     if (doc->url().isEmpty() && doc->isModified())
00309     {
00310       int msgres=KMessageBox::warningYesNoCancel( w,
00311                   i18n("<p>The document '%1' has been modified, but not saved."
00312                        "<p>Do you want to save your changes or discard them?").arg( doc->docName() ),
00313                     i18n("Close Document"), KStdGuiItem::save(), KStdGuiItem::discard() );
00314 
00315       if (msgres==KMessageBox::Cancel)
00316         return false;
00317 
00318       if (msgres==KMessageBox::Yes)
00319       {
00320         KEncodingFileDialog::Result r=KEncodingFileDialog::getSaveURLAndEncoding(
00321               KTextEditor::encodingInterface(doc)->encoding(),QString::null,QString::null,w,i18n("Save As"));
00322 
00323         doc->setEncoding( r.encoding );
00324 
00325         if (!r.URLs.isEmpty())
00326         {
00327           KURL tmp = r.URLs.first();
00328 
00329           if ( !doc->saveAs( tmp ) )
00330             return false;
00331         }
00332         else
00333           return false;
00334       }
00335     }
00336     else
00337     {
00338       if (!doc->queryClose())
00339         return false;
00340     }
00341   }
00342 
00343   return true;
00344 }
00345 
00346 
00347 void KateDocManager::saveDocumentList (KConfig* config)
00348 {
00349   QString prevGrp=config->group();
00350   config->setGroup ("Open Documents");
00351   QString grp = config->group();
00352 
00353   config->writeEntry ("Count", m_docList.count());
00354 
00355   int i=0;
00356   for ( Kate::Document *doc = m_docList.first(); doc; doc = m_docList.next() )
00357   {
00358     config->setGroup(QString("Document %1").arg(i));
00359     doc->writeSessionConfig(config);
00360     config->setGroup(grp);
00361 
00362     i++;
00363   }
00364 
00365   config->setGroup(prevGrp);
00366 }
00367 
00368 void KateDocManager::restoreDocumentList (KConfig* config)
00369 {
00370   QString prevGrp=config->group();
00371   config->setGroup ("Open Documents");
00372   QString grp = config->group();
00373 
00374   int count = config->readNumEntry("Count");
00375 
00376   QProgressDialog *pd=new QProgressDialog(
00377         i18n("Reopening files from the last session..."),
00378         QString::null,
00379         count,
00380         0,
00381         "openprog");
00382 
00383   bool first = true;
00384   for (int i=0; i < count; i++)
00385   {
00386     config->setGroup(QString("Document %1").arg(i));
00387     Kate::Document *doc = 0;
00388 
00389     if (first)
00390     {
00391       first = false;
00392       doc = document (0);
00393     }
00394     else
00395       doc = createDoc ();
00396 
00397     doc->readSessionConfig(config);
00398     config->setGroup (grp);
00399 
00400     pd->setProgress(pd->progress()+1);
00401     kapp->processEvents();
00402   }
00403 
00404   delete pd;
00405 
00406   config->setGroup(prevGrp);
00407 }
00408 
00409 void KateDocManager::slotModifiedOnDisc (Kate::Document *doc, bool b, unsigned char reason)
00410 {
00411   if (m_docInfos[doc])
00412   {
00413     m_docInfos[doc]->modifiedOnDisc = b;
00414     m_docInfos[doc]->modifiedOnDiscReason = reason;
00415   }
00416 }
00417 
00418 void KateDocManager::slotModChanged(Kate::Document *doc)
00419 {
00420   saveMetaInfos(doc);
00421 }
00422 
00426 bool KateDocManager::loadMetaInfos(Kate::Document *doc, const KURL &url)
00427 {
00428   if (!m_saveMetaInfos)
00429     return false;
00430 
00431   if (!m_metaInfos->hasGroup(url.prettyURL()))
00432     return false;
00433 
00434   QCString md5;
00435   bool ok = true;
00436 
00437   if (computeUrlMD5(url, md5))
00438   {
00439     m_metaInfos->setGroup(url.prettyURL());
00440     QString old_md5 = m_metaInfos->readEntry("MD5");
00441 
00442     if ((const char *)md5 == old_md5)
00443       doc->readSessionConfig(m_metaInfos);
00444     else
00445     {
00446       m_metaInfos->deleteGroup(url.prettyURL());
00447       ok = false;
00448     }
00449 
00450     m_metaInfos->sync();
00451   }
00452 
00453   return ok && doc->url() == url;
00454 }
00455 
00459 void KateDocManager::saveMetaInfos(Kate::Document *doc)
00460 {
00461   QCString md5;
00462 
00463   if (!m_saveMetaInfos)
00464     return;
00465 
00466   if (doc->isModified())
00467   {
00468     kdDebug () << "DOC MODIFIED: no meta data saved" << endl;
00469     return;
00470   }
00471 
00472   if (computeUrlMD5(doc->url(), md5))
00473   {
00474     m_metaInfos->setGroup(doc->url().prettyURL());
00475     doc->writeSessionConfig(m_metaInfos);
00476     m_metaInfos->writeEntry("MD5", (const char *)md5);
00477     m_metaInfos->writeEntry("Time", QDateTime::currentDateTime());
00478     m_metaInfos->sync();
00479   }
00480 }
00481 
00482 bool KateDocManager::computeUrlMD5(const KURL &url, QCString &result)
00483 {
00484   QFile f(url.path());
00485 
00486   if (f.open(IO_ReadOnly))
00487   {
00488     KMD5 md5;
00489 
00490     if (!md5.update(f))
00491       return false;
00492 
00493     md5.hexDigest(result);
00494     f.close();
00495   }
00496   else
00497     return false;
00498 
00499   return true;
00500 }
KDE Logo
This file is part of the documentation for kate Library Version 3.3.90.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Tue Apr 5 03:59:28 2005 by doxygen 1.3.9.1 written by Dimitri van Heesch, © 1997-2003