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);
62 foreach(Console *console, m_consoleHash){
65 m_currentConsole = console;
66 treeWidget->setCurrentItem(getFromHash(console));
72 void MainWin::createPages()
75 QTreeWidgetItem *item, *topItem, *firstItem;
79 foreach_res(dir, R_DIRECTOR) {
81 /* Create console tree stacked widget item */
82 m_currentConsole = new Console(stackedWidget);
83 m_currentConsole->setDirRes(dir);
84 m_currentConsole->readSettings();
86 /* The top tree item representing the director */
87 topItem = createTopPage(dir->name());
88 topItem->setIcon(0, QIcon(QString::fromUtf8("images/server.png")));
89 m_currentConsole->setDirectorTreeItem(topItem);
90 m_consoleHash.insert(topItem, m_currentConsole);
92 /* Create Tree Widget Item */
93 item = createPage("Console", topItem);
98 /* insert the cosole and tree widget item into the hashes */
99 hashInsert(item, m_currentConsole);
101 /* Set Color of treeWidgetItem for the console
102 * It will be set to green in the console class if the connection is made.
104 QBrush redBrush(Qt::red);
105 item->setForeground(0, redBrush);
106 m_currentConsole->dockPage();
108 /* create instances of the rest of the classes that will by default exist
109 * under each director */
110 createPagebRestore();
111 createPageMediaList();
112 QString emptymedia(""), emptyclient("");
113 createPageJobList(emptymedia, emptyclient);
116 treeWidget->expandItem(topItem);
117 stackedWidget->setCurrentWidget(m_currentConsole);
123 * create an instance of the the brestore class on the stack
125 void MainWin::createPagebRestore()
127 bRestore* brestore = new bRestore();
128 brestore->dockPage();
132 * create an instance of the the medialist class on the stack
134 void MainWin::createPageMediaList()
136 MediaList* medialist = new MediaList();
137 medialist->dockPage();
141 * create an instance of the the joblist class on the stack
143 void MainWin::createPageJobList(QString &media, QString &client)
145 QTreeWidgetItem *item, *holdItem;
147 /* save current tree widget item in case query produces no results */
148 holdItem = treeWidget->currentItem();
149 JobList* joblist = new JobList(media, client);
151 /* If this is a query of jobs on a specific media */
152 if ((media != "") || (client != "")) {
153 item = getFromHash(joblist);
154 treeWidget->setCurrentItem(item);
155 /* did query produce results, if not close window and set back to hold */
156 if (joblist->m_resultCount == 0) {
157 joblist->closeStackPage();
158 treeWidget->setCurrentItem(holdItem);
164 * create an instance of the the Clients class on the stack
166 void MainWin::createPageClients()
168 Clients* clients = new Clients();
173 /* Create a root Tree Widget */
174 QTreeWidgetItem *MainWin::createTopPage(char *name)
176 QTreeWidgetItem *item = new QTreeWidgetItem(treeWidget);
177 item->setText(0, name);
181 /* Create A Tree Widget Item which will be associated with a Page in the stacked widget */
182 QTreeWidgetItem *MainWin::createPage(char *name, QTreeWidgetItem *parent)
184 QTreeWidgetItem *item = new QTreeWidgetItem(parent);
185 item->setText(0, name);
190 * Handle up and down arrow keys for the command line
193 void MainWin::keyPressEvent(QKeyEvent *event)
195 if (m_cmd_history.size() == 0) {
199 switch (event->key()) {
201 if (m_cmd_last < 0 || m_cmd_last >= (m_cmd_history.size()-1)) {
208 if (m_cmd_last == 0) {
212 if (m_cmd_last < 0 || m_cmd_last > (m_cmd_history.size()-1)) {
213 m_cmd_last = m_cmd_history.size() - 1;
222 lineEdit->setText(m_cmd_history[m_cmd_last]);
225 void MainWin::createConnections()
227 /* Connect signals to slots */
228 connect(lineEdit, SIGNAL(returnPressed()), this, SLOT(input_line()));
229 connect(actionAbout_bat, SIGNAL(triggered()), this, SLOT(about()));
230 connect(treeWidget, SIGNAL(itemClicked(QTreeWidgetItem *, int)), this,
231 SLOT(treeItemClicked(QTreeWidgetItem *, int)));
232 connect(treeWidget, SIGNAL(
233 currentItemChanged(QTreeWidgetItem *, QTreeWidgetItem *)),
234 this, SLOT(treeItemChanged(QTreeWidgetItem *, QTreeWidgetItem *)));
235 connect(stackedWidget, SIGNAL(currentChanged(int)),
236 this, SLOT(stackItemChanged(int)));
237 connect(actionQuit, SIGNAL(triggered()), app, SLOT(closeAllWindows()));
238 connect(actionLabel, SIGNAL(triggered()), this, SLOT(labelDialogClicked()));
239 connect(actionRun, SIGNAL(triggered()), this, SLOT(runDialogClicked()));
240 connect(actionRestore, SIGNAL(triggered()), this, SLOT(restoreDialogClicked()));
241 connect(actionUndock, SIGNAL(triggered()), this, SLOT(undockWindowButton()));
242 connect(actionToggleDock, SIGNAL(triggered()), this, SLOT(toggleDockContextWindow()));
243 connect(actionClosePage, SIGNAL(triggered()), this, SLOT(closePage()));
247 * Reimplementation of QWidget closeEvent virtual function
249 void MainWin::closeEvent(QCloseEvent *event)
252 foreach(Console *console, m_consoleHash){
253 console->writeSettings();
254 console->terminate();
257 foreach(Pages *page, m_pagehash) {
258 if (!page->isDocked())
263 void MainWin::writeSettings()
265 QSettings settings("bacula.org", "bat");
267 settings.beginGroup("MainWin");
268 settings.setValue("winSize", size());
269 settings.setValue("winPos", pos());
273 void MainWin::readSettings()
275 QSettings settings("bacula.org", "bat");
277 settings.beginGroup("MainWin");
278 resize(settings.value("winSize", QSize(1041, 801)).toSize());
279 move(settings.value("winPos", QPoint(200, 150)).toPoint());
284 * This subroutine is called with an item in the Page Selection window
287 void MainWin::treeItemClicked(QTreeWidgetItem *item, int /*column*/)
289 /* Is this a page that has been inserted into the hash */
290 if (getFromHash(item)) {
291 Pages* page = getFromHash(item);
292 int stackindex=stackedWidget->indexOf(page);
294 if (stackindex >= 0) {
295 stackedWidget->setCurrentWidget(page);
297 /* run the virtual function in case this class overrides it */
298 page->PgSeltreeWidgetClicked();
303 * Called with a change of the highlighed tree widget item in the page selector.
305 void MainWin::treeItemChanged(QTreeWidgetItem *currentitem, QTreeWidgetItem *previousitem)
309 /* The Previous item */
312 /* knowing the treeWidgetItem, get the page from the hash */
313 page = getFromHash(previousitem);
314 console = m_consoleHash.value(previousitem);
316 console = page->console();
317 } else if (console) {
320 /* make connections to the current console */
321 disconnect(actionConnect, SIGNAL(triggered()), console, SLOT(connect()));
322 disconnect(actionStatusDir, SIGNAL(triggered()), console, SLOT(status_dir()));
323 disconnect(actionSelectFont, SIGNAL(triggered()), console, SLOT(set_font()));
324 /* make sure the close window and toggle dock options are removed */
325 treeWidget->removeAction(actionClosePage);
326 treeWidget->removeAction(actionToggleDock);
327 /* Is this a page that has been inserted into the hash */
329 foreach(QAction* pageaction, page->m_contextActions) {
330 treeWidget->removeAction(pageaction);
335 /* knowing the treeWidgetItem, get the page from the hash */
336 page = getFromHash(currentitem);
337 console = m_consoleHash.value(currentitem);
338 /* Is this a page that has been inserted into the hash */
340 m_currentConsole = page->console();
341 } else if (console) {
342 m_currentConsole = console;
345 if ((page) || (console)) {
346 /* make connections to the current console */
347 connect(actionConnect, SIGNAL(triggered()), m_currentConsole, SLOT(connect()));
348 connect(actionSelectFont, SIGNAL(triggered()), m_currentConsole, SLOT(set_font()));
349 connect(actionStatusDir, SIGNAL(triggered()), m_currentConsole, SLOT(status_dir()));
350 /* set the value for the currently active console */
351 int stackindex = stackedWidget->indexOf(page);
353 /* Is this page currently on the stack */
354 if (stackindex >= 0) {
355 /* put this page on the top of the stack */
356 stackedWidget->setCurrentIndex(stackindex);
358 /* it is undocked, raise it to the front */
361 setContextMenuDockText(page, currentitem);
363 treeWidget->addAction(actionToggleDock);
364 /* if this page is closeable, then add that action */
365 if (page->isCloseable()) {
366 treeWidget->addAction(actionClosePage);
369 /* Add the actions to the Page Selectors tree widget that are part of the
370 * current items list of desired actions regardless of whether on top of stack*/
371 treeWidget->addActions(page->m_contextActions);
375 void MainWin::labelDialogClicked()
377 new labelDialog(m_currentConsole);
380 void MainWin::runDialogClicked()
382 new runDialog(m_currentConsole);
385 void MainWin::restoreDialogClicked()
387 new prerestoreDialog(m_currentConsole);
391 * The user just finished typing a line in the command line edit box
393 void MainWin::input_line()
395 QString cmdStr = lineEdit->text(); /* Get the text */
396 lineEdit->clear(); /* clear the lineEdit box */
397 if (m_currentConsole->is_connected()) {
398 m_currentConsole->display_text(cmdStr + "\n");
399 m_currentConsole->write_dir(cmdStr.toUtf8().data()); /* send to dir */
401 set_status("Director not connected. Click on connect button.");
403 m_cmd_history.append(cmdStr);
408 void MainWin::about()
410 QMessageBox::about(this, tr("About bat"),
411 tr("<br><h2>bat 0.2, by Kern Sibbald</h2>"
412 "<p>Copyright © " BYEAR " Free Software Foundation Europe e.V."
413 "<p>The <b>bat</b> is an administrative console"
414 " interface to the Director."));
417 void MainWin::set_statusf(const char *fmt, ...)
422 va_start(arg_ptr, fmt);
423 len = bvsnprintf(buf, sizeof(buf), fmt, arg_ptr);
428 void MainWin::set_status_ready()
430 set_status(" Ready");
433 void MainWin::set_status(const char *buf)
435 statusBar()->showMessage(buf);
439 * Function to respond to the button bar button to undock
441 void MainWin::undockWindowButton()
443 Pages* page = (Pages*)stackedWidget->currentWidget();
444 page->togglePageDocking();
445 /* The window has been undocked, lets change the context menu */
446 setContextMenuDockText();
450 * Function to respond to action on page selector context menu to toggle the
451 * dock status of the window associated with the page selectors current
454 void MainWin::toggleDockContextWindow()
456 QTreeWidgetItem *currentitem = treeWidget->currentItem();
458 /* Is this a page that has been inserted into the hash */
459 if (getFromHash(currentitem)) {
460 Pages* page = getFromHash(currentitem);
461 page->togglePageDocking();
462 if (page->isDocked()) {
463 stackedWidget->setCurrentWidget(page);
465 /* Toggle the menu item. The window's dock status has been toggled */
466 setContextMenuDockText(page, currentitem);
471 * Function to set the text of the toggle dock context menu when page and
472 * widget item are NOT known. This is an overoaded funciton.
473 * It is called from MainWin::undockWindowButton, it is not intended to change
474 * for the top pages tree widget, it is for the currently active tree widget
475 * item. Which is why the page is not passed.
477 void MainWin::setContextMenuDockText()
479 QTreeWidgetItem *currentitem = treeWidget->currentItem();
481 /* Is this a page that has been inserted into the hash */
482 if (getFromHash(currentitem)) {
483 Pages* page = getFromHash(currentitem);
484 setContextMenuDockText(page, currentitem);
489 * Function to set the text of the toggle dock context menu when page and
490 * widget item are known. This is the more commonly used.
492 void MainWin::setContextMenuDockText(Pages* page, QTreeWidgetItem* item)
494 QString docktext("");
495 if (page->isDocked()) {
496 docktext += "UnDock ";
498 docktext += "ReDock ";
500 docktext += item->text(0) += " Window";
502 actionToggleDock->setText(docktext);
503 setTreeWidgetItemDockColor(page, item);
507 * Function to set the color of the tree widget item based on whether it is
510 void MainWin::setTreeWidgetItemDockColor(Pages* page, QTreeWidgetItem* item)
512 if (item->text(0) != "Console") {
513 if (page->isDocked()) {
514 /* Set the brush to blue if undocked */
515 QBrush blackBrush(Qt::black);
516 item->setForeground(0, blackBrush);
518 /* Set the brush back to black if docked */
519 QBrush blueBrush(Qt::blue);
520 item->setForeground(0, blueBrush);
526 * Overload of previous function, use treeindex to get item from page
527 * This is called when an undocked window is closed.
529 void MainWin::setTreeWidgetItemDockColor(Pages* page)
531 QTreeWidgetItem* item = getFromHash(page);
533 setTreeWidgetItemDockColor(page, item);
538 * This function is called when the stack item is changed. Call
539 * the virtual function here. Avoids a window being undocked leaving
540 * a window at the top of the stack unpopulated.
542 void MainWin::stackItemChanged(int)
544 Pages* page = (Pages*)stackedWidget->currentWidget();
545 /* run the virtual function in case this class overrides it */
546 page->currentStackItem();
550 * Function to simplify insertion of QTreeWidgetItem <-> Page association
551 * into a double direction hash.
553 void MainWin::hashInsert(QTreeWidgetItem *item, Pages *page)
555 m_pagehash.insert(item, page);
556 m_widgethash.insert(page, item);
560 * Function to simplify removal of QTreeWidgetItem <-> Page association
561 * into a double direction hash.
563 void MainWin::hashRemove(QTreeWidgetItem *item, Pages *page)
565 /* I had all sorts of return status checking code here. Do we have a log
566 * level capability in bat. I would have left it in but it used printf's
567 * and it should really be some kind of log level facility ???
568 * ******FIXME********/
569 m_pagehash.remove(item);
570 m_widgethash.remove(page);
574 * Function to retrieve a Page* when the item in the page selector's tree is
577 Pages* MainWin::getFromHash(QTreeWidgetItem *item)
579 return m_pagehash.value(item);
583 * Function to retrieve the page selectors tree widget item when the page is
586 QTreeWidgetItem* MainWin::getFromHash(Pages *page)
588 return m_widgethash.value(page);
592 * Function to respond to action on page selector context menu to close the
595 void MainWin::closePage()
597 QTreeWidgetItem *currentitem = treeWidget->currentItem();
599 /* Is this a page that has been inserted into the hash */
600 if (getFromHash(currentitem)) {
601 Pages* page = getFromHash(currentitem);
602 if (page->isCloseable()) {
603 page->closeStackPage();