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