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