1 /*
2 SPDX-FileCopyrightText: 2008 Andreas Pakulat <apaku@gmx.de>
3 SPDX-FileCopyrightText: 2010 David Nolden <david.nolden.kdevelop@art-master.de>
4
5 SPDX-License-Identifier: LGPL-2.0-or-later
6 */
7
8 #include "sessioncontroller.h"
9
10 #include <QDir>
11 #include <QHash>
12 #include <QStringList>
13 #include <QAction>
14 #include <QCoreApplication>
15 #include <QDBusConnection>
16 #include <QInputDialog>
17 #include <QLabel>
18 #include <QLineEdit>
19 #include <QListView>
20 #include <QSortFilterProxyModel>
21 #include <QStandardItemModel>
22 #include <QVBoxLayout>
23
24 #include <KActionCollection>
25 #include <KConfigGroup>
26 #include <KIO/CopyJob>
27 #include <KJobWidgets>
28 #include <KLocalizedString>
29 #include <KMessageBox>
30 #include <KProcess>
31 #include <KStringHandler>
32
33 #include "session.h"
34 #include "core.h"
35 #include "uicontroller.h"
36 #include "shellextension.h"
37 #include "sessionlock.h"
38 #include "sessionchooserdialog.h"
39 #include "debug.h"
40
41 #include <sublime/mainwindow.h>
42 #include <serialization/itemrepositoryregistry.h>
43 #include <duchain/duchain.h>
44
45 namespace KDevelop
46 {
47
48 namespace {
49 int argc = 0;
50 char** argv = nullptr;
51 }
52
setArguments(int _argc,char ** _argv)53 void SessionController::setArguments(int _argc, char** _argv)
54 {
55 argc = _argc;
56 argv = _argv;
57 }
58
standardArguments()59 static QStringList standardArguments()
60 {
61 QStringList ret;
62 for(int a = 0; a < argc; ++a)
63 {
64 QString arg = QString::fromLocal8Bit(argv[a]);
65 if(arg.startsWith(QLatin1String("-graphicssystem")) || arg.startsWith(QLatin1String("-style")))
66 {
67 ret << QLatin1Char('-') + arg;
68 if(a+1 < argc)
69 ret << QString::fromLocal8Bit(argv[a+1]);
70 }
71 }
72 return ret;
73 }
74
75 class SessionControllerPrivate : public QObject
76 {
77 Q_OBJECT
78 public:
SessionControllerPrivate(SessionController * s)79 explicit SessionControllerPrivate( SessionController* s )
80 : q(s)
81 , activeSession(nullptr)
82 , grp(nullptr)
83 {
84 }
85
~SessionControllerPrivate()86 ~SessionControllerPrivate() override {
87 }
88
findSessionForName(const QString & name) const89 Session* findSessionForName( const QString& name ) const
90 {
91 for (auto it = sessionActions.begin(), end = sessionActions.end(); it != end; ++it) {
92 Session* s = it.key();
93 if( s->name() == name )
94 return s;
95 }
96 return nullptr;
97 }
98
findSessionForId(const QString & idString) const99 Session* findSessionForId(const QString& idString) const
100 {
101 QUuid id(idString);
102
103 for (auto it = sessionActions.begin(), end = sessionActions.end(); it != end; ++it) {
104 Session* s = it.key();
105 if( s->id() == id)
106 return s;
107 }
108 return nullptr;
109 }
110
newSession()111 void newSession()
112 {
113 #if QT_VERSION < QT_VERSION_CHECK(5, 10, 0)
114 qsrand(static_cast<uint>(QDateTime::currentDateTimeUtc().toSecsSinceEpoch()));
115 #endif
116 auto* session = new Session(QUuid::createUuid().toString());
117
118 KProcess::startDetached(ShellExtension::getInstance()->executableFilePath(), QStringList() << QStringLiteral("-s") << session->id().toString() << standardArguments());
119 delete session;
120 #if 0
121 //Terminate this instance of kdevelop if the user agrees
122 const auto windows = Core::self()->uiController()->controller()->mainWindows();
123 for (Sublime::MainWindow* window : windows) {
124 window->close();
125 }
126 #endif
127 }
128
deleteCurrentSession()129 void deleteCurrentSession()
130 {
131 int choice = KMessageBox::warningContinueCancel(Core::self()->uiController()->activeMainWindow(), i18n("The current session and all contained settings will be deleted. The projects will stay unaffected. Do you really want to continue?"));
132
133 if(choice == KMessageBox::Continue)
134 {
135 q->deleteSessionFromDisk(sessionLock);
136 q->emitQuitSession();
137 }
138 }
139
renameSession()140 void renameSession()
141 {
142 bool ok;
143 auto newSessionName = QInputDialog::getText(Core::self()->uiController()->activeMainWindow(),
144 i18nc("@title:window", "Rename Session"), i18nc("@label:textbox", "New session name:"),
145 QLineEdit::Normal, q->activeSession()->name(), &ok);
146 if (ok) {
147 static_cast<Session*>(q->activeSession())->setName(newSessionName);
148 }
149
150 q->updateXmlGuiActionList(); // resort
151 }
152
loadSessionExternally(Session * s)153 bool loadSessionExternally( Session* s )
154 {
155 Q_ASSERT( s );
156 KProcess::startDetached(ShellExtension::getInstance()->executableFilePath(), QStringList() << QStringLiteral("-s") << s->id().toString() << standardArguments());
157 return true;
158 }
159
activateSession(Session * s)160 TryLockSessionResult activateSession( Session* s )
161 {
162 Q_ASSERT( s );
163
164 activeSession = s;
165 TryLockSessionResult result = SessionController::tryLockSession( s->id().toString());
166 if( !result.lock ) {
167 activeSession = nullptr;
168 return result;
169 }
170 Q_ASSERT(s->id().toString() == result.lock->id());
171 sessionLock = result.lock;
172
173 KConfigGroup grp = KSharedConfig::openConfig()->group( SessionController::cfgSessionGroup() );
174 grp.writeEntry( SessionController::cfgActiveSessionEntry(), s->id().toString() );
175 grp.sync();
176 if (Core::self()->setupFlags() & Core::NoUi) return result;
177
178 QHash<Session*,QAction*>::iterator it = sessionActions.find(s);
179 Q_ASSERT( it != sessionActions.end() );
180 (*it)->setCheckable(true);
181 (*it)->setChecked(true);
182
183 for(it = sessionActions.begin(); it != sessionActions.end(); ++it)
184 {
185 if(it.key() != s)
186 (*it)->setCheckable(false);
187 }
188
189 return result;
190 }
191
loadSessionFromAction(QAction * action)192 void loadSessionFromAction(QAction* action)
193 {
194 auto session = action->data().value<Session*>();
195 loadSessionExternally(session);
196 }
197
addSession(Session * s)198 void addSession( Session* s )
199 {
200 if (Core::self()->setupFlags() & Core::NoUi) {
201 sessionActions[s] = nullptr;
202 return;
203 }
204
205 auto* a = new QAction( grp );
206 a->setText( s->description() );
207 a->setCheckable( false );
208 a->setData(QVariant::fromValue<Session*>(s));
209
210 sessionActions[s] = a;
211 q->actionCollection()->addAction(QLatin1String("session_") + s->id().toString(), a);
212 connect( s, &Session::sessionUpdated, this, &SessionControllerPrivate::sessionUpdated );
213 sessionUpdated( s );
214 }
215
216 SessionController* const q;
217
218 QHash<Session*, QAction*> sessionActions;
219 ISession* activeSession;
220 QActionGroup* grp;
221
222 ISessionLock::Ptr sessionLock;
223
sessionBaseDirectory()224 static QString sessionBaseDirectory()
225 {
226 return QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation)
227 + QLatin1Char('/') + QCoreApplication::applicationName() + QLatin1String("/sessions/");
228 }
229
ownSessionDirectory() const230 QString ownSessionDirectory() const
231 {
232 Q_ASSERT(activeSession);
233 return q->sessionDirectory( activeSession->id().toString() );
234 }
235
236 private Q_SLOTS:
sessionUpdated(KDevelop::ISession * s)237 void sessionUpdated( KDevelop::ISession* s )
238 {
239 sessionActions[static_cast<Session*>( s )]->setText( KStringHandler::rsqueeze(s->description()) );
240 }
241 };
242
243
SessionController(QObject * parent)244 SessionController::SessionController( QObject *parent )
245 : QObject(parent)
246 , d_ptr(new SessionControllerPrivate(this))
247 {
248 Q_D(SessionController);
249
250 setObjectName(QStringLiteral("SessionController"));
251 setComponentName(QStringLiteral("kdevsession"), i18n("Session Manager"));
252
253 setXMLFile(QStringLiteral("kdevsessionui.rc"));
254
255 QDBusConnection::sessionBus().registerObject( QStringLiteral("/org/kdevelop/SessionController"),
256 this, QDBusConnection::ExportScriptableSlots );
257
258 if (Core::self()->setupFlags() & Core::NoUi) return;
259
260 QAction* action = actionCollection()->addAction(QStringLiteral("new_session"));
261 connect(action, &QAction::triggered,
262 this, [this] { Q_D(SessionController); d->newSession(); });
263 action->setText( i18nc("@action:inmenu", "Start New Session") );
264 action->setToolTip( i18nc("@info:tooltip", "Start a new KDevelop instance with an empty session") );
265 action->setIcon(QIcon::fromTheme(QStringLiteral("window-new")));
266
267 action = actionCollection()->addAction(QStringLiteral("rename_session"));
268 connect(action, &QAction::triggered,
269 this, [this] { Q_D(SessionController); d->renameSession(); });
270 action->setText( i18nc("@action", "Rename Current Session...") );
271 action->setIcon(QIcon::fromTheme(QStringLiteral("edit-rename")));
272
273 action = actionCollection()->addAction(QStringLiteral("delete_session"));
274 connect(action, &QAction::triggered,
275 this, [this] { Q_D(SessionController); d->deleteCurrentSession(); });
276 action->setText( i18nc("@action", "Delete Current Session...") );
277 action->setIcon(QIcon::fromTheme(QStringLiteral("edit-delete")));
278
279 action = actionCollection()->addAction( QStringLiteral("quit"), this, SIGNAL(quitSession()) );
280 action->setText( i18nc("@action", "Quit") );
281 action->setMenuRole( QAction::NoRole ); // OSX: prevent QT from hiding this due to conflict with 'Quit KDevelop...'
282 actionCollection()->setDefaultShortcut( action, Qt::CTRL | Qt::Key_Q );
283 action->setIcon(QIcon::fromTheme(QStringLiteral("application-exit")));
284
285 d->grp = new QActionGroup( this );
286 connect(d->grp, &QActionGroup::triggered,
287 this, [this] (QAction* a) { Q_D(SessionController); d->loadSessionFromAction(a); } );
288 }
289
290 SessionController::~SessionController() = default;
291
startNewSession()292 void SessionController::startNewSession()
293 {
294 Q_D(SessionController);
295
296 d->newSession();
297 }
298
cleanup()299 void SessionController::cleanup()
300 {
301 Q_D(SessionController);
302
303 if (d->activeSession) {
304 Q_ASSERT(d->activeSession->id().toString() == d->sessionLock->id());
305
306 if (d->activeSession->isTemporary()) {
307 deleteSessionFromDisk(d->sessionLock);
308 }
309 d->activeSession = nullptr;
310 }
311
312 d->sessionLock.clear();
313 qDeleteAll(d->sessionActions);
314 d->sessionActions.clear();
315 }
316
initialize(const QString & session)317 void SessionController::initialize( const QString& session )
318 {
319 Q_D(SessionController);
320
321 QDir sessiondir( SessionControllerPrivate::sessionBaseDirectory() );
322
323 const auto sessionDirs = sessiondir.entryList(QDir::AllDirs | QDir::NoDotAndDotDot);
324 for (const QString& s : sessionDirs) {
325 QUuid id( s );
326 if( id.isNull() )
327 continue;
328 // Only create sessions for directories that represent proper uuid's
329 auto* ses = new Session(id.toString(), this);
330
331 //Delete sessions that have no name and are empty
332 if( ses->containedProjects().isEmpty() && ses->name().isEmpty()
333 && (session.isEmpty() || (ses->id().toString() != session && ses->name() != session)) )
334 {
335 TryLockSessionResult result = tryLockSession(s);
336 if (result.lock) {
337 deleteSessionFromDisk(result.lock);
338 }
339 delete ses;
340 } else {
341 d->addSession( ses );
342 }
343 }
344
345 loadDefaultSession( session );
346
347 updateXmlGuiActionList();
348 }
349
350
activeSession() const351 ISession* SessionController::activeSession() const
352 {
353 Q_D(const SessionController);
354
355 return d->activeSession;
356 }
357
activeSessionLock() const358 ISessionLock::Ptr SessionController::activeSessionLock() const
359 {
360 Q_D(const SessionController);
361
362 return d->sessionLock;
363 }
364
loadSession(const QString & nameOrId)365 void SessionController::loadSession( const QString& nameOrId )
366 {
367 Q_D(SessionController);
368
369 d->loadSessionExternally( session( nameOrId ) );
370 }
371
sessionNames() const372 QList<QString> SessionController::sessionNames() const
373 {
374 Q_D(const SessionController);
375
376 QList<QString> l;
377 const auto sessions = d->sessionActions.keys();
378 l.reserve(sessions.size());
379 for(const auto* s : sessions) {
380 l << s->name();
381 }
382 return l;
383 }
384
sessions() const385 QList< const KDevelop::Session* > SessionController::sessions() const
386 {
387 Q_D(const SessionController);
388
389 QList< const KDevelop::Session* > ret;
390 const auto sessions = d->sessionActions.keys();
391 ret.reserve(sessions.size());
392 // turn to const pointers
393 for (const auto* s : sessions) {
394 ret << s;
395 }
396 return ret;
397 }
398
createSession(const QString & name)399 Session* SessionController::createSession( const QString& name )
400 {
401 Q_D(SessionController);
402
403 Session* s;
404 if(name.startsWith(QLatin1Char('{'))) {
405 s = new Session( QUuid(name).toString(), this );
406 }else{
407 #if QT_VERSION < QT_VERSION_CHECK(5, 10, 0)
408 qsrand(static_cast<uint>(QDateTime::currentDateTimeUtc().toSecsSinceEpoch()));
409 #endif
410 s = new Session( QUuid::createUuid().toString(), this );
411 s->setName( name );
412 }
413 d->addSession( s );
414 updateXmlGuiActionList();
415 return s;
416 }
417
deleteSession(const ISessionLock::Ptr & lock)418 void SessionController::deleteSession( const ISessionLock::Ptr& lock )
419 {
420 Q_D(SessionController);
421
422 Session* s = session(lock->id());
423
424 QHash<Session*,QAction*>::iterator it = d->sessionActions.find(s);
425 Q_ASSERT( it != d->sessionActions.end() );
426
427 unplugActionList( QStringLiteral("available_sessions") );
428 actionCollection()->removeAction(*it);
429 if (d->grp) { // happens in unit tests
430 d->grp->removeAction(*it);
431 plugActionList( QStringLiteral("available_sessions"), d->grp->actions() );
432 }
433
434 if (s == d->activeSession) {
435 d->activeSession = nullptr;
436 }
437 deleteSessionFromDisk(lock);
438
439 emit sessionDeleted( s->id().toString() );
440 d->sessionActions.remove(s);
441 delete s;
442 }
443
deleteSessionFromDisk(const ISessionLock::Ptr & lock)444 void SessionController::deleteSessionFromDisk( const ISessionLock::Ptr& lock )
445 {
446 qCDebug(SHELL) << "Deleting session:" << lock->id();
447
448 static_cast<SessionLock*>(lock.data())->removeFromDisk();
449 ItemRepositoryRegistry::deleteRepositoryFromDisk(DUChain::repositoryPathForSession(lock));
450 }
451
loadDefaultSession(const QString & session)452 void SessionController::loadDefaultSession( const QString& session )
453 {
454 Q_D(SessionController);
455
456 QString load = session;
457 if (load.isEmpty()) {
458 KConfigGroup grp = KSharedConfig::openConfig()->group( cfgSessionGroup() );
459 load = grp.readEntry( cfgActiveSessionEntry(), "default" );
460 }
461
462 // Iteratively try to load the session, asking user what to do in case of failure
463 // If showForceOpenDialog() returns empty string, stop trying
464 do
465 {
466 Session* s = this->session(load);
467 if( !s ) {
468 s = createSession( load );
469 }
470 TryLockSessionResult result = d->activateSession( s );
471 if( result.lock ) {
472 Q_ASSERT(d->activeSession == s);
473 Q_ASSERT(d->sessionLock = result.lock);
474 break;
475 }
476 load = handleLockedSession( s->name(), s->id().toString(), result.runInfo );
477 } while( !load.isEmpty() );
478 }
479
session(const QString & nameOrId) const480 Session* SessionController::session( const QString& nameOrId ) const
481 {
482 Q_D(const SessionController);
483
484 Session* ret = d->findSessionForName( nameOrId );
485 if(ret)
486 return ret;
487
488 return d->findSessionForId( nameOrId );
489 }
490
cloneSession(const QString & nameOrid)491 QString SessionController::cloneSession( const QString& nameOrid )
492 {
493 Q_D(SessionController);
494
495 Session* origSession = session( nameOrid );
496 #if QT_VERSION < QT_VERSION_CHECK(5, 10, 0)
497 qsrand(static_cast<uint>(QDateTime::currentDateTimeUtc().toSecsSinceEpoch()));
498 #endif
499 QUuid id = QUuid::createUuid();
500 auto copyJob = KIO::copy(QUrl::fromLocalFile(sessionDirectory(origSession->id().toString())),
501 QUrl::fromLocalFile(sessionDirectory( id.toString())));
502 KJobWidgets::setWindow(copyJob, Core::self()->uiController()->activeMainWindow());
503 copyJob->exec();
504
505 auto* newSession = new Session(id.toString(), this);
506 newSession->setName( i18n( "Copy of %1", origSession->name() ) );
507 d->addSession(newSession);
508 updateXmlGuiActionList();
509 return newSession->name();
510 }
511
updateXmlGuiActionList()512 void SessionController::updateXmlGuiActionList()
513 {
514 Q_D(SessionController);
515
516 unplugActionList( QStringLiteral("available_sessions") );
517
518 if (d->grp) {
519 auto actions = d->grp->actions();
520 std::sort(actions.begin(), actions.end(), [](const QAction* lhs, const QAction* rhs) {
521 auto s1 = lhs->data().value<Session*>();
522 auto s2 = rhs->data().value<Session*>();
523 return QString::localeAwareCompare(s1->description(), s2->description()) < 0;
524 });
525 plugActionList(QStringLiteral("available_sessions"), actions);
526 }
527 }
528
529
cfgSessionGroup()530 QString SessionController::cfgSessionGroup() { return QStringLiteral("Sessions"); }
cfgActiveSessionEntry()531 QString SessionController::cfgActiveSessionEntry() { return QStringLiteral("Active Session ID"); }
532
availableSessionInfos()533 SessionInfos SessionController::availableSessionInfos()
534 {
535 SessionInfos sessionInfos;
536 const auto sessionDirs = QDir(SessionControllerPrivate::sessionBaseDirectory()).entryList(QDir::AllDirs);
537 sessionInfos.reserve(sessionDirs.size());
538 for (const QString& sessionId : sessionDirs) {
539 if( !QUuid( sessionId ).isNull() ) {
540 sessionInfos << Session::parse( sessionId );
541 }
542 }
543 sessionInfos.squeeze();
544 return sessionInfos;
545 }
546
sessionDirectory(const QString & sessionId)547 QString SessionController::sessionDirectory(const QString& sessionId)
548 {
549 return SessionControllerPrivate::sessionBaseDirectory() + sessionId;
550 }
551
tryLockSession(const QString & id,bool doLocking)552 TryLockSessionResult SessionController::tryLockSession(const QString& id, bool doLocking)
553 {
554 return SessionLock::tryLockSession(id, doLocking);
555 }
556
isSessionRunning(const QString & id)557 bool SessionController::isSessionRunning(const QString& id)
558 {
559 return sessionRunInfo(id).isRunning;
560 }
561
sessionRunInfo(const QString & id)562 SessionRunInfo SessionController::sessionRunInfo(const QString& id)
563 {
564 return SessionLock::tryLockSession(id, false).runInfo;
565 }
566
showSessionChooserDialog(const QString & headerText,bool onlyRunning)567 QString SessionController::showSessionChooserDialog(const QString& headerText, bool onlyRunning)
568 {
569 ///FIXME: move this code into sessiondialog.cpp
570 auto* view = new QListView;
571 auto* filter = new QLineEdit;
572 filter->setClearButtonEnabled( true );
573 filter->setPlaceholderText(i18nc("@info:placeholder", "Search..."));
574
575 auto* model = new QStandardItemModel(view);
576
577 auto *proxy = new QSortFilterProxyModel(model);
578 proxy->setSourceModel(model);
579 proxy->setFilterKeyColumn( 1 );
580 proxy->setFilterCaseSensitivity( Qt::CaseInsensitive );
581 connect(filter, &QLineEdit::textChanged, proxy, &QSortFilterProxyModel::setFilterFixedString);
582
583 SessionChooserDialog dialog(view, proxy, filter);
584 view->setEditTriggers(QAbstractItemView::NoEditTriggers);
585
586 QVBoxLayout layout(dialog.mainWidget());
587 if(!headerText.isEmpty()) {
588 auto* heading = new QLabel(headerText);
589 QFont font = heading->font();
590 font.setBold(true);
591 heading->setFont(font);
592 layout.addWidget(heading);
593 }
594
595 model->setColumnCount(4);
596 model->setHeaderData(0, Qt::Horizontal,i18nc("@title:column", "Identity"));
597 model->setHeaderData(1, Qt::Horizontal,i18nc("@title:column", "Contents"));
598 model->setHeaderData(2, Qt::Horizontal,i18nc("@title:column", "State"));
599 model->setHeaderData(3, Qt::Horizontal,i18nc("@title:column", "Name"));
600
601 view->setModel(proxy);
602 view->setModelColumn(1);
603
604 auto* filterLayout = new QHBoxLayout();
605 filterLayout->addWidget(new QLabel(i18nc("@label:textbox", "Filter:")));
606 filterLayout->addWidget(filter);
607 layout.addLayout(filterLayout);
608 layout.addWidget(view);
609 filter->setFocus();
610
611 int row = 0;
612
613 QString defaultSession = KSharedConfig::openConfig()->group( cfgSessionGroup() ).readEntry( cfgActiveSessionEntry(), "default" );
614
615 const auto availableSessionInfos = KDevelop::SessionController::availableSessionInfos();
616 for (const KDevelop::SessionInfo& si : availableSessionInfos) {
617 if ( si.name.isEmpty() && si.projects.isEmpty() ) {
618 continue;
619 }
620
621 bool running = KDevelop::SessionController::isSessionRunning(si.uuid.toString());
622
623 if(onlyRunning && !running)
624 continue;
625
626 model->setItem(row, 0, new QStandardItem(si.uuid.toString()));
627 model->setItem(row, 1, new QStandardItem(si.description));
628 model->setItem(row, 2, new QStandardItem);
629 model->setItem(row, 3, new QStandardItem(si.name));
630
631 ++row;
632 }
633 model->sort(1);
634
635 if(!onlyRunning) {
636 model->setItem(row, 0, new QStandardItem);
637 model->setItem(row, 1, new QStandardItem(QIcon::fromTheme(QStringLiteral("window-new")), i18n("Create New Session")));
638 }
639
640 dialog.updateState();
641 dialog.mainWidget()->layout()->setContentsMargins(0,0,0,0);
642
643 const QModelIndex defaultSessionIndex = model->match(model->index(0, 0), Qt::DisplayRole, defaultSession, 1, Qt::MatchExactly).value(0);
644 view->selectionModel()->setCurrentIndex(proxy->mapFromSource(defaultSessionIndex), QItemSelectionModel::ClearAndSelect | QItemSelectionModel::Rows);
645 view->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding);
646 ///@todo We need a way to get a proper size-hint from the view, but unfortunately, that only seems possible after the view was shown.
647 dialog.resize(QSize(900, 600));
648
649 if(dialog.exec() != QDialog::Accepted) // krazy:exclude=crashy
650 {
651 return QString();
652 }
653
654 QModelIndex selected = view->selectionModel()->currentIndex();
655 if (!selected.isValid())
656 return QString();
657
658 const QString selectedSessionId = selected.sibling(selected.row(), 0).data().toString();
659 if (selectedSessionId.isEmpty()) {
660 // "Create New Session" item selected, return a fresh UUID
661 #if QT_VERSION < QT_VERSION_CHECK(5, 10, 0)
662 qsrand(static_cast<uint>(QDateTime::currentDateTimeUtc().toSecsSinceEpoch()));
663 #endif
664 return QUuid::createUuid().toString();
665 }
666 return selectedSessionId;
667 }
668
handleLockedSession(const QString & sessionName,const QString & sessionId,const SessionRunInfo & runInfo)669 QString SessionController::handleLockedSession( const QString& sessionName, const QString& sessionId,
670 const SessionRunInfo& runInfo )
671 {
672 return SessionLock::handleLockedSession(sessionName, sessionId, runInfo);
673 }
674
sessionDir()675 QString SessionController::sessionDir()
676 {
677 Q_D(SessionController);
678
679 if( !activeSession() )
680 return QString();
681 return d->ownSessionDirectory();
682 }
683
sessionName()684 QString SessionController::sessionName()
685 {
686 if(!activeSession())
687 return QString();
688 return activeSession()->description();
689 }
690
691
692 }
693 #include "sessioncontroller.moc"
694 #include "moc_sessioncontroller.cpp"
695