]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/qt-console/mainwin.cpp
This fixes a reproduceable way to have close action show in context for a
[bacula/bacula] / bacula / src / qt-console / mainwin.cpp
1 /*
2    Bacula® - The Network Backup Solution
3
4    Copyright (C) 2007-2007 Free Software Foundation Europe e.V.
5
6    The main author of Bacula is Kern Sibbald, with contributions from
7    many others, a complete list can be found in the file AUTHORS.
8    This program is Free Software; you can redistribute it and/or
9    modify it under the terms of version two of the GNU General Public
10    License as published by the Free Software Foundation and included
11    in the file LICENSE.
12
13    This program is distributed in the hope that it will be useful, but
14    WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16    General Public License for more details.
17
18    You should have received a copy of the GNU General Public License
19    along with this program; if not, write to the Free Software
20    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21    02110-1301, USA.
22
23    Bacula® is a registered trademark of John Walker.
24    The licensor of Bacula is the Free Software Foundation Europe
25    (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich,
26    Switzerland, email:ftf@fsfeurope.org.
27 */
28
29 /*
30  *   Version $Id$
31  *
32  *  Main Window control for bat (qt-console)
33  *
34  *   Kern Sibbald, January MMVII
35  *
36  */ 
37
38 #include "bat.h"
39 #include "joblist/joblist.h"
40 #include "storage/storage.h"
41 #include "fileset/fileset.h"
42 #include "label/label.h"
43 #include "run/run.h"
44 #include "pages.h"
45 #include "restore/restore.h"
46 #include "medialist/medialist.h"
47 #include "joblist/joblist.h"
48 #include "clients/clients.h"
49 #include "restore/restoretree.h"
50 #include "help/help.h"
51 #include "jobs/jobs.h"
52
53 /* 
54  * Daemon message callback
55  */
56 void message_callback(int /* type */, char *msg)
57 {
58    QMessageBox::warning(mainWin, "Bat", msg, QMessageBox::Ok);
59 }
60
61 MainWin::MainWin(QWidget *parent) : QMainWindow(parent)
62 {
63    m_dtformat = "yyyy-MM-dd HH:mm:ss";
64    mainWin = this;
65    setupUi(this);                     /* Setup UI defined by main.ui (designer) */
66    register_message_callback(message_callback);
67    readPreferences();
68    treeWidget->clear();
69    treeWidget->setColumnCount(1);
70    treeWidget->setHeaderLabel("Select Page");
71    treeWidget->setContextMenuPolicy(Qt::ActionsContextMenu);
72
73    createPages();
74
75    resetFocus();
76
77    createConnections();
78
79    this->show();
80
81    readSettings();
82
83    foreach(Console *console, m_consoleHash) {
84       console->connect_dir();
85    }
86    m_currentConsole = (Console*)getFromHash(m_firstItem);
87    m_currentConsole->setCurrent();
88    if (m_miscDebug) {
89       QString directoryResourceName;
90       m_currentConsole->getDirResName(directoryResourceName);
91       Pmsg1(000, "Setting initial window to %s\n", directoryResourceName.toUtf8().data());
92    }
93 }
94
95 void MainWin::createPages()
96 {
97    DIRRES *dir;
98    QTreeWidgetItem *item, *topItem;
99    m_firstItem = NULL;
100
101    LockRes();
102    foreach_res(dir, R_DIRECTOR) {
103
104       /* Create console tree stacked widget item */
105       m_currentConsole = new Console(stackedWidget);
106       m_currentConsole->setDirRes(dir);
107       m_currentConsole->readSettings();
108
109       /* The top tree item representing the director */
110       topItem = new QTreeWidgetItem(treeWidget);
111       topItem->setText(0, dir->name());
112       topItem->setIcon(0, QIcon(":images/server.png"));
113       /* Set background to grey for ease of identification of inactive Director */
114       QBrush greyBrush(Qt::lightGray);
115       topItem->setBackground(0, greyBrush);
116       m_currentConsole->setDirectorTreeItem(topItem);
117       m_consoleHash.insert(topItem, m_currentConsole);
118
119       /* Create Tree Widget Item */
120       item = new QTreeWidgetItem(topItem);
121       item->setText(0, "Console");
122       if (!m_firstItem){ m_firstItem = item; }
123       item->setIcon(0,QIcon(QString::fromUtf8(":images/utilities-terminal.svg")));
124
125       /* insert the cosole and tree widget item into the hashes */
126       hashInsert(item, m_currentConsole);
127
128       /* Set Color of treeWidgetItem for the console
129       * It will be set to green in the console class if the connection is made.
130       */
131       QBrush redBrush(Qt::red);
132       item->setForeground(0, redBrush);
133       m_currentConsole->dockPage();
134
135       /*
136        * Create instances in alphabetic order of the rest 
137        *  of the classes that will by default exist under each Director.  
138        */
139 //      new bRestore();
140       new Clients();
141       new FileSet();
142       new Jobs();
143       createPageJobList("", "", "", "", NULL);
144       new MediaList();
145       new Storage();
146       new restoreTree();
147
148       treeWidget->expandItem(topItem);
149       stackedWidget->setCurrentWidget(m_currentConsole);
150    }
151    UnlockRes();
152 }
153
154 /*
155  * create an instance of the the joblist class on the stack
156  */
157 void MainWin::createPageJobList(const QString &media, const QString &client,
158               const QString &job, const QString &fileset, QTreeWidgetItem *parentTreeWidgetItem)
159 {
160    QTreeWidgetItem *holdItem;
161
162    /* save current tree widget item in case query produces no results */
163    holdItem = treeWidget->currentItem();
164    JobList* joblist = new JobList(media, client, job, fileset, parentTreeWidgetItem);
165    /* If this is a query of jobs on a specific media */
166    if ((media != "") || (client != "") || (job != "") || (fileset != "")) {
167       joblist->setCurrent();
168       /* did query produce results, if not close window and set back to hold */
169       if (joblist->m_resultCount == 0) {
170          joblist->closeStackPage();
171          treeWidget->setCurrentItem(holdItem);
172       }
173    }
174 }
175
176 /*
177  * Handle up and down arrow keys for the command line
178  *  history.
179  */
180 void MainWin::keyPressEvent(QKeyEvent *event)
181 {
182    if (m_cmd_history.size() == 0) {
183       event->ignore();
184       return;
185    }
186    switch (event->key()) {
187    case Qt::Key_Down:
188       if (m_cmd_last < 0 || m_cmd_last >= (m_cmd_history.size()-1)) {
189          event->ignore();
190          return;
191       }
192       m_cmd_last++;
193       break;
194    case Qt::Key_Up:
195       if (m_cmd_last == 0) {
196          event->ignore();
197          return;
198       }
199       if (m_cmd_last < 0 || m_cmd_last > (m_cmd_history.size()-1)) {
200          m_cmd_last = m_cmd_history.size() - 1;
201       } else {
202          m_cmd_last--;
203       }
204       break;
205    default:
206       event->ignore();
207       return;
208    }
209    lineEdit->setText(m_cmd_history[m_cmd_last]);
210 }
211
212 void MainWin::createConnections()
213 {
214    /* Connect signals to slots */
215    connect(lineEdit, SIGNAL(returnPressed()), this, SLOT(input_line()));
216    connect(actionAbout_bat, SIGNAL(triggered()), this, SLOT(about()));
217    connect(actionBat_Help, SIGNAL(triggered()), this, SLOT(help()));
218    connect(treeWidget, SIGNAL(itemClicked(QTreeWidgetItem *, int)), this, 
219            SLOT(treeItemClicked(QTreeWidgetItem *, int)));
220    connect(treeWidget, SIGNAL(
221            currentItemChanged(QTreeWidgetItem *, QTreeWidgetItem *)),
222            this, SLOT(treeItemChanged(QTreeWidgetItem *, QTreeWidgetItem *)));
223    connect(stackedWidget, SIGNAL(currentChanged(int)),
224            this, SLOT(stackItemChanged(int)));
225    connect(actionQuit, SIGNAL(triggered()), app, SLOT(closeAllWindows()));
226    connect(actionLabel, SIGNAL(triggered()), this,  SLOT(labelButtonClicked()));
227    connect(actionRun, SIGNAL(triggered()), this,  SLOT(runButtonClicked()));
228    connect(actionEstimate, SIGNAL(triggered()), this,  SLOT(estimateButtonClicked()));
229    connect(actionBrowse, SIGNAL(triggered()), this,  SLOT(browseButtonClicked()));
230    connect(actionRestore, SIGNAL(triggered()), this,  SLOT(restoreButtonClicked()));
231    connect(actionUndock, SIGNAL(triggered()), this,  SLOT(undockWindowButton()));
232    connect(actionToggleDock, SIGNAL(triggered()), this,  SLOT(toggleDockContextWindow()));
233    connect(actionClosePage, SIGNAL(triggered()), this,  SLOT(closePage()));
234    connect(actionPreferences, SIGNAL(triggered()), this,  SLOT(setPreferences()));
235 }
236
237 /* 
238  * Reimplementation of QWidget closeEvent virtual function   
239  */
240 void MainWin::closeEvent(QCloseEvent *event)
241 {
242    writeSettings();
243    foreach(Console *console, m_consoleHash){
244       console->writeSettings();
245       console->terminate();
246    }
247    event->accept();
248    foreach(Pages *page, m_pagehash) {
249       if (!page->isDocked())
250          page->close();
251    }
252 }
253
254 void MainWin::writeSettings()
255 {
256    QSettings settings("bacula.org", "bat");
257
258    settings.beginGroup("MainWin");
259    settings.setValue("winSize", size());
260    settings.setValue("winPos", pos());
261    settings.setValue("state", saveState());
262    settings.endGroup();
263 }
264
265 void MainWin::readSettings()
266
267    QSettings settings("bacula.org", "bat");
268
269    settings.beginGroup("MainWin");
270    resize(settings.value("winSize", QSize(1041, 801)).toSize());
271    move(settings.value("winPos", QPoint(200, 150)).toPoint());
272    restoreState(settings.value("state").toByteArray());
273    settings.endGroup();
274 }
275
276 /*
277  * This subroutine is called with an item in the Page Selection window
278  *   is clicked 
279  */
280 void MainWin::treeItemClicked(QTreeWidgetItem *item, int /*column*/)
281 {
282    /* Is this a page that has been inserted into the hash  */
283    if (getFromHash(item)) {
284       Pages* page = getFromHash(item);
285       int stackindex=stackedWidget->indexOf(page);
286
287       if (stackindex >= 0) {
288          stackedWidget->setCurrentWidget(page);
289       }
290       /* run the virtual function in case this class overrides it */
291       page->PgSeltreeWidgetClicked();
292    }
293 }
294
295 /*
296  * Called with a change of the highlighed tree widget item in the page selector.
297  */
298 void MainWin::treeItemChanged(QTreeWidgetItem *currentitem, QTreeWidgetItem *previousitem)
299 {
300    Pages *previousPage, *nextPage;
301    Console *previousConsole, *nextConsole;
302
303    /* remove all actions before adding actions appropriate for new page */
304    foreach(QAction* pageAction, treeWidget->actions()) {
305       treeWidget->removeAction(pageAction);
306    }
307
308    /* first determine the next item */
309
310    /* knowing the treeWidgetItem, get the page from the hash */
311    nextPage = getFromHash(currentitem);
312    nextConsole = m_consoleHash.value(currentitem);
313    /* Is this a page that has been inserted into the hash  */
314    if (nextPage) {
315       nextConsole = nextPage->console();
316       /* then is it a treeWidgetItem representing a director */
317    } else if (nextConsole) {
318       /* let the next page BE the console */
319       nextPage = nextConsole;
320    } else {
321       /* Should never get here */
322       nextPage = NULL;
323       nextConsole = NULL;
324    }
325           
326    /* The Previous item */
327
328    /* this condition prevents a segfault.  The first time there is no previousitem*/
329    if (previousitem) {
330       /* knowing the treeWidgetItem, get the page from the hash */
331       previousPage = getFromHash(previousitem);
332       previousConsole = m_consoleHash.value(previousitem);
333       if (previousPage) {
334          previousConsole = previousPage->console();
335       } else if (previousConsole) {
336          previousPage = previousConsole;
337       }
338       if ((previousPage) || (previousConsole)) {
339          if (nextConsole != previousConsole) {
340             /* remove connections to the current console */
341             disconnect(actionConnect, SIGNAL(triggered()), previousConsole, SLOT(connect_dir()));
342             disconnect(actionStatusDir, SIGNAL(triggered()), previousConsole, SLOT(status_dir()));
343             disconnect(actionMessages, SIGNAL(triggered()), previousConsole, SLOT(messages()));
344             disconnect(actionSelectFont, SIGNAL(triggered()), previousConsole, SLOT(set_font()));
345             QTreeWidgetItem *dirItem = previousConsole->directorTreeItem();
346             QBrush greyBrush(Qt::lightGray);
347             dirItem->setBackground(0, greyBrush);
348          }
349       }
350    }
351
352    /* process the current (next) item */
353    
354    if ((nextPage) || (nextConsole)) {
355       if (nextConsole != previousConsole) {
356          /* make connections to the current console */
357          m_currentConsole = nextConsole;
358          connect(actionConnect, SIGNAL(triggered()), m_currentConsole, SLOT(connect_dir()));
359          connect(actionSelectFont, SIGNAL(triggered()), m_currentConsole, SLOT(set_font()));
360          connect(actionStatusDir, SIGNAL(triggered()), m_currentConsole, SLOT(status_dir()));
361          connect(actionMessages, SIGNAL(triggered()), m_currentConsole, SLOT(messages()));
362          /* Set director's tree widget background to magenta for ease of identification */
363          QTreeWidgetItem *dirItem = m_currentConsole->directorTreeItem();
364          QBrush magentaBrush(Qt::magenta);
365          dirItem->setBackground(0, magentaBrush);
366       }
367       /* set the value for the currently active console */
368       int stackindex = stackedWidget->indexOf(nextPage);
369    
370       /* Is this page currently on the stack or is it undocked */
371       if (stackindex >= 0) {
372          /* put this page on the top of the stack */
373          stackedWidget->setCurrentIndex(stackindex);
374       } else {
375          /* it is undocked, raise it to the front */
376          nextPage->raise();
377       }
378       /* for the page selectors menu action to dock or undock, set the text */
379       nextPage->setContextMenuDockText();
380
381       treeWidget->addAction(actionToggleDock);
382       /* if this page is closeable, and it has no childern, then add that action */
383       if ((nextPage->isCloseable()) && (currentitem->child(0) == NULL))
384          treeWidget->addAction(actionClosePage);
385
386       /* Add the actions to the Page Selectors tree widget that are part of the
387        * current items list of desired actions regardless of whether on top of stack*/
388       treeWidget->addActions(nextPage->m_contextActions);
389    }
390 }
391
392 void MainWin::labelButtonClicked() 
393 {
394    new labelPage();
395 }
396
397 void MainWin::runButtonClicked() 
398 {
399    new runPage();
400 }
401
402 void MainWin::estimateButtonClicked() 
403 {
404    new estimatePage();
405 }
406
407 void MainWin::browseButtonClicked() 
408 {
409    new restoreTree();
410 }
411
412 void MainWin::restoreButtonClicked() 
413 {
414    new prerestorePage();
415 }
416
417 /*
418  * The user just finished typing a line in the command line edit box
419  */
420 void MainWin::input_line()
421 {
422    QString cmdStr = lineEdit->text();    /* Get the text */
423    lineEdit->clear();                    /* clear the lineEdit box */
424    if (m_currentConsole->is_connected()) {
425       m_currentConsole->consoleCommand(cmdStr);
426    } else {
427       set_status("Director not connected. Click on connect button.");
428    }
429    m_cmd_history.append(cmdStr);
430    m_cmd_last = -1;
431    if (treeWidget->currentItem() != getFromHash(m_currentConsole))
432       m_currentConsole->setCurrent();
433 }
434
435
436 void MainWin::about()
437 {
438    QMessageBox::about(this, tr("About bat"),
439       tr("<br><h2>bat 1.0, by Dirk H Bartley and Kern Sibbald</h2>"
440          "<p>Copyright &copy; " BYEAR " Free Software Foundation Europe e.V."
441          "<p>The <b>bat</b> is an administrative console"
442          " interface to the Director."));
443 }
444
445 void MainWin::help()
446 {
447    Help::displayFile("index.html");
448 }
449
450 void MainWin::set_statusf(const char *fmt, ...)
451 {
452    va_list arg_ptr;
453    char buf[1000];
454    int len;
455    va_start(arg_ptr, fmt);
456    len = bvsnprintf(buf, sizeof(buf), fmt, arg_ptr);
457    va_end(arg_ptr);
458    set_status(buf);
459 }
460
461 void MainWin::set_status_ready()
462 {
463    set_status(" Ready");
464 }
465
466 void MainWin::set_status(const char *buf)
467 {
468    statusBar()->showMessage(buf);
469 }
470
471 /*
472  * Function to respond to the button bar button to undock
473  */
474 void MainWin::undockWindowButton()
475 {
476    Pages* page = (Pages*)stackedWidget->currentWidget();
477    page->togglePageDocking();
478 }
479
480 /*
481  * Function to respond to action on page selector context menu to toggle the 
482  * dock status of the window associated with the page selectors current
483  * tree widget item.
484  */
485 void MainWin::toggleDockContextWindow()
486 {
487    QTreeWidgetItem *currentitem = treeWidget->currentItem();
488    
489    /* Is this a page that has been inserted into the hash  */
490    if (getFromHash(currentitem)) {
491       Pages* page = getFromHash(currentitem);
492       page->togglePageDocking();
493    }
494 }
495
496 /*
497  * This function is called when the stack item is changed.  Call
498  * the virtual function here.  Avoids a window being undocked leaving
499  * a window at the top of the stack unpopulated.
500  */
501 void MainWin::stackItemChanged(int)
502 {
503    Pages* page = (Pages*)stackedWidget->currentWidget();
504    /* run the virtual function in case this class overrides it */
505    page->currentStackItem();
506 }
507
508 /*
509  * Function to simplify insertion of QTreeWidgetItem <-> Page association
510  * into a double direction hash.
511  */
512 void MainWin::hashInsert(QTreeWidgetItem *item, Pages *page)
513 {
514    m_pagehash.insert(item, page);
515    m_widgethash.insert(page, item);
516 }
517
518 /*
519  * Function to simplify removal of QTreeWidgetItem <-> Page association
520  * into a double direction hash.
521  */
522 void MainWin::hashRemove(QTreeWidgetItem *item, Pages *page)
523 {
524    /* I had all sorts of return status checking code here.  Do we have a log
525     * level capability in bat.  I would have left it in but it used printf's
526     * and it should really be some kind of log level facility ???
527     * ******FIXME********/
528    m_pagehash.remove(item);
529    m_widgethash.remove(page);
530 }
531
532 /*
533  * Function to retrieve a Page* when the item in the page selector's tree is
534  * known.
535  */
536 Pages* MainWin::getFromHash(QTreeWidgetItem *item)
537 {
538    return m_pagehash.value(item);
539 }
540
541 /*
542  * Function to retrieve the page selectors tree widget item when the page is
543  * known.
544  */
545 QTreeWidgetItem* MainWin::getFromHash(Pages *page)
546 {
547    return m_widgethash.value(page);
548 }
549
550 /*
551  * Function to respond to action on page selector context menu to close the
552  * current window.
553  */
554 void MainWin::closePage()
555 {
556    QTreeWidgetItem *currentitem = treeWidget->currentItem();
557    
558    /* Is this a page that has been inserted into the hash  */
559    if (getFromHash(currentitem)) {
560       Pages* page = getFromHash(currentitem);
561       if (page->isCloseable()) {
562          page->closeStackPage();
563       }
564    }
565 }
566
567 /* Quick function to return the current console */
568 Console *MainWin::currentConsole()
569 {
570    return m_currentConsole;
571 }
572 /* Quick function to return the tree item for the director */
573 QTreeWidgetItem *MainWin::currentTopItem()
574 {
575    return m_currentConsole->directorTreeItem();
576 }
577
578 /* Preferences menu item clicked */
579 void MainWin::setPreferences()
580 {
581    prefsDialog prefs;
582    prefs.commDebug->setCheckState(m_commDebug ? Qt::Checked : Qt::Unchecked);
583    prefs.displayAll->setCheckState(m_displayAll ? Qt::Checked : Qt::Unchecked);
584    prefs.sqlDebug->setCheckState(m_sqlDebug ? Qt::Checked : Qt::Unchecked);
585    prefs.commandDebug->setCheckState(m_commandDebug ? Qt::Checked : Qt::Unchecked);
586    prefs.miscDebug->setCheckState(m_miscDebug ? Qt::Checked : Qt::Unchecked);
587    prefs.recordLimit->setCheckState(m_recordLimitCheck ? Qt::Checked : Qt::Unchecked);
588    prefs.recordSpinBox->setValue(m_recordLimitVal);
589    prefs.daysLimit->setCheckState(m_daysLimitCheck ? Qt::Checked : Qt::Unchecked);
590    prefs.daysSpinBox->setValue(m_daysLimitVal);
591    prefs.checkMessages->setCheckState(m_checkMessages ? Qt::Checked : Qt::Unchecked);
592    prefs.checkMessagesSpin->setValue(m_checkMessagesInterval);
593    prefs.executeLongCheckBox->setCheckState(m_longList ? Qt::Checked : Qt::Unchecked);
594
595    prefs.exec();
596 }
597
598 /* Preferences dialog */
599 prefsDialog::prefsDialog()
600 {
601    setupUi(this);
602 }
603
604 void prefsDialog::accept()
605 {
606    this->hide();
607    mainWin->m_commDebug = this->commDebug->checkState() == Qt::Checked;
608    mainWin->m_displayAll = this->displayAll->checkState() == Qt::Checked;
609    mainWin->m_sqlDebug = this->sqlDebug->checkState() == Qt::Checked;
610    mainWin->m_commandDebug = this->commandDebug->checkState() == Qt::Checked;
611    mainWin->m_miscDebug = this->miscDebug->checkState() == Qt::Checked;
612    mainWin->m_recordLimitCheck = this->recordLimit->checkState() == Qt::Checked;
613    mainWin->m_recordLimitVal = this->recordSpinBox->value();
614    mainWin->m_daysLimitCheck = this->daysLimit->checkState() == Qt::Checked;
615    mainWin->m_daysLimitVal = this->daysSpinBox->value();
616    mainWin->m_checkMessages = this->checkMessages->checkState() == Qt::Checked;
617    mainWin->m_checkMessagesInterval = this->checkMessagesSpin->value();
618    mainWin->m_longList = this->executeLongCheckBox->checkState() == Qt::Checked;
619    QSettings settings("www.bacula.org", "bat");
620    settings.beginGroup("Debug");
621    settings.setValue("commDebug", mainWin->m_commDebug);
622    settings.setValue("displayAll", mainWin->m_displayAll);
623    settings.setValue("sqlDebug", mainWin->m_sqlDebug);
624    settings.setValue("commandDebug", mainWin->m_commandDebug);
625    settings.setValue("miscDebug", mainWin->m_miscDebug);
626    settings.endGroup();
627    settings.beginGroup("JobList");
628    settings.setValue("recordLimitCheck", mainWin->m_recordLimitCheck);
629    settings.setValue("recordLimitVal", mainWin->m_recordLimitVal);
630    settings.setValue("daysLimitCheck", mainWin->m_daysLimitCheck);
631    settings.setValue("daysLimitVal", mainWin->m_daysLimitVal);
632    settings.endGroup();
633    settings.beginGroup("Messages");
634    settings.setValue("checkMessages", mainWin->m_checkMessages);
635    settings.setValue("checkMessagesInterval", mainWin->m_checkMessagesInterval);
636    settings.endGroup();
637    settings.beginGroup("Misc");
638    settings.setValue("longList", mainWin->m_longList);
639    settings.endGroup();
640    foreach(Console *console, mainWin->m_consoleHash) {
641       console->startTimer();
642    }
643 }
644
645 void prefsDialog::reject()
646 {
647    this->hide();
648    mainWin->set_status("Canceled");
649 }
650
651 /* read preferences for the prefences dialog box */
652 void MainWin::readPreferences()
653 {
654    QSettings settings("www.bacula.org", "bat");
655    settings.beginGroup("Debug");
656    m_commDebug = settings.value("commDebug", false).toBool();
657    m_displayAll = settings.value("displayAll", false).toBool();
658    m_sqlDebug = settings.value("sqlDebug", false).toBool();
659    m_commandDebug = settings.value("commandDebug", false).toBool();
660    m_miscDebug = settings.value("miscDebug", false).toBool();
661    settings.endGroup();
662    settings.beginGroup("JobList");
663    m_recordLimitCheck = settings.value("recordLimitCheck", true).toBool();
664    m_recordLimitVal = settings.value("recordLimitVal", 150).toInt();
665    m_daysLimitCheck = settings.value("daysLimitCheck", false).toBool();
666    m_daysLimitVal = settings.value("daysLimitVal", 28).toInt();
667    settings.endGroup();
668    settings.beginGroup("Messages");
669    m_checkMessages = settings.value("checkMessages", false).toBool();
670    m_checkMessagesInterval = settings.value("checkMessagesInterval", 28).toInt();
671    settings.endGroup();
672    settings.beginGroup("Misc");
673    m_longList = settings.value("longList", false).toBool();
674    settings.endGroup();
675 }