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"
43 MainWin::MainWin(QWidget *parent) : QMainWindow(parent)
47 setupUi(this); /* Setup UI defined by main.ui (designer) */
49 treeWidget->setColumnCount(1);
50 treeWidget->setHeaderLabel("Select Page");
51 treeWidget->setContextMenuPolicy(Qt::ActionsContextMenu);
63 foreach(Console *console, m_consoleHash){
66 m_currentConsole = (Console*)getFromHash(m_firstItem);
67 treeWidget->setCurrentItem(getFromHash(m_currentConsole));
69 * I'd like to turn this into a debug item
70 * DIRRES* dirres = m_currentConsole->getDirRes();
71 * printf("Setting initial window to %s\n", dirres->name());
75 void MainWin::createPages()
78 QTreeWidgetItem *item, *topItem;
82 foreach_res(dir, R_DIRECTOR) {
84 /* Create console tree stacked widget item */
85 m_currentConsole = new Console(stackedWidget);
86 m_currentConsole->setDirRes(dir);
87 m_currentConsole->readSettings();
89 /* The top tree item representing the director */
90 topItem = createTopPage(dir->name());
91 topItem->setIcon(0, QIcon(QString::fromUtf8("images/server.png")));
92 /* Set background to grey for ease of identification of inactive dirfector */
93 QBrush greyBrush(Qt::lightGray);
94 topItem->setBackground(0, greyBrush);
95 m_currentConsole->setDirectorTreeItem(topItem);
96 m_consoleHash.insert(topItem, m_currentConsole);
98 /* Create Tree Widget Item */
99 item = createPage("Console", topItem);
100 if (!m_firstItem){ m_firstItem = item; }
102 /* insert the cosole and tree widget item into the hashes */
103 hashInsert(item, m_currentConsole);
105 /* Set Color of treeWidgetItem for the console
106 * It will be set to green in the console class if the connection is made.
108 QBrush redBrush(Qt::red);
109 item->setForeground(0, redBrush);
110 m_currentConsole->dockPage();
112 /* create instances of the rest of the classes that will by default exist
113 * under each director */
114 createPagebRestore();
115 createPageMediaList();
116 QString emptymedia(""), emptyclient("");
117 createPageJobList(emptymedia, emptyclient, NULL);
122 treeWidget->expandItem(topItem);
123 stackedWidget->setCurrentWidget(m_currentConsole);
129 * create an instance of the the brestore class on the stack
131 void MainWin::createPagebRestore()
133 bRestore* brestore = new bRestore();
134 brestore->dockPage();
138 * create an instance of the the medialist class on the stack
140 void MainWin::createPageMediaList()
142 MediaList* medialist = new MediaList();
143 medialist->dockPage();
147 * create an instance of the the joblist class on the stack
149 void MainWin::createPageJobList(QString &media, QString &client,
150 QTreeWidgetItem *parentTreeWidgetItem)
152 QTreeWidgetItem *item, *holdItem;
154 /* save current tree widget item in case query produces no results */
155 holdItem = treeWidget->currentItem();
156 JobList* joblist = new JobList(media, client, parentTreeWidgetItem);
158 /* If this is a query of jobs on a specific media */
159 if ((media != "") || (client != "")) {
160 item = getFromHash(joblist);
161 treeWidget->setCurrentItem(item);
162 /* did query produce results, if not close window and set back to hold */
163 if (joblist->m_resultCount == 0) {
164 joblist->closeStackPage();
165 treeWidget->setCurrentItem(holdItem);
171 * create an instance of the the Clients class on the stack
173 void MainWin::createPageClients()
175 Clients* clients = new Clients();
180 * create an instance of the the storage class on the stack
182 void MainWin::createPageStorage()
184 Storage* storage = new Storage();
189 * create an instance of the the fileset class on the stack
191 void MainWin::createPageFileSet()
193 FileSet* fileset = new FileSet();
197 /* Create a root Tree Widget */
198 QTreeWidgetItem *MainWin::createTopPage(char *name)
200 QTreeWidgetItem *item = new QTreeWidgetItem(treeWidget);
201 item->setText(0, name);
205 /* Create A Tree Widget Item which will be associated with a Page in the stacked widget */
206 QTreeWidgetItem *MainWin::createPage(char *name, QTreeWidgetItem *parent)
208 QTreeWidgetItem *item = new QTreeWidgetItem(parent);
209 item->setText(0, name);
214 * Handle up and down arrow keys for the command line
217 void MainWin::keyPressEvent(QKeyEvent *event)
219 if (m_cmd_history.size() == 0) {
223 switch (event->key()) {
225 if (m_cmd_last < 0 || m_cmd_last >= (m_cmd_history.size()-1)) {
232 if (m_cmd_last == 0) {
236 if (m_cmd_last < 0 || m_cmd_last > (m_cmd_history.size()-1)) {
237 m_cmd_last = m_cmd_history.size() - 1;
246 lineEdit->setText(m_cmd_history[m_cmd_last]);
249 void MainWin::createConnections()
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(treeWidget, SIGNAL(itemClicked(QTreeWidgetItem *, int)), this,
255 SLOT(treeItemClicked(QTreeWidgetItem *, int)));
256 connect(treeWidget, SIGNAL(
257 currentItemChanged(QTreeWidgetItem *, QTreeWidgetItem *)),
258 this, SLOT(treeItemChanged(QTreeWidgetItem *, QTreeWidgetItem *)));
259 connect(stackedWidget, SIGNAL(currentChanged(int)),
260 this, SLOT(stackItemChanged(int)));
261 connect(actionQuit, SIGNAL(triggered()), app, SLOT(closeAllWindows()));
262 connect(actionLabel, SIGNAL(triggered()), this, SLOT(labelDialogClicked()));
263 connect(actionRun, SIGNAL(triggered()), this, SLOT(runDialogClicked()));
264 connect(actionRestore, SIGNAL(triggered()), this, SLOT(restoreDialogClicked()));
265 connect(actionUndock, SIGNAL(triggered()), this, SLOT(undockWindowButton()));
266 connect(actionToggleDock, SIGNAL(triggered()), this, SLOT(toggleDockContextWindow()));
267 connect(actionClosePage, SIGNAL(triggered()), this, SLOT(closePage()));
271 * Reimplementation of QWidget closeEvent virtual function
273 void MainWin::closeEvent(QCloseEvent *event)
276 foreach(Console *console, m_consoleHash){
277 console->writeSettings();
278 console->terminate();
281 foreach(Pages *page, m_pagehash) {
282 if (!page->isDocked())
287 void MainWin::writeSettings()
289 QSettings settings("bacula.org", "bat");
291 settings.beginGroup("MainWin");
292 settings.setValue("winSize", size());
293 settings.setValue("winPos", pos());
297 void MainWin::readSettings()
299 QSettings settings("bacula.org", "bat");
301 settings.beginGroup("MainWin");
302 resize(settings.value("winSize", QSize(1041, 801)).toSize());
303 move(settings.value("winPos", QPoint(200, 150)).toPoint());
308 * This subroutine is called with an item in the Page Selection window
311 void MainWin::treeItemClicked(QTreeWidgetItem *item, int /*column*/)
313 /* Is this a page that has been inserted into the hash */
314 if (getFromHash(item)) {
315 Pages* page = getFromHash(item);
316 int stackindex=stackedWidget->indexOf(page);
318 if (stackindex >= 0) {
319 stackedWidget->setCurrentWidget(page);
321 /* run the virtual function in case this class overrides it */
322 page->PgSeltreeWidgetClicked();
327 * Called with a change of the highlighed tree widget item in the page selector.
329 void MainWin::treeItemChanged(QTreeWidgetItem *currentitem, QTreeWidgetItem *previousitem)
331 Pages *previousPage, *nextPage;
332 Console *previousConsole, *nextConsole;
334 /* first determine the next item */
336 /* knowing the treeWidgetItem, get the page from the hash */
337 nextPage = getFromHash(currentitem);
338 nextConsole = m_consoleHash.value(currentitem);
339 /* Is this a page that has been inserted into the hash */
341 nextConsole = nextPage->console();
342 /* then is it a treeWidgetItem representing a director */
343 } else if (nextConsole) {
344 /* let the next page BE the console */
345 nextPage = nextConsole;
347 printf("Should never get here\n");
352 /* The Previous item */
354 /* this condition prevents a segfault. The first time there is no previousitem*/
356 /* knowing the treeWidgetItem, get the page from the hash */
357 previousPage = getFromHash(previousitem);
358 previousConsole = m_consoleHash.value(previousitem);
360 previousConsole = previousPage->console();
361 } else if (previousConsole) {
362 previousPage = previousConsole;
364 if ((previousPage) || (previousConsole)) {
365 if (nextConsole != previousConsole) {
366 /* remove connections to the current console */
367 disconnect(actionConnect, SIGNAL(triggered()), previousConsole, SLOT(connect()));
368 disconnect(actionStatusDir, SIGNAL(triggered()), previousConsole, SLOT(status_dir()));
369 disconnect(actionSelectFont, SIGNAL(triggered()), previousConsole, SLOT(set_font()));
370 QTreeWidgetItem *dirItem = previousConsole->directorTreeItem();
371 QBrush greyBrush(Qt::lightGray);
372 dirItem->setBackground(0, greyBrush);
374 /* make sure the close window and toggle dock options are removed */
375 treeWidget->removeAction(actionClosePage);
376 treeWidget->removeAction(actionToggleDock);
377 /* Is this a page that has been inserted into the hash */
379 foreach(QAction* pageaction, previousPage->m_contextActions) {
380 treeWidget->removeAction(pageaction);
386 /* now process the next item */
388 if ((nextPage) || (nextConsole)) {
389 if (nextConsole != previousConsole) {
390 /* make connections to the current console */
391 m_currentConsole = nextConsole;
392 connect(actionConnect, SIGNAL(triggered()), m_currentConsole, SLOT(connect()));
393 connect(actionSelectFont, SIGNAL(triggered()), m_currentConsole, SLOT(set_font()));
394 connect(actionStatusDir, SIGNAL(triggered()), m_currentConsole, SLOT(status_dir()));
395 /* Set director's tree widget background to magenta for ease of identification */
396 QTreeWidgetItem *dirItem = m_currentConsole->directorTreeItem();
397 QBrush magentaBrush(Qt::magenta);
398 dirItem->setBackground(0, magentaBrush);
400 /* set the value for the currently active console */
401 int stackindex = stackedWidget->indexOf(nextPage);
403 /* Is this page currently on the stack or is it undocked */
404 if (stackindex >= 0) {
405 /* put this page on the top of the stack */
406 stackedWidget->setCurrentIndex(stackindex);
408 /* it is undocked, raise it to the front */
411 /* for the page selectors menu action to dock or undock, set the text */
412 setContextMenuDockText(nextPage, currentitem);
414 treeWidget->addAction(actionToggleDock);
415 /* if this page is closeable, then add that action */
416 if (nextPage->isCloseable()) {
417 treeWidget->addAction(actionClosePage);
420 /* Add the actions to the Page Selectors tree widget that are part of the
421 * current items list of desired actions regardless of whether on top of stack*/
422 treeWidget->addActions(nextPage->m_contextActions);
426 void MainWin::labelDialogClicked()
428 new labelDialog(m_currentConsole);
431 void MainWin::runDialogClicked()
433 new runDialog(m_currentConsole);
436 void MainWin::restoreDialogClicked()
438 new prerestoreDialog(m_currentConsole);
442 * The user just finished typing a line in the command line edit box
444 void MainWin::input_line()
446 QString cmdStr = lineEdit->text(); /* Get the text */
447 lineEdit->clear(); /* clear the lineEdit box */
448 if (m_currentConsole->is_connected()) {
449 m_currentConsole->display_text(cmdStr + "\n");
450 m_currentConsole->write_dir(cmdStr.toUtf8().data()); /* send to dir */
452 set_status("Director not connected. Click on connect button.");
454 m_cmd_history.append(cmdStr);
459 void MainWin::about()
461 QMessageBox::about(this, tr("About bat"),
462 tr("<br><h2>bat 0.2, by Kern Sibbald</h2>"
463 "<p>Copyright © " BYEAR " Free Software Foundation Europe e.V."
464 "<p>The <b>bat</b> is an administrative console"
465 " interface to the Director."));
468 void MainWin::set_statusf(const char *fmt, ...)
473 va_start(arg_ptr, fmt);
474 len = bvsnprintf(buf, sizeof(buf), fmt, arg_ptr);
479 void MainWin::set_status_ready()
481 set_status(" Ready");
484 void MainWin::set_status(const char *buf)
486 statusBar()->showMessage(buf);
490 * Function to respond to the button bar button to undock
492 void MainWin::undockWindowButton()
494 Pages* page = (Pages*)stackedWidget->currentWidget();
495 page->togglePageDocking();
496 /* The window has been undocked, lets change the context menu */
497 setContextMenuDockText();
501 * Function to respond to action on page selector context menu to toggle the
502 * dock status of the window associated with the page selectors current
505 void MainWin::toggleDockContextWindow()
507 QTreeWidgetItem *currentitem = treeWidget->currentItem();
509 /* Is this a page that has been inserted into the hash */
510 if (getFromHash(currentitem)) {
511 Pages* page = getFromHash(currentitem);
512 page->togglePageDocking();
513 if (page->isDocked()) {
514 stackedWidget->setCurrentWidget(page);
516 /* Toggle the menu item. The window's dock status has been toggled */
517 setContextMenuDockText(page, currentitem);
522 * Function to set the text of the toggle dock context menu when page and
523 * widget item are NOT known. This is an overoaded funciton.
524 * It is called from MainWin::undockWindowButton, it is not intended to change
525 * for the top pages tree widget, it is for the currently active tree widget
526 * item. Which is why the page is not passed.
528 void MainWin::setContextMenuDockText()
530 QTreeWidgetItem *currentitem = treeWidget->currentItem();
532 /* Is this a page that has been inserted into the hash */
533 if (getFromHash(currentitem)) {
534 Pages* page = getFromHash(currentitem);
535 setContextMenuDockText(page, currentitem);
540 * Function to set the text of the toggle dock context menu when page and
541 * widget item are known. This is the more commonly used.
543 void MainWin::setContextMenuDockText(Pages* page, QTreeWidgetItem* item)
545 QString docktext("");
546 if (page->isDocked()) {
547 docktext += "UnDock ";
549 docktext += "ReDock ";
551 docktext += item->text(0) += " Window";
553 actionToggleDock->setText(docktext);
554 setTreeWidgetItemDockColor(page, item);
558 * Function to set the color of the tree widget item based on whether it is
561 void MainWin::setTreeWidgetItemDockColor(Pages* page, QTreeWidgetItem* item)
563 if (item->text(0) != "Console") {
564 if (page->isDocked()) {
565 /* Set the brush to blue if undocked */
566 QBrush blackBrush(Qt::black);
567 item->setForeground(0, blackBrush);
569 /* Set the brush back to black if docked */
570 QBrush blueBrush(Qt::blue);
571 item->setForeground(0, blueBrush);
577 * Overload of previous function, use treeindex to get item from page
578 * This is called when an undocked window is closed.
580 void MainWin::setTreeWidgetItemDockColor(Pages* page)
582 QTreeWidgetItem* item = getFromHash(page);
584 setTreeWidgetItemDockColor(page, item);
589 * This function is called when the stack item is changed. Call
590 * the virtual function here. Avoids a window being undocked leaving
591 * a window at the top of the stack unpopulated.
593 void MainWin::stackItemChanged(int)
595 Pages* page = (Pages*)stackedWidget->currentWidget();
596 /* run the virtual function in case this class overrides it */
597 page->currentStackItem();
601 * Function to simplify insertion of QTreeWidgetItem <-> Page association
602 * into a double direction hash.
604 void MainWin::hashInsert(QTreeWidgetItem *item, Pages *page)
606 m_pagehash.insert(item, page);
607 m_widgethash.insert(page, item);
611 * Function to simplify removal of QTreeWidgetItem <-> Page association
612 * into a double direction hash.
614 void MainWin::hashRemove(QTreeWidgetItem *item, Pages *page)
616 /* I had all sorts of return status checking code here. Do we have a log
617 * level capability in bat. I would have left it in but it used printf's
618 * and it should really be some kind of log level facility ???
619 * ******FIXME********/
620 m_pagehash.remove(item);
621 m_widgethash.remove(page);
625 * Function to retrieve a Page* when the item in the page selector's tree is
628 Pages* MainWin::getFromHash(QTreeWidgetItem *item)
630 return m_pagehash.value(item);
634 * Function to retrieve the page selectors tree widget item when the page is
637 QTreeWidgetItem* MainWin::getFromHash(Pages *page)
639 return m_widgethash.value(page);
643 * Function to respond to action on page selector context menu to close the
646 void MainWin::closePage()
648 QTreeWidgetItem *currentitem = treeWidget->currentItem();
650 /* Is this a page that has been inserted into the hash */
651 if (getFromHash(currentitem)) {
652 Pages* page = getFromHash(currentitem);
653 if (page->isCloseable()) {
654 page->closeStackPage();