2 Bacula® - The Network Backup Solution
4 Copyright (C) 2007-2007 Free Software Foundation Europe e.V.
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 plus additions
11 that are listed in the file LICENSE.
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.
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
23 Bacula® is a registered trademark of John Walker.
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.
32 * Main Window control for bat (qt-console)
34 * Kern Sibbald, January MMVII
39 #include "joblist/joblist.h"
40 #include "storage/storage.h"
41 #include "fileset/fileset.h"
42 #include "label/label.h"
45 #include "restore/restore.h"
46 #include "medialist/medialist.h"
47 #include "joblist/joblist.h"
48 #include "clients/clients.h"
50 extern bool commDebug;
52 MainWin::MainWin(QWidget *parent) : QMainWindow(parent)
56 setupUi(this); /* Setup UI defined by main.ui (designer) */
58 treeWidget->setColumnCount(1);
59 treeWidget->setHeaderLabel("Select Page");
60 treeWidget->setContextMenuPolicy(Qt::ActionsContextMenu);
72 foreach(Console *console, m_consoleHash){
75 m_currentConsole = (Console*)getFromHash(m_firstItem);
76 m_currentConsole->setCurrent();
78 * I'd like to turn this into a debug item
79 * DIRRES* dirres = m_currentConsole->getDirRes();
80 * printf("Setting initial window to %s\n", dirres->name());
84 void MainWin::createPages()
87 QTreeWidgetItem *item, *topItem;
91 foreach_res(dir, R_DIRECTOR) {
93 /* Create console tree stacked widget item */
94 m_currentConsole = new Console(stackedWidget);
95 m_currentConsole->setDirRes(dir);
96 m_currentConsole->readSettings();
98 /* The top tree item representing the director */
99 topItem = createTopPage(dir->name());
100 topItem->setIcon(0, QIcon(":images/server.png"));
101 /* Set background to grey for ease of identification of inactive dirfector */
102 QBrush greyBrush(Qt::lightGray);
103 topItem->setBackground(0, greyBrush);
104 m_currentConsole->setDirectorTreeItem(topItem);
105 m_consoleHash.insert(topItem, m_currentConsole);
107 /* Create Tree Widget Item */
108 item = createPage("Console", topItem);
109 if (!m_firstItem){ m_firstItem = item; }
111 /* insert the cosole and tree widget item into the hashes */
112 hashInsert(item, m_currentConsole);
114 /* Set Color of treeWidgetItem for the console
115 * It will be set to green in the console class if the connection is made.
117 QBrush redBrush(Qt::red);
118 item->setForeground(0, redBrush);
119 m_currentConsole->dockPage();
121 /* create instances of the rest of the classes that will by default exist
122 * under each director */
123 // createPagebRestore();
124 createPageMediaList();
125 QString emptymedia(""), emptyclient("");
126 createPageJobList(emptymedia, emptyclient, NULL);
131 treeWidget->expandItem(topItem);
132 stackedWidget->setCurrentWidget(m_currentConsole);
138 * create an instance of the the brestore class on the stack
140 void MainWin::createPagebRestore()
142 bRestore* brestore = new bRestore();
143 brestore->dockPage();
147 * create an instance of the the medialist class on the stack
149 void MainWin::createPageMediaList()
151 MediaList* medialist = new MediaList();
152 medialist->dockPage();
156 * create an instance of the the joblist class on the stack
158 void MainWin::createPageJobList(QString &media, QString &client,
159 QTreeWidgetItem *parentTreeWidgetItem)
161 QTreeWidgetItem *holdItem;
163 /* save current tree widget item in case query produces no results */
164 holdItem = treeWidget->currentItem();
165 JobList* joblist = new JobList(media, client, parentTreeWidgetItem);
167 /* If this is a query of jobs on a specific media */
168 if ((media != "") || (client != "")) {
169 joblist->setCurrent();
170 /* did query produce results, if not close window and set back to hold */
171 if (joblist->m_resultCount == 0) {
172 joblist->closeStackPage();
173 treeWidget->setCurrentItem(holdItem);
179 * create an instance of the the Clients class on the stack
181 void MainWin::createPageClients()
183 Clients* clients = new Clients();
188 * create an instance of the the storage class on the stack
190 void MainWin::createPageStorage()
192 Storage* storage = new Storage();
197 * create an instance of the the fileset class on the stack
199 void MainWin::createPageFileSet()
201 FileSet* fileset = new FileSet();
205 /* Create a root Tree Widget */
206 QTreeWidgetItem *MainWin::createTopPage(char *name)
208 QTreeWidgetItem *item = new QTreeWidgetItem(treeWidget);
209 item->setText(0, name);
213 /* Create A Tree Widget Item which will be associated with a Page in the stacked widget */
214 QTreeWidgetItem *MainWin::createPage(char *name, QTreeWidgetItem *parent)
216 QTreeWidgetItem *item = new QTreeWidgetItem(parent);
217 item->setText(0, name);
222 * Handle up and down arrow keys for the command line
225 void MainWin::keyPressEvent(QKeyEvent *event)
227 if (m_cmd_history.size() == 0) {
231 switch (event->key()) {
233 if (m_cmd_last < 0 || m_cmd_last >= (m_cmd_history.size()-1)) {
240 if (m_cmd_last == 0) {
244 if (m_cmd_last < 0 || m_cmd_last > (m_cmd_history.size()-1)) {
245 m_cmd_last = m_cmd_history.size() - 1;
254 lineEdit->setText(m_cmd_history[m_cmd_last]);
257 void MainWin::createConnections()
259 /* Connect signals to slots */
260 connect(lineEdit, SIGNAL(returnPressed()), this, SLOT(input_line()));
261 connect(actionAbout_bat, SIGNAL(triggered()), this, SLOT(about()));
262 connect(treeWidget, SIGNAL(itemClicked(QTreeWidgetItem *, int)), this,
263 SLOT(treeItemClicked(QTreeWidgetItem *, int)));
264 connect(treeWidget, SIGNAL(
265 currentItemChanged(QTreeWidgetItem *, QTreeWidgetItem *)),
266 this, SLOT(treeItemChanged(QTreeWidgetItem *, QTreeWidgetItem *)));
267 connect(stackedWidget, SIGNAL(currentChanged(int)),
268 this, SLOT(stackItemChanged(int)));
269 connect(actionQuit, SIGNAL(triggered()), app, SLOT(closeAllWindows()));
270 connect(actionLabel, SIGNAL(triggered()), this, SLOT(labelButtonClicked()));
271 connect(actionRun, SIGNAL(triggered()), this, SLOT(runButtonClicked()));
272 connect(actionRestore, SIGNAL(triggered()), this, SLOT(restoreButtonClicked()));
273 connect(actionUndock, SIGNAL(triggered()), this, SLOT(undockWindowButton()));
274 connect(actionToggleDock, SIGNAL(triggered()), this, SLOT(toggleDockContextWindow()));
275 connect(actionClosePage, SIGNAL(triggered()), this, SLOT(closePage()));
276 connect(actionPreferences, SIGNAL(triggered()), this, SLOT(setPreferences()));
280 * Reimplementation of QWidget closeEvent virtual function
282 void MainWin::closeEvent(QCloseEvent *event)
285 foreach(Console *console, m_consoleHash){
286 console->writeSettings();
287 console->terminate();
290 foreach(Pages *page, m_pagehash) {
291 if (!page->isDocked())
296 void MainWin::writeSettings()
298 QSettings settings("bacula.org", "bat");
300 settings.beginGroup("MainWin");
301 settings.setValue("winSize", size());
302 settings.setValue("winPos", pos());
306 void MainWin::readSettings()
308 QSettings settings("bacula.org", "bat");
310 settings.beginGroup("MainWin");
311 resize(settings.value("winSize", QSize(1041, 801)).toSize());
312 move(settings.value("winPos", QPoint(200, 150)).toPoint());
317 * This subroutine is called with an item in the Page Selection window
320 void MainWin::treeItemClicked(QTreeWidgetItem *item, int /*column*/)
322 /* Is this a page that has been inserted into the hash */
323 if (getFromHash(item)) {
324 Pages* page = getFromHash(item);
325 int stackindex=stackedWidget->indexOf(page);
327 if (stackindex >= 0) {
328 stackedWidget->setCurrentWidget(page);
330 /* run the virtual function in case this class overrides it */
331 page->PgSeltreeWidgetClicked();
336 * Called with a change of the highlighed tree widget item in the page selector.
338 void MainWin::treeItemChanged(QTreeWidgetItem *currentitem, QTreeWidgetItem *previousitem)
340 Pages *previousPage, *nextPage;
341 Console *previousConsole, *nextConsole;
343 /* first determine the next item */
345 /* knowing the treeWidgetItem, get the page from the hash */
346 nextPage = getFromHash(currentitem);
347 nextConsole = m_consoleHash.value(currentitem);
348 /* Is this a page that has been inserted into the hash */
350 nextConsole = nextPage->console();
351 /* then is it a treeWidgetItem representing a director */
352 } else if (nextConsole) {
353 /* let the next page BE the console */
354 nextPage = nextConsole;
356 /* Should never get here */
361 /* The Previous item */
363 /* this condition prevents a segfault. The first time there is no previousitem*/
365 /* knowing the treeWidgetItem, get the page from the hash */
366 previousPage = getFromHash(previousitem);
367 previousConsole = m_consoleHash.value(previousitem);
369 previousConsole = previousPage->console();
370 } else if (previousConsole) {
371 previousPage = previousConsole;
373 if ((previousPage) || (previousConsole)) {
374 if (nextConsole != previousConsole) {
375 /* remove connections to the current console */
376 disconnect(actionConnect, SIGNAL(triggered()), previousConsole, SLOT(connect()));
377 disconnect(actionStatusDir, SIGNAL(triggered()), previousConsole, SLOT(status_dir()));
378 disconnect(actionMessages, SIGNAL(triggered()), previousConsole, SLOT(messages()));
379 disconnect(actionSelectFont, SIGNAL(triggered()), previousConsole, SLOT(set_font()));
380 QTreeWidgetItem *dirItem = previousConsole->directorTreeItem();
381 QBrush greyBrush(Qt::lightGray);
382 dirItem->setBackground(0, greyBrush);
384 /* make sure the close window and toggle dock options are removed */
385 treeWidget->removeAction(actionClosePage);
386 treeWidget->removeAction(actionToggleDock);
387 /* Is this a page that has been inserted into the hash */
389 foreach(QAction* pageaction, previousPage->m_contextActions) {
390 treeWidget->removeAction(pageaction);
396 /* process the current (next) item */
398 if ((nextPage) || (nextConsole)) {
399 if (nextConsole != previousConsole) {
400 /* make connections to the current console */
401 m_currentConsole = nextConsole;
402 connect(actionConnect, SIGNAL(triggered()), m_currentConsole, SLOT(connect()));
403 connect(actionSelectFont, SIGNAL(triggered()), m_currentConsole, SLOT(set_font()));
404 connect(actionStatusDir, SIGNAL(triggered()), m_currentConsole, SLOT(status_dir()));
405 connect(actionMessages, SIGNAL(triggered()), m_currentConsole, SLOT(messages()));
406 /* Set director's tree widget background to magenta for ease of identification */
407 QTreeWidgetItem *dirItem = m_currentConsole->directorTreeItem();
408 QBrush magentaBrush(Qt::magenta);
409 dirItem->setBackground(0, magentaBrush);
411 /* set the value for the currently active console */
412 int stackindex = stackedWidget->indexOf(nextPage);
414 /* Is this page currently on the stack or is it undocked */
415 if (stackindex >= 0) {
416 /* put this page on the top of the stack */
417 stackedWidget->setCurrentIndex(stackindex);
419 /* it is undocked, raise it to the front */
422 /* for the page selectors menu action to dock or undock, set the text */
423 nextPage->setContextMenuDockText();
425 treeWidget->addAction(actionToggleDock);
426 /* if this page is closeable, then add that action */
427 if (nextPage->isCloseable()) {
428 treeWidget->addAction(actionClosePage);
431 /* Add the actions to the Page Selectors tree widget that are part of the
432 * current items list of desired actions regardless of whether on top of stack*/
433 treeWidget->addActions(nextPage->m_contextActions);
437 void MainWin::labelButtonClicked()
442 void MainWin::runButtonClicked()
447 void MainWin::restoreButtonClicked()
449 new prerestorePage();
453 * The user just finished typing a line in the command line edit box
455 void MainWin::input_line()
457 QString cmdStr = lineEdit->text(); /* Get the text */
458 lineEdit->clear(); /* clear the lineEdit box */
459 if (m_currentConsole->is_connected()) {
460 m_currentConsole->display_text(cmdStr + "\n");
461 m_currentConsole->write_dir(cmdStr.toUtf8().data()); /* send to dir */
463 set_status("Director not connected. Click on connect button.");
465 m_cmd_history.append(cmdStr);
467 if (treeWidget->currentItem() != getFromHash(m_currentConsole))
468 m_currentConsole->setCurrent();
472 void MainWin::about()
474 QMessageBox::about(this, tr("About bat"),
475 tr("<br><h2>bat 1.0, by Dirk H Bartley and Kern Sibbald</h2>"
476 "<p>Copyright © " BYEAR " Free Software Foundation Europe e.V."
477 "<p>The <b>bat</b> is an administrative console"
478 " interface to the Director."));
481 void MainWin::set_statusf(const char *fmt, ...)
486 va_start(arg_ptr, fmt);
487 len = bvsnprintf(buf, sizeof(buf), fmt, arg_ptr);
492 void MainWin::set_status_ready()
494 set_status(" Ready");
497 void MainWin::set_status(const char *buf)
499 statusBar()->showMessage(buf);
503 * Function to respond to the button bar button to undock
505 void MainWin::undockWindowButton()
507 Pages* page = (Pages*)stackedWidget->currentWidget();
508 page->togglePageDocking();
512 * Function to respond to action on page selector context menu to toggle the
513 * dock status of the window associated with the page selectors current
516 void MainWin::toggleDockContextWindow()
518 QTreeWidgetItem *currentitem = treeWidget->currentItem();
520 /* Is this a page that has been inserted into the hash */
521 if (getFromHash(currentitem)) {
522 Pages* page = getFromHash(currentitem);
523 page->togglePageDocking();
528 * This function is called when the stack item is changed. Call
529 * the virtual function here. Avoids a window being undocked leaving
530 * a window at the top of the stack unpopulated.
532 void MainWin::stackItemChanged(int)
534 Pages* page = (Pages*)stackedWidget->currentWidget();
535 /* run the virtual function in case this class overrides it */
536 page->currentStackItem();
540 * Function to simplify insertion of QTreeWidgetItem <-> Page association
541 * into a double direction hash.
543 void MainWin::hashInsert(QTreeWidgetItem *item, Pages *page)
545 m_pagehash.insert(item, page);
546 m_widgethash.insert(page, item);
550 * Function to simplify removal of QTreeWidgetItem <-> Page association
551 * into a double direction hash.
553 void MainWin::hashRemove(QTreeWidgetItem *item, Pages *page)
555 /* I had all sorts of return status checking code here. Do we have a log
556 * level capability in bat. I would have left it in but it used printf's
557 * and it should really be some kind of log level facility ???
558 * ******FIXME********/
559 m_pagehash.remove(item);
560 m_widgethash.remove(page);
564 * Function to retrieve a Page* when the item in the page selector's tree is
567 Pages* MainWin::getFromHash(QTreeWidgetItem *item)
569 return m_pagehash.value(item);
573 * Function to retrieve the page selectors tree widget item when the page is
576 QTreeWidgetItem* MainWin::getFromHash(Pages *page)
578 return m_widgethash.value(page);
582 * Function to respond to action on page selector context menu to close the
585 void MainWin::closePage()
587 QTreeWidgetItem *currentitem = treeWidget->currentItem();
589 /* Is this a page that has been inserted into the hash */
590 if (getFromHash(currentitem)) {
591 Pages* page = getFromHash(currentitem);
592 if (page->isCloseable()) {
593 page->closeStackPage();
598 /* Quick function to return the current console */
599 Console *MainWin::currentConsole()
601 return m_currentConsole;
603 /* Quick function to return the tree item for the director */
604 QTreeWidgetItem *MainWin::currentTopItem()
606 return m_currentConsole->directorTreeItem();
609 /* Preferences menu item clicked */
610 void MainWin::setPreferences()
613 prefs.checkBox->setCheckState(commDebug ? Qt::Checked : Qt::Unchecked);
617 /* Preferences dialog */
618 prefsDialog::prefsDialog()
623 void prefsDialog::accept()
626 commDebug = this->checkBox->checkState() == Qt::Checked;
629 void prefsDialog::reject()
632 mainWin->set_status("Canceled");