]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/qt-console/pages.cpp
First cut of bat rerun a Job from Jobs Run
[bacula/bacula] / bacula / src / qt-console / pages.cpp
1 /*
2    Bacula® - The Network Backup Solution
3
4    Copyright (C) 2007-2010 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 three of the GNU Affero General Public
10    License as published by the Free Software Foundation and included
11    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 Affero 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 Kern Sibbald.
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  *   Version $Id$
30  *
31  *   Dirk Bartley, March 2007
32  */
33
34 #include "bat.h"
35 #include "pages.h"
36
37 /* A global function */
38 bool isWin32Path(QString &fullPath) 
39 {
40    if (fullPath.size()<2) {
41       return false;
42    }
43
44    bool toret = fullPath[1].toAscii() == ':' && fullPath[0].isLetter();
45    if (mainWin->m_miscDebug) {
46       if (toret)
47          Pmsg1(000, "returning from isWin32Path true %s\n", fullPath.toUtf8().data());
48       else
49          Pmsg1(000, "returning from isWin32Path false %s\n", fullPath.toUtf8().data());
50    }
51    return toret;
52 }
53
54 /* Need to initialize variables here */
55 Pages::Pages()
56 {
57    m_docked = false;
58    m_onceDocked = false;
59    m_closeable = true;
60    m_dockOnFirstUse = true;
61 }
62
63 /* first Use Dock */
64 void Pages::firstUseDock()
65 {
66    if (!m_onceDocked && m_dockOnFirstUse) {
67       dockPage();
68    }
69 }
70
71 /*
72  * dockPage
73  * This function is intended to be called from within the Pages class to pull
74  * a window from floating to in the stack widget.
75  */
76
77 void Pages::dockPage()
78 {
79    if (isDocked()) {
80       return;
81    }
82
83    /* These two lines are for making sure if it is being changed from a window
84     * that it has the proper window flag and parent.
85     */
86    setWindowFlags(Qt::Widget);
87
88    /* calculate the index that the tab should be inserted into */
89    int tabPos = 0;
90    QTreeWidgetItemIterator it(mainWin->treeWidget);
91    while (*it) {
92       Pages *somepage = mainWin->getFromHash(*it);
93       if (this == somepage) {
94          tabPos += 1;
95          break;
96       }
97       int pageindex = mainWin->tabWidget->indexOf(somepage);
98       if (pageindex != -1) { tabPos = pageindex; }
99       ++it;
100    }
101
102    /* This was being done already */
103    m_parent->insertTab(tabPos, this, m_name);
104
105    /* Set docked flag */
106    m_docked = true;
107    m_onceDocked = true;
108    mainWin->tabWidget->setCurrentWidget(this);
109    /* lets set the page selectors action for docking or undocking */
110    setContextMenuDockText();
111 }
112
113 /*
114  * undockPage
115  * This function is intended to be called from within the Pages class to put
116  * a window from the stack widget to a floating window.
117  */
118
119 void Pages::undockPage()
120 {
121    if (!isDocked()) {
122       return;
123    }
124
125    /* Change from a stacked widget to a normal window */
126    m_parent->removeTab(m_parent->indexOf(this));
127    setWindowFlags(Qt::Window);
128    show();
129    /* Clear docked flag */
130    m_docked = false;
131    /* The window has been undocked, lets change the context menu */
132    setContextMenuDockText();
133 }
134
135 /*
136  * This function is intended to be called with the subclasses.  When it is 
137  * called the specific sublclass does not have to be known to Pages.  When it 
138  * is called this function will change the page from it's current state of being
139  * docked or undocked and change it to the other.
140  */
141
142 void Pages::togglePageDocking()
143 {
144    if (m_docked) {
145       undockPage();
146    } else {
147       dockPage();
148    }
149 }
150
151 /*
152  * This function is because I wanted for some reason to keep it protected but still 
153  * give any subclasses the ability to find out if it is currently stacked or not.
154  */
155 bool Pages::isDocked()
156 {
157    return m_docked;
158 }
159
160 /*
161  * This function is because after the tabbed widget was added I could not tell
162  * from is docked if it had been docked yet.  To prevent status pages from requesting
163  * status from the director
164  */
165 bool Pages::isOnceDocked()
166 {
167    return m_onceDocked;
168 }
169
170
171 /*
172  * To keep m_closeable protected as well
173  */
174 bool Pages::isCloseable()
175 {
176    return m_closeable;
177 }
178
179 /*
180  * When a window is closed, this slot is called.  The idea is to put it back in the
181  * stack here, and it works.  I wanted to get it to the top of the stack so that the
182  * user immediately sees where his window went.  Also, if he undocks the window, then
183  * closes it with the tree item highlighted, it may be confusing that the highlighted
184  * treewidgetitem is not the stack item in the front.
185  */
186
187 void Pages::closeEvent(QCloseEvent* event)
188 {
189    /* A Widget was closed, lets toggle it back into the window, and set it in front. */
190    dockPage();
191
192    /* this fixes my woes of getting the widget to show up on top when closed */
193    event->ignore();
194
195    /* Set the current tree widget item in the Page Selector window to the item 
196     * which represents "this" 
197     * Which will also bring "this" to the top of the stacked widget */
198    setCurrent();
199 }
200
201 /*
202  * The next three are virtual functions.  The idea here is that each subclass will have the
203  * built in virtual function to override if the programmer wants to populate the window
204  * when it it is first clicked.
205  */
206 void Pages::PgSeltreeWidgetClicked()
207 {
208 }
209
210 /*
211  *  Virtual function which is called when this page is visible on the stack.
212  *  This will be overridden by classes that want to populate if they are on the
213  *  top.
214  */
215 void Pages::currentStackItem()
216 {
217 }
218
219 /*
220  * Function to close the stacked page and remove the widget from the
221  * Page selector window
222  */
223 void Pages::closeStackPage()
224 {
225    /* First get the tree widget item and destroy it */
226    QTreeWidgetItem *item=mainWin->getFromHash(this);
227    /* remove the QTreeWidgetItem <-> page from the hash */
228    if (item) {
229       mainWin->hashRemove(item, this);
230       /* remove the item from the page selector by destroying it */
231       delete item;
232    }
233    /* remove this */
234    delete this;
235 }
236
237 /*
238  * Function to set members from the external mainwin and it's overload being
239  * passed a specific QTreeWidgetItem to be it's parent on the tree
240  */
241 void Pages::pgInitialize()
242 {
243    pgInitialize(QString(), NULL);
244 }
245
246 void Pages::pgInitialize(const QString &name)
247 {
248    pgInitialize(name, NULL);
249 }
250
251 void Pages::pgInitialize(const QString &tname, QTreeWidgetItem *parentTreeWidgetItem)
252 {
253    m_docked = false;
254    m_onceDocked = false;
255    if (tname.size()) {
256       m_name = tname;
257    }
258    m_parent = mainWin->tabWidget;
259    m_console = mainWin->currentConsole();
260
261    if (!parentTreeWidgetItem) {
262       parentTreeWidgetItem = m_console->directorTreeItem();
263    }
264
265    QTreeWidgetItem *item = new QTreeWidgetItem(parentTreeWidgetItem);
266    QString name; 
267    treeWidgetName(name);
268    item->setText(0, name);
269    mainWin->hashInsert(item, this);
270    setTitle();
271 }
272
273 /*
274  * Virtual Function to return a name
275  * All subclasses should override this function
276  */
277 void Pages::treeWidgetName(QString &name)
278 {
279    name = m_name;
280 }
281
282 /*
283  * Function to simplify executing a console command and bringing the
284  * console to the front of the stack
285  */
286 void Pages::consoleCommand(QString &command)
287 {
288    consoleCommand(command, true);
289 }
290
291 void Pages::consoleCommand(QString &command, bool setCurrent)
292 {
293    int conn;
294    bool donotify = false;
295    if (m_console->getDirComm(conn))  {
296       if (m_console->is_notify_enabled(conn)) {
297          donotify = true;
298          m_console->notify(conn, false);
299       }
300       consoleCommand(command, conn, setCurrent);
301       if (donotify) { m_console->notify(conn, true); }
302    }
303 }
304
305 void Pages::consoleCommand(QString &command, int conn)
306 {
307    consoleCommand(command, conn, true);
308 }
309
310 void Pages::consoleCommand(QString &command, int conn, bool setCurrent)
311 {
312    /* Bring this director's console to the front of the stack */
313    if (setCurrent) { setConsoleCurrent(); }
314    QString displayhtml("<font color=\"blue\">");
315    displayhtml += command + "</font>\n";
316    m_console->display_html(displayhtml);
317    m_console->display_text("\n");
318    mainWin->waitEnter();
319    m_console->write_dir(conn, command.toUtf8().data(), false);
320    m_console->displayToPrompt(conn);
321    mainWin->waitExit();
322 }
323
324 /*
325  * Function for handling undocked windows becoming active.
326  * Change the currently selected item in the page selector window to the now
327  * active undocked window.  This will also make the console for the undocked
328  * window m_currentConsole.
329  */
330 void Pages::changeEvent(QEvent *event)
331 {
332    if ((event->type() ==  QEvent::ActivationChange) && (isActiveWindow())) {
333       setCurrent();
334    }
335 }
336
337 /*
338  * Function to simplify getting the name of the class and the director into
339  * the caption or title of the window
340  */
341 void Pages::setTitle()
342 {
343    QString wdgname, director;
344    treeWidgetName(wdgname);
345    m_console->getDirResName(director);
346    QString title = tr("%1 of Director %2").arg(wdgname).arg(director);
347    setWindowTitle(title);
348 }
349
350 /*
351  * Bring the current directors console window to the top of the stack.
352  */
353 void Pages::setConsoleCurrent()
354 {
355    mainWin->treeWidget->setCurrentItem(mainWin->getFromHash(m_console));
356 }
357
358 /*
359  * Bring this window to the top of the stack.
360  */
361 void Pages::setCurrent()
362 {
363    mainWin->treeWidget->setCurrentItem(mainWin->getFromHash(this));
364 }
365
366 /*
367  * Function to set the text of the toggle dock context menu when page and
368  * widget item are NOT known.  
369  */
370 void Pages::setContextMenuDockText()
371 {
372    QTreeWidgetItem *item = mainWin->getFromHash(this);
373    QString docktext;
374    if (isDocked()) {
375       docktext = tr("UnDock %1 Window").arg(item->text(0));
376    } else {
377       docktext = tr("ReDock %1 Window").arg(item->text(0));
378    }
379       
380    mainWin->actionToggleDock->setText(docktext);
381    setTreeWidgetItemDockColor();
382 }
383
384 /*
385  * Function to set the color of the tree widget item based on whether it is
386  * docked or not.
387  */
388 void Pages::setTreeWidgetItemDockColor()
389 {
390    QTreeWidgetItem* item = mainWin->getFromHash(this);
391    if (item) {
392       if (item->text(0) != tr("Console")) {
393          if (isDocked()) {
394          /* Set the brush to blue if undocked */
395             QBrush blackBrush(Qt::black);
396             item->setForeground(0, blackBrush);
397          } else {
398          /* Set the brush back to black if docked */
399             QBrush blueBrush(Qt::blue);
400             item->setForeground(0, blueBrush);
401          }
402       }
403    }
404 }
405
406 /* Function to get a list of volumes */
407 void Pages::getVolumeList(QStringList &volumeList)
408 {
409    QString query("SELECT VolumeName AS Media FROM Media ORDER BY Media");
410    if (mainWin->m_sqlDebug) {
411       Pmsg1(000, "Query cmd : %s\n",query.toUtf8().data());
412    }
413    QStringList results;
414    if (m_console->sql_cmd(query, results)) {
415       QString field;
416       QStringList fieldlist;
417       /* Iterate through the lines of results. */
418       foreach (QString resultline, results) {
419          fieldlist = resultline.split("\t");
420          volumeList.append(fieldlist[0]);
421       } /* foreach resultline */
422    } /* if results from query */
423 }
424
425 /* Function to get a list of volumes */
426 void Pages::getStatusList(QStringList &statusLongList)
427 {
428    QString statusQuery("SELECT JobStatusLong FROM Status");
429    if (mainWin->m_sqlDebug) {
430       Pmsg1(000, "Query cmd : %s\n",statusQuery.toUtf8().data());
431    }
432    QStringList statusResults;
433    if (m_console->sql_cmd(statusQuery, statusResults)) {
434       QString field;
435       QStringList fieldlist;
436       /* Iterate through the lines of results. */
437       foreach (QString resultline, statusResults) {
438          fieldlist = resultline.split("\t");
439          statusLongList.append(fieldlist[0]);
440       } /* foreach resultline */
441    } /* if results from statusquery */
442 }