~ubuntu-branches/ubuntu/vivid/kate/vivid-updates

« back to all changes in this revision

Viewing changes to kate/src/session/katesessionmanager.cpp

  • Committer: Package Import Robot
  • Author(s): Jonathan Riddell
  • Date: 2014-12-04 16:49:41 UTC
  • mfrom: (1.6.6)
  • Revision ID: package-import@ubuntu.com-20141204164941-l3qbvsly83hhlw2v
Tags: 4:14.11.97-0ubuntu1
* New upstream release
* Update build-deps and use pkg-kde v3 for Qt 5 build
* kate-data now kate5-data for co-installability

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* This file is part of the KDE project
 
2
 *
 
3
 *  Copyright (C) 2005 Christoph Cullmann <cullmann@kde.org>
 
4
 *
 
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.
 
9
 *
 
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.
 
14
 *
 
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.
 
19
 */
 
20
 
 
21
#include "config.h"
 
22
 
 
23
#include "katesessionmanager.h"
 
24
 
 
25
#include "katesessionchooser.h"
 
26
#include "katesessionmanagedialog.h"
 
27
#include "katesessionopendialog.h"
 
28
 
 
29
#include "kateapp.h"
 
30
#include "katepluginmanager.h"
 
31
#include "katerunninginstanceinfo.h"
 
32
 
 
33
#include <KConfigGroup>
 
34
#include <KSharedConfig>
 
35
#include <KLocalizedString>
 
36
#include <KMessageBox>
 
37
#include <KIO/CopyJob>
 
38
#include <KDirWatch>
 
39
 
 
40
#include <QApplication>
 
41
#include <QDir>
 
42
#include <QInputDialog>
 
43
#include <QUrl>
 
44
 
 
45
#ifndef Q_OS_WIN
 
46
#include <unistd.h>
 
47
#endif
 
48
 
 
49
//BEGIN KateSessionManager
 
50
 
 
51
KateSessionManager::KateSessionManager(QObject *parent, const QString &sessionsDir)
 
52
    : QObject(parent)
 
53
{
 
54
    if (sessionsDir.isEmpty()) {
 
55
        m_sessionsDir = QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) + QStringLiteral("/kate/sessions");
 
56
    } else {
 
57
        m_sessionsDir = sessionsDir;
 
58
    }
 
59
 
 
60
    // create dir if needed
 
61
    QDir().mkpath(m_sessionsDir);
 
62
 
 
63
    m_dirWatch = new KDirWatch(this);
 
64
    m_dirWatch->addDir(m_sessionsDir);
 
65
    connect(m_dirWatch, SIGNAL(dirty(QString)), this, SLOT(updateSessionList()));
 
66
 
 
67
    updateSessionList();
 
68
 
 
69
    m_activeSession = KateSession::createAnonymous(anonymousSessionFile());
 
70
}
 
71
 
 
72
KateSessionManager::~KateSessionManager()
 
73
{
 
74
    delete m_dirWatch;
 
75
}
 
76
 
 
77
void KateSessionManager::updateSessionList()
 
78
{
 
79
    QStringList list;
 
80
 
 
81
    // Let's get a list of all session we have atm
 
82
    QDir dir(m_sessionsDir, QStringLiteral("*.katesession"));
 
83
 
 
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());
 
88
    }
 
89
 
 
90
    // delete old items;
 
91
    QMutableHashIterator<QString, KateSession::Ptr> i(m_sessions);
 
92
 
 
93
    while (i.hasNext()) {
 
94
        i.next();
 
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
 
98
                i.remove();
 
99
            }
 
100
        } else { // remove it from scan list
 
101
            list.removeAt(idx);
 
102
        }
 
103
    }
 
104
 
 
105
    // load the new ones
 
106
    foreach(const QString & newName, list) {
 
107
        const QString file = sessionFileForName(newName);
 
108
        m_sessions[newName] = KateSession::create(file, newName);
 
109
    }
 
110
}
 
111
 
 
112
bool KateSessionManager::activateSession(KateSession::Ptr session,
 
113
        const bool closeAndSaveLast,
 
114
        const bool loadNew)
 
115
{
 
116
    if (m_activeSession == session) {
 
117
        return true;
 
118
    }
 
119
 
 
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."));
 
125
            return false;
 
126
        }
 
127
 
 
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);
 
133
                return false;
 
134
            }
 
135
        }
 
136
 
 
137
        cleanupRunningKateAppInstanceMap(&instances);
 
138
    }
 
139
    // try to close and save last session
 
140
    if (closeAndSaveLast) {
 
141
        if (KateApp::self()->activeKateMainWindow()) {
 
142
            if (!KateApp::self()->activeKateMainWindow()->queryClose_internal()) {
 
143
                return true;
 
144
            }
 
145
        }
 
146
 
 
147
        // save last session or not?
 
148
        saveActiveSession();
 
149
 
 
150
        // really close last
 
151
        KateApp::self()->documentManager()->closeAllDocuments();
 
152
    }
 
153
 
 
154
    // set the new session
 
155
    m_activeSession = session;
 
156
 
 
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
 
160
    if (loadNew) {
 
161
        loadSession(session);
 
162
    }
 
163
 
 
164
    emit sessionChanged();
 
165
    return true;
 
166
}
 
167
 
 
168
void KateSessionManager::loadSession(const KateSession::Ptr &session) const
 
169
{
 
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
 
174
 
 
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);
 
179
 
 
180
    if (loadDocs) {
 
181
        KateApp::self()->documentManager()->restoreDocumentList(sc);
 
182
    }
 
183
 
 
184
    // window config
 
185
    KConfigGroup c(sharedConfig, "General");
 
186
 
 
187
    if (c.readEntry("Restore Window Configuration", true)) {
 
188
        KConfig *cfg = sc;
 
189
        bool delete_cfg = false;
 
190
        // a new, named session, read settings of the default session.
 
191
        if (! sc->hasGroup("Open MainWindows")) {
 
192
            delete_cfg = true;
 
193
            cfg = new KConfig(anonymousSessionFile(), KConfig::SimpleConfig);
 
194
        }
 
195
 
 
196
        int wCount = cfg->group("Open MainWindows").readEntry("Count", 1);
 
197
 
 
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));
 
201
            } else {
 
202
                KateApp::self()->mainWindow(i)->readProperties(KConfigGroup(cfg, QString::fromLatin1("MainWindow%1").arg(i)));
 
203
            }
 
204
 
 
205
            KateApp::self()->mainWindow(i)->restoreWindowConfig(KConfigGroup(cfg, QString::fromLatin1("MainWindow%1 Settings").arg(i)));
 
206
        }
 
207
 
 
208
        if (delete_cfg) {
 
209
            delete cfg;
 
210
        }
 
211
 
 
212
        // remove mainwindows we need no longer...
 
213
        if (wCount > 0) {
 
214
            while (wCount < KateApp::self()->mainWindowsCount()) {
 
215
                delete KateApp::self()->mainWindow(KateApp::self()->mainWindowsCount() - 1);
 
216
            }
 
217
        }
 
218
    }
 
219
}
 
220
 
 
221
bool KateSessionManager::activateSession(const QString &name, const bool closeAndSaveLast, const bool loadNew)
 
222
{
 
223
    return activateSession(giveSession(name), closeAndSaveLast, loadNew);
 
224
}
 
225
 
 
226
bool KateSessionManager::activateAnonymousSession()
 
227
{
 
228
    return activateSession(QString(), false);
 
229
}
 
230
 
 
231
KateSession::Ptr KateSessionManager::giveSession(const QString &name)
 
232
{
 
233
    if (name.isEmpty()) {
 
234
        return KateSession::createAnonymous(anonymousSessionFile());
 
235
    }
 
236
 
 
237
    if (m_sessions.contains(name)) {
 
238
        return m_sessions.value(name);
 
239
    }
 
240
 
 
241
    KateSession::Ptr s = KateSession::create(sessionFileForName(name), name);
 
242
    saveSessionTo(s->config());
 
243
    m_sessions[name] = s;
 
244
    return s;
 
245
}
 
246
 
 
247
void KateSessionManager::deleteSession(KateSession::Ptr session)
 
248
{
 
249
    QFile::remove(session->file());
 
250
    if (session != activeSession()) {
 
251
        m_sessions.remove(session->name());
 
252
    }
 
253
}
 
254
 
 
255
bool KateSessionManager::renameSession(KateSession::Ptr session, const QString &newName)
 
256
{
 
257
    Q_ASSERT(!newName.isEmpty());
 
258
 
 
259
    if (session->name() == newName) {
 
260
        return true;
 
261
    }
 
262
 
 
263
    const QString newFile = sessionFileForName(newName);
 
264
 
 
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"));
 
269
        return false;
 
270
    }
 
271
 
 
272
    session->config()->sync();
 
273
 
 
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);
 
277
 
 
278
    if (!job->exec()) {
 
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"));
 
282
        return false;
 
283
    }
 
284
 
 
285
    m_sessions[newName] = m_sessions.take(session->name());
 
286
    session->setName(newName);
 
287
    session->setFile(newFile);
 
288
 
 
289
    if (session == activeSession()) {
 
290
        emit sessionChanged();
 
291
    }
 
292
 
 
293
    return true;
 
294
}
 
295
 
 
296
void KateSessionManager::saveSessionTo(KConfig *sc) const
 
297
{
 
298
    // save plugin configs and which plugins to load
 
299
    KateApp::self()->pluginManager()->writeConfig(sc);
 
300
 
 
301
    // save document configs + which documents to load
 
302
    KateApp::self()->documentManager()->saveDocumentList(sc);
 
303
 
 
304
    sc->group("Open MainWindows").writeEntry("Count", KateApp::self()->mainWindowsCount());
 
305
 
 
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)));
 
313
        }
 
314
    }
 
315
 
 
316
    sc->sync();
 
317
 
 
318
    /**
 
319
     * try to sync file to disk
 
320
     */
 
321
    QFile fileToSync(sc->name());
 
322
    if (fileToSync.open(QIODevice::ReadOnly)) {
 
323
#ifndef Q_OS_WIN
 
324
        // ensure that the file is written to disk
 
325
#ifdef HAVE_FDATASYNC
 
326
        fdatasync(fileToSync.handle());
 
327
#else
 
328
        fsync(fileToSync.handle());
 
329
#endif
 
330
#endif
 
331
    }
 
332
}
 
333
 
 
334
bool KateSessionManager::saveActiveSession(bool rememberAsLast)
 
335
{
 
336
    KConfig *sc = activeSession()->config();
 
337
 
 
338
    saveSessionTo(sc);
 
339
 
 
340
    if (rememberAsLast) {
 
341
        KSharedConfigPtr c = KSharedConfig::openConfig();
 
342
        c->group("General").writeEntry("Last Session", activeSession()->name());
 
343
        c->sync();
 
344
    }
 
345
    return true;
 
346
}
 
347
 
 
348
bool KateSessionManager::chooseSession()
 
349
{
 
350
    const KConfigGroup c(KSharedConfig::openConfig(), "General");
 
351
 
 
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"));
 
355
 
 
356
    // uhh, just open last used session, show no chooser
 
357
    if (sesStart == QStringLiteral("last")) {
 
358
        activateSession(lastSession, false);
 
359
        return true;
 
360
    }
 
361
 
 
362
    // start with empty new session or in case no sessions exist
 
363
    if (sesStart == QStringLiteral("new") || sessionList().size() == 0) {
 
364
        activateAnonymousSession();
 
365
        return true;
 
366
    }
 
367
 
 
368
    QScopedPointer<KateSessionChooser> chooser(new KateSessionChooser(0, lastSession));
 
369
    const int res = chooser->exec();
 
370
    bool success = true;
 
371
 
 
372
    switch (res) {
 
373
    case KateSessionChooser::resultOpen: {
 
374
        KateSession::Ptr s = chooser->selectedSession(); // dialog guarantees this to be valid
 
375
        success = activateSession(s, false);
 
376
        break;
 
377
    }
 
378
 
 
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);
 
383
        break;
 
384
    }
 
385
 
 
386
    // exit the app lateron
 
387
    case KateSessionChooser::resultQuit:
 
388
        return false;
 
389
 
 
390
    case KateSessionChooser::resultNew:
 
391
    default:
 
392
        activateAnonymousSession();
 
393
        break;
 
394
    }
 
395
 
 
396
    // write back our nice boolean :)
 
397
    if (success && chooser->reopenLastSession()) {
 
398
        KConfigGroup generalConfig(KSharedConfig::openConfig(), QStringLiteral("General"));
 
399
 
 
400
        if (res == KateSessionChooser::resultOpen) {
 
401
            generalConfig.writeEntry("Startup Session", "last");
 
402
        } else if (res == KateSessionChooser::resultNew) {
 
403
            generalConfig.writeEntry("Startup Session", "new");
 
404
        }
 
405
 
 
406
        generalConfig.sync();
 
407
    }
 
408
 
 
409
    return success;
 
410
}
 
411
 
 
412
void KateSessionManager::sessionNew()
 
413
{
 
414
    activateSession(giveSession(QString()));
 
415
}
 
416
 
 
417
void KateSessionManager::sessionOpen()
 
418
{
 
419
    QScopedPointer<KateSessionOpenDialog> chooser(new KateSessionOpenDialog(0));
 
420
 
 
421
    const int res = chooser->exec();
 
422
 
 
423
    if (res == KateSessionOpenDialog::resultCancel) {
 
424
        return;
 
425
    }
 
426
 
 
427
    KateSession::Ptr s = chooser->selectedSession();
 
428
 
 
429
    if (s) {
 
430
        activateSession(s);
 
431
    }
 
432
}
 
433
 
 
434
void KateSessionManager::sessionSave()
 
435
{
 
436
    saveActiveSession(); // this is the optional point to handle saveSessionAs for anonymous session
 
437
}
 
438
 
 
439
void KateSessionManager::sessionSaveAs()
 
440
{
 
441
    if (newSessionName()) {
 
442
        saveActiveSession();
 
443
        emit sessionChanged();
 
444
    }
 
445
}
 
446
 
 
447
bool KateSessionManager::newSessionName()
 
448
{
 
449
    bool alreadyExists = false;
 
450
 
 
451
    do {
 
452
        bool ok = 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);
 
457
 
 
458
        if (!ok) {
 
459
            return false;
 
460
        }
 
461
 
 
462
        if (name.isEmpty()) {
 
463
            KMessageBox::sorry(0, i18n("To save a session, you must specify a name."), i18n("Missing Session Name"));
 
464
            continue;
 
465
        }
 
466
 
 
467
        const QString file = sessionFileForName(name);
 
468
        if (QFile::exists(file)) {
 
469
            alreadyExists = true;
 
470
            continue;
 
471
        }
 
472
 
 
473
        activeSession()->config()->sync();
 
474
        KateSession::Ptr ns = KateSession::createFrom(activeSession(), file, name);
 
475
        m_activeSession = ns;
 
476
 
 
477
        emit sessionChanged();
 
478
 
 
479
        alreadyExists = false;
 
480
    } while (alreadyExists);
 
481
    return true;
 
482
}
 
483
 
 
484
void KateSessionManager::sessionManage()
 
485
{
 
486
    QScopedPointer<KateSessionManageDialog>(new KateSessionManageDialog(0))->exec();
 
487
}
 
488
 
 
489
QString KateSessionManager::anonymousSessionFile() const
 
490
{
 
491
    const QString file = m_sessionsDir + QStringLiteral("/../anonymous.katesession");
 
492
    return QDir().cleanPath(file);
 
493
}
 
494
 
 
495
QString KateSessionManager::sessionFileForName(const QString &name) const
 
496
{
 
497
    Q_ASSERT(!name.isEmpty());
 
498
    const QString sname = QString::fromLatin1(QUrl::toPercentEncoding(name, QByteArray(), QByteArray(".")));
 
499
    return m_sessionsDir + QStringLiteral("/") + sname + QStringLiteral(".katesession");
 
500
}
 
501
 
 
502
KateSessionList KateSessionManager::sessionList()
 
503
{
 
504
    return m_sessions.values();
 
505
}
 
506
 
 
507
//END KateSessionManager
 
508