]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/qt-console/mainwin.cpp
Fix backup-bacula-test
[bacula/bacula] / bacula / src / qt-console / mainwin.cpp
1 /*
2    Bacula® - The Network Backup Solution
3
4    Copyright (C) 2007-2007 Free Software Foundation Europe e.V.
5
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.
12
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.
17
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
21    02110-1301, USA.
22
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.
27 */
28
29 /*
30  *   Version $Id$
31  *
32  *  Main Window control for bat (qt-console)
33  *
34  *   Kern Sibbald, January MMVII
35  *
36  */ 
37
38 #include "bat.h"
39 #include "joblist/joblist.h"
40
41 MainWin::MainWin(QWidget *parent) : QMainWindow(parent)
42 {
43
44    mainWin = this;
45    setupUi(this);                     /* Setup UI defined by main.ui (designer) */
46    treeWidget->clear();
47    treeWidget->setColumnCount(1);
48    treeWidget->setHeaderLabel("Select Page");
49    treeWidget->setContextMenuPolicy(Qt::ActionsContextMenu);
50
51    createPages();
52
53    resetFocus();
54
55    createConnections();
56
57    this->show();
58
59    readSettings();
60
61    m_console->connect();
62 }
63
64 void MainWin::createPages()
65 {
66    DIRRES *dir;
67    QTreeWidgetItem *item;
68
69    /* Create console tree stacked widget item */
70    m_console = new Console(stackedWidget);
71
72    /* Console is special -> needs director*/
73    /* Just take the first Director */
74    LockRes();
75    dir = (DIRRES *)GetNextRes(R_DIRECTOR, NULL);
76    m_console->setDirRes(dir);
77    UnlockRes();
78
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")));
82
83    /* Create Tree Widget Item */
84    item = createPage("Console", m_topItem);
85    m_console->setTreeItem(item);
86
87    /* insert the cosole and tree widget item into the hashes */
88    hashInsert(item, m_console);
89
90    /* Set Color of treeWidgetItem for the console
91    * It will be set to green in the console class if the connection is made.
92    */
93    QBrush redBrush(Qt::red);
94    item->setForeground(0, redBrush);
95    m_console->dockPage();
96
97    /* create instances of the rest of the classes that will by default exist
98    * under each director */
99    createPagebrestore();
100    createPagemedialist();
101    QString emptymedia("");
102    createPagejoblist(emptymedia);
103
104    treeWidget->expandItem(m_topItem);
105    stackedWidget->setCurrentWidget(m_console);
106 }
107
108 /*
109  * create an instance of the the brestore class on the stack
110  */
111 void MainWin::createPagebrestore()
112 {
113    QTreeWidgetItem *item=createPage("brestore", m_topItem);
114    bRestore* brestore = new bRestore(stackedWidget);
115    hashInsert(item, brestore);
116    brestore->dockPage();
117 }
118
119 /*
120  * create an instance of the the medialist class on the stack
121  */
122 void MainWin::createPagemedialist()
123 {
124    QTreeWidgetItem *item=createPage("Media", m_topItem);
125    MediaList* medialist = new MediaList(stackedWidget, m_console);
126    hashInsert(item, medialist);
127    medialist->dockPage();
128 }
129
130 /*
131  * create an instance of the the joblist class on the stack
132  */
133 void MainWin::createPagejoblist(QString &media)
134 {
135    QTreeWidgetItem *item;
136    if (media == "") {
137       item=createPage("All Jobs", m_topItem);
138    } else {
139       QString desc("Jobs on ");
140       desc += media;
141       item=createPage(desc.toUtf8().data(), m_topItem);
142    }
143    JobList* joblist = new JobList(stackedWidget, m_console, media);
144    hashInsert(item, joblist);
145    joblist->dockPage();
146    if (media != "") {
147       stackedWidget->setCurrentWidget(joblist);
148       treeWidget->setCurrentItem(item);
149    }
150 }
151
152 /* Create a root Tree Widget */
153 QTreeWidgetItem *MainWin::createTopPage(char *name)
154 {
155    QTreeWidgetItem *item = new QTreeWidgetItem(treeWidget);
156    item->setText(0, name);
157    return item;
158 }
159
160 /* Create A Tree Widget Item which will be associated with a Page in the stacked widget */
161 QTreeWidgetItem *MainWin::createPage(char *name, QTreeWidgetItem *parent)
162 {
163    QTreeWidgetItem *item = new QTreeWidgetItem(parent);
164    item->setText(0, name);
165    return item;
166 }
167
168 /*
169  * Handle up and down arrow keys for the command line
170  *  history.
171  */
172 void MainWin::keyPressEvent(QKeyEvent *event)
173 {
174    if (m_cmd_history.size() == 0) {
175       event->ignore();
176       return;
177    }
178    switch (event->key()) {
179    case Qt::Key_Down:
180       if (m_cmd_last < 0 || m_cmd_last >= (m_cmd_history.size()-1)) {
181          event->ignore();
182          return;
183       }
184       m_cmd_last++;
185       break;
186    case Qt::Key_Up:
187       if (m_cmd_last == 0) {
188          event->ignore();
189          return;
190       }
191       if (m_cmd_last < 0 || m_cmd_last > (m_cmd_history.size()-1)) {
192          m_cmd_last = m_cmd_history.size() - 1;
193       } else {
194          m_cmd_last--;
195       }
196       break;
197    default:
198       event->ignore();
199       return;
200    }
201    lineEdit->setText(m_cmd_history[m_cmd_last]);
202 }
203
204 void MainWin::createConnections()
205 {
206    /* Connect signals to slots */
207    connect(lineEdit, SIGNAL(returnPressed()), this, SLOT(input_line()));
208    connect(actionAbout_bat, SIGNAL(triggered()), this, SLOT(about()));
209
210 #ifdef xxx
211      connect(treeWidget, SIGNAL(itemActivated(QTreeWidgetItem *, int)), this, 
212            SLOT(treeItemClicked(QTreeWidgetItem *, int)));
213    connect(treeWidget, SIGNAL(itemPressed(QTreeWidgetItem *, int)), this, 
214            SLOT(treeItemClicked(QTreeWidgetItem *, int)));  
215 #endif
216    connect(treeWidget, SIGNAL(itemClicked(QTreeWidgetItem *, int)), this, 
217            SLOT(treeItemClicked(QTreeWidgetItem *, int)));
218    connect(treeWidget, SIGNAL(itemDoubleClicked(QTreeWidgetItem *, int)), this, 
219            SLOT(treeItemDoubleClicked(QTreeWidgetItem *, int)));
220    connect(treeWidget, SIGNAL(
221            currentItemChanged(QTreeWidgetItem *, QTreeWidgetItem *)),
222            this, SLOT(treeItemChanged(QTreeWidgetItem *, QTreeWidgetItem *)));
223    connect(stackedWidget, SIGNAL(currentChanged(int)),
224            this, SLOT(stackItemChanged(int)));
225
226    connect(actionQuit, SIGNAL(triggered()), app, SLOT(closeAllWindows()));
227    connect(actionConnect, SIGNAL(triggered()), m_console, SLOT(connect()));
228    connect(actionStatusDir, SIGNAL(triggered()), m_console, SLOT(status_dir()));
229    connect(actionSelectFont, SIGNAL(triggered()), m_console, SLOT(set_font()));
230    connect(actionLabel, SIGNAL(triggered()), this,  SLOT(labelDialogClicked()));
231    connect(actionRun, SIGNAL(triggered()), this,  SLOT(runDialogClicked()));
232    connect(actionRestore, SIGNAL(triggered()), this,  SLOT(restoreDialogClicked()));
233    connect(actionUndock, SIGNAL(triggered()), this,  SLOT(undockWindowButton()));
234    connect(actionToggleDock, SIGNAL(triggered()), this,  SLOT(toggleDockContextWindow()));
235    connect(actionClosePage, SIGNAL(triggered()), this,  SLOT(closePage()));
236 }
237
238 /* 
239  * Reimplementation of QWidget closeEvent virtual function   
240  */
241 void MainWin::closeEvent(QCloseEvent *event)
242 {
243    writeSettings();
244    m_console->writeSettings();
245    m_console->terminate();
246    event->accept();
247    foreach(Pages *page, m_pagehash) {
248       if (!page->isDocked())
249          page->close();
250    }
251 }
252
253 void MainWin::writeSettings()
254 {
255    QSettings settings("bacula.org", "bat");
256
257    settings.beginGroup("MainWin");
258    settings.setValue("winSize", size());
259    settings.setValue("winPos", pos());
260    settings.endGroup();
261 }
262
263 void MainWin::readSettings()
264
265    QSettings settings("bacula.org", "bat");
266
267    settings.beginGroup("MainWin");
268    resize(settings.value("winSize", QSize(1041, 801)).toSize());
269    move(settings.value("winPos", QPoint(200, 150)).toPoint());
270    settings.endGroup();
271 }
272
273 /*
274  * This subroutine is called with an item in the Page Selection window
275  *   is clicked 
276  */
277 void MainWin::treeItemClicked(QTreeWidgetItem *item, int /*column*/)
278 {
279    /* Is this a page that has been inserted into the hash  */
280    if (getFromHash(item)) {
281       Pages* page = getFromHash(item);
282       int stackindex=stackedWidget->indexOf(page);
283
284       if (stackindex >= 0) {
285          stackedWidget->setCurrentWidget(page);
286       }
287       /* run the virtual function in case this class overrides it */
288       page->PgSeltreeWidgetClicked();
289    }
290 }
291
292 /*
293  * This subroutine is called with an item in the Page Selection window
294  *   is double clicked
295  */
296 /* This could be removed from here and from pages and from medialist
297  * Do you agree dhb */
298 void MainWin::treeItemDoubleClicked(QTreeWidgetItem *item, int /*column*/)
299 {
300    Pages* page = getFromHash(item);
301    page->PgSeltreeWidgetDoubleClicked();
302 }
303
304 /*
305  * Called with a change of the highlighed tree widget item in the page selector.
306  */
307 void MainWin::treeItemChanged(QTreeWidgetItem *currentitem, QTreeWidgetItem *previousitem)
308 {
309    /* The Previous item */
310
311    if (previousitem) {
312       /* Is this a page that has been inserted into the hash  */
313       if (getFromHash(previousitem)) {
314          Pages* page = getFromHash(previousitem);
315          treeWidget->removeAction(actionToggleDock);
316          /* make sure the close window option is removed */
317          if (page->isCloseable()) {
318             treeWidget->removeAction(actionClosePage);
319          }
320          foreach(QAction* pageaction, page->m_contextActions) {
321             treeWidget->removeAction(pageaction);
322          } 
323       }
324    }
325
326    /* Is this a page that has been inserted into the hash  */
327    if (getFromHash(currentitem)) {
328       Pages* page = getFromHash(currentitem);
329       int stackindex = stackedWidget->indexOf(page);
330    
331       /* Is this page currently on the stack */
332       if (stackindex >= 0) {
333          /* put this page on the top of the stack */
334          stackedWidget->setCurrentIndex(stackindex);
335       } else {
336          /* it is undocked, raise it to the front */
337          page->raise();
338       }
339       setContextMenuDockText(page, currentitem);
340
341       treeWidget->addAction(actionToggleDock);
342       /* if this page is closeable, then add that action */
343       if (page->isCloseable()) {
344          treeWidget->addAction(actionClosePage);
345       }
346
347       /* Add the actions to the Page Selectors tree widget that are part of the
348        * current items list of desired actions regardless of whether on top of stack*/
349       treeWidget->addActions(page->m_contextActions);
350    }
351 }
352
353 void MainWin::labelDialogClicked() 
354 {
355    new labelDialog(m_console);
356 }
357
358 void MainWin::runDialogClicked() 
359 {
360    new runDialog(m_console);
361 }
362
363 void MainWin::restoreDialogClicked() 
364 {
365    new prerestoreDialog(m_console);
366 }
367
368
369
370 /*
371  * The user just finished typing a line in the command line edit box
372  */
373 void MainWin::input_line()
374 {
375    QString cmdStr = lineEdit->text();    /* Get the text */
376    lineEdit->clear();                    /* clear the lineEdit box */
377    if (m_console->is_connected()) {
378       m_console->display_text(cmdStr + "\n");
379       m_console->write_dir(cmdStr.toUtf8().data());         /* send to dir */
380    } else {
381       set_status("Director not connected. Click on connect button.");
382    }
383    m_cmd_history.append(cmdStr);
384    m_cmd_last = -1;
385 }
386
387
388 void MainWin::about()
389 {
390    QMessageBox::about(this, tr("About bat"),
391             tr("<br><h2>bat 0.2, by Kern Sibbald</h2>"
392             "<p>Copyright &copy; " BYEAR " Free Software Foundation Europe e.V."
393             "<p>The <b>bat</b> is an administrative console"
394                " interface to the Director."));
395 }
396
397 void MainWin::set_statusf(const char *fmt, ...)
398 {
399    va_list arg_ptr;
400    char buf[1000];
401    int len;
402    va_start(arg_ptr, fmt);
403    len = bvsnprintf(buf, sizeof(buf), fmt, arg_ptr);
404    va_end(arg_ptr);
405    set_status(buf);
406 }
407
408 void MainWin::set_status_ready()
409 {
410    set_status(" Ready");
411 }
412
413 void MainWin::set_status(const char *buf)
414 {
415    statusBar()->showMessage(buf);
416 }
417
418 /*
419  * Function to respond to the button bar button to undock
420  */
421 void MainWin::undockWindowButton()
422 {
423    Pages* page = (Pages*)stackedWidget->currentWidget();
424    page->togglePageDocking();
425    /* The window has been undocked, lets change the context menu */
426    setContextMenuDockText();
427 }
428
429 /*
430  * Function to respond to action on page selector context menu to toggle the 
431  * dock status of the window associated with the page selectors current
432  * tree widget item.
433  */
434 void MainWin::toggleDockContextWindow()
435 {
436    QTreeWidgetItem *currentitem = treeWidget->currentItem();
437    
438    /* Is this a page that has been inserted into the hash  */
439    if (getFromHash(currentitem)) {
440       Pages* page = getFromHash(currentitem);
441       page->togglePageDocking();
442       if (page->isDocked()) {
443          stackedWidget->setCurrentWidget(page);
444       }
445       /* Toggle the menu item.  The window's dock status has been toggled */
446       setContextMenuDockText(page, currentitem);
447    }
448 }
449
450 /*
451  * Function to set the text of the toggle dock context menu when page and
452  * widget item are NOT known.  This is an overoaded funciton.
453  * It is called from MainWin::undockWindowButton, it is not intended to change
454  * for the top pages tree widget, it is for the currently active tree widget
455  * item.  Which is why the page is not passed.
456  */
457 void MainWin::setContextMenuDockText()
458 {
459    QTreeWidgetItem *currentitem = treeWidget->currentItem();
460    
461    /* Is this a page that has been inserted into the hash  */
462    if (getFromHash(currentitem)) {
463       Pages* page = getFromHash(currentitem);
464       setContextMenuDockText(page, currentitem);
465    }
466 }
467
468 /*
469  * Function to set the text of the toggle dock context menu when page and
470  * widget item are known.  This is the more commonly used.
471  */
472 void MainWin::setContextMenuDockText(Pages* page, QTreeWidgetItem* item)
473 {
474    QString docktext("");
475    if (page->isDocked()) {
476       docktext += "UnDock ";
477    } else {
478       docktext += "ReDock ";
479    }
480    docktext += item->text(0) += " Window";
481    
482    actionToggleDock->setText(docktext);
483    setTreeWidgetItemDockColor(page, item);
484 }
485
486 /*
487  * Function to set the color of the tree widget item based on whether it is
488  * docked or not.
489  */
490 void MainWin::setTreeWidgetItemDockColor(Pages* page, QTreeWidgetItem* item)
491 {
492    if (item->text(0) != "Console") {
493       if (page->isDocked()) {
494       /* Set the brush to blue if undocked */
495          QBrush blackBrush(Qt::black);
496          item->setForeground(0, blackBrush);
497       } else {
498       /* Set the brush back to black if docked */
499          QBrush blueBrush(Qt::blue);
500          item->setForeground(0, blueBrush);
501       }
502    }
503 }
504
505 /*
506  *  Overload of previous function, use treeindex to get item from page
507  *  This is called when an undocked window is closed.
508  */
509 void MainWin::setTreeWidgetItemDockColor(Pages* page)
510 {
511    QTreeWidgetItem* item = getFromHash(page);
512    if (item) {
513      setTreeWidgetItemDockColor(page, item);
514    }
515 }
516
517 /*
518  * This function is called when the stack item is changed.  Call
519  * the virtual function here.  Avoids a window being undocked leaving
520  * a window at the top of the stack unpopulated.
521  */
522 void MainWin::stackItemChanged(int)
523 {
524    Pages* page = (Pages*)stackedWidget->currentWidget();
525    /* run the virtual function in case this class overrides it */
526    page->currentStackItem();
527 }
528
529 /*
530  * Function to simplify insertion of QTreeWidgetItem <-> Page association
531  * into a double direction hash.
532  */
533 void MainWin::hashInsert(QTreeWidgetItem *item, Pages *page)
534 {
535    m_pagehash.insert(item, page);
536    m_widgethash.insert(page, item);
537 }
538
539 /*
540  * Function to simplify removal of QTreeWidgetItem <-> Page association
541  * into a double direction hash.
542  */
543 void MainWin::hashRemove(QTreeWidgetItem *item, Pages *page)
544 {
545    /* I had all sorts of return status checking code here.  Do we have a log
546     * level capability in bat.  I would have left it in but it used printf's
547     * and it should really be some kind of log level facility ???
548     * ******FIXME********/
549    m_pagehash.remove(item);
550    m_widgethash.remove(page);
551 }
552
553 /*
554  * Function to retrieve a Page* when the item in the page selector's tree is
555  * known.
556  */
557 Pages* MainWin::getFromHash(QTreeWidgetItem *item)
558 {
559    return m_pagehash.value(item);
560 }
561
562 /*
563  * Function to retrieve the page selectors tree widget item when the page is
564  * known.
565  */
566 QTreeWidgetItem* MainWin::getFromHash(Pages *page)
567 {
568    return m_widgethash.value(page);
569 }
570
571 /*
572  * Function to respond to action on page selector context menu to close the
573  * current window.
574  */
575 void MainWin::closePage()
576 {
577    QTreeWidgetItem *currentitem = treeWidget->currentItem();
578    
579    /* Is this a page that has been inserted into the hash  */
580    if (getFromHash(currentitem)) {
581       Pages* page = getFromHash(currentitem);
582       if (page->isCloseable()) {
583          page->closeStackPage();
584       }
585    }
586 }
587