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