]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/qt-console/mainwin.cpp
3d0d5f480b391fadab9235760ac581c3e39119bb
[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 green 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->setCurrentWidget(m_console);
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 a page that has been inserted into the hash  */
249    if( getFromHash(item) ){
250       Pages* page = getFromHash(item);
251       int stackindex=stackedWidget->indexOf(page);
252
253       if( stackindex >= 0 ){
254          stackedWidget->setCurrentWidget(page);
255       }
256       /* run the virtual function in case this class overrides it */
257       page->PgSeltreeWidgetClicked();
258    }
259 }
260
261 /*
262  * This subroutine is called with an item in the Page Selection window
263  *   is double clicked
264  */
265 void MainWin::treeItemDoubleClicked(QTreeWidgetItem * /*item*/, int /*column*/)
266 {
267 }
268
269 /*
270  * Called with a change of the highlighed tree widget item in the page selector.
271  */
272 void MainWin::treeItemChanged(QTreeWidgetItem *currentitem, QTreeWidgetItem *previousitem)
273 {
274    /* The Previous item */
275
276    if ( previousitem ){
277       /* Is this a page that has been inserted into the hash  */
278       if( getFromHash(previousitem) ){
279          Pages* page = getFromHash(previousitem);
280          treeWidget->removeAction(actionToggleDock);
281          foreach( QAction* pageaction, page->m_contextActions ){
282             treeWidget->removeAction(pageaction);
283          } 
284       }
285    }
286
287    /* Is this a page that has been inserted into the hash  */
288    if( getFromHash(currentitem) ){
289       Pages* page = getFromHash(currentitem);
290       int stackindex = stackedWidget->indexOf(page);
291    
292       /* Is this page currently on the stack */
293       if( stackindex >= 0 ){
294          /* put this page on the top of the stack */
295          stackedWidget->setCurrentIndex(stackindex);
296       } else {
297          /* it is undocked, raise it to the front */
298          page->raise();
299       }
300       setContextMenuDockText(page, currentitem);
301
302       treeWidget->addAction(actionToggleDock);
303
304       /* Add the actions to the Page Selectors tree widget that are part of the
305        * current items list of desired actions regardless of whether on top of stack*/
306       treeWidget->addActions(page->m_contextActions);
307    }
308 }
309
310 void MainWin::labelDialogClicked() 
311 {
312    new labelDialog(m_console);
313 }
314
315 void MainWin::runDialogClicked() 
316 {
317    new runDialog(m_console);
318 }
319
320 void MainWin::restoreDialogClicked() 
321 {
322    new prerestoreDialog(m_console);
323 }
324
325
326
327 /*
328  * The user just finished typing a line in the command line edit box
329  */
330 void MainWin::input_line()
331 {
332    QString cmdStr = lineEdit->text();    /* Get the text */
333    lineEdit->clear();                    /* clear the lineEdit box */
334    if (m_console->is_connected()) {
335       m_console->display_text(cmdStr + "\n");
336       m_console->write_dir(cmdStr.toUtf8().data());         /* send to dir */
337    } else {
338       set_status("Director not connected. Click on connect button.");
339    }
340    m_cmd_history.append(cmdStr);
341    m_cmd_last = -1;
342 }
343
344
345 void MainWin::about()
346 {
347    QMessageBox::about(this, tr("About bat"),
348             tr("<br><h2>bat 0.2, by Kern Sibbald</h2>"
349             "<p>Copyright &copy; " BYEAR " Free Software Foundation Europe e.V."
350             "<p>The <b>bat</b> is an administrative console"
351                " interface to the Director."));
352 }
353
354 void MainWin::set_statusf(const char *fmt, ...)
355 {
356    va_list arg_ptr;
357    char buf[1000];
358    int len;
359    va_start(arg_ptr, fmt);
360    len = bvsnprintf(buf, sizeof(buf), fmt, arg_ptr);
361    va_end(arg_ptr);
362    set_status(buf);
363 }
364
365 void MainWin::set_status_ready()
366 {
367    set_status(" Ready");
368 }
369
370 void MainWin::set_status(const char *buf)
371 {
372    statusBar()->showMessage(buf);
373 }
374
375 /*
376  * Function to respond to the button bar button to undock
377  */
378 void MainWin::undockWindowButton()
379 {
380    Pages* page = (Pages*)stackedWidget->currentWidget();
381    page->togglePageDocking();
382    /* The window has been undocked, lets change the context menu */
383    setContextMenuDockText();
384 }
385
386 /*
387  * Function to respond to action on page selector context menu to toggle the 
388  * dock status of the window associated with the page selectors current
389  * tree widget item.
390  */
391 void MainWin::toggleDockContextWindow()
392 {
393    QTreeWidgetItem *currentitem = treeWidget->currentItem();
394    
395    /* Is this a page that has been inserted into the hash  */
396    if( getFromHash(currentitem) ){
397       Pages* page = getFromHash(currentitem);
398       page->togglePageDocking();
399       if ( page->isDocked() ){
400          stackedWidget->setCurrentWidget(page);
401       }
402       /* Toggle the menu item.  The window's dock status has been toggled */
403       setContextMenuDockText(page, currentitem);
404    }
405 }
406
407 /*
408  * Function to set the text of the toggle dock context menu when page and
409  * widget item are NOT known.  This is an overoaded funciton.
410  * It is called from MainWin::undockWindowButton, it is not intended to change
411  * for the top pages tree widget, it is for the currently active tree widget
412  * item.  Which is why the page is not passed.
413  */
414 void MainWin::setContextMenuDockText()
415 {
416    QTreeWidgetItem *currentitem = treeWidget->currentItem();
417    
418    /* Is this a page that has been inserted into the hash  */
419    if( getFromHash(currentitem) ){
420       Pages* page = getFromHash(currentitem);
421       setContextMenuDockText(page, currentitem);
422    }
423 }
424
425 /*
426  * Function to set the text of the toggle dock context menu when page and
427  * widget item are known.  This is the more commonly used.
428  */
429 void MainWin::setContextMenuDockText(Pages* page, QTreeWidgetItem* item)
430 {
431    QString docktext("");
432    if( page->isDocked() ){
433       docktext += "UnDock ";
434    } else {
435       docktext += "ReDock ";
436    }
437    docktext += item->text(0) += " Window";
438    
439    actionToggleDock->setText(docktext);
440    setTreeWidgetItemDockColor(page, item);
441 }
442
443 /*
444  * Function to set the color of the tree widget item based on whether it is
445  * docked or not.
446  */
447 void MainWin::setTreeWidgetItemDockColor(Pages* page, QTreeWidgetItem* item)
448 {
449    if( item->text(0) != "Console" ){
450       if( page->isDocked() ){
451       /* Set the brush to blue if undocked */
452          QBrush blackBrush(Qt::black);
453          item->setForeground(0, blackBrush);
454       } else {
455       /* Set the brush back to black if docked */
456          QBrush blueBrush(Qt::blue);
457          item->setForeground(0, blueBrush);
458       }
459    }
460 }
461
462 /*
463  *  Overload of previous function, use treeindex to get item from page
464  *  This is called when an undocked window is closed.
465  */
466 void MainWin::setTreeWidgetItemDockColor(Pages* page)
467 {
468    QTreeWidgetItem* item = getFromHash(page);
469    if( item ){
470      setTreeWidgetItemDockColor(page, item);
471    }
472 }
473
474 /*
475  * This function is called when the stack item is changed.  Call
476  * the virtual function here.  Avoids a window being undocked leaving
477  * a window at the top of the stack unpopulated.
478  */
479 void MainWin::stackItemChanged(int)
480 {
481    Pages* page = (Pages*)stackedWidget->currentWidget();
482    /* run the virtual function in case this class overrides it */
483    page->currentStackItem();
484 }
485
486 /*
487  * Function to simplify insertion of QTreeWidgetItem <-> Page association
488  * into a double direction hash.
489  */
490 void MainWin::hashInsert(QTreeWidgetItem *item, Pages *page)
491 {
492    m_pagehash.insert(item, page);
493    m_widgethash.insert(page, item);
494 }
495
496 /*
497  * Function to retrieve a Page* when the item in the page selector's tree is
498  * known.
499  */
500 Pages* MainWin::getFromHash(QTreeWidgetItem *item)
501 {
502    return m_pagehash.value(item);
503 }
504
505 /*
506  * Function to retrieve the page selectors tree widget item when the page is
507  * known.
508  */
509 QTreeWidgetItem* MainWin::getFromHash(Pages *page)
510 {
511    return m_widgethash.value(page);
512 }