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