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