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