1 | /* This file is part of the KDE project |
2 | Copyright (C) 2005 Christoph Cullmann <cullmann@kde.org> |
3 | |
4 | This library is free software; you can redistribute it and/or |
5 | modify it under the terms of the GNU Library General Public |
6 | License version 2 as published by the Free Software Foundation. |
7 | |
8 | This library is distributed in the hope that it will be useful, |
9 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
10 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
11 | Library General Public License for more details. |
12 | |
13 | You should have received a copy of the GNU Library General Public License |
14 | along with this library; see the file COPYING.LIB. If not, write to |
15 | the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, |
16 | Boston, MA 02110-1301, USA. |
17 | */ |
18 | |
19 | #include "config.h" |
20 | |
21 | #include "katesession.h" |
22 | #include "katesession.moc" |
23 | |
24 | #include "kateapp.h" |
25 | #include "katemainwindow.h" |
26 | #include "katedocmanager.h" |
27 | #include "katepluginmanager.h" |
28 | #include "katerunninginstanceinfo.h" |
29 | |
30 | #include <KStandardDirs> |
31 | #include <KLocale> |
32 | #include <kdebug.h> |
33 | #include <KDirWatch> |
34 | #include <KInputDialog> |
35 | #include <KIconLoader> |
36 | #include <KMessageBox> |
37 | #include <KCodecs> |
38 | #include <KStandardGuiItem> |
39 | #include <KPushButton> |
40 | #include <KMenu> |
41 | #include <KActionCollection> |
42 | #include <KIO/NetAccess> |
43 | #include <KIO/CopyJob> |
44 | #include <KStringHandler> |
45 | |
46 | #include <QDir> |
47 | #include <QLabel> |
48 | #include <QCheckBox> |
49 | #include <QVBoxLayout> |
50 | #include <QHBoxLayout> |
51 | #include <QStyle> |
52 | #include <QtAlgorithms> |
53 | |
54 | #include <unistd.h> |
55 | #include <time.h> |
56 | |
57 | |
58 | bool katesessions_compare_sessions_ptr(const KateSession::Ptr &s1, const KateSession::Ptr &s2) { |
59 | return KStringHandler::naturalCompare(s1->sessionName(),s2->sessionName())==-1; |
60 | } |
61 | |
62 | //BEGIN KateSession |
63 | |
64 | KateSession::KateSession (KateSessionManager *manager, const QString &fileName) |
65 | : m_sessionFileRel (fileName) |
66 | , m_documents (0) |
67 | , m_manager (manager) |
68 | , m_readConfig (0) |
69 | , m_writeConfig (0) |
70 | { |
71 | m_sessionName = QUrl::fromPercentEncoding(QFile::encodeName(fileName)); |
72 | m_sessionName.chop(12);//.katesession==12 |
73 | init (); |
74 | } |
75 | |
76 | void KateSession::init () |
77 | { |
78 | // given file exists, use it to load some stuff ;) |
79 | if (!m_sessionFileRel.isEmpty() && KGlobal::dirs()->exists(sessionFile ())) |
80 | { |
81 | KConfig config (sessionFile (), KConfig::SimpleConfig); |
82 | |
83 | // get the document count |
84 | m_documents = config.group("Open Documents" ).readEntry("Count" , 0); |
85 | |
86 | return; |
87 | } |
88 | |
89 | if (!m_sessionFileRel.isEmpty() && !KGlobal::dirs()->exists(sessionFile ())) |
90 | kDebug() << "Warning, session file not found: " << m_sessionFileRel; |
91 | } |
92 | |
93 | KateSession::~KateSession () |
94 | { |
95 | delete m_readConfig; |
96 | delete m_writeConfig; |
97 | } |
98 | |
99 | QString KateSession::sessionFile () const |
100 | { |
101 | if (m_sessionFileRel.isEmpty()) { |
102 | return QString(); |
103 | } |
104 | |
105 | return m_manager->sessionsDir() + '/' + m_sessionFileRel; |
106 | } |
107 | |
108 | bool KateSession::create (const QString &name, bool force) |
109 | { |
110 | if (!force && (name.isEmpty() || !m_sessionFileRel.isEmpty())) |
111 | return false; |
112 | |
113 | delete m_writeConfig; |
114 | m_writeConfig = 0; |
115 | |
116 | delete m_readConfig; |
117 | m_readConfig = 0; |
118 | |
119 | m_sessionName = name; |
120 | QString oldSessionFileRel = m_sessionFileRel; |
121 | m_sessionFileRel = QUrl::toPercentEncoding(name, "" , "." ) + QString(".katesession" ); |
122 | if (KGlobal::dirs()->exists(sessionFile ())) |
123 | { |
124 | m_sessionFileRel = oldSessionFileRel; |
125 | return false; |
126 | } |
127 | |
128 | // create the file, write name to it! |
129 | KConfig config (sessionFile (), KConfig::SimpleConfig); |
130 | // config.group("General").writeEntry ("Name", m_sessionName); |
131 | config.sync (); |
132 | |
133 | // reinit ourselfs ;) |
134 | init (); |
135 | |
136 | return true; |
137 | } |
138 | |
139 | bool KateSession::rename (const QString &name) |
140 | { |
141 | if (name.isEmpty () || m_sessionFileRel.isEmpty()) |
142 | return false; |
143 | |
144 | if (name == m_sessionName) return true; |
145 | QString oldRel = m_sessionFileRel; |
146 | QString oldSessionFile = sessionFile(); |
147 | m_sessionFileRel = QUrl::toPercentEncoding(name, "" , "." ) + QString(".katesession" ); |
148 | if (KGlobal::dirs()->exists(sessionFile ())) |
149 | { |
150 | m_sessionFileRel = oldRel; |
151 | return false; |
152 | } |
153 | KUrl srcUrl(QString("file://" )); |
154 | srcUrl.addPath(oldSessionFile); |
155 | KUrl destUrl(QString("file://" )); |
156 | destUrl.addPath(sessionFile()); |
157 | KIO::CopyJob *job = KIO::move(srcUrl, destUrl, KIO::HideProgressInfo); |
158 | if ( ! KIO::NetAccess::synchronousRun(job, 0) ) |
159 | { |
160 | m_sessionFileRel = oldRel; |
161 | return false; |
162 | } |
163 | m_sessionName = name; |
164 | delete m_writeConfig; |
165 | m_writeConfig=0; |
166 | delete m_readConfig; |
167 | m_readConfig=0; |
168 | return true; |
169 | } |
170 | |
171 | KConfig *KateSession::configRead () |
172 | { |
173 | if (m_sessionFileRel.isEmpty()) |
174 | return KGlobal::config().data(); |
175 | |
176 | if (m_readConfig) |
177 | return m_readConfig; |
178 | |
179 | return m_readConfig = new KConfig (sessionFile (), KConfig::SimpleConfig); |
180 | } |
181 | |
182 | KConfig *KateSession::configWrite () |
183 | { |
184 | if (m_sessionFileRel.isEmpty()) |
185 | return KGlobal::config().data(); |
186 | |
187 | if (m_writeConfig) |
188 | return m_writeConfig; |
189 | |
190 | m_writeConfig = new KConfig (sessionFile (), KConfig::SimpleConfig); |
191 | |
192 | return m_writeConfig; |
193 | } |
194 | |
195 | void KateSession::makeAnonymous() |
196 | { |
197 | delete m_readConfig; |
198 | m_readConfig = 0; |
199 | |
200 | delete m_writeConfig; |
201 | m_writeConfig = 0; |
202 | |
203 | m_sessionFileRel.clear(); |
204 | m_sessionName.clear(); |
205 | } |
206 | |
207 | //END KateSession |
208 | |
209 | |
210 | //BEGIN KateSessionManager |
211 | |
212 | KateSessionManager::KateSessionManager (QObject *parent) |
213 | : QObject (parent) |
214 | , m_sessionsDir (KStandardDirs::locateLocal( "data" , "kate/sessions" )) |
215 | , m_activeSession (new KateSession (this, QString())) |
216 | { |
217 | kDebug() << "LOCAL SESSION DIR: " << m_sessionsDir; |
218 | |
219 | // create dir if needed |
220 | KGlobal::dirs()->makeDir (m_sessionsDir); |
221 | } |
222 | |
223 | KateSessionManager::~KateSessionManager() |
224 | {} |
225 | |
226 | KateSessionManager *KateSessionManager::self() |
227 | { |
228 | return KateApp::self()->sessionManager (); |
229 | } |
230 | |
231 | void KateSessionManager::dirty (const QString &) |
232 | { |
233 | updateSessionList (); |
234 | } |
235 | |
236 | void KateSessionManager::updateSessionList () |
237 | { |
238 | m_sessionList.clear (); |
239 | |
240 | // Let's get a list of all session we have atm |
241 | QDir dir (m_sessionsDir, "*.katesession" ); |
242 | |
243 | for (unsigned int i = 0; i < dir.count(); ++i) |
244 | { |
245 | KateSession *session = new KateSession (this, dir[i]); |
246 | if (m_activeSession) |
247 | if (session->sessionName()==m_activeSession->sessionName()) |
248 | { |
249 | delete session; |
250 | session=m_activeSession.data(); |
251 | } |
252 | m_sessionList.append (KateSession::Ptr(session)); |
253 | |
254 | //kDebug () << "FOUND SESSION: " << session->sessionName() << " FILE: " << session->sessionFile() << " dir[i];" << dir[i]; |
255 | } |
256 | |
257 | qSort(m_sessionList.begin(), m_sessionList.end(), katesessions_compare_sessions_ptr); |
258 | } |
259 | |
260 | bool KateSessionManager::activateSession (KateSession::Ptr session, |
261 | bool closeLast, |
262 | bool saveLast, |
263 | bool loadNew) |
264 | { |
265 | if ( (!session->sessionName().isEmpty()) && (m_activeSession!=session)) { |
266 | //check if the requested session is already open in another instance |
267 | KateRunningInstanceMap instances; |
268 | if (!fillinRunningKateAppInstances(&instances)) |
269 | { |
270 | KMessageBox::error(0,i18n("Internal error: there is more than one instance open for a given session." )); |
271 | return false; |
272 | } |
273 | |
274 | if (instances.contains(session->sessionName())) |
275 | { |
276 | if (KMessageBox::questionYesNo(0,i18n("Session '%1' is already opened in another kate instance, change there instead of reopening?" ,session->sessionName()), |
277 | QString(),KStandardGuiItem::yes(),KStandardGuiItem::no(),"katesessionmanager_switch_instance" )==KMessageBox::Yes) |
278 | { |
279 | instances[session->sessionName()]->dbus_if->call("activate" ); |
280 | cleanupRunningKateAppInstanceMap(&instances); |
281 | return false; |
282 | } |
283 | } |
284 | |
285 | cleanupRunningKateAppInstanceMap(&instances); |
286 | } |
287 | // try to close last session |
288 | if (closeLast) |
289 | { |
290 | if (KateApp::self()->activeMainWindow()) |
291 | { |
292 | if (!KateApp::self()->activeMainWindow()->queryClose_internal()) |
293 | return true; |
294 | } |
295 | } |
296 | |
297 | // save last session or not? |
298 | if (saveLast) |
299 | saveActiveSession (); |
300 | |
301 | // really close last |
302 | if (closeLast) |
303 | KateDocManager::self()->closeAllDocuments (); |
304 | |
305 | // set the new session |
306 | m_activeSession = session; |
307 | |
308 | if (loadNew) |
309 | { |
310 | // open the new session |
311 | KConfig *sc = activeSession()->configRead(); |
312 | const bool loadDocs = (sc != KGlobal::config().data()); // do not load docs for new sessions |
313 | |
314 | // if we have no session config object, try to load the default |
315 | // (anonymous/unnamed sessions) |
316 | if ( !sc ) |
317 | sc = KGlobal::config().data(); |
318 | // load plugin config + plugins |
319 | KatePluginManager::self()->loadConfig (sc); |
320 | |
321 | if (sc && loadDocs) |
322 | KateApp::self()->documentManager()->restoreDocumentList (sc); |
323 | |
324 | // window config |
325 | KConfigGroup c(KGlobal::config(), "General" ); |
326 | |
327 | if (c.readEntry("Restore Window Configuration" , true)) |
328 | { |
329 | // a new, named session, read settings of the default session. |
330 | if ( ! sc->hasGroup("Open MainWindows" ) ) |
331 | sc = KGlobal::config().data(); |
332 | |
333 | int wCount = sc->group("Open MainWindows" ).readEntry("Count" , 1); |
334 | |
335 | for (int i = 0; i < wCount; ++i) |
336 | { |
337 | if (i >= KateApp::self()->mainWindows()) |
338 | { |
339 | KateApp::self()->newMainWindow(sc, QString ("MainWindow%1" ).arg(i)); |
340 | } |
341 | else |
342 | { |
343 | KateApp::self()->mainWindow(i)->readProperties(KConfigGroup(sc, QString ("MainWindow%1" ).arg(i) )); |
344 | } |
345 | |
346 | KateApp::self()->mainWindow(i)->restoreWindowConfig(KConfigGroup(sc, QString ("MainWindow%1 Settings" ).arg(i))); |
347 | } |
348 | |
349 | // remove mainwindows we need no longer... |
350 | if (wCount > 0) |
351 | { |
352 | while (wCount < KateApp::self()->mainWindows()) |
353 | delete KateApp::self()->mainWindow(KateApp::self()->mainWindows() - 1); |
354 | } |
355 | } |
356 | } |
357 | |
358 | emit sessionChanged(); |
359 | return true; |
360 | } |
361 | |
362 | KateSession::Ptr KateSessionManager::giveSession (const QString &name) |
363 | { |
364 | if (name.isEmpty()) |
365 | return KateSession::Ptr(new KateSession (this, QString())); |
366 | |
367 | updateSessionList(); |
368 | |
369 | for (int i = 0; i < m_sessionList.count(); ++i) |
370 | { |
371 | if (m_sessionList[i]->sessionName() == name) |
372 | return m_sessionList[i]; |
373 | } |
374 | |
375 | KateSession::Ptr s(new KateSession (this, QString())); |
376 | s->create (name); |
377 | return s; |
378 | } |
379 | |
380 | // helper function to save the session to a given config object |
381 | static void saveSessionTo(KConfig *sc) |
382 | { |
383 | // save plugin configs and which plugins to load |
384 | KatePluginManager::self()->writeConfig(sc); |
385 | |
386 | // save document configs + which documents to load |
387 | KateDocManager::self()->saveDocumentList (sc); |
388 | |
389 | sc->group("Open MainWindows" ).writeEntry ("Count" , KateApp::self()->mainWindows ()); |
390 | |
391 | // save config for all windows around ;) |
392 | bool saveWindowConfig = KConfigGroup(KGlobal::config(), "General" ).readEntry("Restore Window Configuration" , true); |
393 | for (int i = 0; i < KateApp::self()->mainWindows (); ++i ) |
394 | { |
395 | KConfigGroup cg(sc, QString ("MainWindow%1" ).arg(i) ); |
396 | KateApp::self()->mainWindow(i)->saveProperties (cg); |
397 | if (saveWindowConfig) |
398 | KateApp::self()->mainWindow(i)->saveWindowConfig(KConfigGroup(sc, QString ("MainWindow%1 Settings" ).arg(i))); |
399 | } |
400 | |
401 | sc->sync(); |
402 | |
403 | /** |
404 | * try to sync file to disk |
405 | */ |
406 | QFile fileToSync (sc->name()); |
407 | if (fileToSync.open (QIODevice::ReadOnly)) { |
408 | #ifndef Q_OS_WIN |
409 | // ensure that the file is written to disk |
410 | #ifdef HAVE_FDATASYNC |
411 | fdatasync (fileToSync.handle()); |
412 | #else |
413 | fsync (fileToSync.handle()); |
414 | #endif |
415 | #endif |
416 | } |
417 | } |
418 | |
419 | bool KateSessionManager::saveActiveSession (bool rememberAsLast) |
420 | { |
421 | // if (activeSession()->isAnonymous()) |
422 | // newSessionName(); |
423 | |
424 | KConfig *sc = activeSession()->configWrite(); |
425 | |
426 | if (!sc) |
427 | return false; |
428 | |
429 | saveSessionTo(sc); |
430 | |
431 | if (rememberAsLast) |
432 | { |
433 | KSharedConfig::Ptr c = KGlobal::config(); |
434 | c->group("General" ).writeEntry ("Last Session" , activeSession()->sessionFileRelative()); |
435 | c->sync (); |
436 | } |
437 | return true; |
438 | } |
439 | |
440 | bool KateSessionManager::chooseSession () |
441 | { |
442 | bool success = true; |
443 | |
444 | // app config |
445 | KConfigGroup c(KGlobal::config(), "General" ); |
446 | |
447 | // get last used session, default to default session |
448 | QString lastSession (c.readEntry ("Last Session" , QString())); |
449 | QString sesStart (c.readEntry ("Startup Session" , "manual" )); |
450 | |
451 | // uhh, just open last used session, show no chooser |
452 | if (sesStart == "last" ) |
453 | { |
454 | activateSession (KateSession::Ptr(new KateSession (this, lastSession)), false, false); |
455 | return success; |
456 | } |
457 | |
458 | // start with empty new session |
459 | // also, if no sessions exist |
460 | if (sesStart == "new" || sessionList().size() == 0) |
461 | { |
462 | activateSession (KateSession::Ptr(new KateSession (this, QString())), false, false); |
463 | return success; |
464 | } |
465 | |
466 | KateSessionChooser *chooser = new KateSessionChooser (0, lastSession); |
467 | |
468 | bool retry = true; |
469 | int res = 0; |
470 | while (retry) |
471 | { |
472 | res = chooser->exec (); |
473 | |
474 | switch (res) |
475 | { |
476 | case KateSessionChooser::resultOpen: |
477 | { |
478 | KateSession::Ptr s = chooser->selectedSession (); |
479 | |
480 | if (!s) |
481 | { |
482 | KMessageBox::error (chooser, i18n("No session selected to open." ), i18n ("No Session Selected" )); |
483 | break; |
484 | } |
485 | |
486 | success = activateSession (s, false, false); |
487 | retry = false; |
488 | break; |
489 | } |
490 | |
491 | // exit the app lateron |
492 | case KateSessionChooser::resultQuit: |
493 | success = false; |
494 | retry = false; |
495 | break; |
496 | |
497 | case KateSessionChooser::resultNew: { |
498 | success = true; |
499 | retry = false; |
500 | activateSession (KateSession::Ptr(new KateSession (this, QString())), false, false); |
501 | break; |
502 | } |
503 | |
504 | case KateSessionChooser::resultCopy: { |
505 | KateSession::Ptr s = chooser->selectedSession (); |
506 | if (!s) { |
507 | KMessageBox::error (chooser, i18n("No session selected to copy." ), i18n ("No Session Selected" )); |
508 | break; |
509 | } |
510 | |
511 | success = true; |
512 | retry = false; |
513 | activateSession (s, false, false); |
514 | s->makeAnonymous(); |
515 | // emit signal again, now we are anonymous |
516 | emit sessionChanged(); |
517 | break; |
518 | } |
519 | |
520 | default: |
521 | activateSession (KateSession::Ptr(new KateSession (this, QString())), false, false) ; |
522 | retry = false; |
523 | break; |
524 | } |
525 | } |
526 | |
527 | // write back our nice boolean :) |
528 | if (success && chooser->reopenLastSession ()) |
529 | { |
530 | KConfigGroup generalConfig(KGlobal::config(), "General" ); |
531 | |
532 | if (res == KateSessionChooser::resultOpen) |
533 | generalConfig.writeEntry ("Startup Session" , "last" ); |
534 | else if (res == KateSessionChooser::resultNew) |
535 | generalConfig.writeEntry ("Startup Session" , "new" ); |
536 | |
537 | generalConfig.sync (); |
538 | } |
539 | |
540 | delete chooser; |
541 | |
542 | return success; |
543 | } |
544 | |
545 | void KateSessionManager::sessionNew () |
546 | { |
547 | activateSession (KateSession::Ptr(new KateSession (this, "" ))); |
548 | } |
549 | |
550 | void KateSessionManager::sessionOpen () |
551 | { |
552 | KateSessionOpenDialog *chooser = new KateSessionOpenDialog (0); |
553 | |
554 | int res = chooser->exec (); |
555 | |
556 | if (res == KateSessionOpenDialog::resultCancel) |
557 | { |
558 | delete chooser; |
559 | return; |
560 | } |
561 | |
562 | KateSession::Ptr s = chooser->selectedSession (); |
563 | |
564 | if (s) |
565 | activateSession (s); |
566 | |
567 | delete chooser; |
568 | } |
569 | |
570 | void KateSessionManager::sessionSave () |
571 | { |
572 | // if the active session is valid, just save it :) |
573 | if (saveActiveSession ()) |
574 | return; |
575 | |
576 | sessionSaveAs(); |
577 | } |
578 | |
579 | void KateSessionManager::sessionSaveAs () |
580 | { |
581 | newSessionName(); |
582 | saveActiveSession (); |
583 | emit sessionChanged(); |
584 | } |
585 | |
586 | bool KateSessionManager::newSessionName() |
587 | { |
588 | bool alreadyExists = false; |
589 | QString name; |
590 | do { |
591 | bool ok = false; |
592 | name = KInputDialog::getText ( |
593 | i18n("Specify New Name for Current Session" ), |
594 | alreadyExists ? i18n("There is already an existing session with your chosen name.\nPlease choose a different one\nSession name:" ) : i18n("Session name:" ) |
595 | , name, &ok); |
596 | |
597 | if (!ok) |
598 | return false; |
599 | |
600 | if (name.isEmpty()) |
601 | KMessageBox::sorry (0, i18n("To save a session, you must specify a name." ), i18n ("Missing Session Name" )); |
602 | |
603 | alreadyExists = true; |
604 | } |
605 | while (!activeSession()->create (name, true)); |
606 | return true; |
607 | } |
608 | |
609 | void KateSessionManager::sessionManage () |
610 | { |
611 | KateSessionManageDialog *dlg = new KateSessionManageDialog (0); |
612 | |
613 | dlg->exec (); |
614 | |
615 | delete dlg; |
616 | } |
617 | |
618 | //END KateSessionManager |
619 | |
620 | //BEGIN CHOOSER DIALOG |
621 | |
622 | class KateSessionChooserItem : public QTreeWidgetItem |
623 | { |
624 | public: |
625 | KateSessionChooserItem (QTreeWidget *tw, KateSession::Ptr s) |
626 | : QTreeWidgetItem (tw, QStringList(s->sessionName())) |
627 | , session (s) |
628 | { |
629 | QString docs; |
630 | docs.setNum (s->documents()); |
631 | setText (1, docs); |
632 | } |
633 | |
634 | KateSession::Ptr session; |
635 | }; |
636 | |
637 | KateSessionChooser::KateSessionChooser (QWidget *parent, const QString &lastSession) |
638 | : KDialog ( parent ) |
639 | { |
640 | setCaption( i18n ("Session Chooser" ) ); |
641 | setButtons( User1 | User2 | User3 ); |
642 | setButtonGuiItem( User1, KStandardGuiItem::quit() ); |
643 | setButtonGuiItem( User2, KGuiItem (i18n ("Open Session" ), "document-open" ) ); |
644 | setButtonGuiItem( User3, KGuiItem (i18n ("New Session" ), "document-new" ) ); |
645 | |
646 | //showButtonSeparator(true); |
647 | QFrame *page = new QFrame (this); |
648 | QVBoxLayout *tll = new QVBoxLayout(page); |
649 | page->setMinimumSize (400, 200); |
650 | setMainWidget(page); |
651 | |
652 | m_sessions = new QTreeWidget (page); |
653 | tll->addWidget(m_sessions); |
654 | QStringList ; |
655 | header << i18n("Session Name" ); |
656 | header << i18nc("The number of open documents" , "Open Documents" ); |
657 | m_sessions->setHeaderLabels(header); |
658 | m_sessions->setRootIsDecorated( false ); |
659 | m_sessions->setItemsExpandable( false ); |
660 | m_sessions->setAllColumnsShowFocus( true ); |
661 | m_sessions->setSelectionBehavior(QAbstractItemView::SelectRows); |
662 | m_sessions->setSelectionMode (QAbstractItemView::SingleSelection); |
663 | |
664 | connect (m_sessions, SIGNAL(currentItemChanged(QTreeWidgetItem*,QTreeWidgetItem*)), this, SLOT(selectionChanged(QTreeWidgetItem*,QTreeWidgetItem*))); |
665 | |
666 | QMenu* = new QMenu(this); |
667 | button(KDialog::User3)->setDelayedMenu(popup); |
668 | QAction *a = popup->addAction(i18n("Use selected session as template" )); |
669 | connect(a, SIGNAL(triggered()), this, SLOT(slotCopySession())); |
670 | |
671 | const KateSessionList &slist (KateSessionManager::self()->sessionList()); |
672 | kDebug()<<"Last session is:" <<lastSession; |
673 | for (int i = 0; i < slist.count(); ++i) |
674 | { |
675 | KateSessionChooserItem *item = new KateSessionChooserItem (m_sessions, slist[i]); |
676 | |
677 | kDebug()<<"Session added to chooser:" <<slist[i]->sessionName()<<"........" <<slist[i]->sessionFileRelative(); |
678 | if (slist[i]->sessionFileRelative() == lastSession) |
679 | m_sessions->setCurrentItem (item); |
680 | } |
681 | |
682 | m_sessions->resizeColumnToContents(0); |
683 | |
684 | m_useLast = new QCheckBox (i18n ("&Always use this choice" ), page); |
685 | tll->addWidget(m_useLast); |
686 | |
687 | setResult (resultNone); |
688 | |
689 | // trigger action update |
690 | selectionChanged (NULL, NULL); |
691 | connect(this, SIGNAL(user1Clicked()), this, SLOT(slotUser1())); |
692 | connect(this, SIGNAL(user2Clicked()), this, SLOT(slotUser2())); |
693 | connect(m_sessions, SIGNAL(itemDoubleClicked(QTreeWidgetItem*,int)), this, SLOT(slotUser2())); |
694 | connect(this, SIGNAL(user3Clicked()), this, SLOT(slotUser3())); |
695 | enableButton (KDialog::User2, m_sessions->currentIndex().isValid()); |
696 | |
697 | setDefaultButton(KDialog::User2); |
698 | setEscapeButton(KDialog::User1); |
699 | setButtonFocus(KDialog::User2); |
700 | } |
701 | |
702 | KateSessionChooser::~KateSessionChooser () |
703 | {} |
704 | |
705 | void KateSessionChooser::slotCopySession() |
706 | { |
707 | done(resultCopy); |
708 | } |
709 | |
710 | KateSession::Ptr KateSessionChooser::selectedSession () |
711 | { |
712 | KateSessionChooserItem *item = static_cast<KateSessionChooserItem *>(m_sessions->currentItem ()); |
713 | |
714 | if (!item) |
715 | return KateSession::Ptr(); |
716 | |
717 | return item->session; |
718 | } |
719 | |
720 | bool KateSessionChooser::reopenLastSession () |
721 | { |
722 | return m_useLast->isChecked (); |
723 | } |
724 | |
725 | void KateSessionChooser::slotUser2 () |
726 | { |
727 | done (resultOpen); |
728 | } |
729 | |
730 | void KateSessionChooser::slotUser3 () |
731 | { |
732 | done (resultNew); |
733 | } |
734 | |
735 | void KateSessionChooser::slotUser1 () |
736 | { |
737 | done (resultQuit); |
738 | } |
739 | |
740 | void KateSessionChooser::selectionChanged(QTreeWidgetItem *current, QTreeWidgetItem *) |
741 | { |
742 | enableButton (KDialog::User2, current); |
743 | } |
744 | |
745 | //END CHOOSER DIALOG |
746 | |
747 | //BEGIN OPEN DIALOG |
748 | |
749 | KateSessionOpenDialog::KateSessionOpenDialog (QWidget *parent) |
750 | : KDialog ( parent ) |
751 | |
752 | { |
753 | setCaption( i18n ("Open Session" ) ); |
754 | setButtons( User1 | User2 ); |
755 | setButtonGuiItem( User1, KStandardGuiItem::cancel() ); |
756 | // don't use KStandardGuiItem::open() here which has trailing ellipsis! |
757 | setButtonGuiItem( User2, KGuiItem( i18n("&Open" ), "document-open" ) ); |
758 | setDefaultButton( KDialog::User2 ); |
759 | enableButton( KDialog::User2, false ); |
760 | //showButtonSeparator(true); |
761 | /*QFrame *page = new QFrame (this); |
762 | page->setMinimumSize (400, 200); |
763 | setMainWidget(page); |
764 | |
765 | QHBoxLayout *hb = new QHBoxLayout (page); |
766 | |
767 | QVBoxLayout *vb = new QVBoxLayout (); |
768 | hb->addItem(vb);*/ |
769 | m_sessions = new QTreeWidget (this); |
770 | m_sessions->setMinimumSize(400, 200); |
771 | setMainWidget(m_sessions); |
772 | //vb->addWidget(m_sessions); |
773 | QStringList ; |
774 | header << i18n("Session Name" ); |
775 | header << i18nc("The number of open documents" , "Open Documents" ); |
776 | m_sessions->setHeaderLabels(header); |
777 | m_sessions->setRootIsDecorated( false ); |
778 | m_sessions->setItemsExpandable( false ); |
779 | m_sessions->setAllColumnsShowFocus( true ); |
780 | m_sessions->setSelectionBehavior(QAbstractItemView::SelectRows); |
781 | m_sessions->setSelectionMode (QAbstractItemView::SingleSelection); |
782 | |
783 | const KateSessionList &slist (KateSessionManager::self()->sessionList()); |
784 | for (int i = 0; i < slist.count(); ++i) |
785 | { |
786 | new KateSessionChooserItem (m_sessions, slist[i]); |
787 | } |
788 | m_sessions->resizeColumnToContents(0); |
789 | |
790 | setResult (resultCancel); |
791 | connect(this, SIGNAL(user1Clicked()), this, SLOT(slotUser1())); |
792 | connect(this, SIGNAL(user2Clicked()), this, SLOT(slotUser2())); |
793 | connect(m_sessions, SIGNAL(currentItemChanged(QTreeWidgetItem*,QTreeWidgetItem*)), this, SLOT(selectionChanged(QTreeWidgetItem*,QTreeWidgetItem*))); |
794 | connect(m_sessions, SIGNAL(itemDoubleClicked(QTreeWidgetItem*,int)), this, SLOT(slotUser2())); |
795 | |
796 | } |
797 | |
798 | KateSessionOpenDialog::~KateSessionOpenDialog () |
799 | {} |
800 | |
801 | KateSession::Ptr KateSessionOpenDialog::selectedSession () |
802 | { |
803 | KateSessionChooserItem *item = static_cast<KateSessionChooserItem *>(m_sessions->currentItem ()); |
804 | |
805 | if (!item) |
806 | return KateSession::Ptr(); |
807 | |
808 | return item->session; |
809 | } |
810 | |
811 | void KateSessionOpenDialog::slotUser1 () |
812 | { |
813 | done (resultCancel); |
814 | } |
815 | |
816 | void KateSessionOpenDialog::slotUser2 () |
817 | { |
818 | done (resultOk); |
819 | } |
820 | |
821 | void KateSessionOpenDialog::selectionChanged(QTreeWidgetItem *current, QTreeWidgetItem *) |
822 | { |
823 | enableButton (KDialog::User2, current); |
824 | } |
825 | |
826 | //END OPEN DIALOG |
827 | |
828 | //BEGIN MANAGE DIALOG |
829 | |
830 | KateSessionManageDialog::KateSessionManageDialog (QWidget *parent) |
831 | : KDialog ( parent ) |
832 | { |
833 | setCaption( i18n ("Manage Sessions" ) ); |
834 | setButtons( User1 | User2 ); |
835 | setButtonGuiItem( User1, KStandardGuiItem::close() ); |
836 | // don't use KStandardGuiItem::open() here which has trailing ellipsis! |
837 | setButtonGuiItem( User2, KGuiItem( i18n("&Open" ), "document-open" ) ); |
838 | |
839 | setDefaultButton(KDialog::User1); |
840 | QFrame *page = new QFrame (this); |
841 | page->setMinimumSize (400, 200); |
842 | setMainWidget(page); |
843 | |
844 | QHBoxLayout *hb = new QHBoxLayout (page); |
845 | hb->setSpacing (KDialog::spacingHint()); |
846 | |
847 | m_sessions = new QTreeWidget (page); |
848 | hb->addWidget(m_sessions); |
849 | m_sessions->setColumnCount(2); |
850 | QStringList ; |
851 | header << i18n("Session Name" ); |
852 | header << i18nc("The number of open documents" , "Open Documents" ); |
853 | m_sessions->setHeaderLabels(header); |
854 | m_sessions->setRootIsDecorated( false ); |
855 | m_sessions->setItemsExpandable( false ); |
856 | m_sessions->setAllColumnsShowFocus( true ); |
857 | m_sessions->setSelectionBehavior(QAbstractItemView::SelectRows); |
858 | m_sessions->setSelectionMode (QAbstractItemView::SingleSelection); |
859 | |
860 | connect (m_sessions, SIGNAL(currentItemChanged(QTreeWidgetItem*,QTreeWidgetItem*)), this, SLOT(selectionChanged(QTreeWidgetItem*,QTreeWidgetItem*))); |
861 | |
862 | updateSessionList (); |
863 | m_sessions->resizeColumnToContents(0); |
864 | |
865 | QVBoxLayout *vb = new QVBoxLayout (); |
866 | hb->addItem(vb); |
867 | vb->setSpacing (KDialog::spacingHint()); |
868 | |
869 | m_rename = new KPushButton (i18n("&Rename..." ), page); |
870 | connect (m_rename, SIGNAL(clicked()), this, SLOT(rename())); |
871 | vb->addWidget (m_rename); |
872 | |
873 | m_del = new KPushButton (KStandardGuiItem::del (), page); |
874 | connect (m_del, SIGNAL(clicked()), this, SLOT(del())); |
875 | vb->addWidget (m_del); |
876 | |
877 | vb->addStretch (); |
878 | |
879 | // trigger action update |
880 | selectionChanged (NULL, NULL); |
881 | connect(this, SIGNAL(user1Clicked()), this, SLOT(slotUser1())); |
882 | connect(this, SIGNAL(user2Clicked()), this, SLOT(open())); |
883 | } |
884 | |
885 | KateSessionManageDialog::~KateSessionManageDialog () |
886 | {} |
887 | |
888 | void KateSessionManageDialog::slotUser1 () |
889 | { |
890 | done (0); |
891 | } |
892 | |
893 | void KateSessionManageDialog::selectionChanged (QTreeWidgetItem *current, QTreeWidgetItem *) |
894 | { |
895 | const bool validItem = (current != NULL); |
896 | |
897 | m_rename->setEnabled (validItem); |
898 | m_del->setEnabled (validItem && (static_cast<KateSessionChooserItem*>(current))->session!=KateSessionManager::self()->activeSession()); |
899 | button(User2)->setEnabled (validItem); |
900 | } |
901 | |
902 | void KateSessionManageDialog::rename () |
903 | { |
904 | KateSessionChooserItem *item = static_cast<KateSessionChooserItem *>(m_sessions->currentItem ()); |
905 | |
906 | if (!item) |
907 | return; |
908 | |
909 | bool ok = false; |
910 | QString name = KInputDialog::getText (i18n("Specify New Name for Session" ), i18n("Session name:" ), item->session->sessionName(), &ok); |
911 | |
912 | if (!ok) |
913 | return; |
914 | |
915 | if (name.isEmpty()) |
916 | { |
917 | KMessageBox::sorry (this, i18n("To save a session, you must specify a name." ), i18n ("Missing Session Name" )); |
918 | return; |
919 | } |
920 | |
921 | if (item->session->rename (name)) { |
922 | if (item->session==KateSessionManager::self()->activeSession()) { |
923 | emit KateSessionManager::self()->sessionChanged(); |
924 | } |
925 | updateSessionList (); |
926 | } |
927 | else |
928 | KMessageBox::sorry(this, i18n("The session could not be renamed to \"%1\", there already exists another session with the same name" , name), i18n("Session Renaming" )); |
929 | } |
930 | |
931 | void KateSessionManageDialog::del () |
932 | { |
933 | KateSessionChooserItem *item = static_cast<KateSessionChooserItem *>(m_sessions->currentItem ()); |
934 | |
935 | if (!item) |
936 | return; |
937 | |
938 | QFile::remove (item->session->sessionFile()); |
939 | KateSessionManager::self()->updateSessionList (); |
940 | updateSessionList (); |
941 | } |
942 | |
943 | void KateSessionManageDialog::open () |
944 | { |
945 | KateSessionChooserItem *item = static_cast<KateSessionChooserItem *>(m_sessions->currentItem ()); |
946 | |
947 | if (!item) |
948 | return; |
949 | |
950 | hide(); |
951 | KateSessionManager::self()->activateSession (item->session); |
952 | done(0); |
953 | } |
954 | |
955 | void KateSessionManageDialog::updateSessionList () |
956 | { |
957 | m_sessions->clear (); |
958 | |
959 | const KateSessionList &slist (KateSessionManager::self()->sessionList()); |
960 | for (int i = 0; i < slist.count(); ++i) |
961 | { |
962 | new KateSessionChooserItem (m_sessions, slist[i]); |
963 | } |
964 | } |
965 | |
966 | //END MANAGE DIALOG |
967 | |
968 | |
969 | KateSessionsAction::KateSessionsAction(const QString& text, QObject* parent) |
970 | : KActionMenu(text, parent) |
971 | { |
972 | connect(menu(), SIGNAL(aboutToShow()), this, SLOT(slotAboutToShow())); |
973 | |
974 | sessionsGroup = new QActionGroup( menu() ); |
975 | |
976 | // reason for Qt::QueuedConnection: when switching session with N mainwindows |
977 | // to e.g. 1 mainwindow, the last N - 1 mainwindows are deleted. Invoking |
978 | // a session switch without queued connection deletes a mainwindow in which |
979 | // the current code path is executed ---> crash. See bug #227008. |
980 | connect(sessionsGroup, SIGNAL(triggered(QAction*)), this, SLOT(openSession(QAction*)), Qt::QueuedConnection); |
981 | |
982 | connect(KateSessionManager::self(), SIGNAL(sessionChanged()), this, SLOT(slotSessionChanged())); |
983 | setDisabled(KateSessionManager::self()->sessionList().size() == 0); |
984 | } |
985 | |
986 | void KateSessionsAction::slotAboutToShow() |
987 | { |
988 | qDeleteAll( sessionsGroup->actions() ); |
989 | |
990 | const KateSessionList &slist (KateSessionManager::self()->sessionList()); |
991 | for (int i = 0; i < slist.count(); ++i) |
992 | { |
993 | QString sessionName = slist[i]->sessionName(); |
994 | sessionName.replace("&" , "&&" ); |
995 | QAction *action = new QAction( sessionName, sessionsGroup ); |
996 | action->setData(QVariant(i)); |
997 | menu()->addAction (action); |
998 | } |
999 | } |
1000 | |
1001 | void KateSessionsAction::openSession (QAction *action) |
1002 | { |
1003 | const KateSessionList &slist (KateSessionManager::self()->sessionList()); |
1004 | |
1005 | int i = action->data().toInt(); |
1006 | if (i >= slist.count()) |
1007 | return; |
1008 | |
1009 | KateSessionManager::self()->activateSession(slist[i]); |
1010 | } |
1011 | |
1012 | void KateSessionsAction::slotSessionChanged() |
1013 | { |
1014 | setDisabled(KateSessionManager::self()->sessionList().size() == 0); |
1015 | } |
1016 | |
1017 | // kate: space-indent on; indent-width 2; replace-tabs on; |
1018 | |