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);
64 void MainWin::createPages()
67 QTreeWidgetItem *item;
69 /* Create console tree stacked widget item */
70 m_console = new Console(stackedWidget);
72 /* Console is special -> needs director*/
73 /* Just take the first Director */
75 dir = (DIRRES *)GetNextRes(R_DIRECTOR, NULL);
76 m_console->setDirRes(dir);
79 /* The top tree item representing the director */
80 m_topItem = createTopPage(dir->name());
81 m_topItem->setIcon(0, QIcon(QString::fromUtf8("images/server.png")));
83 /* Create Tree Widget Item */
84 item = createPage("Console", m_topItem);
85 m_console->setTreeItem(item);
87 /* insert the cosole and tree widget item into the hashes */
88 hashInsert(item, m_console);
90 /* Set Color of treeWidgetItem for the console
91 * It will be set to green in the console class if the connection is made.
93 QBrush redBrush(Qt::red);
94 item->setForeground(0, redBrush);
95 m_console->dockPage();
97 /* create instances of the rest of the classes that will by default exist
98 * under each director */
100 createPageMediaList();
101 QString emptymedia(""), emptyclient("");
102 createPageJobList(emptymedia, emptyclient);
105 treeWidget->expandItem(m_topItem);
106 stackedWidget->setCurrentWidget(m_console);
110 * create an instance of the the brestore class on the stack
112 void MainWin::createPagebRestore()
114 QTreeWidgetItem *item=createPage("brestore", m_topItem);
115 bRestore* brestore = new bRestore(stackedWidget);
116 hashInsert(item, brestore);
117 brestore->dockPage();
121 * create an instance of the the medialist class on the stack
123 void MainWin::createPageMediaList()
125 QTreeWidgetItem *item=createPage("Media", m_topItem);
126 MediaList* medialist = new MediaList(stackedWidget, m_console);
127 hashInsert(item, medialist);
128 medialist->dockPage();
132 * create an instance of the the joblist class on the stack
134 void MainWin::createPageJobList(QString &media, QString &client)
136 QTreeWidgetItem *item, *holdItem;
137 /* save current tree widget item in case query produces no results */
138 holdItem = treeWidget->currentItem();
139 if ((media == "") && (client == "")) {
140 item=createPage("All Jobs", m_topItem);
142 QString desc("Jobs ");
144 desc += "on Volume " + media;
147 desc += "of Client " + client;
149 item=createPage(desc.toUtf8().data(), m_topItem);
151 JobList* joblist = new JobList(stackedWidget, m_console, media, client);
152 hashInsert(item, joblist);
154 /* If this is a query of jobs on a specific media */
155 if ((media != "") || (client != "")) {
156 stackedWidget->setCurrentWidget(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 QTreeWidgetItem *item=createPage("Clients", m_topItem);
172 Clients* clients = new Clients(stackedWidget, m_console);
173 hashInsert(item, clients);
178 /* Create a root Tree Widget */
179 QTreeWidgetItem *MainWin::createTopPage(char *name)
181 QTreeWidgetItem *item = new QTreeWidgetItem(treeWidget);
182 item->setText(0, name);
186 /* Create A Tree Widget Item which will be associated with a Page in the stacked widget */
187 QTreeWidgetItem *MainWin::createPage(char *name, QTreeWidgetItem *parent)
189 QTreeWidgetItem *item = new QTreeWidgetItem(parent);
190 item->setText(0, name);
195 * Handle up and down arrow keys for the command line
198 void MainWin::keyPressEvent(QKeyEvent *event)
200 if (m_cmd_history.size() == 0) {
204 switch (event->key()) {
206 if (m_cmd_last < 0 || m_cmd_last >= (m_cmd_history.size()-1)) {
213 if (m_cmd_last == 0) {
217 if (m_cmd_last < 0 || m_cmd_last > (m_cmd_history.size()-1)) {
218 m_cmd_last = m_cmd_history.size() - 1;
227 lineEdit->setText(m_cmd_history[m_cmd_last]);
230 void MainWin::createConnections()
232 /* Connect signals to slots */
233 connect(lineEdit, SIGNAL(returnPressed()), this, SLOT(input_line()));
234 connect(actionAbout_bat, SIGNAL(triggered()), this, SLOT(about()));
237 connect(treeWidget, SIGNAL(itemActivated(QTreeWidgetItem *, int)), this,
238 SLOT(treeItemClicked(QTreeWidgetItem *, int)));
239 connect(treeWidget, SIGNAL(itemPressed(QTreeWidgetItem *, int)), this,
240 SLOT(treeItemClicked(QTreeWidgetItem *, int)));
242 connect(treeWidget, SIGNAL(itemClicked(QTreeWidgetItem *, int)), this,
243 SLOT(treeItemClicked(QTreeWidgetItem *, int)));
244 connect(treeWidget, SIGNAL(itemDoubleClicked(QTreeWidgetItem *, int)), this,
245 SLOT(treeItemDoubleClicked(QTreeWidgetItem *, int)));
246 connect(treeWidget, SIGNAL(
247 currentItemChanged(QTreeWidgetItem *, QTreeWidgetItem *)),
248 this, SLOT(treeItemChanged(QTreeWidgetItem *, QTreeWidgetItem *)));
249 connect(stackedWidget, SIGNAL(currentChanged(int)),
250 this, SLOT(stackItemChanged(int)));
252 connect(actionQuit, SIGNAL(triggered()), app, SLOT(closeAllWindows()));
253 connect(actionConnect, SIGNAL(triggered()), m_console, SLOT(connect()));
254 connect(actionStatusDir, SIGNAL(triggered()), m_console, SLOT(status_dir()));
255 connect(actionSelectFont, SIGNAL(triggered()), m_console, SLOT(set_font()));
256 connect(actionLabel, SIGNAL(triggered()), this, SLOT(labelDialogClicked()));
257 connect(actionRun, SIGNAL(triggered()), this, SLOT(runDialogClicked()));
258 connect(actionRestore, SIGNAL(triggered()), this, SLOT(restoreDialogClicked()));
259 connect(actionUndock, SIGNAL(triggered()), this, SLOT(undockWindowButton()));
260 connect(actionToggleDock, SIGNAL(triggered()), this, SLOT(toggleDockContextWindow()));
261 connect(actionClosePage, SIGNAL(triggered()), this, SLOT(closePage()));
265 * Reimplementation of QWidget closeEvent virtual function
267 void MainWin::closeEvent(QCloseEvent *event)
270 m_console->writeSettings();
271 m_console->terminate();
273 foreach(Pages *page, m_pagehash) {
274 if (!page->isDocked())
279 void MainWin::writeSettings()
281 QSettings settings("bacula.org", "bat");
283 settings.beginGroup("MainWin");
284 settings.setValue("winSize", size());
285 settings.setValue("winPos", pos());
289 void MainWin::readSettings()
291 QSettings settings("bacula.org", "bat");
293 settings.beginGroup("MainWin");
294 resize(settings.value("winSize", QSize(1041, 801)).toSize());
295 move(settings.value("winPos", QPoint(200, 150)).toPoint());
300 * This subroutine is called with an item in the Page Selection window
303 void MainWin::treeItemClicked(QTreeWidgetItem *item, int /*column*/)
305 /* Is this a page that has been inserted into the hash */
306 if (getFromHash(item)) {
307 Pages* page = getFromHash(item);
308 int stackindex=stackedWidget->indexOf(page);
310 if (stackindex >= 0) {
311 stackedWidget->setCurrentWidget(page);
313 /* run the virtual function in case this class overrides it */
314 page->PgSeltreeWidgetClicked();
319 * This subroutine is called with an item in the Page Selection window
322 /* This could be removed from here and from pages and from medialist
323 * Do you agree dhb */
324 void MainWin::treeItemDoubleClicked(QTreeWidgetItem *item, int /*column*/)
326 Pages* page = getFromHash(item);
327 page->PgSeltreeWidgetDoubleClicked();
331 * Called with a change of the highlighed tree widget item in the page selector.
333 void MainWin::treeItemChanged(QTreeWidgetItem *currentitem, QTreeWidgetItem *previousitem)
335 /* The Previous item */
338 /* make sure the close window and toggle dock options are removed */
339 treeWidget->removeAction(actionClosePage);
340 treeWidget->removeAction(actionToggleDock);
341 /* Is this a page that has been inserted into the hash */
342 if (getFromHash(previousitem)) {
343 Pages* page = getFromHash(previousitem);
344 foreach(QAction* pageaction, page->m_contextActions) {
345 treeWidget->removeAction(pageaction);
350 /* Is this a page that has been inserted into the hash */
351 if (getFromHash(currentitem)) {
352 Pages* page = getFromHash(currentitem);
353 int stackindex = stackedWidget->indexOf(page);
355 /* Is this page currently on the stack */
356 if (stackindex >= 0) {
357 /* put this page on the top of the stack */
358 stackedWidget->setCurrentIndex(stackindex);
360 /* it is undocked, raise it to the front */
363 setContextMenuDockText(page, currentitem);
365 treeWidget->addAction(actionToggleDock);
366 /* if this page is closeable, then add that action */
367 if (page->isCloseable()) {
368 treeWidget->addAction(actionClosePage);
371 /* Add the actions to the Page Selectors tree widget that are part of the
372 * current items list of desired actions regardless of whether on top of stack*/
373 treeWidget->addActions(page->m_contextActions);
377 void MainWin::labelDialogClicked()
379 new labelDialog(m_console);
382 void MainWin::runDialogClicked()
384 new runDialog(m_console);
387 void MainWin::restoreDialogClicked()
389 new prerestoreDialog(m_console);
395 * The user just finished typing a line in the command line edit box
397 void MainWin::input_line()
399 QString cmdStr = lineEdit->text(); /* Get the text */
400 lineEdit->clear(); /* clear the lineEdit box */
401 if (m_console->is_connected()) {
402 m_console->display_text(cmdStr + "\n");
403 m_console->write_dir(cmdStr.toUtf8().data()); /* send to dir */
405 set_status("Director not connected. Click on connect button.");
407 m_cmd_history.append(cmdStr);
412 void MainWin::about()
414 QMessageBox::about(this, tr("About bat"),
415 tr("<br><h2>bat 0.2, by Kern Sibbald</h2>"
416 "<p>Copyright © " BYEAR " Free Software Foundation Europe e.V."
417 "<p>The <b>bat</b> is an administrative console"
418 " interface to the Director."));
421 void MainWin::set_statusf(const char *fmt, ...)
426 va_start(arg_ptr, fmt);
427 len = bvsnprintf(buf, sizeof(buf), fmt, arg_ptr);
432 void MainWin::set_status_ready()
434 set_status(" Ready");
437 void MainWin::set_status(const char *buf)
439 statusBar()->showMessage(buf);
443 * Function to respond to the button bar button to undock
445 void MainWin::undockWindowButton()
447 Pages* page = (Pages*)stackedWidget->currentWidget();
448 page->togglePageDocking();
449 /* The window has been undocked, lets change the context menu */
450 setContextMenuDockText();
454 * Function to respond to action on page selector context menu to toggle the
455 * dock status of the window associated with the page selectors current
458 void MainWin::toggleDockContextWindow()
460 QTreeWidgetItem *currentitem = treeWidget->currentItem();
462 /* Is this a page that has been inserted into the hash */
463 if (getFromHash(currentitem)) {
464 Pages* page = getFromHash(currentitem);
465 page->togglePageDocking();
466 if (page->isDocked()) {
467 stackedWidget->setCurrentWidget(page);
469 /* Toggle the menu item. The window's dock status has been toggled */
470 setContextMenuDockText(page, currentitem);
475 * Function to set the text of the toggle dock context menu when page and
476 * widget item are NOT known. This is an overoaded funciton.
477 * It is called from MainWin::undockWindowButton, it is not intended to change
478 * for the top pages tree widget, it is for the currently active tree widget
479 * item. Which is why the page is not passed.
481 void MainWin::setContextMenuDockText()
483 QTreeWidgetItem *currentitem = treeWidget->currentItem();
485 /* Is this a page that has been inserted into the hash */
486 if (getFromHash(currentitem)) {
487 Pages* page = getFromHash(currentitem);
488 setContextMenuDockText(page, currentitem);
493 * Function to set the text of the toggle dock context menu when page and
494 * widget item are known. This is the more commonly used.
496 void MainWin::setContextMenuDockText(Pages* page, QTreeWidgetItem* item)
498 QString docktext("");
499 if (page->isDocked()) {
500 docktext += "UnDock ";
502 docktext += "ReDock ";
504 docktext += item->text(0) += " Window";
506 actionToggleDock->setText(docktext);
507 setTreeWidgetItemDockColor(page, item);
511 * Function to set the color of the tree widget item based on whether it is
514 void MainWin::setTreeWidgetItemDockColor(Pages* page, QTreeWidgetItem* item)
516 if (item->text(0) != "Console") {
517 if (page->isDocked()) {
518 /* Set the brush to blue if undocked */
519 QBrush blackBrush(Qt::black);
520 item->setForeground(0, blackBrush);
522 /* Set the brush back to black if docked */
523 QBrush blueBrush(Qt::blue);
524 item->setForeground(0, blueBrush);
530 * Overload of previous function, use treeindex to get item from page
531 * This is called when an undocked window is closed.
533 void MainWin::setTreeWidgetItemDockColor(Pages* page)
535 QTreeWidgetItem* item = getFromHash(page);
537 setTreeWidgetItemDockColor(page, item);
542 * This function is called when the stack item is changed. Call
543 * the virtual function here. Avoids a window being undocked leaving
544 * a window at the top of the stack unpopulated.
546 void MainWin::stackItemChanged(int)
548 Pages* page = (Pages*)stackedWidget->currentWidget();
549 /* run the virtual function in case this class overrides it */
550 page->currentStackItem();
554 * Function to simplify insertion of QTreeWidgetItem <-> Page association
555 * into a double direction hash.
557 void MainWin::hashInsert(QTreeWidgetItem *item, Pages *page)
559 m_pagehash.insert(item, page);
560 m_widgethash.insert(page, item);
564 * Function to simplify removal of QTreeWidgetItem <-> Page association
565 * into a double direction hash.
567 void MainWin::hashRemove(QTreeWidgetItem *item, Pages *page)
569 /* I had all sorts of return status checking code here. Do we have a log
570 * level capability in bat. I would have left it in but it used printf's
571 * and it should really be some kind of log level facility ???
572 * ******FIXME********/
573 m_pagehash.remove(item);
574 m_widgethash.remove(page);
578 * Function to retrieve a Page* when the item in the page selector's tree is
581 Pages* MainWin::getFromHash(QTreeWidgetItem *item)
583 return m_pagehash.value(item);
587 * Function to retrieve the page selectors tree widget item when the page is
590 QTreeWidgetItem* MainWin::getFromHash(Pages *page)
592 return m_widgethash.value(page);
596 * Function to respond to action on page selector context menu to close the
599 void MainWin::closePage()
601 QTreeWidgetItem *currentitem = treeWidget->currentItem();
603 /* Is this a page that has been inserted into the hash */
604 if (getFromHash(currentitem)) {
605 Pages* page = getFromHash(currentitem);
606 if (page->isCloseable()) {
607 page->closeStackPage();