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, *topItem;
71 foreach_res(dir, R_DIRECTOR) {
73 /* Create console tree stacked widget item */
74 console = new Console(stackedWidget);
75 console->setDirRes(dir);
77 /* The top tree item representing the director */
78 topItem = createTopPage(dir->name());
79 topItem->setIcon(0, QIcon(QString::fromUtf8("images/server.png")));
81 /* Create Tree Widget Item */
82 item = createPage("Console", topItem);
83 console->setTreeItem(item);
85 /* insert the cosole and tree widget item into the hashes */
86 hashInsert(item, console);
88 /* Set Color of treeWidgetItem for the console
89 * It will be set to green in the console class if the connection is made.
91 QBrush redBrush(Qt::red);
92 item->setForeground(0, redBrush);
95 /* create instances of the rest of the classes that will by default exist
96 * under each director */
97 createPagebRestore(topItem, console);
98 createPageMediaList(topItem, console);
99 QString emptymedia(""), emptyclient("");
100 createPageJobList(emptymedia, emptyclient, topItem, console);
101 createPageClients(topItem, console);
103 treeWidget->expandItem(topItem);
104 stackedWidget->setCurrentWidget(console);
107 * Set the first console as current console
109 * ***FIXME**** note, to make this work correctly, we need a
110 * list of consoles, so that we can save/restore the settings
111 * for all consoles, and we need to figure out some way to
112 * set the current console and the current topItem (actually Director)
113 * when a page within a given console is clicked. We also need
114 * to redo the connections (signals/slots) that use m_console.
125 * create an instance of the the brestore class on the stack
127 void MainWin::createPagebRestore(QTreeWidgetItem *parent, Console * /*console*/)
129 QTreeWidgetItem *item=createPage("brestore", parent);
130 bRestore* brestore = new bRestore(stackedWidget);
131 hashInsert(item, brestore);
132 brestore->dockPage();
136 * create an instance of the the medialist class on the stack
138 void MainWin::createPageMediaList(QTreeWidgetItem *parent, Console *console)
140 QTreeWidgetItem *item=createPage("Media", parent);
141 MediaList* medialist = new MediaList(stackedWidget, console);
142 hashInsert(item, 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 *parent, Console *console)
152 QTreeWidgetItem *item, *holdItem;
153 /* save current tree widget item in case query produces no results */
154 holdItem = treeWidget->currentItem();
155 if ((media == "") && (client == "")) {
156 item = createPage("All Jobs", parent);
158 QString desc("Jobs ");
160 desc += "on Volume " + media;
163 desc += "of Client " + client;
165 item = createPage(desc.toUtf8().data(), parent);
167 JobList* joblist = new JobList(stackedWidget, console, media, client);
168 hashInsert(item, joblist);
170 /* If this is a query of jobs on a specific media */
171 if ((media != "") || (client != "")) {
172 stackedWidget->setCurrentWidget(joblist);
173 treeWidget->setCurrentItem(item);
174 /* did query produce results, if not close window and set back to hold */
175 if (joblist->m_resultCount == 0) {
176 joblist->closeStackPage();
177 treeWidget->setCurrentItem(holdItem);
183 * create an instance of the the Clients class on the stack
185 void MainWin::createPageClients(QTreeWidgetItem *parent, Console *console)
187 QTreeWidgetItem *item=createPage("Clients", parent);
188 Clients* clients = new Clients(stackedWidget, console);
189 hashInsert(item, clients);
194 /* Create a root Tree Widget */
195 QTreeWidgetItem *MainWin::createTopPage(char *name)
197 QTreeWidgetItem *item = new QTreeWidgetItem(treeWidget);
198 item->setText(0, name);
202 /* Create A Tree Widget Item which will be associated with a Page in the stacked widget */
203 QTreeWidgetItem *MainWin::createPage(char *name, QTreeWidgetItem *parent)
205 QTreeWidgetItem *item = new QTreeWidgetItem(parent);
206 item->setText(0, name);
211 * Handle up and down arrow keys for the command line
214 void MainWin::keyPressEvent(QKeyEvent *event)
216 if (m_cmd_history.size() == 0) {
220 switch (event->key()) {
222 if (m_cmd_last < 0 || m_cmd_last >= (m_cmd_history.size()-1)) {
229 if (m_cmd_last == 0) {
233 if (m_cmd_last < 0 || m_cmd_last > (m_cmd_history.size()-1)) {
234 m_cmd_last = m_cmd_history.size() - 1;
243 lineEdit->setText(m_cmd_history[m_cmd_last]);
246 void MainWin::createConnections()
248 /* Connect signals to slots */
249 connect(lineEdit, SIGNAL(returnPressed()), this, SLOT(input_line()));
250 connect(actionAbout_bat, SIGNAL(triggered()), this, SLOT(about()));
253 connect(treeWidget, SIGNAL(itemActivated(QTreeWidgetItem *, int)), this,
254 SLOT(treeItemClicked(QTreeWidgetItem *, int)));
255 connect(treeWidget, SIGNAL(itemPressed(QTreeWidgetItem *, int)), this,
256 SLOT(treeItemClicked(QTreeWidgetItem *, int)));
258 connect(treeWidget, SIGNAL(itemClicked(QTreeWidgetItem *, int)), this,
259 SLOT(treeItemClicked(QTreeWidgetItem *, int)));
260 connect(treeWidget, SIGNAL(itemDoubleClicked(QTreeWidgetItem *, int)), this,
261 SLOT(treeItemDoubleClicked(QTreeWidgetItem *, int)));
262 connect(treeWidget, SIGNAL(
263 currentItemChanged(QTreeWidgetItem *, QTreeWidgetItem *)),
264 this, SLOT(treeItemChanged(QTreeWidgetItem *, QTreeWidgetItem *)));
265 connect(stackedWidget, SIGNAL(currentChanged(int)),
266 this, SLOT(stackItemChanged(int)));
268 connect(actionQuit, SIGNAL(triggered()), app, SLOT(closeAllWindows()));
269 connect(actionConnect, SIGNAL(triggered()), m_console, SLOT(connect()));
270 connect(actionStatusDir, SIGNAL(triggered()), m_console, SLOT(status_dir()));
271 connect(actionSelectFont, SIGNAL(triggered()), m_console, SLOT(set_font()));
272 connect(actionLabel, SIGNAL(triggered()), this, SLOT(labelDialogClicked()));
273 connect(actionRun, SIGNAL(triggered()), this, SLOT(runDialogClicked()));
274 connect(actionRestore, SIGNAL(triggered()), this, SLOT(restoreDialogClicked()));
275 connect(actionUndock, SIGNAL(triggered()), this, SLOT(undockWindowButton()));
276 connect(actionToggleDock, SIGNAL(triggered()), this, SLOT(toggleDockContextWindow()));
277 connect(actionClosePage, SIGNAL(triggered()), this, SLOT(closePage()));
281 * Reimplementation of QWidget closeEvent virtual function
283 void MainWin::closeEvent(QCloseEvent *event)
286 m_console->writeSettings();
287 m_console->terminate();
289 foreach(Pages *page, m_pagehash) {
290 if (!page->isDocked())
295 void MainWin::writeSettings()
297 QSettings settings("bacula.org", "bat");
299 settings.beginGroup("MainWin");
300 settings.setValue("winSize", size());
301 settings.setValue("winPos", pos());
305 void MainWin::readSettings()
307 QSettings settings("bacula.org", "bat");
309 settings.beginGroup("MainWin");
310 resize(settings.value("winSize", QSize(1041, 801)).toSize());
311 move(settings.value("winPos", QPoint(200, 150)).toPoint());
316 * This subroutine is called with an item in the Page Selection window
319 void MainWin::treeItemClicked(QTreeWidgetItem *item, int /*column*/)
321 /* Is this a page that has been inserted into the hash */
322 if (getFromHash(item)) {
323 Pages* page = getFromHash(item);
324 int stackindex=stackedWidget->indexOf(page);
326 if (stackindex >= 0) {
327 stackedWidget->setCurrentWidget(page);
329 /* run the virtual function in case this class overrides it */
330 page->PgSeltreeWidgetClicked();
335 * This subroutine is called with an item in the Page Selection window
338 /* This could be removed from here and from pages and from medialist
339 * Do you agree dhb */
340 void MainWin::treeItemDoubleClicked(QTreeWidgetItem *item, int /*column*/)
342 Pages* page = getFromHash(item);
343 page->PgSeltreeWidgetDoubleClicked();
347 * Called with a change of the highlighed tree widget item in the page selector.
349 void MainWin::treeItemChanged(QTreeWidgetItem *currentitem, QTreeWidgetItem *previousitem)
351 /* The Previous item */
354 /* make sure the close window and toggle dock options are removed */
355 treeWidget->removeAction(actionClosePage);
356 treeWidget->removeAction(actionToggleDock);
357 /* Is this a page that has been inserted into the hash */
358 if (getFromHash(previousitem)) {
359 Pages* page = getFromHash(previousitem);
360 foreach(QAction* pageaction, page->m_contextActions) {
361 treeWidget->removeAction(pageaction);
366 /* Is this a page that has been inserted into the hash */
367 if (getFromHash(currentitem)) {
368 Pages* page = getFromHash(currentitem);
369 int stackindex = stackedWidget->indexOf(page);
371 /* Is this page currently on the stack */
372 if (stackindex >= 0) {
373 /* put this page on the top of the stack */
374 stackedWidget->setCurrentIndex(stackindex);
376 /* it is undocked, raise it to the front */
379 setContextMenuDockText(page, currentitem);
381 treeWidget->addAction(actionToggleDock);
382 /* if this page is closeable, then add that action */
383 if (page->isCloseable()) {
384 treeWidget->addAction(actionClosePage);
387 /* Add the actions to the Page Selectors tree widget that are part of the
388 * current items list of desired actions regardless of whether on top of stack*/
389 treeWidget->addActions(page->m_contextActions);
393 void MainWin::labelDialogClicked()
395 new labelDialog(m_console);
398 void MainWin::runDialogClicked()
400 new runDialog(m_console);
403 void MainWin::restoreDialogClicked()
405 new prerestoreDialog(m_console);
411 * The user just finished typing a line in the command line edit box
413 void MainWin::input_line()
415 QString cmdStr = lineEdit->text(); /* Get the text */
416 lineEdit->clear(); /* clear the lineEdit box */
417 if (m_console->is_connected()) {
418 m_console->display_text(cmdStr + "\n");
419 m_console->write_dir(cmdStr.toUtf8().data()); /* send to dir */
421 set_status("Director not connected. Click on connect button.");
423 m_cmd_history.append(cmdStr);
428 void MainWin::about()
430 QMessageBox::about(this, tr("About bat"),
431 tr("<br><h2>bat 0.2, by Kern Sibbald</h2>"
432 "<p>Copyright © " BYEAR " Free Software Foundation Europe e.V."
433 "<p>The <b>bat</b> is an administrative console"
434 " interface to the Director."));
437 void MainWin::set_statusf(const char *fmt, ...)
442 va_start(arg_ptr, fmt);
443 len = bvsnprintf(buf, sizeof(buf), fmt, arg_ptr);
448 void MainWin::set_status_ready()
450 set_status(" Ready");
453 void MainWin::set_status(const char *buf)
455 statusBar()->showMessage(buf);
459 * Function to respond to the button bar button to undock
461 void MainWin::undockWindowButton()
463 Pages* page = (Pages*)stackedWidget->currentWidget();
464 page->togglePageDocking();
465 /* The window has been undocked, lets change the context menu */
466 setContextMenuDockText();
470 * Function to respond to action on page selector context menu to toggle the
471 * dock status of the window associated with the page selectors current
474 void MainWin::toggleDockContextWindow()
476 QTreeWidgetItem *currentitem = treeWidget->currentItem();
478 /* Is this a page that has been inserted into the hash */
479 if (getFromHash(currentitem)) {
480 Pages* page = getFromHash(currentitem);
481 page->togglePageDocking();
482 if (page->isDocked()) {
483 stackedWidget->setCurrentWidget(page);
485 /* Toggle the menu item. The window's dock status has been toggled */
486 setContextMenuDockText(page, currentitem);
491 * Function to set the text of the toggle dock context menu when page and
492 * widget item are NOT known. This is an overoaded funciton.
493 * It is called from MainWin::undockWindowButton, it is not intended to change
494 * for the top pages tree widget, it is for the currently active tree widget
495 * item. Which is why the page is not passed.
497 void MainWin::setContextMenuDockText()
499 QTreeWidgetItem *currentitem = treeWidget->currentItem();
501 /* Is this a page that has been inserted into the hash */
502 if (getFromHash(currentitem)) {
503 Pages* page = getFromHash(currentitem);
504 setContextMenuDockText(page, currentitem);
509 * Function to set the text of the toggle dock context menu when page and
510 * widget item are known. This is the more commonly used.
512 void MainWin::setContextMenuDockText(Pages* page, QTreeWidgetItem* item)
514 QString docktext("");
515 if (page->isDocked()) {
516 docktext += "UnDock ";
518 docktext += "ReDock ";
520 docktext += item->text(0) += " Window";
522 actionToggleDock->setText(docktext);
523 setTreeWidgetItemDockColor(page, item);
527 * Function to set the color of the tree widget item based on whether it is
530 void MainWin::setTreeWidgetItemDockColor(Pages* page, QTreeWidgetItem* item)
532 if (item->text(0) != "Console") {
533 if (page->isDocked()) {
534 /* Set the brush to blue if undocked */
535 QBrush blackBrush(Qt::black);
536 item->setForeground(0, blackBrush);
538 /* Set the brush back to black if docked */
539 QBrush blueBrush(Qt::blue);
540 item->setForeground(0, blueBrush);
546 * Overload of previous function, use treeindex to get item from page
547 * This is called when an undocked window is closed.
549 void MainWin::setTreeWidgetItemDockColor(Pages* page)
551 QTreeWidgetItem* item = getFromHash(page);
553 setTreeWidgetItemDockColor(page, item);
558 * This function is called when the stack item is changed. Call
559 * the virtual function here. Avoids a window being undocked leaving
560 * a window at the top of the stack unpopulated.
562 void MainWin::stackItemChanged(int)
564 Pages* page = (Pages*)stackedWidget->currentWidget();
565 /* run the virtual function in case this class overrides it */
566 page->currentStackItem();
570 * Function to simplify insertion of QTreeWidgetItem <-> Page association
571 * into a double direction hash.
573 void MainWin::hashInsert(QTreeWidgetItem *item, Pages *page)
575 m_pagehash.insert(item, page);
576 m_widgethash.insert(page, item);
580 * Function to simplify removal of QTreeWidgetItem <-> Page association
581 * into a double direction hash.
583 void MainWin::hashRemove(QTreeWidgetItem *item, Pages *page)
585 /* I had all sorts of return status checking code here. Do we have a log
586 * level capability in bat. I would have left it in but it used printf's
587 * and it should really be some kind of log level facility ???
588 * ******FIXME********/
589 m_pagehash.remove(item);
590 m_widgethash.remove(page);
594 * Function to retrieve a Page* when the item in the page selector's tree is
597 Pages* MainWin::getFromHash(QTreeWidgetItem *item)
599 return m_pagehash.value(item);
603 * Function to retrieve the page selectors tree widget item when the page is
606 QTreeWidgetItem* MainWin::getFromHash(Pages *page)
608 return m_widgethash.value(page);
612 * Function to respond to action on page selector context menu to close the
615 void MainWin::closePage()
617 QTreeWidgetItem *currentitem = treeWidget->currentItem();
619 /* Is this a page that has been inserted into the hash */
620 if (getFromHash(currentitem)) {
621 Pages* page = getFromHash(currentitem);
622 if (page->isCloseable()) {
623 page->closeStackPage();