]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/qt-console/mainwin.cpp
After much effort, I think I've got it. Was having a heck of a time
[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 }
269
270 void MainWin::disconnectSignals()
271 {
272    /* Connect signals to slots */
273    disconnect(lineEdit, SIGNAL(returnPressed()), this, SLOT(input_line()));
274    disconnect(actionAbout_bat, SIGNAL(triggered()), this, SLOT(about()));
275    disconnect(actionBat_Help, SIGNAL(triggered()), this, SLOT(help()));
276    disconnect(treeWidget, SIGNAL(itemClicked(QTreeWidgetItem *, int)), this, SLOT(treeItemClicked(QTreeWidgetItem *, int)));
277    disconnect(treeWidget, SIGNAL( currentItemChanged(QTreeWidgetItem *, QTreeWidgetItem *)), this, SLOT(treeItemChanged(QTreeWidgetItem *, QTreeWidgetItem *)));
278    disconnect(stackedWidget, SIGNAL(currentChanged(int)), this, SLOT(stackItemChanged(int)));
279    disconnect(actionQuit, SIGNAL(triggered()), app, SLOT(closeAllWindows()));
280    disconnect(actionLabel, SIGNAL(triggered()), this,  SLOT(labelButtonClicked()));
281    disconnect(actionRun, SIGNAL(triggered()), this,  SLOT(runButtonClicked()));
282    disconnect(actionEstimate, SIGNAL(triggered()), this,  SLOT(estimateButtonClicked()));
283    disconnect(actionBrowse, SIGNAL(triggered()), this,  SLOT(browseButtonClicked()));
284    disconnect(actionStatusDirPage, SIGNAL(triggered()), this,  SLOT(statusPageButtonClicked()));
285 #ifdef HAVE_QWT
286    disconnect(actionJobPlot, SIGNAL(triggered()), this,  SLOT(jobPlotButtonClicked()));
287 #endif
288    disconnect(actionRestore, SIGNAL(triggered()), this,  SLOT(restoreButtonClicked()));
289    disconnect(actionUndock, SIGNAL(triggered()), this,  SLOT(undockWindowButton()));
290    disconnect(actionToggleDock, SIGNAL(triggered()), this,  SLOT(toggleDockContextWindow()));
291    disconnect(actionClosePage, SIGNAL(triggered()), this,  SLOT(closePage()));
292    disconnect(actionPreferences, SIGNAL(triggered()), this,  SLOT(setPreferences()));
293    disconnect(actionRepopLists, SIGNAL(triggered()), this,  SLOT(repopLists()));
294 }
295
296 /*
297  *  Enter wait state
298  */
299 void MainWin::waitEnter()
300 {
301    if (m_waitState){ 
302       if (mainWin->m_connDebug)
303          Pmsg0(000, "Should Never Get Here DANGER DANGER, for now I'll return\n");
304       return;
305    }
306    m_waitState = true;
307    if (mainWin->m_connDebug)
308       Pmsg0(000, "Entering Wait State\n");
309    app->setOverrideCursor(QCursor(Qt::WaitCursor));
310    disconnectSignals();
311    disconnectConsoleSignals(m_currentConsole);
312    m_waitTreeItem = treeWidget->currentItem();
313 }
314
315 /*
316  *  Leave wait state
317  */
318 void MainWin::waitExit()
319 {
320    m_waitState = false;
321    if (mainWin->m_connDebug)
322       Pmsg0(000, "Exiting Wait State\n");
323    app->restoreOverrideCursor();
324    if (m_waitTreeItem != treeWidget->currentItem())
325       treeWidget->setCurrentItem(m_waitTreeItem);
326    if (m_doConnect) {
327       connectSignals();
328       connectConsoleSignals();
329    }
330 }
331
332 void MainWin::connectConsoleSignals()
333 {
334    connect(actionConnect, SIGNAL(triggered()), m_currentConsole, SLOT(connect_dir()));
335    connect(actionSelectFont, SIGNAL(triggered()), m_currentConsole, SLOT(set_font()));
336    connect(actionStatusDir, SIGNAL(triggered()), m_currentConsole, SLOT(status_dir()));
337    connect(actionMessages, SIGNAL(triggered()), m_currentConsole, SLOT(messages()));
338 }
339
340 void MainWin::disconnectConsoleSignals(Console *console)
341 {
342    disconnect(actionConnect, SIGNAL(triggered()), console, SLOT(connect_dir()));
343    disconnect(actionStatusDir, SIGNAL(triggered()), console, SLOT(status_dir()));
344    disconnect(actionMessages, SIGNAL(triggered()), console, SLOT(messages()));
345    disconnect(actionSelectFont, SIGNAL(triggered()), console, SLOT(set_font()));
346 }
347
348 void MainWin::repopLists()
349 {
350    m_currentConsole->populateLists(false);
351 }
352
353 /* 
354  * Reimplementation of QWidget closeEvent virtual function   
355  */
356 void MainWin::closeEvent(QCloseEvent *event)
357 {
358    m_isClosing = true;
359    writeSettings();
360    /* close all non console pages, this will call settings in destructors */
361    while (m_consoleHash.count() < m_pagehash.count()) {
362       foreach(Pages *page, m_pagehash) {
363          if (page !=  page->console()) {
364             QTreeWidgetItem* pageSelectorTreeWidgetItem = mainWin->getFromHash(page);
365             if (pageSelectorTreeWidgetItem->childCount() == 0) {
366                page->console()->setCurrent();
367                page->closeStackPage();
368             }
369          }
370       }
371    }
372    foreach(Console *console, m_consoleHash){
373       console->writeSettings();
374       console->terminate();
375       console->closeStackPage();
376    }
377    event->accept();
378 }
379
380 void MainWin::writeSettings()
381 {
382    QSettings settings("bacula.org", "bat");
383
384    settings.beginGroup("MainWin");
385    settings.setValue("winSize", size());
386    settings.setValue("winPos", pos());
387    settings.setValue("state", saveState());
388    settings.endGroup();
389 }
390
391 void MainWin::readSettings()
392
393    QSettings settings("bacula.org", "bat");
394
395    settings.beginGroup("MainWin");
396    resize(settings.value("winSize", QSize(1041, 801)).toSize());
397    move(settings.value("winPos", QPoint(200, 150)).toPoint());
398    restoreState(settings.value("state").toByteArray());
399    settings.endGroup();
400 }
401
402 /*
403  * This subroutine is called with an item in the Page Selection window
404  *   is clicked 
405  */
406 void MainWin::treeItemClicked(QTreeWidgetItem *item, int /*column*/)
407 {
408    /* Is this a page that has been inserted into the hash  */
409    if (getFromHash(item)) {
410       Pages* page = getFromHash(item);
411       int stackindex=stackedWidget->indexOf(page);
412
413       if (stackindex >= 0) {
414          stackedWidget->setCurrentWidget(page);
415       }
416       /* run the virtual function in case this class overrides it */
417       page->PgSeltreeWidgetClicked();
418    }
419 }
420
421 /*
422  * Called with a change of the highlighed tree widget item in the page selector.
423  */
424 void MainWin::treeItemChanged(QTreeWidgetItem *currentitem, QTreeWidgetItem *previousitem)
425 {
426    if (m_isClosing) return; /* if closing the application, do nothing here */
427
428    Pages *previousPage, *nextPage;
429    Console *previousConsole = NULL;
430    Console *nextConsole;
431
432    /* remove all actions before adding actions appropriate for new page */
433    foreach(QAction* pageAction, treeWidget->actions()) {
434       treeWidget->removeAction(pageAction);
435    }
436
437    /* first determine the next item */
438
439    /* knowing the treeWidgetItem, get the page from the hash */
440    nextPage = getFromHash(currentitem);
441    nextConsole = m_consoleHash.value(currentitem);
442    /* Is this a page that has been inserted into the hash  */
443    if (nextPage) {
444       nextConsole = nextPage->console();
445       /* then is it a treeWidgetItem representing a director */
446    } else if (nextConsole) {
447       /* let the next page BE the console */
448       nextPage = nextConsole;
449    } else {
450       /* Should never get here */
451       nextPage = NULL;
452       nextConsole = NULL;
453    }
454           
455    /* The Previous item */
456
457    /* this condition prevents a segfault.  The first time there is no previousitem*/
458    if (previousitem) {
459       /* knowing the treeWidgetItem, get the page from the hash */
460       previousPage = getFromHash(previousitem);
461       previousConsole = m_consoleHash.value(previousitem);
462       if (previousPage) {
463          previousConsole = previousPage->console();
464       } else if (previousConsole) {
465          previousPage = previousConsole;
466       }
467       if ((previousPage) || (previousConsole)) {
468          if (nextConsole != previousConsole) {
469             /* remove connections to the current console */
470             disconnectConsoleSignals(previousConsole);
471             QTreeWidgetItem *dirItem = previousConsole->directorTreeItem();
472             QBrush greyBrush(Qt::lightGray);
473             dirItem->setBackground(0, greyBrush);
474          }
475       }
476    }
477
478    /* process the current (next) item */
479    
480    if ((nextPage) || (nextConsole)) {
481       if (nextConsole != previousConsole) {
482          /* make connections to the current console */
483          m_currentConsole = nextConsole;
484          connectConsoleSignals();
485          setMessageIcon();
486          /* Set director's tree widget background to magenta for ease of identification */
487          QTreeWidgetItem *dirItem = m_currentConsole->directorTreeItem();
488          QBrush magentaBrush(Qt::magenta);
489          dirItem->setBackground(0, magentaBrush);
490       }
491       /* set the value for the currently active console */
492       int stackindex = stackedWidget->indexOf(nextPage);
493    
494       /* Is this page currently on the stack or is it undocked */
495       if (stackindex >= 0) {
496          /* put this page on the top of the stack */
497          stackedWidget->setCurrentIndex(stackindex);
498       } else {
499          /* it is undocked, raise it to the front */
500          nextPage->raise();
501       }
502       /* for the page selectors menu action to dock or undock, set the text */
503       nextPage->setContextMenuDockText();
504
505       treeWidget->addAction(actionToggleDock);
506       /* if this page is closeable, and it has no childern, then add that action */
507       if ((nextPage->isCloseable()) && (currentitem->child(0) == NULL))
508          treeWidget->addAction(actionClosePage);
509
510       /* Add the actions to the Page Selectors tree widget that are part of the
511        * current items list of desired actions regardless of whether on top of stack*/
512       treeWidget->addActions(nextPage->m_contextActions);
513    }
514 }
515
516 void MainWin::labelButtonClicked() 
517 {
518    new labelPage();
519 }
520
521 void MainWin::runButtonClicked() 
522 {
523    new runPage("");
524 }
525
526 void MainWin::estimateButtonClicked() 
527 {
528    new estimatePage();
529 }
530
531 void MainWin::browseButtonClicked() 
532 {
533    new restoreTree();
534 }
535
536 void MainWin::statusPageButtonClicked()
537 {
538    /* if one exists, then just set it current */
539    bool found = false;
540    foreach(Pages *page, m_pagehash) {
541       if (m_currentConsole == page->console()) {
542          if (page->name() == tr("Director Status")) {
543             found = true;
544             page->setCurrent();
545          }
546       }
547    }
548    if (!found)
549       new DirStat();
550 }
551
552 void MainWin::restoreButtonClicked() 
553 {
554    new prerestorePage();
555 }
556
557 void MainWin::jobPlotButtonClicked()
558 {
559 #ifdef HAVE_QWT
560    JobPlotPass pass;
561    pass.use = false;
562    new JobPlot(NULL, pass);
563 #endif
564 }
565
566 /*
567  * The user just finished typing a line in the command line edit box
568  */
569 void MainWin::input_line()
570 {
571    QString cmdStr = lineEdit->text();    /* Get the text */
572    lineEdit->clear();                    /* clear the lineEdit box */
573    if (m_currentConsole->is_connected()) {
574       /* Use consoleCommand to allow typing anything */
575       m_currentConsole->consoleCommand(cmdStr);
576    } else {
577       set_status(tr("Director not connected. Click on connect button."));
578    }
579    m_cmd_history.append(cmdStr);
580    m_cmd_last = -1;
581    if (treeWidget->currentItem() != getFromHash(m_currentConsole))
582       m_currentConsole->setCurrent();
583 }
584
585
586 void MainWin::about()
587 {
588    QMessageBox::about(this, tr("About bat"),
589       tr("<br><h2>bat %1 (%2), by Dirk H Bartley and Kern Sibbald</h2>"
590          "<p>Copyright &copy; 2007-%3 Free Software Foundation Europe e.V."
591          "<p>The <b>bat</b> is an administrative console"
592          " interface to the Director.").arg(VERSION).arg(BDATE).arg(BYEAR));
593 }
594
595 void MainWin::help()
596 {
597    Help::displayFile("index.html");
598 }
599
600 void MainWin::set_statusf(const char *fmt, ...)
601 {
602    va_list arg_ptr;
603    char buf[1000];
604    int len;
605    va_start(arg_ptr, fmt);
606    len = bvsnprintf(buf, sizeof(buf), fmt, arg_ptr);
607    va_end(arg_ptr);
608    set_status(buf);
609 }
610
611 void MainWin::set_status_ready()
612 {
613    set_status(tr(" Ready"));
614 }
615
616 void MainWin::set_status(const QString &str)
617 {
618    statusBar()->showMessage(str);
619 }
620
621 void MainWin::set_status(const char *buf)
622 {
623    statusBar()->showMessage(buf);
624 }
625
626 /*
627  * Function to respond to the button bar button to undock
628  */
629 void MainWin::undockWindowButton()
630 {
631    Pages* page = (Pages*)stackedWidget->currentWidget();
632    page->togglePageDocking();
633 }
634
635 /*
636  * Function to respond to action on page selector context menu to toggle the 
637  * dock status of the window associated with the page selectors current
638  * tree widget item.
639  */
640 void MainWin::toggleDockContextWindow()
641 {
642    QTreeWidgetItem *currentitem = treeWidget->currentItem();
643    
644    /* Is this a page that has been inserted into the hash  */
645    if (getFromHash(currentitem)) {
646       Pages* page = getFromHash(currentitem);
647       page->togglePageDocking();
648    }
649 }
650
651 /*
652  * This function is called when the stack item is changed.  Call
653  * the virtual function here.  Avoids a window being undocked leaving
654  * a window at the top of the stack unpopulated.
655  */
656 void MainWin::stackItemChanged(int)
657 {
658    if (m_isClosing) return; /* if closing the application, do nothing here */
659    Pages* page = (Pages*)stackedWidget->currentWidget();
660    /* run the virtual function in case this class overrides it */
661    page->currentStackItem();
662 }
663
664 /*
665  * Function to simplify insertion of QTreeWidgetItem <-> Page association
666  * into a double direction hash.
667  */
668 void MainWin::hashInsert(QTreeWidgetItem *item, Pages *page)
669 {
670    m_pagehash.insert(item, page);
671    m_widgethash.insert(page, item);
672 }
673
674 /*
675  * Function to simplify removal of QTreeWidgetItem <-> Page association
676  * into a double direction hash.
677  */
678 void MainWin::hashRemove(QTreeWidgetItem *item, Pages *page)
679 {
680    /* I had all sorts of return status checking code here.  Do we have a log
681     * level capability in bat.  I would have left it in but it used printf's
682     * and it should really be some kind of log level facility ???
683     * ******FIXME********/
684    m_pagehash.remove(item);
685    m_widgethash.remove(page);
686 }
687
688 /*
689  * Function to retrieve a Page* when the item in the page selector's tree is
690  * known.
691  */
692 Pages* MainWin::getFromHash(QTreeWidgetItem *item)
693 {
694    return m_pagehash.value(item);
695 }
696
697 /*
698  * Function to retrieve the page selectors tree widget item when the page is
699  * known.
700  */
701 QTreeWidgetItem* MainWin::getFromHash(Pages *page)
702 {
703    return m_widgethash.value(page);
704 }
705
706 /*
707  * Function to respond to action on page selector context menu to close the
708  * current window.
709  */
710 void MainWin::closePage()
711 {
712    QTreeWidgetItem *currentitem = treeWidget->currentItem();
713    
714    /* Is this a page that has been inserted into the hash  */
715    if (getFromHash(currentitem)) {
716       Pages* page = getFromHash(currentitem);
717       if (page->isCloseable()) {
718          page->closeStackPage();
719       }
720    }
721 }
722
723 /* Quick function to return the current console */
724 Console *MainWin::currentConsole()
725 {
726    return m_currentConsole;
727 }
728
729 /* Quick function to return the tree item for the director */
730 QTreeWidgetItem *MainWin::currentTopItem()
731 {
732    return m_currentConsole->directorTreeItem();
733 }
734
735 /* Preferences menu item clicked */
736 void MainWin::setPreferences()
737 {
738    prefsDialog prefs;
739    prefs.commDebug->setCheckState(m_commDebug ? Qt::Checked : Qt::Unchecked);
740    prefs.connDebug->setCheckState(m_connDebug ? Qt::Checked : Qt::Unchecked);
741    prefs.displayAll->setCheckState(m_displayAll ? Qt::Checked : Qt::Unchecked);
742    prefs.sqlDebug->setCheckState(m_sqlDebug ? Qt::Checked : Qt::Unchecked);
743    prefs.commandDebug->setCheckState(m_commandDebug ? Qt::Checked : Qt::Unchecked);
744    prefs.miscDebug->setCheckState(m_miscDebug ? Qt::Checked : Qt::Unchecked);
745    prefs.recordLimit->setCheckState(m_recordLimitCheck ? Qt::Checked : Qt::Unchecked);
746    prefs.recordSpinBox->setValue(m_recordLimitVal);
747    prefs.daysLimit->setCheckState(m_daysLimitCheck ? Qt::Checked : Qt::Unchecked);
748    prefs.daysSpinBox->setValue(m_daysLimitVal);
749    prefs.checkMessages->setCheckState(m_checkMessages ? Qt::Checked : Qt::Unchecked);
750    prefs.checkMessagesSpin->setValue(m_checkMessagesInterval);
751    prefs.refreshStatusDir->setCheckState(m_refreshStatusDir ? Qt::Checked : Qt::Unchecked);
752    prefs.refreshStatusDirSpin->setValue(m_refreshStatusDirInterval);
753    prefs.executeLongCheckBox->setCheckState(m_longList ? Qt::Checked : Qt::Unchecked);
754    prefs.rtPopDirCheckBox->setCheckState(m_rtPopDirDebug ? Qt::Checked : Qt::Unchecked);
755    prefs.rtDirCurICCheckBox->setCheckState(m_rtDirCurICDebug ? Qt::Checked : Qt::Unchecked);
756    prefs.rtDirICCheckBox->setCheckState(m_rtDirICDebug ? Qt::Checked : Qt::Unchecked);
757    prefs.rtFileTabICCheckBox->setCheckState(m_rtFileTabICDebug ? Qt::Checked : Qt::Unchecked);
758    prefs.rtVerTabICCheckBox->setCheckState(m_rtVerTabICDebug ? Qt::Checked : Qt::Unchecked);
759    prefs.rtUpdateFTCheckBox->setCheckState(m_rtUpdateFTDebug ? Qt::Checked : Qt::Unchecked);
760    prefs.rtUpdateVTCheckBox->setCheckState(m_rtUpdateVTDebug ? Qt::Checked : Qt::Unchecked);
761    prefs.rtChecksCheckBox->setCheckState(m_rtChecksDebug ? Qt::Checked : Qt::Unchecked);
762    prefs.rtIconStateCheckBox->setCheckState(m_rtIconStateDebug ? Qt::Checked : Qt::Unchecked);
763    prefs.rtRestore1CheckBox->setCheckState(m_rtRestore1Debug ? Qt::Checked : Qt::Unchecked);
764    prefs.rtRestore2CheckBox->setCheckState(m_rtRestore2Debug ? Qt::Checked : Qt::Unchecked);
765    prefs.rtRestore3CheckBox->setCheckState(m_rtRestore3Debug ? Qt::Checked : Qt::Unchecked);
766    switch (ItemFormatterBase::getBytesConversion()) {
767    case ItemFormatterBase::BYTES_CONVERSION_NONE:
768       prefs.radioConvertOff->setChecked(Qt::Checked);
769       break;
770    case ItemFormatterBase::BYTES_CONVERSION_IEC:
771       prefs.radioConvertIEC->setChecked(Qt::Checked);
772       break;
773    default:
774       prefs.radioConvertStandard->setChecked(Qt::Checked);
775       break;
776    }
777    prefs.openPlotCheckBox->setCheckState(m_openPlot ? Qt::Checked : Qt::Unchecked);
778 #ifndef HAVE_QWT
779    prefs.openPlotCheckBox->setVisible(false);
780 #endif
781    prefs.openBrowserCheckBox->setCheckState(m_openBrowser ? Qt::Checked : Qt::Unchecked);
782    prefs.openDirStatCheckBox->setCheckState(m_openDirStat ? Qt::Checked : Qt::Unchecked);
783    prefs.exec();
784 }
785
786 /* Preferences dialog */
787 prefsDialog::prefsDialog()
788 {
789    setupUi(this);
790 }
791
792 void prefsDialog::accept()
793 {
794    this->hide();
795    mainWin->m_commDebug = this->commDebug->checkState() == Qt::Checked;
796    mainWin->m_connDebug = this->connDebug->checkState() == Qt::Checked;
797    mainWin->m_displayAll = this->displayAll->checkState() == Qt::Checked;
798    mainWin->m_sqlDebug = this->sqlDebug->checkState() == Qt::Checked;
799    mainWin->m_commandDebug = this->commandDebug->checkState() == Qt::Checked;
800    mainWin->m_miscDebug = this->miscDebug->checkState() == Qt::Checked;
801    mainWin->m_recordLimitCheck = this->recordLimit->checkState() == Qt::Checked;
802    mainWin->m_recordLimitVal = this->recordSpinBox->value();
803    mainWin->m_daysLimitCheck = this->daysLimit->checkState() == Qt::Checked;
804    mainWin->m_daysLimitVal = this->daysSpinBox->value();
805    mainWin->m_checkMessages = this->checkMessages->checkState() == Qt::Checked;
806    mainWin->m_checkMessagesInterval = this->checkMessagesSpin->value();
807    mainWin->m_refreshStatusDir = this->refreshStatusDir->checkState() == Qt::Checked;
808    mainWin->m_refreshStatusDirInterval = this->refreshStatusDirSpin->value();
809    mainWin->m_longList = this->executeLongCheckBox->checkState() == Qt::Checked;
810
811    mainWin->m_rtPopDirDebug = this->rtPopDirCheckBox->checkState() == Qt::Checked;
812    mainWin->m_rtDirCurICDebug = this->rtDirCurICCheckBox->checkState() == Qt::Checked;
813    mainWin->m_rtDirICDebug = this->rtDirICCheckBox->checkState() == Qt::Checked;
814    mainWin->m_rtFileTabICDebug = this->rtFileTabICCheckBox->checkState() == Qt::Checked;
815    mainWin->m_rtVerTabICDebug = this->rtVerTabICCheckBox->checkState() == Qt::Checked;
816    mainWin->m_rtUpdateFTDebug = this->rtUpdateFTCheckBox->checkState() == Qt::Checked;
817    mainWin->m_rtUpdateVTDebug = this->rtUpdateVTCheckBox->checkState() == Qt::Checked;
818    mainWin->m_rtChecksDebug = this->rtChecksCheckBox->checkState() == Qt::Checked;
819    mainWin->m_rtIconStateDebug = this->rtIconStateCheckBox->checkState() == Qt::Checked;
820    mainWin->m_rtRestore1Debug = this->rtRestore1CheckBox->checkState() == Qt::Checked;
821    mainWin->m_rtRestore2Debug = this->rtRestore2CheckBox->checkState() == Qt::Checked;
822    mainWin->m_rtRestore3Debug = this->rtRestore3CheckBox->checkState() == Qt::Checked;
823    if (this->radioConvertOff->isChecked()) {
824       ItemFormatterBase::setBytesConversion(ItemFormatterBase::BYTES_CONVERSION_NONE);
825    } else if (this->radioConvertIEC->isChecked()){
826       ItemFormatterBase::setBytesConversion(ItemFormatterBase::BYTES_CONVERSION_IEC);
827    } else {
828       ItemFormatterBase::setBytesConversion(ItemFormatterBase::BYTES_CONVERSION_SI);
829    }
830    mainWin->m_openPlot = this->openPlotCheckBox->checkState() == Qt::Checked;
831    mainWin->m_openBrowser = this->openBrowserCheckBox->checkState() == Qt::Checked;
832    mainWin->m_openDirStat = this->openDirStatCheckBox->checkState() == Qt::Checked;
833
834    QSettings settings("www.bacula.org", "bat");
835    settings.beginGroup("Debug");
836    settings.setValue("commDebug", mainWin->m_commDebug);
837    settings.setValue("connDebug", mainWin->m_connDebug);
838    settings.setValue("displayAll", mainWin->m_displayAll);
839    settings.setValue("sqlDebug", mainWin->m_sqlDebug);
840    settings.setValue("commandDebug", mainWin->m_commandDebug);
841    settings.setValue("miscDebug", mainWin->m_miscDebug);
842    settings.endGroup();
843    settings.beginGroup("JobList");
844    settings.setValue("recordLimitCheck", mainWin->m_recordLimitCheck);
845    settings.setValue("recordLimitVal", mainWin->m_recordLimitVal);
846    settings.setValue("daysLimitCheck", mainWin->m_daysLimitCheck);
847    settings.setValue("daysLimitVal", mainWin->m_daysLimitVal);
848    settings.endGroup();
849    settings.beginGroup("Timers");
850    settings.setValue("checkMessages", mainWin->m_checkMessages);
851    settings.setValue("checkMessagesInterval", mainWin->m_checkMessagesInterval);
852    settings.setValue("refreshStatusDir", mainWin->m_refreshStatusDir);
853    settings.setValue("refreshStatusDirInterval", mainWin->m_refreshStatusDirInterval);
854    settings.endGroup();
855    settings.beginGroup("Misc");
856    settings.setValue("longList", mainWin->m_longList);
857    settings.setValue("byteConvert", ItemFormatterBase::getBytesConversion());
858    settings.setValue("openplot", mainWin->m_openPlot);
859    settings.setValue("openbrowser", mainWin->m_openBrowser);
860    settings.setValue("opendirstat", mainWin->m_openDirStat);
861    settings.endGroup();
862    settings.beginGroup("RestoreTree");
863    settings.setValue("rtPopDirDebug", mainWin->m_rtPopDirDebug);
864    settings.setValue("rtDirCurICDebug", mainWin->m_rtDirCurICDebug);
865    settings.setValue("rtDirCurICRetDebug", mainWin->m_rtDirICDebug);
866    settings.setValue("rtFileTabICDebug", mainWin->m_rtFileTabICDebug);
867    settings.setValue("rtVerTabICDebug", mainWin->m_rtVerTabICDebug);
868    settings.setValue("rtUpdateFTDebug", mainWin->m_rtUpdateFTDebug);
869    settings.setValue("rtUpdateVTDebug", mainWin->m_rtUpdateVTDebug);
870    settings.setValue("rtChecksDebug", mainWin->m_rtChecksDebug);
871    settings.setValue("rtIconStateDebug", mainWin->m_rtIconStateDebug);
872    settings.setValue("rtRestore1Debug", mainWin->m_rtRestore1Debug);
873    settings.setValue("rtRestore2Debug", mainWin->m_rtRestore2Debug);
874    settings.setValue("rtRestore3Debug", mainWin->m_rtRestore3Debug);
875    settings.endGroup();
876 }
877
878 void prefsDialog::reject()
879 {
880    this->hide();
881    mainWin->set_status(tr("Canceled"));
882 }
883
884 /* read preferences for the prefences dialog box */
885 void MainWin::readPreferences()
886 {
887    QSettings settings("www.bacula.org", "bat");
888    settings.beginGroup("Debug");
889    m_commDebug = settings.value("commDebug", false).toBool();
890    m_connDebug = settings.value("connDebug", false).toBool();
891    m_displayAll = settings.value("displayAll", false).toBool();
892    m_sqlDebug = settings.value("sqlDebug", false).toBool();
893    m_commandDebug = settings.value("commandDebug", false).toBool();
894    m_miscDebug = settings.value("miscDebug", false).toBool();
895    settings.endGroup();
896    settings.beginGroup("JobList");
897    m_recordLimitCheck = settings.value("recordLimitCheck", true).toBool();
898    m_recordLimitVal = settings.value("recordLimitVal", 150).toInt();
899    m_daysLimitCheck = settings.value("daysLimitCheck", false).toBool();
900    m_daysLimitVal = settings.value("daysLimitVal", 28).toInt();
901    settings.endGroup();
902    settings.beginGroup("Timers");
903    m_checkMessages = settings.value("checkMessages", false).toBool();
904    m_checkMessagesInterval = settings.value("checkMessagesInterval", 28).toInt();
905    m_refreshStatusDir = settings.value("refreshStatusDir", false).toBool();
906    m_refreshStatusDirInterval = settings.value("refreshStatusDirInterval", 28).toInt();
907    settings.endGroup();
908    settings.beginGroup("Misc");
909    m_longList = settings.value("longList", false).toBool();
910    ItemFormatterBase::setBytesConversion(
911          (ItemFormatterBase::BYTES_CONVERSION) settings.value("byteConvert", 
912          ItemFormatterBase::BYTES_CONVERSION_IEC).toInt());
913    m_openPlot = settings.value("openplot", false).toBool();
914    m_openBrowser = settings.value("openbrowser", false).toBool();
915    m_openDirStat = settings.value("opendirstat", false).toBool();
916    settings.endGroup();
917    settings.beginGroup("RestoreTree");
918    m_rtPopDirDebug = settings.value("rtPopDirDebug", false).toBool();
919    m_rtDirCurICDebug = settings.value("rtDirCurICDebug", false).toBool();
920    m_rtDirICDebug = settings.value("rtDirCurICRetDebug", false).toBool();
921    m_rtFileTabICDebug = settings.value("rtFileTabICDebug", false).toBool();
922    m_rtVerTabICDebug = settings.value("rtVerTabICDebug", false).toBool();
923    m_rtUpdateFTDebug = settings.value("rtUpdateFTDebug", false).toBool();
924    m_rtUpdateVTDebug = settings.value("rtUpdateVTDebug", false).toBool();
925    m_rtChecksDebug = settings.value("rtChecksDebug", false).toBool();
926    m_rtIconStateDebug = settings.value("rtIconStateDebug", false).toBool();
927    m_rtRestore1Debug = settings.value("rtRestore1Debug", false).toBool();
928    m_rtRestore2Debug = settings.value("rtRestore2Debug", false).toBool();
929    m_rtRestore3Debug = settings.value("rtRestore3Debug", false).toBool();
930    settings.endGroup();
931 }
932
933 void MainWin::setMessageIcon()
934 {
935    if (m_currentConsole->is_messagesPending())
936       actionMessages->setIcon(QIcon(QString::fromUtf8(":/images/mail-message-pending.png")));
937    else
938       actionMessages->setIcon(QIcon(QString::fromUtf8(":/images/mail-message-new.png")));
939 }