1 /*********
2 *
3 * This file is part of BibleTime's source code, http://www.bibletime.info/.
4 *
5 * Copyright 1999-2016 by the BibleTime developers.
6 * The BibleTime source code is licensed under the GNU General Public License version 2.0.
7 *
8 **********/
9 
10 #include "bibletime.h"
11 
12 #include <QAction>
13 #include <QApplication>
14 #include <QClipboard>
15 #include <QDebug>
16 #include <QDesktopServices>
17 #include <QInputDialog>
18 #include <QList>
19 #include <QMdiSubWindow>
20 #include <QMenu>
21 #include <QProcess>
22 #include <QtGlobal>
23 #include <QToolBar>
24 #include <QUrl>
25 #include "backend/config/btconfig.h"
26 #include "backend/keys/cswordversekey.h"
27 #include "frontend/btaboutdialog.h"
28 #include "frontend/cinfodisplay.h"
29 #include "frontend/cmdiarea.h"
30 #include "frontend/bookshelfwizard/btbookshelfwizard.h"
31 #include "frontend/display/btfindwidget.h"
32 #include "frontend/displaywindow/btmodulechooserbar.h"
33 #include "frontend/displaywindow/cdisplaywindow.h"
34 #include "frontend/messagedialog.h"
35 #include "frontend/searchdialog/csearchdialog.h"
36 #include "frontend/settingsdialogs/cconfigurationdialog.h"
37 #include "frontend/tips/bttipdialog.h"
38 #include "util/btassert.h"
39 #include "util/btconnect.h"
40 #include "util/directory.h"
41 
42 
43 /** Opens the optionsdialog of BibleTime. */
slotSettingsOptions()44 void BibleTime::slotSettingsOptions() {
45     qDebug() << "BibleTime::slotSettingsOptions";
46     CConfigurationDialog *dlg = new CConfigurationDialog(this, m_actionCollection);
47     BT_CONNECT(dlg,  SIGNAL(signalSettingsChanged()),
48                this, SLOT(slotSettingsChanged()) );
49 
50     dlg->show();
51 }
52 
53 /** Save the settings, used when no settings have been saved before **/
saveConfigSettings()54 void BibleTime::saveConfigSettings() {
55     CConfigurationDialog* dlg = new CConfigurationDialog(this, nullptr);
56     dlg->save();
57     delete dlg;
58 }
59 
60 /** Is called when settings in the optionsdialog were changed (ok or apply) */
slotSettingsChanged()61 void BibleTime::slotSettingsChanged() {
62     qDebug() << "BibleTime::slotSettingsChanged";
63     const QString language = btConfig().value<QString>("GUI/booknameLanguage", QLocale::system().name());
64     CSwordBackend::instance()->booknameLanguage(language);
65 
66 // \todo update the bookmarks after Bible bookname language has been changed
67 //     QTreeWidgetItemIterator it(m_mainIndex);
68 //     while (*it) {
69 //         CIndexItemBase* citem = dynamic_cast<CIndexItemBase*>(*it);
70 //         if (citem) {
71 //             citem->update();
72 //         }
73 //         ++it;
74 //     }
75 
76     m_actionCollection->readShortcuts("Application shortcuts");
77     refreshDisplayWindows();
78     refreshProfileMenus();
79     qDebug() << "BibleTime::slotSettingsChanged";
80 }
81 
82 /** Opens the bookshelf wizard. */
slotBookshelfWizard()83 void BibleTime::slotBookshelfWizard() {
84     BtBookshelfWizard dlg(BibleTime::instance());
85     dlg.exec();
86 }
87 
88 /** Is called just before the window menu is shown. */
slotWindowMenuAboutToShow()89 void BibleTime::slotWindowMenuAboutToShow() {
90     BT_ASSERT(m_windowMenu);
91 
92     const int numSubWindows = m_mdi->subWindowList().count();
93     m_windowCloseAction->setEnabled(numSubWindows);
94     m_windowCloseAllAction->setEnabled(numSubWindows);
95     m_openWindowsMenu->setEnabled(numSubWindows);
96 
97     const bool enableManualArrangeActions = numSubWindows > 1;
98     m_windowCascadeAction->setEnabled(enableManualArrangeActions);
99     m_windowTileAction->setEnabled(enableManualArrangeActions);
100     m_windowTileVerticalAction->setEnabled(enableManualArrangeActions);
101     m_windowTileHorizontalAction->setEnabled(enableManualArrangeActions);
102 }
103 
104 /** Is called just before the open windows menu is shown. */
slotOpenWindowsMenuAboutToShow()105 void BibleTime::slotOpenWindowsMenuAboutToShow() {
106     BT_ASSERT(m_openWindowsMenu);
107 
108     m_openWindowsMenu->clear();
109     Q_FOREACH (QMdiSubWindow * const window, m_mdi->usableWindowList()) {
110         QAction *openWindowAction = m_openWindowsMenu->addAction(window->windowTitle());
111         openWindowAction->setCheckable(true);
112         openWindowAction->setChecked(window == m_mdi->activeSubWindow());
113         BT_CONNECT(openWindowAction, SIGNAL(triggered()),
114                    m_windowMapper,   SLOT(map()));
115         m_windowMapper->setMapping(openWindowAction, window);
116     }
117 }
118 
119 /** This slot is connected with the windowAutoTileAction object */
slotUpdateWindowArrangementActions(QAction * trigerredAction)120 void BibleTime::slotUpdateWindowArrangementActions(QAction * trigerredAction) {
121     BT_ASSERT(trigerredAction);
122 
123     if (trigerredAction == m_windowAutoTileVerticalAction) {
124         m_mdi->setMDIArrangementMode(CMDIArea::ArrangementModeTileVertical);
125         btConfig().setSessionValue("GUI/alignmentMode", autoTileVertical);
126     }
127     else if (trigerredAction == m_windowAutoTileHorizontalAction) {
128         m_mdi->setMDIArrangementMode(CMDIArea::ArrangementModeTileHorizontal);
129         btConfig().setSessionValue("GUI/alignmentMode", autoTileHorizontal);
130     }
131     else if (trigerredAction == m_windowAutoTileAction) {
132         m_mdi->setMDIArrangementMode(CMDIArea::ArrangementModeTile);
133         btConfig().setSessionValue("GUI/alignmentMode", autoTile);
134     }
135     else if (trigerredAction == m_windowAutoTabbedAction) {
136         m_mdi->setMDIArrangementMode(CMDIArea::ArrangementModeTabbed);
137         btConfig().setSessionValue("GUI/alignmentMode", autoTabbed);
138     }
139     else if (trigerredAction == m_windowAutoCascadeAction) {
140         m_mdi->setMDIArrangementMode(CMDIArea::ArrangementModeCascade);
141         btConfig().setSessionValue("GUI/alignmentMode", autoCascade);
142     }
143     else {
144         BT_ASSERT(trigerredAction == m_windowManualModeAction
145                  || trigerredAction == m_windowTileAction
146                  || trigerredAction == m_windowCascadeAction
147                  || trigerredAction == m_windowTileVerticalAction
148                  || trigerredAction == m_windowTileHorizontalAction);
149 
150         if (trigerredAction != m_windowManualModeAction)
151             m_windowManualModeAction->setChecked(true);
152 
153         m_mdi->enableWindowMinMaxFlags(true);
154         m_mdi->setMDIArrangementMode(CMDIArea::ArrangementModeManual);
155         btConfig().setSessionValue("GUI/alignmentMode", manual);
156 
157         if (trigerredAction == m_windowTileAction)
158             m_mdi->myTile();
159         else if (trigerredAction == m_windowCascadeAction)
160             m_mdi->myCascade();
161         else if (trigerredAction == m_windowTileVerticalAction)
162             m_mdi->myTileVertical();
163         else if (trigerredAction == m_windowTileHorizontalAction)
164             m_mdi->myTileHorizontal();
165 
166         return;
167     }
168 
169     m_mdi->enableWindowMinMaxFlags(false);
170 }
171 
slotTile()172 void BibleTime::slotTile() {
173     slotUpdateWindowArrangementActions( m_windowTileAction );
174 }
175 
slotCascade()176 void BibleTime::slotCascade() {
177     slotUpdateWindowArrangementActions( m_windowCascadeAction );
178 }
179 
slotTileVertical()180 void BibleTime::slotTileVertical() {
181     slotUpdateWindowArrangementActions( m_windowTileVerticalAction );
182 }
183 
slotTileHorizontal()184 void BibleTime::slotTileHorizontal() {
185     slotUpdateWindowArrangementActions( m_windowTileHorizontalAction );
186 }
187 
188 /** Shows/hides the toolbar */
slotToggleMainToolbar()189 void BibleTime::slotToggleMainToolbar() {
190     BT_ASSERT(m_mainToolBar);
191     bool currentState = btConfig().sessionValue<bool>("GUI/showMainToolbar", true);
192     btConfig().setSessionValue("GUI/showMainToolbar", !currentState);
193     if ( m_showMainWindowToolbarAction->isChecked()) {
194         m_mainToolBar->show();
195     }
196     else {
197         m_mainToolBar->hide();
198     }
199 }
200 
slotToggleTextWindowHeader()201 void BibleTime::slotToggleTextWindowHeader() {
202     bool currentState = btConfig().sessionValue<bool>("GUI/showTextWindowHeaders", true);
203     btConfig().setSessionValue("GUI/showTextWindowHeaders", !currentState);
204     emit toggledTextWindowHeader(!currentState);
205 }
206 
slotToggleNavigatorToolbar()207 void BibleTime::slotToggleNavigatorToolbar() {
208     bool currentState = btConfig().sessionValue<bool>("GUI/showTextWindowNavigator", true);
209     btConfig().setSessionValue("GUI/showTextWindowNavigator", !currentState);
210     if (btConfig().sessionValue<bool>("GUI/showToolbarsInEachWindow", true))
211         emit toggledTextWindowNavigator(!currentState);
212     else
213         m_navToolBar->setVisible(btConfig().sessionValue<bool>("GUI/showTextWindowNavigator", true));
214 }
215 
slotToggleToolsToolbar()216 void BibleTime::slotToggleToolsToolbar() {
217     bool currentState = btConfig().sessionValue<bool>("GUI/showTextWindowToolButtons", true);
218     btConfig().setSessionValue("GUI/showTextWindowToolButtons", !currentState);
219     if (btConfig().sessionValue<bool>("GUI/showToolbarsInEachWindow", true))
220         emit toggledTextWindowToolButtons(!currentState);
221     else
222         m_toolsToolBar->setVisible(btConfig().sessionValue<bool>("GUI/showTextWindowToolButtons", true));
223 }
224 
slotToggleWorksToolbar()225 void BibleTime::slotToggleWorksToolbar() {
226     bool currentState = btConfig().sessionValue<bool>("GUI/showTextWindowModuleSelectorButtons", true);
227     btConfig().setSessionValue("GUI/showTextWindowModuleSelectorButtons", !currentState);
228     if (btConfig().sessionValue<bool>("GUI/showToolbarsInEachWindow", true))
229         emit toggledTextWindowModuleChooser(!currentState);
230     else
231         m_worksToolBar->setVisible(btConfig().sessionValue<bool>("GUI/showTextWindowModuleSelectorButtons", true));
232 }
233 
slotToggleFormatToolbar()234 void BibleTime::slotToggleFormatToolbar() {
235     bool currentState = btConfig().sessionValue<bool>("GUI/showFormatToolbarButtons", true);
236     btConfig().setSessionValue("GUI/showFormatToolbarButtons", !currentState);
237     if (btConfig().sessionValue<bool>("GUI/showToolbarsInEachWindow", true))
238         emit toggledTextWindowFormatToolbar(!currentState);
239     else
240         m_formatToolBar->setVisible(!currentState);
241 }
242 
slotToggleToolBarsInEachWindow()243 void BibleTime::slotToggleToolBarsInEachWindow() {
244     bool currentState = btConfig().sessionValue<bool>("GUI/showToolbarsInEachWindow", true);
245     btConfig().setSessionValue("GUI/showToolbarsInEachWindow", !currentState);
246     showOrHideToolBars();
247 }
248 
showOrHideToolBars()249 void BibleTime::showOrHideToolBars() {
250     if (btConfig().sessionValue<bool>("GUI/showToolbarsInEachWindow", true)) {
251         // set main window widgets invisible
252         m_navToolBar->setVisible(false);
253         m_worksToolBar->setVisible(false);
254         m_toolsToolBar->setVisible(false);
255         m_formatToolBar->setVisible(false);
256         // set state of sub window widets
257         emit toggledTextWindowNavigator(btConfig().sessionValue<bool>("GUI/showTextWindowNavigator", true));
258         emit toggledTextWindowModuleChooser(btConfig().sessionValue<bool>("GUI/showTextWindowModuleSelectorButtons", true));
259         emit toggledTextWindowToolButtons(btConfig().sessionValue<bool>("GUI/showTextWindowToolButtons", true));
260         emit toggledTextWindowFormatToolbar(btConfig().sessionValue<bool>("GUI/showFormatToolbarButtons", true));
261     }
262     else {
263         // set state of main window widgets
264         m_navToolBar->setVisible(btConfig().sessionValue<bool>("GUI/showTextWindowNavigator", true));
265         m_worksToolBar->setVisible(btConfig().sessionValue<bool>("GUI/showTextWindowModuleSelectorButtons", true));
266         m_toolsToolBar->setVisible(btConfig().sessionValue<bool>("GUI/showTextWindowToolButtons", true));
267         m_formatToolBar->setVisible(btConfig().sessionValue<bool>("GUI/showFormatToolbarButtons", true));
268         //set sub window widgets invisible
269         emit toggledTextWindowNavigator(false);
270         emit toggledTextWindowToolButtons(false);
271         emit toggledTextWindowModuleChooser(false);
272         emit toggledTextWindowFormatToolbar(false);
273     }
274 }
275 
276 /** Sets the active window. */
slotSetActiveSubWindow(QWidget * window)277 void BibleTime::slotSetActiveSubWindow(QWidget* window) {
278     if (!window)
279         return;
280     m_mdi->setActiveSubWindow(dynamic_cast<QMdiSubWindow*>(window));
281 }
282 
slotSearchModules()283 void BibleTime::slotSearchModules() {
284     //get the modules of the open windows
285     BtConstModuleList modules;
286 
287     Q_FOREACH (const QMdiSubWindow * const subWindow, m_mdi->subWindowList()) {
288         const CDisplayWindow * const w = dynamic_cast<CDisplayWindow*>(subWindow->widget());
289         if (w != nullptr) {
290             modules << w->modules();
291         }
292     }
293     Search::CSearchDialog::openDialog(modules, QString::null);
294 }
295 
slotActiveWindowChanged(QMdiSubWindow * window)296 void BibleTime::slotActiveWindowChanged(QMdiSubWindow* window)
297 {
298     if (window == nullptr)
299         m_findWidget->setVisible(false);
300 }
301 
302 /* Search default Bible slot
303  * Call CSearchDialog::openDialog with only the default bible module
304  */
slotSearchDefaultBible()305 void BibleTime::slotSearchDefaultBible() {
306     BtConstModuleList module;
307     CSwordModuleInfo* bible = btConfig().getDefaultSwordModuleByType("standardBible");
308     if (bible) {
309         module.append(bible);
310     }
311     Search::CSearchDialog::openDialog(module, QString::null);
312 }
313 
openOnlineHelp_Handbook()314 void BibleTime::openOnlineHelp_Handbook() {
315     QString filePath(util::directory::getHandbookDir().canonicalPath() + "/index.html");
316     QDesktopServices::openUrl(QUrl::fromLocalFile(filePath));
317 }
318 
openOnlineHelp_Howto()319 void BibleTime::openOnlineHelp_Howto() {
320     QString filePath(util::directory::getHowtoDir().canonicalPath() + "/index.html");
321     QDesktopServices::openUrl(QUrl::fromLocalFile(filePath));
322 }
323 
slotOpenAboutDialog()324 void BibleTime::slotOpenAboutDialog() {
325     BtAboutDialog* dlg = new BtAboutDialog(this);
326     dlg->show();
327 }
328 
slotOpenTipDialog()329 void BibleTime::slotOpenTipDialog() {
330     BtTipDialog* dlg = new BtTipDialog(this);
331     dlg->show();
332 }
333 
saveProfile()334 void BibleTime::saveProfile() {
335     // Save main window settings:
336     BtConfig & conf = btConfig();
337     conf.setSessionValue("MainWindow/geometry", saveGeometry());
338     conf.setSessionValue("MainWindow/state", saveState());
339     conf.setSessionValue("MainWindow/MDIArrangementMode", static_cast<int>(m_mdi->getMDIArrangementMode()));
340 
341     conf.setSessionValue("FindIsVisible", m_findWidget->isVisibleTo(this));
342 
343     QStringList windowsList;
344     Q_FOREACH (const QMdiSubWindow * const w,
345                m_mdi->subWindowList(QMdiArea::StackingOrder))
346     {
347         CDisplayWindow * const displayWindow = dynamic_cast<CDisplayWindow*>(w->widget());
348         if (!displayWindow)
349             continue;
350 
351         const QString windowKey = QString::number(windowsList.size());
352         windowsList.append(windowKey);
353         const QString windowGroup = "window/" + windowKey + '/';
354         displayWindow->storeProfileSettings(windowGroup);
355     }
356     conf.setSessionValue("windowsList", windowsList);
357 }
358 
loadProfile(QAction * action)359 void BibleTime::loadProfile(QAction * action) {
360     BT_ASSERT(action);
361     QVariant keyProperty = action->property("ProfileKey");
362     BT_ASSERT(keyProperty.type() == QVariant::String);
363     BT_ASSERT(btConfig().sessionNames().contains(keyProperty.toString()));
364     loadProfile(keyProperty.toString());
365 }
366 
loadProfile(const QString & profileKey)367 void BibleTime::loadProfile(const QString & profileKey) {
368     BT_ASSERT(btConfig().sessionNames().contains(profileKey));
369 
370     // do nothing if requested session is the current session
371     if (profileKey == btConfig().currentSessionKey())
372         return;
373 
374     // Save old profile:
375     saveProfile();
376 
377     // Close all open windows BEFORE switching profile:
378     m_mdi->closeAllSubWindows();
379 
380     // Switch profile Activate profile:
381     btConfig().setCurrentSession(profileKey);
382     reloadProfile();
383     refreshProfileMenus();
384 }
385 
386 namespace {
387 
388 /// Helper object for reloadProfile()
389 struct WindowLoadStatus {
WindowLoadStatus__anonad7c52950111::WindowLoadStatus390     inline WindowLoadStatus() : window(nullptr) {}
391     QStringList failedModules;
392     QList<CSwordModuleInfo*> okModules;
393     CDisplayWindow * window;
394 };
395 
396 } // anonymous namespace
397 
reloadProfile()398 void BibleTime::reloadProfile() {
399     using MAM = CMDIArea::MDIArrangementMode;
400     using WWT = CPlainWriteWindow::WriteWindowType;
401     using message::setQActionCheckedNoTrigger;
402 
403     // Cache pointer to config:
404     BtConfig & conf = btConfig();
405 
406     // Disable updates while doing big changes:
407     setUpdatesEnabled(false);
408 
409     // Close all open windows:
410     m_mdi->closeAllSubWindows();
411 
412     // Reload main window settings:
413     restoreGeometry(conf.sessionValue<QByteArray>("MainWindow/geometry"));
414     restoreState(conf.sessionValue<QByteArray>("MainWindow/state"));
415 
416     /*
417      * restoreState includes visibility of child widgets, the manually added
418      * qactions (so not including bookmark, bookshelf and mag) are not restored
419      * though, so we restore their state here.
420      */
421     setQActionCheckedNoTrigger(m_windowFullscreenAction, isFullScreen());
422     setQActionCheckedNoTrigger(m_showTextAreaHeadersAction, conf.sessionValue<bool>("GUI/showTextWindowHeaders", true));
423     setQActionCheckedNoTrigger(m_showMainWindowToolbarAction, conf.sessionValue<bool>("GUI/showMainToolbar", true));
424     setQActionCheckedNoTrigger(m_showTextWindowNavigationAction, conf.sessionValue<bool>("GUI/showTextWindowNavigator", true));
425     setQActionCheckedNoTrigger(m_showTextWindowModuleChooserAction, conf.sessionValue<bool>("GUI/showTextWindowModuleSelectorButtons", true));
426     setQActionCheckedNoTrigger(m_showTextWindowToolButtonsAction, conf.sessionValue<bool>("GUI/showTextWindowToolButtons", true));
427     setQActionCheckedNoTrigger(m_showFormatToolbarAction, conf.sessionValue<bool>("GUI/showFormatToolbarButtons", true));
428     setQActionCheckedNoTrigger(m_toolbarsInEachWindow, conf.sessionValue<bool>("GUI/showToolbarsInEachWindow", true));
429 
430     m_mdi->setMDIArrangementMode(static_cast<MAM>(
431                                      conf.sessionValue<int>("MainWindow/MDIArrangementMode",CMDIArea::ArrangementModeTile)));
432 
433     m_findWidget->setVisible(conf.sessionValue<bool>("FindIsVisible", false));
434 
435     QWidget * focusWindow = nullptr;
436     QMap<QString, WindowLoadStatus> failedWindows;
437     Q_FOREACH (const QString & w,
438                conf.sessionValue<QStringList>("windowsList"))
439     {
440         const QString windowGroup = "window/" + w + '/';
441 
442         // Try to determine window modules:
443         WindowLoadStatus wls;
444         Q_FOREACH (const QString &moduleName,
445                    conf.sessionValue<QStringList>(windowGroup + "modules"))
446         {
447             CSwordModuleInfo * const m = CSwordBackend::instance()->findModuleByName(moduleName);
448             if (m) {
449                 wls.okModules.append(m);
450             } else {
451                 wls.failedModules.append(moduleName);
452             }
453         }
454 
455         // Check whether the window totally failed (no modules can be loaded):
456         if (wls.okModules.isEmpty()) {
457             failedWindows.insert(w, wls);
458             continue;
459         }
460 
461         // Check whether the window partially failed:
462         if (!wls.failedModules.isEmpty())
463             failedWindows.insert(w, wls);
464 
465         // Try to respawn the window:
466         BT_ASSERT(!wls.window);
467         const QString key = conf.sessionValue<QString>(windowGroup + "key");
468         WWT wwt = static_cast<WWT>(conf.sessionValue<int>(windowGroup + "writeWindowType", 0));
469         if (wwt > 0) {
470             // Note, that we *might* lose the rest of wls.okModules here:
471             if (wls.okModules.size() > 1)
472                 qWarning() << "Got more modules for a \"write window\" than expected from the profile!";
473 
474             wls.window = createWriteDisplayWindow(wls.okModules.first(), key, wwt);
475         } else {
476             wls.window = createReadDisplayWindow(wls.okModules, key);
477         }
478 
479         if (wls.window) {
480             wls.window->applyProfileSettings(windowGroup);
481             if (conf.sessionValue<bool>(windowGroup + "hasFocus", false))
482                 focusWindow = wls.window;
483         } else {
484             failedWindows.insert(w, wls);
485         }
486     }
487 
488     /* This call is necessary to restore the visibility of the toolbars in the child
489      * windows, since their state is not saved automatically.
490      */
491     showOrHideToolBars();
492 
493     // Re-arrange MDI:
494     m_mdi->triggerWindowUpdate();
495 
496     // Activate focused window:
497     if (focusWindow)
498         focusWindow->setFocus();
499 
500     // Re-enable updates and repaint:
501     setUpdatesEnabled(true);
502     repaint(); /// \bug The main window (except decors) is all black without this (not even hover over toolbar buttons work)
503     raise(); /// \bug The main window would not refresh at all. A call to this function or adjustSize() seems to fix this
504 
505     /// \todo For windows in failedWindows ask whether to keep the settings / close windows etc
506 }
507 
deleteProfile(QAction * action)508 void BibleTime::deleteProfile(QAction* action) {
509     BT_ASSERT(action);
510     QVariant keyProperty = action->property("ProfileKey");
511     BT_ASSERT(keyProperty.type() == QVariant::String);
512     BT_ASSERT(btConfig().sessionNames().contains(keyProperty.toString()));
513 
514     /// \todo Ask for confirmation
515     btConfig().deleteSession(keyProperty.toString());
516     refreshProfileMenus();
517 }
518 
toggleFullscreen()519 void BibleTime::toggleFullscreen() {
520     setWindowState(windowState() ^ Qt::WindowFullScreen);
521     m_mdi->triggerWindowUpdate();
522 }
523 
524 /** Saves current settings into a new profile. */
saveToNewProfile()525 void BibleTime::saveToNewProfile() {
526     BtConfig & conf = btConfig();
527 
528     // Get new unique name:
529     QString name;
530     for (;;) {
531         bool ok;
532         name = QInputDialog::getText(
533                    this, tr("New Session"),
534                    tr("Please enter a name for the new session."),
535                    QLineEdit::Normal, name, &ok);
536         if (!ok)
537             return;
538 
539         if (!name.isEmpty()) {
540             // Check whether name already exists:
541             if (conf.sessionNames().values().contains(name)) {
542                 message::showInformation(this, tr("Session already exists"),
543                                          tr("Session with the name \"%1\" "
544                                             "already exists. Please provide a "
545                                             "different name.").arg(name));
546             } else {
547                 break;
548             }
549         }
550     }
551 
552     // Also save old profile:
553     saveProfile();
554 
555     // Save new profile:
556     conf.setCurrentSession(conf.addSession(name));
557     saveProfile();
558 
559     // Refresh profile menus:
560     refreshProfileMenus();
561 }
562 
563 /** Slot to refresh the saved profile and load profile menus. */
refreshProfileMenus()564 void BibleTime::refreshProfileMenus() {
565     using SNHM = BtConfig::SessionNamesHashMap;
566     using SNHMCI = SNHM::const_iterator;
567 
568     m_windowLoadProfileMenu->clear();
569     m_windowDeleteProfileMenu->clear();
570 
571     BtConfig & conf = btConfig();
572     const BtConfig::SessionNamesHashMap &sessions = conf.sessionNames();
573 
574     const bool enableActions = sessions.size() > 1;
575     m_windowLoadProfileMenu->setEnabled(enableActions);
576     m_windowDeleteProfileMenu->setEnabled(enableActions);
577 
578 
579     if (enableActions) {
580         for (SNHMCI it = sessions.constBegin(); it != sessions.constEnd(); ++it) {
581             QAction * a;
582 
583             a = m_windowLoadProfileMenu->addAction(it.value());
584             a->setProperty("ProfileKey", it.key());
585             a->setActionGroup(m_windowLoadProfileActionGroup);
586             a->setCheckable(true);
587             if (it.key() == conf.currentSessionKey())
588                 a->setChecked(true);
589 
590             a = m_windowDeleteProfileMenu->addAction(it.value());
591             a->setProperty("ProfileKey", it.key());
592             if (it.key() == conf.currentSessionKey())
593                 a->setDisabled(true);
594         }
595     }
596 }
597 
598 // Quit from BibleTime
quit()599 void BibleTime::quit() {
600     Search::CSearchDialog::closeDialog();
601     close();
602 }
603