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