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