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("");
102 createPageJobList(emptymedia);
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)
136 QTreeWidgetItem *item, *holdItem;
137 /* save current tree widget item in case query produces no results */
138 holdItem = treeWidget->currentItem();
140 item=createPage("All Jobs", m_topItem);
142 QString desc("Jobs on ");
144 item=createPage(desc.toUtf8().data(), m_topItem);
146 JobList* joblist = new JobList(stackedWidget, m_console, media);
147 hashInsert(item, joblist);
149 /* If this is a query of jobs on a specific media */
151 stackedWidget->setCurrentWidget(joblist);
152 treeWidget->setCurrentItem(item);
153 /* did query produce results, if not close window and set back to hold */
154 if (joblist->m_resultCount == 0) {
155 joblist->closeStackPage();
156 treeWidget->setCurrentItem(holdItem);
162 * create an instance of the the Clients class on the stack
164 void MainWin::createPageClients()
166 QTreeWidgetItem *item=createPage("Clients", m_topItem);
167 Clients* clients = new Clients(stackedWidget, m_console);
168 hashInsert(item, 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()));
232 connect(treeWidget, SIGNAL(itemActivated(QTreeWidgetItem *, int)), this,
233 SLOT(treeItemClicked(QTreeWidgetItem *, int)));
234 connect(treeWidget, SIGNAL(itemPressed(QTreeWidgetItem *, int)), this,
235 SLOT(treeItemClicked(QTreeWidgetItem *, int)));
237 connect(treeWidget, SIGNAL(itemClicked(QTreeWidgetItem *, int)), this,
238 SLOT(treeItemClicked(QTreeWidgetItem *, int)));
239 connect(treeWidget, SIGNAL(itemDoubleClicked(QTreeWidgetItem *, int)), this,
240 SLOT(treeItemDoubleClicked(QTreeWidgetItem *, int)));
241 connect(treeWidget, SIGNAL(
242 currentItemChanged(QTreeWidgetItem *, QTreeWidgetItem *)),
243 this, SLOT(treeItemChanged(QTreeWidgetItem *, QTreeWidgetItem *)));
244 connect(stackedWidget, SIGNAL(currentChanged(int)),
245 this, SLOT(stackItemChanged(int)));
247 connect(actionQuit, SIGNAL(triggered()), app, SLOT(closeAllWindows()));
248 connect(actionConnect, SIGNAL(triggered()), m_console, SLOT(connect()));
249 connect(actionStatusDir, SIGNAL(triggered()), m_console, SLOT(status_dir()));
250 connect(actionSelectFont, SIGNAL(triggered()), m_console, SLOT(set_font()));
251 connect(actionLabel, SIGNAL(triggered()), this, SLOT(labelDialogClicked()));
252 connect(actionRun, SIGNAL(triggered()), this, SLOT(runDialogClicked()));
253 connect(actionRestore, SIGNAL(triggered()), this, SLOT(restoreDialogClicked()));
254 connect(actionUndock, SIGNAL(triggered()), this, SLOT(undockWindowButton()));
255 connect(actionToggleDock, SIGNAL(triggered()), this, SLOT(toggleDockContextWindow()));
256 connect(actionClosePage, SIGNAL(triggered()), this, SLOT(closePage()));
260 * Reimplementation of QWidget closeEvent virtual function
262 void MainWin::closeEvent(QCloseEvent *event)
265 m_console->writeSettings();
266 m_console->terminate();
268 foreach(Pages *page, m_pagehash) {
269 if (!page->isDocked())
274 void MainWin::writeSettings()
276 QSettings settings("bacula.org", "bat");
278 settings.beginGroup("MainWin");
279 settings.setValue("winSize", size());
280 settings.setValue("winPos", pos());
284 void MainWin::readSettings()
286 QSettings settings("bacula.org", "bat");
288 settings.beginGroup("MainWin");
289 resize(settings.value("winSize", QSize(1041, 801)).toSize());
290 move(settings.value("winPos", QPoint(200, 150)).toPoint());
295 * This subroutine is called with an item in the Page Selection window
298 void MainWin::treeItemClicked(QTreeWidgetItem *item, int /*column*/)
300 /* Is this a page that has been inserted into the hash */
301 if (getFromHash(item)) {
302 Pages* page = getFromHash(item);
303 int stackindex=stackedWidget->indexOf(page);
305 if (stackindex >= 0) {
306 stackedWidget->setCurrentWidget(page);
308 /* run the virtual function in case this class overrides it */
309 page->PgSeltreeWidgetClicked();
314 * This subroutine is called with an item in the Page Selection window
317 /* This could be removed from here and from pages and from medialist
318 * Do you agree dhb */
319 void MainWin::treeItemDoubleClicked(QTreeWidgetItem *item, int /*column*/)
321 Pages* page = getFromHash(item);
322 page->PgSeltreeWidgetDoubleClicked();
326 * Called with a change of the highlighed tree widget item in the page selector.
328 void MainWin::treeItemChanged(QTreeWidgetItem *currentitem, QTreeWidgetItem *previousitem)
330 /* The Previous item */
333 /* make sure the close window and toggle dock options are removed */
334 treeWidget->removeAction(actionClosePage);
335 treeWidget->removeAction(actionToggleDock);
336 /* Is this a page that has been inserted into the hash */
337 if (getFromHash(previousitem)) {
338 Pages* page = getFromHash(previousitem);
339 foreach(QAction* pageaction, page->m_contextActions) {
340 treeWidget->removeAction(pageaction);
345 /* Is this a page that has been inserted into the hash */
346 if (getFromHash(currentitem)) {
347 Pages* page = getFromHash(currentitem);
348 int stackindex = stackedWidget->indexOf(page);
350 /* Is this page currently on the stack */
351 if (stackindex >= 0) {
352 /* put this page on the top of the stack */
353 stackedWidget->setCurrentIndex(stackindex);
355 /* it is undocked, raise it to the front */
358 setContextMenuDockText(page, currentitem);
360 treeWidget->addAction(actionToggleDock);
361 /* if this page is closeable, then add that action */
362 if (page->isCloseable()) {
363 treeWidget->addAction(actionClosePage);
366 /* Add the actions to the Page Selectors tree widget that are part of the
367 * current items list of desired actions regardless of whether on top of stack*/
368 treeWidget->addActions(page->m_contextActions);
372 void MainWin::labelDialogClicked()
374 new labelDialog(m_console);
377 void MainWin::runDialogClicked()
379 new runDialog(m_console);
382 void MainWin::restoreDialogClicked()
384 new prerestoreDialog(m_console);
390 * The user just finished typing a line in the command line edit box
392 void MainWin::input_line()
394 QString cmdStr = lineEdit->text(); /* Get the text */
395 lineEdit->clear(); /* clear the lineEdit box */
396 if (m_console->is_connected()) {
397 m_console->display_text(cmdStr + "\n");
398 m_console->write_dir(cmdStr.toUtf8().data()); /* send to dir */
400 set_status("Director not connected. Click on connect button.");
402 m_cmd_history.append(cmdStr);
407 void MainWin::about()
409 QMessageBox::about(this, tr("About bat"),
410 tr("<br><h2>bat 0.2, by Kern Sibbald</h2>"
411 "<p>Copyright © " BYEAR " Free Software Foundation Europe e.V."
412 "<p>The <b>bat</b> is an administrative console"
413 " interface to the Director."));
416 void MainWin::set_statusf(const char *fmt, ...)
421 va_start(arg_ptr, fmt);
422 len = bvsnprintf(buf, sizeof(buf), fmt, arg_ptr);
427 void MainWin::set_status_ready()
429 set_status(" Ready");
432 void MainWin::set_status(const char *buf)
434 statusBar()->showMessage(buf);
438 * Function to respond to the button bar button to undock
440 void MainWin::undockWindowButton()
442 Pages* page = (Pages*)stackedWidget->currentWidget();
443 page->togglePageDocking();
444 /* The window has been undocked, lets change the context menu */
445 setContextMenuDockText();
449 * Function to respond to action on page selector context menu to toggle the
450 * dock status of the window associated with the page selectors current
453 void MainWin::toggleDockContextWindow()
455 QTreeWidgetItem *currentitem = treeWidget->currentItem();
457 /* Is this a page that has been inserted into the hash */
458 if (getFromHash(currentitem)) {
459 Pages* page = getFromHash(currentitem);
460 page->togglePageDocking();
461 if (page->isDocked()) {
462 stackedWidget->setCurrentWidget(page);
464 /* Toggle the menu item. The window's dock status has been toggled */
465 setContextMenuDockText(page, currentitem);
470 * Function to set the text of the toggle dock context menu when page and
471 * widget item are NOT known. This is an overoaded funciton.
472 * It is called from MainWin::undockWindowButton, it is not intended to change
473 * for the top pages tree widget, it is for the currently active tree widget
474 * item. Which is why the page is not passed.
476 void MainWin::setContextMenuDockText()
478 QTreeWidgetItem *currentitem = treeWidget->currentItem();
480 /* Is this a page that has been inserted into the hash */
481 if (getFromHash(currentitem)) {
482 Pages* page = getFromHash(currentitem);
483 setContextMenuDockText(page, currentitem);
488 * Function to set the text of the toggle dock context menu when page and
489 * widget item are known. This is the more commonly used.
491 void MainWin::setContextMenuDockText(Pages* page, QTreeWidgetItem* item)
493 QString docktext("");
494 if (page->isDocked()) {
495 docktext += "UnDock ";
497 docktext += "ReDock ";
499 docktext += item->text(0) += " Window";
501 actionToggleDock->setText(docktext);
502 setTreeWidgetItemDockColor(page, item);
506 * Function to set the color of the tree widget item based on whether it is
509 void MainWin::setTreeWidgetItemDockColor(Pages* page, QTreeWidgetItem* item)
511 if (item->text(0) != "Console") {
512 if (page->isDocked()) {
513 /* Set the brush to blue if undocked */
514 QBrush blackBrush(Qt::black);
515 item->setForeground(0, blackBrush);
517 /* Set the brush back to black if docked */
518 QBrush blueBrush(Qt::blue);
519 item->setForeground(0, blueBrush);
525 * Overload of previous function, use treeindex to get item from page
526 * This is called when an undocked window is closed.
528 void MainWin::setTreeWidgetItemDockColor(Pages* page)
530 QTreeWidgetItem* item = getFromHash(page);
532 setTreeWidgetItemDockColor(page, item);
537 * This function is called when the stack item is changed. Call
538 * the virtual function here. Avoids a window being undocked leaving
539 * a window at the top of the stack unpopulated.
541 void MainWin::stackItemChanged(int)
543 Pages* page = (Pages*)stackedWidget->currentWidget();
544 /* run the virtual function in case this class overrides it */
545 page->currentStackItem();
549 * Function to simplify insertion of QTreeWidgetItem <-> Page association
550 * into a double direction hash.
552 void MainWin::hashInsert(QTreeWidgetItem *item, Pages *page)
554 m_pagehash.insert(item, page);
555 m_widgethash.insert(page, item);
559 * Function to simplify removal of QTreeWidgetItem <-> Page association
560 * into a double direction hash.
562 void MainWin::hashRemove(QTreeWidgetItem *item, Pages *page)
564 /* I had all sorts of return status checking code here. Do we have a log
565 * level capability in bat. I would have left it in but it used printf's
566 * and it should really be some kind of log level facility ???
567 * ******FIXME********/
568 m_pagehash.remove(item);
569 m_widgethash.remove(page);
573 * Function to retrieve a Page* when the item in the page selector's tree is
576 Pages* MainWin::getFromHash(QTreeWidgetItem *item)
578 return m_pagehash.value(item);
582 * Function to retrieve the page selectors tree widget item when the page is
585 QTreeWidgetItem* MainWin::getFromHash(Pages *page)
587 return m_widgethash.value(page);
591 * Function to respond to action on page selector context menu to close the
594 void MainWin::closePage()
596 QTreeWidgetItem *currentitem = treeWidget->currentItem();
598 /* Is this a page that has been inserted into the hash */
599 if (getFromHash(currentitem)) {
600 Pages* page = getFromHash(currentitem);
601 if (page->isCloseable()) {
602 page->closeStackPage();