]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/qt-console/mainwin.cpp
kes Fix bat seg fault at termination.
[bacula/bacula] / bacula / src / qt-console / mainwin.cpp
1 /*
2    Bacula® - The Network Backup Solution
3
4    Copyright (C) 2007-2008 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 "version.h"
40 #include "joblist/joblist.h"
41 #include "storage/storage.h"
42 #include "fileset/fileset.h"
43 #include "label/label.h"
44 #include "run/run.h"
45 #include "pages.h"
46 #include "restore/restore.h"
47 #include "medialist/medialist.h"
48 #include "joblist/joblist.h"
49 #include "clients/clients.h"
50 #include "restore/restoretree.h"
51 #include "help/help.h"
52 #include "jobs/jobs.h"
53 #include "jobgraphs/jobplot.h"
54 #include "status/dirstat.h"
55
56 /* 
57  * Daemon message callback
58  */
59 void message_callback(int /* type */, char *msg)
60 {
61    QMessageBox::warning(mainWin, "Bat", msg, QMessageBox::Ok);
62 }
63
64 MainWin::MainWin(QWidget *parent) : QMainWindow(parent)
65 {
66    m_isClosing = false;
67    m_dtformat = "yyyy-MM-dd HH:mm:ss";
68    mainWin = this;
69    setupUi(this);                     /* Setup UI defined by main.ui (designer) */
70    register_message_callback(message_callback);
71    readPreferences();
72    treeWidget->clear();
73    treeWidget->setColumnCount(1);
74    treeWidget->setHeaderLabel("Select Page");
75    treeWidget->setContextMenuPolicy(Qt::ActionsContextMenu);
76
77    createPages();
78
79    resetFocus();
80
81    createConnections();
82
83    this->show();
84
85    readSettings();
86
87    foreach(Console *console, m_consoleHash) {
88       console->connect_dir();
89    }
90    m_currentConsole = (Console*)getFromHash(m_firstItem);
91    m_currentConsole->setCurrent();
92    if (m_miscDebug) {
93       QString directoryResourceName;
94       m_currentConsole->getDirResName(directoryResourceName);
95       Pmsg1(000, "Setting initial window to %s\n", directoryResourceName.toUtf8().data());
96    }
97 }
98
99 void MainWin::createPages()
100 {
101    DIRRES *dir;
102    QTreeWidgetItem *item, *topItem;
103    m_firstItem = NULL;
104
105    LockRes();
106    foreach_res(dir, R_DIRECTOR) {
107
108       /* Create console tree stacked widget item */
109       m_currentConsole = new Console(stackedWidget);
110       m_currentConsole->setDirRes(dir);
111       m_currentConsole->readSettings();
112
113       /* The top tree item representing the director */
114       topItem = new QTreeWidgetItem(treeWidget);
115       topItem->setText(0, dir->name());
116       topItem->setIcon(0, QIcon(":images/server.png"));
117       /* Set background to grey for ease of identification of inactive Director */
118       QBrush greyBrush(Qt::lightGray);
119       topItem->setBackground(0, greyBrush);
120       m_currentConsole->setDirectorTreeItem(topItem);
121       m_consoleHash.insert(topItem, m_currentConsole);
122
123       /* Create Tree Widget Item */
124       item = new QTreeWidgetItem(topItem);
125       item->setText(0, "Console");
126       if (!m_firstItem){ m_firstItem = item; }
127       item->setIcon(0,QIcon(QString::fromUtf8(":images/utilities-terminal.png")));
128
129       /* insert the cosole and tree widget item into the hashes */
130       hashInsert(item, m_currentConsole);
131
132       /* Set Color of treeWidgetItem for the console
133       * It will be set to green in the console class if the connection is made.
134       */
135       QBrush redBrush(Qt::red);
136       item->setForeground(0, redBrush);
137       m_currentConsole->dockPage();
138
139       /*
140        * Create instances in alphabetic order of the rest 
141        *  of the classes that will by default exist under each Director.  
142        */
143 //      new bRestore();
144       new Clients();
145       new FileSet();
146       new Jobs();
147       createPageJobList("", "", "", "", NULL);
148       JobPlotPass pass;
149       pass.use = false;
150       if (m_openPlot)
151          new JobPlot(NULL, pass);
152       new MediaList();
153       new Storage();
154       if (m_openBrowser)
155          new restoreTree();
156       if (m_openDirStat)
157          new DirStat();
158
159       treeWidget->expandItem(topItem);
160       stackedWidget->setCurrentWidget(m_currentConsole);
161    }
162    UnlockRes();
163 }
164
165 /*
166  * create an instance of the the joblist class on the stack
167  */
168 void MainWin::createPageJobList(const QString &media, const QString &client,
169               const QString &job, const QString &fileset, QTreeWidgetItem *parentTreeWidgetItem)
170 {
171    QTreeWidgetItem *holdItem;
172
173    /* save current tree widget item in case query produces no results */
174    holdItem = treeWidget->currentItem();
175    JobList* joblist = new JobList(media, client, job, fileset, parentTreeWidgetItem);
176    /* If this is a query of jobs on a specific media */
177    if ((media != "") || (client != "") || (job != "") || (fileset != "")) {
178       joblist->setCurrent();
179       /* did query produce results, if not close window and set back to hold */
180       if (joblist->m_resultCount == 0) {
181          joblist->closeStackPage();
182          treeWidget->setCurrentItem(holdItem);
183       }
184    }
185 }
186
187 /*
188  * Handle up and down arrow keys for the command line
189  *  history.
190  */
191 void MainWin::keyPressEvent(QKeyEvent *event)
192 {
193    if (m_cmd_history.size() == 0) {
194       event->ignore();
195       return;
196    }
197    switch (event->key()) {
198    case Qt::Key_Down:
199       if (m_cmd_last < 0 || m_cmd_last >= (m_cmd_history.size()-1)) {
200          event->ignore();
201          return;
202       }
203       m_cmd_last++;
204       break;
205    case Qt::Key_Up:
206       if (m_cmd_last == 0) {
207          event->ignore();
208          return;
209       }
210       if (m_cmd_last < 0 || m_cmd_last > (m_cmd_history.size()-1)) {
211          m_cmd_last = m_cmd_history.size() - 1;
212       } else {
213          m_cmd_last--;
214       }
215       break;
216    default:
217       event->ignore();
218       return;
219    }
220    lineEdit->setText(m_cmd_history[m_cmd_last]);
221 }
222
223 void MainWin::createConnections()
224 {
225    /* Connect signals to slots */
226    connect(lineEdit, SIGNAL(returnPressed()), this, SLOT(input_line()));
227    connect(actionAbout_bat, SIGNAL(triggered()), this, SLOT(about()));
228    connect(actionBat_Help, SIGNAL(triggered()), this, SLOT(help()));
229    connect(treeWidget, SIGNAL(itemClicked(QTreeWidgetItem *, int)), this, 
230            SLOT(treeItemClicked(QTreeWidgetItem *, int)));
231    connect(treeWidget, SIGNAL(
232            currentItemChanged(QTreeWidgetItem *, QTreeWidgetItem *)),
233            this, SLOT(treeItemChanged(QTreeWidgetItem *, QTreeWidgetItem *)));
234    connect(stackedWidget, SIGNAL(currentChanged(int)),
235            this, SLOT(stackItemChanged(int)));
236    connect(actionQuit, SIGNAL(triggered()), app, SLOT(closeAllWindows()));
237    connect(actionLabel, SIGNAL(triggered()), this,  SLOT(labelButtonClicked()));
238    connect(actionRun, SIGNAL(triggered()), this,  SLOT(runButtonClicked()));
239    connect(actionEstimate, SIGNAL(triggered()), this,  SLOT(estimateButtonClicked()));
240    connect(actionBrowse, SIGNAL(triggered()), this,  SLOT(browseButtonClicked()));
241    connect(actionStatusDirPage, SIGNAL(triggered()), this,  SLOT(statusPageButtonClicked()));
242    connect(actionJobPlot, SIGNAL(triggered()), this,  SLOT(jobPlotButtonClicked()));
243    connect(actionRestore, SIGNAL(triggered()), this,  SLOT(restoreButtonClicked()));
244    connect(actionUndock, SIGNAL(triggered()), this,  SLOT(undockWindowButton()));
245    connect(actionToggleDock, SIGNAL(triggered()), this,  SLOT(toggleDockContextWindow()));
246    connect(actionClosePage, SIGNAL(triggered()), this,  SLOT(closePage()));
247    connect(actionPreferences, SIGNAL(triggered()), this,  SLOT(setPreferences()));
248 }
249
250 /* 
251  * Reimplementation of QWidget closeEvent virtual function   
252  */
253 void MainWin::closeEvent(QCloseEvent *event)
254 {
255    m_isClosing = true;
256    writeSettings();
257    foreach(Console *console, m_consoleHash){
258       console->writeSettings();
259       console->terminate();
260       console->closeStackPage();
261    }
262    /* close all non console pages, this will call settings in destructors */
263    while (m_consoleHash.count() < m_pagehash.count()) {
264       foreach(Pages *page, m_pagehash) {
265          if (page !=  page->console()) {
266             QTreeWidgetItem* pageSelectorTreeWidgetItem = mainWin->getFromHash(page);
267             if (pageSelectorTreeWidgetItem->childCount() == 0) {
268                page->console()->setCurrent();
269                page->closeStackPage();
270             }
271          }
272       }
273    }
274    foreach(Console *console, m_consoleHash){
275       console->writeSettings();
276       console->terminate();
277       console->closeStackPage();
278    }
279    event->accept();
280 }
281
282 void MainWin::writeSettings()
283 {
284    QSettings settings("bacula.org", "bat");
285
286    settings.beginGroup("MainWin");
287    settings.setValue("winSize", size());
288    settings.setValue("winPos", pos());
289    settings.setValue("state", saveState());
290    settings.endGroup();
291 }
292
293 void MainWin::readSettings()
294
295    QSettings settings("bacula.org", "bat");
296
297    settings.beginGroup("MainWin");
298    resize(settings.value("winSize", QSize(1041, 801)).toSize());
299    move(settings.value("winPos", QPoint(200, 150)).toPoint());
300    restoreState(settings.value("state").toByteArray());
301    settings.endGroup();
302 }
303
304 /*
305  * This subroutine is called with an item in the Page Selection window
306  *   is clicked 
307  */
308 void MainWin::treeItemClicked(QTreeWidgetItem *item, int /*column*/)
309 {
310    /* Is this a page that has been inserted into the hash  */
311    if (getFromHash(item)) {
312       Pages* page = getFromHash(item);
313       int stackindex=stackedWidget->indexOf(page);
314
315       if (stackindex >= 0) {
316          stackedWidget->setCurrentWidget(page);
317       }
318       /* run the virtual function in case this class overrides it */
319       page->PgSeltreeWidgetClicked();
320    }
321 }
322
323 /*
324  * Called with a change of the highlighed tree widget item in the page selector.
325  */
326 void MainWin::treeItemChanged(QTreeWidgetItem *currentitem, QTreeWidgetItem *previousitem)
327 {
328    if (m_isClosing) return; /* if closing the application, do nothing here */
329
330    Pages *previousPage, *nextPage;
331    Console *previousConsole = NULL;
332    Console *nextConsole;
333
334    /* remove all actions before adding actions appropriate for new page */
335    foreach(QAction* pageAction, treeWidget->actions()) {
336       treeWidget->removeAction(pageAction);
337    }
338
339    /* first determine the next item */
340
341    /* knowing the treeWidgetItem, get the page from the hash */
342    nextPage = getFromHash(currentitem);
343    nextConsole = m_consoleHash.value(currentitem);
344    /* Is this a page that has been inserted into the hash  */
345    if (nextPage) {
346       nextConsole = nextPage->console();
347       /* then is it a treeWidgetItem representing a director */
348    } else if (nextConsole) {
349       /* let the next page BE the console */
350       nextPage = nextConsole;
351    } else {
352       /* Should never get here */
353       nextPage = NULL;
354       nextConsole = NULL;
355    }
356           
357    /* The Previous item */
358
359    /* this condition prevents a segfault.  The first time there is no previousitem*/
360    if (previousitem) {
361       /* knowing the treeWidgetItem, get the page from the hash */
362       previousPage = getFromHash(previousitem);
363       previousConsole = m_consoleHash.value(previousitem);
364       if (previousPage) {
365          previousConsole = previousPage->console();
366       } else if (previousConsole) {
367          previousPage = previousConsole;
368       }
369       if ((previousPage) || (previousConsole)) {
370          if (nextConsole != previousConsole) {
371             /* remove connections to the current console */
372             disconnect(actionConnect, SIGNAL(triggered()), previousConsole, SLOT(connect_dir()));
373             disconnect(actionStatusDir, SIGNAL(triggered()), previousConsole, SLOT(status_dir()));
374             disconnect(actionMessages, SIGNAL(triggered()), previousConsole, SLOT(messages()));
375             disconnect(actionSelectFont, SIGNAL(triggered()), previousConsole, SLOT(set_font()));
376             QTreeWidgetItem *dirItem = previousConsole->directorTreeItem();
377             QBrush greyBrush(Qt::lightGray);
378             dirItem->setBackground(0, greyBrush);
379          }
380       }
381    }
382
383    /* process the current (next) item */
384    
385    if ((nextPage) || (nextConsole)) {
386       if (nextConsole != previousConsole) {
387          /* make connections to the current console */
388          m_currentConsole = nextConsole;
389          connect(actionConnect, SIGNAL(triggered()), m_currentConsole, SLOT(connect_dir()));
390          connect(actionSelectFont, SIGNAL(triggered()), m_currentConsole, SLOT(set_font()));
391          connect(actionStatusDir, SIGNAL(triggered()), m_currentConsole, SLOT(status_dir()));
392          connect(actionMessages, SIGNAL(triggered()), m_currentConsole, SLOT(messages()));
393          /* Set director's tree widget background to magenta for ease of identification */
394          QTreeWidgetItem *dirItem = m_currentConsole->directorTreeItem();
395          QBrush magentaBrush(Qt::magenta);
396          dirItem->setBackground(0, magentaBrush);
397       }
398       /* set the value for the currently active console */
399       int stackindex = stackedWidget->indexOf(nextPage);
400    
401       /* Is this page currently on the stack or is it undocked */
402       if (stackindex >= 0) {
403          /* put this page on the top of the stack */
404          stackedWidget->setCurrentIndex(stackindex);
405       } else {
406          /* it is undocked, raise it to the front */
407          nextPage->raise();
408       }
409       /* for the page selectors menu action to dock or undock, set the text */
410       nextPage->setContextMenuDockText();
411
412       treeWidget->addAction(actionToggleDock);
413       /* if this page is closeable, and it has no childern, then add that action */
414       if ((nextPage->isCloseable()) && (currentitem->child(0) == NULL))
415          treeWidget->addAction(actionClosePage);
416
417       /* Add the actions to the Page Selectors tree widget that are part of the
418        * current items list of desired actions regardless of whether on top of stack*/
419       treeWidget->addActions(nextPage->m_contextActions);
420    }
421 }
422
423 void MainWin::labelButtonClicked() 
424 {
425    new labelPage();
426 }
427
428 void MainWin::runButtonClicked() 
429 {
430    new runPage("");
431 }
432
433 void MainWin::estimateButtonClicked() 
434 {
435    new estimatePage();
436 }
437
438 void MainWin::browseButtonClicked() 
439 {
440    new restoreTree();
441 }
442
443 void MainWin::statusPageButtonClicked()
444 {
445    /* if one exists, then just set it current */
446    bool found = false;
447    foreach(Pages *page, m_pagehash) {
448       if (m_currentConsole == page->console()) {
449          if (page->name() == "Director Status") {
450             found = true;
451             page->setCurrent();
452          }
453       }
454    }
455    if (!found)
456       new DirStat();
457 }
458
459 void MainWin::restoreButtonClicked() 
460 {
461    new prerestorePage();
462 }
463
464 void MainWin::jobPlotButtonClicked()
465 {
466    JobPlotPass pass;
467    pass.use = false;
468    new JobPlot(NULL, pass);
469 }
470
471 /*
472  * The user just finished typing a line in the command line edit box
473  */
474 void MainWin::input_line()
475 {
476    QString cmdStr = lineEdit->text();    /* Get the text */
477    lineEdit->clear();                    /* clear the lineEdit box */
478    if (m_currentConsole->is_connected()) {
479       /* Use consoleInput to allow typing anything */
480       m_currentConsole->consoleInput(cmdStr);
481    } else {
482       set_status(tr("Director not connected. Click on connect button."));
483    }
484    m_cmd_history.append(cmdStr);
485    m_cmd_last = -1;
486    if (treeWidget->currentItem() != getFromHash(m_currentConsole))
487       m_currentConsole->setCurrent();
488 }
489
490
491 void MainWin::about()
492 {
493    QMessageBox::about(this, tr("About bat"),
494       tr("<br><h2>bat " VERSION "(" BDATE "), by Dirk H Bartley and Kern Sibbald</h2>"
495          "<p>Copyright &copy; 2007-" BYEAR " Free Software Foundation Europe e.V."
496          "<p>The <b>bat</b> is an administrative console"
497          " interface to the Director."));
498 }
499
500 void MainWin::help()
501 {
502    Help::displayFile("index.html");
503 }
504
505 void MainWin::set_statusf(const char *fmt, ...)
506 {
507    va_list arg_ptr;
508    char buf[1000];
509    int len;
510    va_start(arg_ptr, fmt);
511    len = bvsnprintf(buf, sizeof(buf), fmt, arg_ptr);
512    va_end(arg_ptr);
513    set_status(buf);
514 }
515
516 void MainWin::set_status_ready()
517 {
518    set_status(tr(" Ready"));
519 }
520
521 void MainWin::set_status(const QString &str)
522 {
523    statusBar()->showMessage(str);
524 }
525
526 void MainWin::set_status(const char *buf)
527 {
528    statusBar()->showMessage(buf);
529 }
530
531 /*
532  * Function to respond to the button bar button to undock
533  */
534 void MainWin::undockWindowButton()
535 {
536    Pages* page = (Pages*)stackedWidget->currentWidget();
537    page->togglePageDocking();
538 }
539
540 /*
541  * Function to respond to action on page selector context menu to toggle the 
542  * dock status of the window associated with the page selectors current
543  * tree widget item.
544  */
545 void MainWin::toggleDockContextWindow()
546 {
547    QTreeWidgetItem *currentitem = treeWidget->currentItem();
548    
549    /* Is this a page that has been inserted into the hash  */
550    if (getFromHash(currentitem)) {
551       Pages* page = getFromHash(currentitem);
552       page->togglePageDocking();
553    }
554 }
555
556 /*
557  * This function is called when the stack item is changed.  Call
558  * the virtual function here.  Avoids a window being undocked leaving
559  * a window at the top of the stack unpopulated.
560  */
561 void MainWin::stackItemChanged(int)
562 {
563    if (m_isClosing) return; /* if closing the application, do nothing here */
564    Pages* page = (Pages*)stackedWidget->currentWidget();
565    /* run the virtual function in case this class overrides it */
566    page->currentStackItem();
567 }
568
569 /*
570  * Function to simplify insertion of QTreeWidgetItem <-> Page association
571  * into a double direction hash.
572  */
573 void MainWin::hashInsert(QTreeWidgetItem *item, Pages *page)
574 {
575    m_pagehash.insert(item, page);
576    m_widgethash.insert(page, item);
577 }
578
579 /*
580  * Function to simplify removal of QTreeWidgetItem <-> Page association
581  * into a double direction hash.
582  */
583 void MainWin::hashRemove(QTreeWidgetItem *item, Pages *page)
584 {
585    /* I had all sorts of return status checking code here.  Do we have a log
586     * level capability in bat.  I would have left it in but it used printf's
587     * and it should really be some kind of log level facility ???
588     * ******FIXME********/
589    m_pagehash.remove(item);
590    m_widgethash.remove(page);
591 }
592
593 /*
594  * Function to retrieve a Page* when the item in the page selector's tree is
595  * known.
596  */
597 Pages* MainWin::getFromHash(QTreeWidgetItem *item)
598 {
599    return m_pagehash.value(item);
600 }
601
602 /*
603  * Function to retrieve the page selectors tree widget item when the page is
604  * known.
605  */
606 QTreeWidgetItem* MainWin::getFromHash(Pages *page)
607 {
608    return m_widgethash.value(page);
609 }
610
611 /*
612  * Function to respond to action on page selector context menu to close the
613  * current window.
614  */
615 void MainWin::closePage()
616 {
617    QTreeWidgetItem *currentitem = treeWidget->currentItem();
618    
619    /* Is this a page that has been inserted into the hash  */
620    if (getFromHash(currentitem)) {
621       Pages* page = getFromHash(currentitem);
622       if (page->isCloseable()) {
623          page->closeStackPage();
624       }
625    }
626 }
627
628 /* Quick function to return the current console */
629 Console *MainWin::currentConsole()
630 {
631    return m_currentConsole;
632 }
633 /* Quick function to return the tree item for the director */
634 QTreeWidgetItem *MainWin::currentTopItem()
635 {
636    return m_currentConsole->directorTreeItem();
637 }
638
639 /* Preferences menu item clicked */
640 void MainWin::setPreferences()
641 {
642    prefsDialog prefs;
643    prefs.commDebug->setCheckState(m_commDebug ? Qt::Checked : Qt::Unchecked);
644    prefs.displayAll->setCheckState(m_displayAll ? Qt::Checked : Qt::Unchecked);
645    prefs.sqlDebug->setCheckState(m_sqlDebug ? Qt::Checked : Qt::Unchecked);
646    prefs.commandDebug->setCheckState(m_commandDebug ? Qt::Checked : Qt::Unchecked);
647    prefs.miscDebug->setCheckState(m_miscDebug ? Qt::Checked : Qt::Unchecked);
648    prefs.recordLimit->setCheckState(m_recordLimitCheck ? Qt::Checked : Qt::Unchecked);
649    prefs.recordSpinBox->setValue(m_recordLimitVal);
650    prefs.daysLimit->setCheckState(m_daysLimitCheck ? Qt::Checked : Qt::Unchecked);
651    prefs.daysSpinBox->setValue(m_daysLimitVal);
652    prefs.checkMessages->setCheckState(m_checkMessages ? Qt::Checked : Qt::Unchecked);
653    prefs.checkMessagesSpin->setValue(m_checkMessagesInterval);
654    prefs.refreshStatusDir->setCheckState(m_refreshStatusDir ? Qt::Checked : Qt::Unchecked);
655    prefs.refreshStatusDirSpin->setValue(m_refreshStatusDirInterval);
656    prefs.executeLongCheckBox->setCheckState(m_longList ? Qt::Checked : Qt::Unchecked);
657    prefs.rtPopDirCheckBox->setCheckState(m_rtPopDirDebug ? Qt::Checked : Qt::Unchecked);
658    prefs.rtDirCurICCheckBox->setCheckState(m_rtDirCurICDebug ? Qt::Checked : Qt::Unchecked);
659    prefs.rtDirICCheckBox->setCheckState(m_rtDirICDebug ? Qt::Checked : Qt::Unchecked);
660    prefs.rtFileTabICCheckBox->setCheckState(m_rtFileTabICDebug ? Qt::Checked : Qt::Unchecked);
661    prefs.rtVerTabICCheckBox->setCheckState(m_rtVerTabICDebug ? Qt::Checked : Qt::Unchecked);
662    prefs.rtUpdateFTCheckBox->setCheckState(m_rtUpdateFTDebug ? Qt::Checked : Qt::Unchecked);
663    prefs.rtUpdateVTCheckBox->setCheckState(m_rtUpdateVTDebug ? Qt::Checked : Qt::Unchecked);
664    prefs.rtChecksCheckBox->setCheckState(m_rtChecksDebug ? Qt::Checked : Qt::Unchecked);
665    prefs.rtIconStateCheckBox->setCheckState(m_rtIconStateDebug ? Qt::Checked : Qt::Unchecked);
666    prefs.rtRestore1CheckBox->setCheckState(m_rtRestore1Debug ? Qt::Checked : Qt::Unchecked);
667    prefs.rtRestore2CheckBox->setCheckState(m_rtRestore2Debug ? Qt::Checked : Qt::Unchecked);
668    prefs.rtRestore3CheckBox->setCheckState(m_rtRestore3Debug ? Qt::Checked : Qt::Unchecked);
669    if (m_radioConvert == 0) {
670       prefs.radioConvertOff->setChecked(Qt::Checked);
671    } else if (m_radioConvert == 1){
672       prefs.radioConvertIEC->setChecked(Qt::Checked);
673    } else {
674       m_radioConvert = 2;
675       prefs.radioConvertStandard->setChecked(Qt::Checked);
676    }
677    prefs.openPlotCheckBox->setCheckState(m_openPlot ? Qt::Checked : Qt::Unchecked);
678    prefs.openBrowserCheckBox->setCheckState(m_openBrowser ? Qt::Checked : Qt::Unchecked);
679    prefs.openDirStatCheckBox->setCheckState(m_openDirStat ? Qt::Checked : Qt::Unchecked);
680    prefs.exec();
681 }
682
683 /* Preferences dialog */
684 prefsDialog::prefsDialog()
685 {
686    setupUi(this);
687 }
688
689 void prefsDialog::accept()
690 {
691    this->hide();
692    mainWin->m_commDebug = this->commDebug->checkState() == Qt::Checked;
693    mainWin->m_displayAll = this->displayAll->checkState() == Qt::Checked;
694    mainWin->m_sqlDebug = this->sqlDebug->checkState() == Qt::Checked;
695    mainWin->m_commandDebug = this->commandDebug->checkState() == Qt::Checked;
696    mainWin->m_miscDebug = this->miscDebug->checkState() == Qt::Checked;
697    mainWin->m_recordLimitCheck = this->recordLimit->checkState() == Qt::Checked;
698    mainWin->m_recordLimitVal = this->recordSpinBox->value();
699    mainWin->m_daysLimitCheck = this->daysLimit->checkState() == Qt::Checked;
700    mainWin->m_daysLimitVal = this->daysSpinBox->value();
701    mainWin->m_checkMessages = this->checkMessages->checkState() == Qt::Checked;
702    mainWin->m_checkMessagesInterval = this->checkMessagesSpin->value();
703    mainWin->m_refreshStatusDir = this->refreshStatusDir->checkState() == Qt::Checked;
704    mainWin->m_refreshStatusDirInterval = this->refreshStatusDirSpin->value();
705    mainWin->m_longList = this->executeLongCheckBox->checkState() == Qt::Checked;
706
707    mainWin->m_rtPopDirDebug = this->rtPopDirCheckBox->checkState() == Qt::Checked;
708    mainWin->m_rtDirCurICDebug = this->rtDirCurICCheckBox->checkState() == Qt::Checked;
709    mainWin->m_rtDirICDebug = this->rtDirICCheckBox->checkState() == Qt::Checked;
710    mainWin->m_rtFileTabICDebug = this->rtFileTabICCheckBox->checkState() == Qt::Checked;
711    mainWin->m_rtVerTabICDebug = this->rtVerTabICCheckBox->checkState() == Qt::Checked;
712    mainWin->m_rtUpdateFTDebug = this->rtUpdateFTCheckBox->checkState() == Qt::Checked;
713    mainWin->m_rtUpdateVTDebug = this->rtUpdateVTCheckBox->checkState() == Qt::Checked;
714    mainWin->m_rtChecksDebug = this->rtChecksCheckBox->checkState() == Qt::Checked;
715    mainWin->m_rtIconStateDebug = this->rtIconStateCheckBox->checkState() == Qt::Checked;
716    mainWin->m_rtRestore1Debug = this->rtRestore1CheckBox->checkState() == Qt::Checked;
717    mainWin->m_rtRestore2Debug = this->rtRestore2CheckBox->checkState() == Qt::Checked;
718    mainWin->m_rtRestore3Debug = this->rtRestore3CheckBox->checkState() == Qt::Checked;
719    if (this->radioConvertOff->isChecked()) {
720       mainWin->m_radioConvert = 0;
721    } else if (this->radioConvertIEC->isChecked()){
722       mainWin->m_radioConvert = 1;
723    } else {
724       mainWin->m_radioConvert = 2;
725    }
726    mainWin->m_openPlot = this->openPlotCheckBox->checkState() == Qt::Checked;
727    mainWin->m_openBrowser = this->openBrowserCheckBox->checkState() == Qt::Checked;
728    mainWin->m_openDirStat = this->openDirStatCheckBox->checkState() == Qt::Checked;
729
730    QSettings settings("www.bacula.org", "bat");
731    settings.beginGroup("Debug");
732    settings.setValue("commDebug", mainWin->m_commDebug);
733    settings.setValue("displayAll", mainWin->m_displayAll);
734    settings.setValue("sqlDebug", mainWin->m_sqlDebug);
735    settings.setValue("commandDebug", mainWin->m_commandDebug);
736    settings.setValue("miscDebug", mainWin->m_miscDebug);
737    settings.endGroup();
738    settings.beginGroup("JobList");
739    settings.setValue("recordLimitCheck", mainWin->m_recordLimitCheck);
740    settings.setValue("recordLimitVal", mainWin->m_recordLimitVal);
741    settings.setValue("daysLimitCheck", mainWin->m_daysLimitCheck);
742    settings.setValue("daysLimitVal", mainWin->m_daysLimitVal);
743    settings.endGroup();
744    settings.beginGroup("Timers");
745    settings.setValue("checkMessages", mainWin->m_checkMessages);
746    settings.setValue("checkMessagesInterval", mainWin->m_checkMessagesInterval);
747    settings.setValue("refreshStatusDir", mainWin->m_refreshStatusDir);
748    settings.setValue("refreshStatusDirInterval", mainWin->m_refreshStatusDirInterval);
749    settings.endGroup();
750    settings.beginGroup("Misc");
751    settings.setValue("longList", mainWin->m_longList);
752    settings.setValue("byteConvert", mainWin->m_radioConvert);
753    settings.setValue("openplot", mainWin->m_openPlot);
754    settings.setValue("openbrowser", mainWin->m_openBrowser);
755    settings.setValue("opendirstat", mainWin->m_openDirStat);
756    settings.endGroup();
757    settings.beginGroup("RestoreTree");
758    settings.setValue("rtPopDirDebug", mainWin->m_rtPopDirDebug);
759    settings.setValue("rtDirCurICDebug", mainWin->m_rtDirCurICDebug);
760    settings.setValue("rtDirCurICRetDebug", mainWin->m_rtDirICDebug);
761    settings.setValue("rtFileTabICDebug", mainWin->m_rtFileTabICDebug);
762    settings.setValue("rtVerTabICDebug", mainWin->m_rtVerTabICDebug);
763    settings.setValue("rtUpdateFTDebug", mainWin->m_rtUpdateFTDebug);
764    settings.setValue("rtUpdateVTDebug", mainWin->m_rtUpdateVTDebug);
765    settings.setValue("rtChecksDebug", mainWin->m_rtChecksDebug);
766    settings.setValue("rtIconStateDebug", mainWin->m_rtIconStateDebug);
767    settings.setValue("rtRestore1Debug", mainWin->m_rtRestore1Debug);
768    settings.setValue("rtRestore2Debug", mainWin->m_rtRestore2Debug);
769    settings.setValue("rtRestore3Debug", mainWin->m_rtRestore3Debug);
770    settings.endGroup();
771    foreach(Console *console, mainWin->m_consoleHash) {
772       console->startTimer();
773    }
774 }
775
776 void prefsDialog::reject()
777 {
778    this->hide();
779    mainWin->set_status(tr("Canceled"));
780 }
781
782 /* read preferences for the prefences dialog box */
783 void MainWin::readPreferences()
784 {
785    QSettings settings("www.bacula.org", "bat");
786    settings.beginGroup("Debug");
787    m_commDebug = settings.value("commDebug", false).toBool();
788    m_displayAll = settings.value("displayAll", false).toBool();
789    m_sqlDebug = settings.value("sqlDebug", false).toBool();
790    m_commandDebug = settings.value("commandDebug", false).toBool();
791    m_miscDebug = settings.value("miscDebug", false).toBool();
792    settings.endGroup();
793    settings.beginGroup("JobList");
794    m_recordLimitCheck = settings.value("recordLimitCheck", true).toBool();
795    m_recordLimitVal = settings.value("recordLimitVal", 150).toInt();
796    m_daysLimitCheck = settings.value("daysLimitCheck", false).toBool();
797    m_daysLimitVal = settings.value("daysLimitVal", 28).toInt();
798    settings.endGroup();
799    settings.beginGroup("Timers");
800    m_checkMessages = settings.value("checkMessages", false).toBool();
801    m_checkMessagesInterval = settings.value("checkMessagesInterval", 28).toInt();
802    m_refreshStatusDir = settings.value("refreshStatusDir", false).toBool();
803    m_refreshStatusDirInterval = settings.value("refreshStatusDirInterval", 28).toInt();
804    settings.endGroup();
805    settings.beginGroup("Misc");
806    m_longList = settings.value("longList", false).toBool();
807    m_radioConvert = settings.value("byteConvert", false).toInt();
808    m_openPlot = settings.value("openplot", false).toBool();
809    m_openBrowser = settings.value("openbrowser", false).toBool();
810    m_openDirStat = settings.value("opendirstat", false).toBool();
811    settings.endGroup();
812    settings.beginGroup("RestoreTree");
813    m_rtPopDirDebug = settings.value("rtPopDirDebug", false).toBool();
814    m_rtDirCurICDebug = settings.value("rtDirCurICDebug", false).toBool();
815    m_rtDirICDebug = settings.value("rtDirCurICRetDebug", false).toBool();
816    m_rtFileTabICDebug = settings.value("rtFileTabICDebug", false).toBool();
817    m_rtVerTabICDebug = settings.value("rtVerTabICDebug", false).toBool();
818    m_rtUpdateFTDebug = settings.value("rtUpdateFTDebug", false).toBool();
819    m_rtUpdateVTDebug = settings.value("rtUpdateVTDebug", false).toBool();
820    m_rtChecksDebug = settings.value("rtChecksDebug", false).toBool();
821    m_rtIconStateDebug = settings.value("rtIconStateDebug", false).toBool();
822    m_rtRestore1Debug = settings.value("rtRestore1Debug", false).toBool();
823    m_rtRestore2Debug = settings.value("rtRestore2Debug", false).toBool();
824    m_rtRestore3Debug = settings.value("rtRestore3Debug", false).toBool();
825    settings.endGroup();
826 }
827
828 void MainWin::hrConvert(QString &ret, qlonglong &inval)
829 {
830    double net = 0;
831    qlonglong base;
832    QStringList suflist;
833
834    if (m_radioConvert == 0) {
835       ret =  QString("%1").arg(inval);
836       return;
837    } else if (m_radioConvert == 1){
838       base = 1000;
839       suflist = (QStringList() << "B" << "KiB" << "MiB" << "GiB" << "TiB" << "PiB" << "EiB" << "ZiB");
840    } else {
841       base = 1024;
842       suflist = (QStringList() << "B" << "KB" << "MB" << "GB" << "TB" << "PB" << "EB" << "ZB");
843    }
844    qlonglong running = base;
845    bool done = false;
846    int count = 1;
847    while (done == false) {
848       QString test1 =  QString("%1").arg(inval);
849       QString test2 =  QString("%1").arg(running);
850       if (float(inval) < (float)(running)) {
851          done = true;
852          ret = suflist[count - 1];
853          net = (float)inval / (float)(running/base);
854       }
855       count += 1;
856       if (count > suflist.count()) done = true;
857       running *= base;
858    }
859    char format = 'f';
860    if (net != 0)
861       ret =  QString("%1 %2")
862                   .arg(net, 0, format, 2, QLatin1Char(' '))
863                   .arg(ret);
864    else ret = "0 B";
865 }
866
867 void MainWin::hrConvertSeconds(QString &ret, qlonglong &inval)
868 {
869    double net = 0;
870    QList<qlonglong> durations;
871    durations.append(1);
872    durations.append(60);
873    durations.append(3600);
874    durations.append(86400);
875    durations.append(2592000);
876    durations.append(31536000);
877    QStringList abbrlist = (QStringList() << "Sec" << "Min" << "Hrs" << "Days" << "Mnth" << "Yrs");
878    bool done = false;
879    int count = 1;
880    while (done == false) {
881       QString test1 =  QString("%1").arg(inval);
882       QString test2 =  QString("%1").arg(durations[count]);
883       if ((inval < durations[count]) || (count >= abbrlist.count() - 1)) { 
884          done = true;
885          net = (float)inval / (float)(durations[count - 1]);
886          if (net != 0)
887             ret =  QString("%1 %2")
888                   .arg(net, 0, 'f', 2, QLatin1Char(' '))
889                   .arg(abbrlist[count - 1]);
890          else ret = "0 S";
891       }
892       count += 1;
893    }
894 }