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"
41 MainWin::MainWin(QWidget *parent) : QMainWindow(parent)
45 setupUi(this); /* Setup UI defined by main.ui (designer) */
47 treeWidget->setColumnCount(1);
48 treeWidget->setHeaderLabel("Select Page");
49 treeWidget->setContextMenuPolicy(Qt::ActionsContextMenu);
61 foreach(Console *console, m_consoleHash){
64 m_currentConsole = (Console*)getFromHash(m_firstItem);
65 treeWidget->setCurrentItem(getFromHash(m_currentConsole));
67 * I'd like to turn this into a debug item
68 * DIRRES* dirres = m_currentConsole->getDirRes();
69 * printf("Setting initial window to %s\n", dirres->name());
73 void MainWin::createPages()
76 QTreeWidgetItem *item, *topItem;
80 foreach_res(dir, R_DIRECTOR) {
82 /* Create console tree stacked widget item */
83 m_currentConsole = new Console(stackedWidget);
84 m_currentConsole->setDirRes(dir);
85 m_currentConsole->readSettings();
87 /* The top tree item representing the director */
88 topItem = createTopPage(dir->name());
89 topItem->setIcon(0, QIcon(QString::fromUtf8("images/server.png")));
90 /* Set background to grey for ease of identification of inactive dirfector */
91 QBrush greyBrush(Qt::lightGray);
92 topItem->setBackground(0, greyBrush);
93 m_currentConsole->setDirectorTreeItem(topItem);
94 m_consoleHash.insert(topItem, m_currentConsole);
96 /* Create Tree Widget Item */
97 item = createPage("Console", topItem);
98 if (!m_firstItem){ m_firstItem = item; }
100 /* insert the cosole and tree widget item into the hashes */
101 hashInsert(item, m_currentConsole);
103 /* Set Color of treeWidgetItem for the console
104 * It will be set to green in the console class if the connection is made.
106 QBrush redBrush(Qt::red);
107 item->setForeground(0, redBrush);
108 m_currentConsole->dockPage();
110 /* create instances of the rest of the classes that will by default exist
111 * under each director */
112 createPagebRestore();
113 createPageMediaList();
114 QString emptymedia(""), emptyclient("");
115 createPageJobList(emptymedia, emptyclient, NULL);
118 treeWidget->expandItem(topItem);
119 stackedWidget->setCurrentWidget(m_currentConsole);
125 * create an instance of the the brestore class on the stack
127 void MainWin::createPagebRestore()
129 bRestore* brestore = new bRestore();
130 brestore->dockPage();
134 * create an instance of the the medialist class on the stack
136 void MainWin::createPageMediaList()
138 MediaList* medialist = new MediaList();
139 medialist->dockPage();
143 * create an instance of the the joblist class on the stack
145 void MainWin::createPageJobList(QString &media, QString &client,
146 QTreeWidgetItem *parentTreeWidgetItem)
148 QTreeWidgetItem *item, *holdItem;
150 /* save current tree widget item in case query produces no results */
151 holdItem = treeWidget->currentItem();
152 JobList* joblist = new JobList(media, client, parentTreeWidgetItem);
154 /* If this is a query of jobs on a specific media */
155 if ((media != "") || (client != "")) {
156 item = getFromHash(joblist);
157 treeWidget->setCurrentItem(item);
158 /* did query produce results, if not close window and set back to hold */
159 if (joblist->m_resultCount == 0) {
160 joblist->closeStackPage();
161 treeWidget->setCurrentItem(holdItem);
167 * create an instance of the the Clients class on the stack
169 void MainWin::createPageClients()
171 Clients* clients = new Clients();
176 /* Create a root Tree Widget */
177 QTreeWidgetItem *MainWin::createTopPage(char *name)
179 QTreeWidgetItem *item = new QTreeWidgetItem(treeWidget);
180 item->setText(0, name);
184 /* Create A Tree Widget Item which will be associated with a Page in the stacked widget */
185 QTreeWidgetItem *MainWin::createPage(char *name, QTreeWidgetItem *parent)
187 QTreeWidgetItem *item = new QTreeWidgetItem(parent);
188 item->setText(0, name);
193 * Handle up and down arrow keys for the command line
196 void MainWin::keyPressEvent(QKeyEvent *event)
198 if (m_cmd_history.size() == 0) {
202 switch (event->key()) {
204 if (m_cmd_last < 0 || m_cmd_last >= (m_cmd_history.size()-1)) {
211 if (m_cmd_last == 0) {
215 if (m_cmd_last < 0 || m_cmd_last > (m_cmd_history.size()-1)) {
216 m_cmd_last = m_cmd_history.size() - 1;
225 lineEdit->setText(m_cmd_history[m_cmd_last]);
228 void MainWin::createConnections()
230 /* Connect signals to slots */
231 connect(lineEdit, SIGNAL(returnPressed()), this, SLOT(input_line()));
232 connect(actionAbout_bat, SIGNAL(triggered()), this, SLOT(about()));
233 connect(treeWidget, SIGNAL(itemClicked(QTreeWidgetItem *, int)), this,
234 SLOT(treeItemClicked(QTreeWidgetItem *, int)));
235 connect(treeWidget, SIGNAL(
236 currentItemChanged(QTreeWidgetItem *, QTreeWidgetItem *)),
237 this, SLOT(treeItemChanged(QTreeWidgetItem *, QTreeWidgetItem *)));
238 connect(stackedWidget, SIGNAL(currentChanged(int)),
239 this, SLOT(stackItemChanged(int)));
240 connect(actionQuit, SIGNAL(triggered()), app, SLOT(closeAllWindows()));
241 connect(actionLabel, SIGNAL(triggered()), this, SLOT(labelDialogClicked()));
242 connect(actionRun, SIGNAL(triggered()), this, SLOT(runDialogClicked()));
243 connect(actionRestore, SIGNAL(triggered()), this, SLOT(restoreDialogClicked()));
244 connect(actionUndock, SIGNAL(triggered()), this, SLOT(undockWindowButton()));
245 connect(actionToggleDock, SIGNAL(triggered()), this, SLOT(toggleDockContextWindow()));
246 connect(actionClosePage, SIGNAL(triggered()), this, SLOT(closePage()));
250 * Reimplementation of QWidget closeEvent virtual function
252 void MainWin::closeEvent(QCloseEvent *event)
255 foreach(Console *console, m_consoleHash){
256 console->writeSettings();
257 console->terminate();
260 foreach(Pages *page, m_pagehash) {
261 if (!page->isDocked())
266 void MainWin::writeSettings()
268 QSettings settings("bacula.org", "bat");
270 settings.beginGroup("MainWin");
271 settings.setValue("winSize", size());
272 settings.setValue("winPos", pos());
276 void MainWin::readSettings()
278 QSettings settings("bacula.org", "bat");
280 settings.beginGroup("MainWin");
281 resize(settings.value("winSize", QSize(1041, 801)).toSize());
282 move(settings.value("winPos", QPoint(200, 150)).toPoint());
287 * This subroutine is called with an item in the Page Selection window
290 void MainWin::treeItemClicked(QTreeWidgetItem *item, int /*column*/)
292 /* Is this a page that has been inserted into the hash */
293 if (getFromHash(item)) {
294 Pages* page = getFromHash(item);
295 int stackindex=stackedWidget->indexOf(page);
297 if (stackindex >= 0) {
298 stackedWidget->setCurrentWidget(page);
300 /* run the virtual function in case this class overrides it */
301 page->PgSeltreeWidgetClicked();
306 * Called with a change of the highlighed tree widget item in the page selector.
308 void MainWin::treeItemChanged(QTreeWidgetItem *currentitem, QTreeWidgetItem *previousitem)
310 Pages *previousPage, *nextPage;
311 Console *previousConsole, *nextConsole;
313 /* first determine the next item */
315 /* knowing the treeWidgetItem, get the page from the hash */
316 nextPage = getFromHash(currentitem);
317 nextConsole = m_consoleHash.value(currentitem);
318 /* Is this a page that has been inserted into the hash */
320 nextConsole = nextPage->console();
321 /* then is it a treeWidgetItem representing a director */
322 } else if (nextConsole) {
323 /* let the next page BE the console */
324 nextPage = nextConsole;
326 printf("Should never get here\n");
331 /* The Previous item */
333 /* this condition prevents a segfault. The first time there is no previousitem*/
335 /* knowing the treeWidgetItem, get the page from the hash */
336 previousPage = getFromHash(previousitem);
337 previousConsole = m_consoleHash.value(previousitem);
339 previousConsole = previousPage->console();
340 } else if (previousConsole) {
341 previousPage = previousConsole;
343 if ((previousPage) || (previousConsole)) {
344 if (nextConsole != previousConsole) {
345 /* remove connections to the current console */
346 disconnect(actionConnect, SIGNAL(triggered()), previousConsole, SLOT(connect()));
347 disconnect(actionStatusDir, SIGNAL(triggered()), previousConsole, SLOT(status_dir()));
348 disconnect(actionSelectFont, SIGNAL(triggered()), previousConsole, SLOT(set_font()));
349 QTreeWidgetItem *dirItem = previousConsole->directorTreeItem();
350 QBrush greyBrush(Qt::lightGray);
351 dirItem->setBackground(0, greyBrush);
353 /* make sure the close window and toggle dock options are removed */
354 treeWidget->removeAction(actionClosePage);
355 treeWidget->removeAction(actionToggleDock);
356 /* Is this a page that has been inserted into the hash */
358 foreach(QAction* pageaction, previousPage->m_contextActions) {
359 treeWidget->removeAction(pageaction);
365 /* now process the next item */
367 if ((nextPage) || (nextConsole)) {
368 if (nextConsole != previousConsole) {
369 /* make connections to the current console */
370 m_currentConsole = nextConsole;
371 connect(actionConnect, SIGNAL(triggered()), m_currentConsole, SLOT(connect()));
372 connect(actionSelectFont, SIGNAL(triggered()), m_currentConsole, SLOT(set_font()));
373 connect(actionStatusDir, SIGNAL(triggered()), m_currentConsole, SLOT(status_dir()));
374 /* Set director's tree widget background to magenta for ease of identification */
375 QTreeWidgetItem *dirItem = m_currentConsole->directorTreeItem();
376 QBrush magentaBrush(Qt::magenta);
377 dirItem->setBackground(0, magentaBrush);
379 /* set the value for the currently active console */
380 int stackindex = stackedWidget->indexOf(nextPage);
382 /* Is this page currently on the stack or is it undocked */
383 if (stackindex >= 0) {
384 /* put this page on the top of the stack */
385 stackedWidget->setCurrentIndex(stackindex);
387 /* it is undocked, raise it to the front */
390 /* for the page selectors menu action to dock or undock, set the text */
391 setContextMenuDockText(nextPage, currentitem);
393 treeWidget->addAction(actionToggleDock);
394 /* if this page is closeable, then add that action */
395 if (nextPage->isCloseable()) {
396 treeWidget->addAction(actionClosePage);
399 /* Add the actions to the Page Selectors tree widget that are part of the
400 * current items list of desired actions regardless of whether on top of stack*/
401 treeWidget->addActions(nextPage->m_contextActions);
405 void MainWin::labelDialogClicked()
407 new labelDialog(m_currentConsole);
410 void MainWin::runDialogClicked()
412 new runDialog(m_currentConsole);
415 void MainWin::restoreDialogClicked()
417 new prerestoreDialog(m_currentConsole);
421 * The user just finished typing a line in the command line edit box
423 void MainWin::input_line()
425 QString cmdStr = lineEdit->text(); /* Get the text */
426 lineEdit->clear(); /* clear the lineEdit box */
427 if (m_currentConsole->is_connected()) {
428 m_currentConsole->display_text(cmdStr + "\n");
429 m_currentConsole->write_dir(cmdStr.toUtf8().data()); /* send to dir */
431 set_status("Director not connected. Click on connect button.");
433 m_cmd_history.append(cmdStr);
438 void MainWin::about()
440 QMessageBox::about(this, tr("About bat"),
441 tr("<br><h2>bat 0.2, by Kern Sibbald</h2>"
442 "<p>Copyright © " BYEAR " Free Software Foundation Europe e.V."
443 "<p>The <b>bat</b> is an administrative console"
444 " interface to the Director."));
447 void MainWin::set_statusf(const char *fmt, ...)
452 va_start(arg_ptr, fmt);
453 len = bvsnprintf(buf, sizeof(buf), fmt, arg_ptr);
458 void MainWin::set_status_ready()
460 set_status(" Ready");
463 void MainWin::set_status(const char *buf)
465 statusBar()->showMessage(buf);
469 * Function to respond to the button bar button to undock
471 void MainWin::undockWindowButton()
473 Pages* page = (Pages*)stackedWidget->currentWidget();
474 page->togglePageDocking();
475 /* The window has been undocked, lets change the context menu */
476 setContextMenuDockText();
480 * Function to respond to action on page selector context menu to toggle the
481 * dock status of the window associated with the page selectors current
484 void MainWin::toggleDockContextWindow()
486 QTreeWidgetItem *currentitem = treeWidget->currentItem();
488 /* Is this a page that has been inserted into the hash */
489 if (getFromHash(currentitem)) {
490 Pages* page = getFromHash(currentitem);
491 page->togglePageDocking();
492 if (page->isDocked()) {
493 stackedWidget->setCurrentWidget(page);
495 /* Toggle the menu item. The window's dock status has been toggled */
496 setContextMenuDockText(page, currentitem);
501 * Function to set the text of the toggle dock context menu when page and
502 * widget item are NOT known. This is an overoaded funciton.
503 * It is called from MainWin::undockWindowButton, it is not intended to change
504 * for the top pages tree widget, it is for the currently active tree widget
505 * item. Which is why the page is not passed.
507 void MainWin::setContextMenuDockText()
509 QTreeWidgetItem *currentitem = treeWidget->currentItem();
511 /* Is this a page that has been inserted into the hash */
512 if (getFromHash(currentitem)) {
513 Pages* page = getFromHash(currentitem);
514 setContextMenuDockText(page, currentitem);
519 * Function to set the text of the toggle dock context menu when page and
520 * widget item are known. This is the more commonly used.
522 void MainWin::setContextMenuDockText(Pages* page, QTreeWidgetItem* item)
524 QString docktext("");
525 if (page->isDocked()) {
526 docktext += "UnDock ";
528 docktext += "ReDock ";
530 docktext += item->text(0) += " Window";
532 actionToggleDock->setText(docktext);
533 setTreeWidgetItemDockColor(page, item);
537 * Function to set the color of the tree widget item based on whether it is
540 void MainWin::setTreeWidgetItemDockColor(Pages* page, QTreeWidgetItem* item)
542 if (item->text(0) != "Console") {
543 if (page->isDocked()) {
544 /* Set the brush to blue if undocked */
545 QBrush blackBrush(Qt::black);
546 item->setForeground(0, blackBrush);
548 /* Set the brush back to black if docked */
549 QBrush blueBrush(Qt::blue);
550 item->setForeground(0, blueBrush);
556 * Overload of previous function, use treeindex to get item from page
557 * This is called when an undocked window is closed.
559 void MainWin::setTreeWidgetItemDockColor(Pages* page)
561 QTreeWidgetItem* item = getFromHash(page);
563 setTreeWidgetItemDockColor(page, item);
568 * This function is called when the stack item is changed. Call
569 * the virtual function here. Avoids a window being undocked leaving
570 * a window at the top of the stack unpopulated.
572 void MainWin::stackItemChanged(int)
574 Pages* page = (Pages*)stackedWidget->currentWidget();
575 /* run the virtual function in case this class overrides it */
576 page->currentStackItem();
580 * Function to simplify insertion of QTreeWidgetItem <-> Page association
581 * into a double direction hash.
583 void MainWin::hashInsert(QTreeWidgetItem *item, Pages *page)
585 m_pagehash.insert(item, page);
586 m_widgethash.insert(page, item);
590 * Function to simplify removal of QTreeWidgetItem <-> Page association
591 * into a double direction hash.
593 void MainWin::hashRemove(QTreeWidgetItem *item, Pages *page)
595 /* I had all sorts of return status checking code here. Do we have a log
596 * level capability in bat. I would have left it in but it used printf's
597 * and it should really be some kind of log level facility ???
598 * ******FIXME********/
599 m_pagehash.remove(item);
600 m_widgethash.remove(page);
604 * Function to retrieve a Page* when the item in the page selector's tree is
607 Pages* MainWin::getFromHash(QTreeWidgetItem *item)
609 return m_pagehash.value(item);
613 * Function to retrieve the page selectors tree widget item when the page is
616 QTreeWidgetItem* MainWin::getFromHash(Pages *page)
618 return m_widgethash.value(page);
622 * Function to respond to action on page selector context menu to close the
625 void MainWin::closePage()
627 QTreeWidgetItem *currentitem = treeWidget->currentItem();
629 /* Is this a page that has been inserted into the hash */
630 if (getFromHash(currentitem)) {
631 Pages* page = getFromHash(currentitem);
632 if (page->isCloseable()) {
633 page->closeStackPage();