1
/* This file is part of the KDE project
3
* Copyright (C) 2005 Christoph Cullmann <cullmann@kde.org>
5
* This library is free software; you can redistribute it and/or
6
* modify it under the terms of the GNU Library General Public
7
* License as published by the Free Software Foundation; either
8
* version 2 of the License, or (at your option) any later version.
10
* This library is distributed in the hope that it will be useful,
11
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13
* Library General Public License for more details.
15
* You should have received a copy of the GNU Library General Public License
16
* along with this library; see the file COPYING.LIB. If not, write to
17
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18
* Boston, MA 02110-1301, USA.
23
#include "katesessionmanager.h"
25
#include "katesessionchooser.h"
26
#include "katesessionmanagedialog.h"
27
#include "katesessionopendialog.h"
30
#include "katepluginmanager.h"
31
#include "katerunninginstanceinfo.h"
33
#include <KConfigGroup>
34
#include <KSharedConfig>
35
#include <KLocalizedString>
36
#include <KMessageBox>
37
#include <KIO/CopyJob>
40
#include <QApplication>
42
#include <QInputDialog>
49
//BEGIN KateSessionManager
51
KateSessionManager::KateSessionManager(QObject *parent, const QString &sessionsDir)
54
if (sessionsDir.isEmpty()) {
55
m_sessionsDir = QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) + QStringLiteral("/kate/sessions");
57
m_sessionsDir = sessionsDir;
60
// create dir if needed
61
QDir().mkpath(m_sessionsDir);
63
m_dirWatch = new KDirWatch(this);
64
m_dirWatch->addDir(m_sessionsDir);
65
connect(m_dirWatch, SIGNAL(dirty(QString)), this, SLOT(updateSessionList()));
69
m_activeSession = KateSession::createAnonymous(anonymousSessionFile());
72
KateSessionManager::~KateSessionManager()
77
void KateSessionManager::updateSessionList()
81
// Let's get a list of all session we have atm
82
QDir dir(m_sessionsDir, QStringLiteral("*.katesession"));
84
for (unsigned int i = 0; i < dir.count(); ++i) {
85
QString name = dir[i];
86
name.chop(12); // .katesession
87
list << QUrl::fromPercentEncoding(name.toLatin1());
91
QMutableHashIterator<QString, KateSession::Ptr> i(m_sessions);
95
const int idx = list.indexOf(i.key());
96
if (idx == -1) { // the key is invalid, remove it from m_session
97
if (i.value() != m_activeSession) { // if active, ignore missing config
100
} else { // remove it from scan list
106
foreach(const QString & newName, list) {
107
const QString file = sessionFileForName(newName);
108
m_sessions[newName] = KateSession::create(file, newName);
112
bool KateSessionManager::activateSession(KateSession::Ptr session,
113
const bool closeAndSaveLast,
116
if (m_activeSession == session) {
120
if (!session->isAnonymous()) {
121
//check if the requested session is already open in another instance
122
KateRunningInstanceMap instances;
123
if (!fillinRunningKateAppInstances(&instances)) {
124
KMessageBox::error(0, i18n("Internal error: there is more than one instance open for a given session."));
128
if (instances.contains(session->name())) {
129
if (KMessageBox::questionYesNo(0, i18n("Session '%1' is already opened in another kate instance, change there instead of reopening?", session->name()),
130
QString(), KStandardGuiItem::yes(), KStandardGuiItem::no(), QStringLiteral("katesessionmanager_switch_instance")) == KMessageBox::Yes) {
131
instances[session->name()]->dbus_if->call(QStringLiteral("activate"));
132
cleanupRunningKateAppInstanceMap(&instances);
137
cleanupRunningKateAppInstanceMap(&instances);
139
// try to close and save last session
140
if (closeAndSaveLast) {
141
if (KateApp::self()->activeKateMainWindow()) {
142
if (!KateApp::self()->activeKateMainWindow()->queryClose_internal()) {
147
// save last session or not?
151
KateApp::self()->documentManager()->closeAllDocuments();
154
// set the new session
155
m_activeSession = session;
157
// there is one case in which we don't want the restoration and that is
158
// when restoring session from session manager.
159
// In that case the restore is handled by the caller
161
loadSession(session);
164
emit sessionChanged();
168
void KateSessionManager::loadSession(const KateSession::Ptr &session) const
170
// open the new session
171
KSharedConfigPtr sharedConfig = KSharedConfig::openConfig();
172
KConfig *sc = session->config();
173
const bool loadDocs = !session->isAnonymous(); // do not load docs for new sessions
175
// if we have no session config object, try to load the default
176
// (anonymous/unnamed sessions)
177
// load plugin config + plugins
178
KateApp::self()->pluginManager()->loadConfig(sc);
181
KateApp::self()->documentManager()->restoreDocumentList(sc);
185
KConfigGroup c(sharedConfig, "General");
187
if (c.readEntry("Restore Window Configuration", true)) {
189
bool delete_cfg = false;
190
// a new, named session, read settings of the default session.
191
if (! sc->hasGroup("Open MainWindows")) {
193
cfg = new KConfig(anonymousSessionFile(), KConfig::SimpleConfig);
196
int wCount = cfg->group("Open MainWindows").readEntry("Count", 1);
198
for (int i = 0; i < wCount; ++i) {
199
if (i >= KateApp::self()->mainWindowsCount()) {
200
KateApp::self()->newMainWindow(cfg, QString::fromLatin1("MainWindow%1").arg(i));
202
KateApp::self()->mainWindow(i)->readProperties(KConfigGroup(cfg, QString::fromLatin1("MainWindow%1").arg(i)));
205
KateApp::self()->mainWindow(i)->restoreWindowConfig(KConfigGroup(cfg, QString::fromLatin1("MainWindow%1 Settings").arg(i)));
212
// remove mainwindows we need no longer...
214
while (wCount < KateApp::self()->mainWindowsCount()) {
215
delete KateApp::self()->mainWindow(KateApp::self()->mainWindowsCount() - 1);
221
bool KateSessionManager::activateSession(const QString &name, const bool closeAndSaveLast, const bool loadNew)
223
return activateSession(giveSession(name), closeAndSaveLast, loadNew);
226
bool KateSessionManager::activateAnonymousSession()
228
return activateSession(QString(), false);
231
KateSession::Ptr KateSessionManager::giveSession(const QString &name)
233
if (name.isEmpty()) {
234
return KateSession::createAnonymous(anonymousSessionFile());
237
if (m_sessions.contains(name)) {
238
return m_sessions.value(name);
241
KateSession::Ptr s = KateSession::create(sessionFileForName(name), name);
242
saveSessionTo(s->config());
243
m_sessions[name] = s;
247
void KateSessionManager::deleteSession(KateSession::Ptr session)
249
QFile::remove(session->file());
250
if (session != activeSession()) {
251
m_sessions.remove(session->name());
255
bool KateSessionManager::renameSession(KateSession::Ptr session, const QString &newName)
257
Q_ASSERT(!newName.isEmpty());
259
if (session->name() == newName) {
263
const QString newFile = sessionFileForName(newName);
265
if (QFile::exists(newFile)) {
266
KMessageBox::sorry(QApplication::activeWindow(),
267
i18n("The session could not be renamed to \"%1\", there already exists another session with the same name", newName),
268
i18n("Session Renaming"));
272
session->config()->sync();
274
const QUrl srcUrl = QUrl::fromLocalFile(session->file());
275
const QUrl dstUrl = QUrl::fromLocalFile(newFile);
276
KIO::CopyJob *job = KIO::move(srcUrl, dstUrl, KIO::HideProgressInfo);
279
KMessageBox::sorry(QApplication::activeWindow(),
280
i18n("The session could not be renamed to \"%1\". Failed to write to \"%2\"", newName, newFile),
281
i18n("Session Renaming"));
285
m_sessions[newName] = m_sessions.take(session->name());
286
session->setName(newName);
287
session->setFile(newFile);
289
if (session == activeSession()) {
290
emit sessionChanged();
296
void KateSessionManager::saveSessionTo(KConfig *sc) const
298
// save plugin configs and which plugins to load
299
KateApp::self()->pluginManager()->writeConfig(sc);
301
// save document configs + which documents to load
302
KateApp::self()->documentManager()->saveDocumentList(sc);
304
sc->group("Open MainWindows").writeEntry("Count", KateApp::self()->mainWindowsCount());
306
// save config for all windows around ;)
307
bool saveWindowConfig = KConfigGroup(KSharedConfig::openConfig(), "General").readEntry("Restore Window Configuration", true);
308
for (int i = 0; i < KateApp::self()->mainWindowsCount(); ++i) {
309
KConfigGroup cg(sc, QString::fromLatin1("MainWindow%1").arg(i));
310
KateApp::self()->mainWindow(i)->saveProperties(cg);
311
if (saveWindowConfig) {
312
KateApp::self()->mainWindow(i)->saveWindowConfig(KConfigGroup(sc, QString::fromLatin1("MainWindow%1 Settings").arg(i)));
319
* try to sync file to disk
321
QFile fileToSync(sc->name());
322
if (fileToSync.open(QIODevice::ReadOnly)) {
324
// ensure that the file is written to disk
325
#ifdef HAVE_FDATASYNC
326
fdatasync(fileToSync.handle());
328
fsync(fileToSync.handle());
334
bool KateSessionManager::saveActiveSession(bool rememberAsLast)
336
KConfig *sc = activeSession()->config();
340
if (rememberAsLast) {
341
KSharedConfigPtr c = KSharedConfig::openConfig();
342
c->group("General").writeEntry("Last Session", activeSession()->name());
348
bool KateSessionManager::chooseSession()
350
const KConfigGroup c(KSharedConfig::openConfig(), "General");
352
// get last used session, default to default session
353
const QString lastSession(c.readEntry("Last Session", QString()));
354
const QString sesStart(c.readEntry("Startup Session", "manual"));
356
// uhh, just open last used session, show no chooser
357
if (sesStart == QStringLiteral("last")) {
358
activateSession(lastSession, false);
362
// start with empty new session or in case no sessions exist
363
if (sesStart == QStringLiteral("new") || sessionList().size() == 0) {
364
activateAnonymousSession();
368
QScopedPointer<KateSessionChooser> chooser(new KateSessionChooser(0, lastSession));
369
const int res = chooser->exec();
373
case KateSessionChooser::resultOpen: {
374
KateSession::Ptr s = chooser->selectedSession(); // dialog guarantees this to be valid
375
success = activateSession(s, false);
379
case KateSessionChooser::resultCopy: {
380
KateSession::Ptr s = chooser->selectedSession(); // dialog guarantees this to be valid
381
KateSession::Ptr ns = KateSession::createAnonymousFrom(s, anonymousSessionFile());
382
activateSession(ns, false);
386
// exit the app lateron
387
case KateSessionChooser::resultQuit:
390
case KateSessionChooser::resultNew:
392
activateAnonymousSession();
396
// write back our nice boolean :)
397
if (success && chooser->reopenLastSession()) {
398
KConfigGroup generalConfig(KSharedConfig::openConfig(), QStringLiteral("General"));
400
if (res == KateSessionChooser::resultOpen) {
401
generalConfig.writeEntry("Startup Session", "last");
402
} else if (res == KateSessionChooser::resultNew) {
403
generalConfig.writeEntry("Startup Session", "new");
406
generalConfig.sync();
412
void KateSessionManager::sessionNew()
414
activateSession(giveSession(QString()));
417
void KateSessionManager::sessionOpen()
419
QScopedPointer<KateSessionOpenDialog> chooser(new KateSessionOpenDialog(0));
421
const int res = chooser->exec();
423
if (res == KateSessionOpenDialog::resultCancel) {
427
KateSession::Ptr s = chooser->selectedSession();
434
void KateSessionManager::sessionSave()
436
saveActiveSession(); // this is the optional point to handle saveSessionAs for anonymous session
439
void KateSessionManager::sessionSaveAs()
441
if (newSessionName()) {
443
emit sessionChanged();
447
bool KateSessionManager::newSessionName()
449
bool alreadyExists = false;
453
const QString name = QInputDialog::getText(QApplication::activeWindow(),
454
i18n("Specify New Name for Current Session"),
455
alreadyExists ? i18n("There is already an existing session with your chosen name.\nPlease choose a different one\nSession name:") : i18n("Session name:"),
456
QLineEdit::Normal, activeSession()->name(), &ok);
462
if (name.isEmpty()) {
463
KMessageBox::sorry(0, i18n("To save a session, you must specify a name."), i18n("Missing Session Name"));
467
const QString file = sessionFileForName(name);
468
if (QFile::exists(file)) {
469
alreadyExists = true;
473
activeSession()->config()->sync();
474
KateSession::Ptr ns = KateSession::createFrom(activeSession(), file, name);
475
m_activeSession = ns;
477
emit sessionChanged();
479
alreadyExists = false;
480
} while (alreadyExists);
484
void KateSessionManager::sessionManage()
486
QScopedPointer<KateSessionManageDialog>(new KateSessionManageDialog(0))->exec();
489
QString KateSessionManager::anonymousSessionFile() const
491
const QString file = m_sessionsDir + QStringLiteral("/../anonymous.katesession");
492
return QDir().cleanPath(file);
495
QString KateSessionManager::sessionFileForName(const QString &name) const
497
Q_ASSERT(!name.isEmpty());
498
const QString sname = QString::fromLatin1(QUrl::toPercentEncoding(name, QByteArray(), QByteArray(".")));
499
return m_sessionsDir + QStringLiteral("/") + sname + QStringLiteral(".katesession");
502
KateSessionList KateSessionManager::sessionList()
504
return m_sessions.values();
507
//END KateSessionManager