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