00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
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
00069
for (Kate::Document *doc = m_docList.first(); doc; doc = m_docList.next())
00070 saveMetaInfos(doc);
00071
00072
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
00129
if (activeId ==
id)
00130 {
00131
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
00219
return findDocumentByUrl (url) != 0;
00220 }
00221
00222 Kate::Document *KateDocManager::openURL (
const KURL& url,
const QString &encoding, uint *
id)
00223 {
00224
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 }