]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/qt-console/pages.cpp
Fix invalid .mod command in BAT during restore
[bacula/bacula] / bacula / src / qt-console / pages.cpp
1 /*
2    Bacula® - The Network Backup Solution
3
4    Copyright (C) 2007-2011 Free Software Foundation Europe e.V.
5
6    The main author of Bacula is Kern Sibbald, with contributions from many
7    others, a complete list can be found in the file AUTHORS.
8
9    You may use this file and others of this release according to the
10    license defined in the LICENSE file, which includes the Affero General
11    Public License, v3.0 ("AGPLv3") and some additional permissions and
12    terms pursuant to its AGPLv3 Section 7.
13
14    Bacula® is a registered trademark of Kern Sibbald.
15 */
16 /*
17  *   Dirk Bartley, March 2007
18  */
19
20 #include "bat.h"
21 #include "pages.h"
22
23 /* A global function */
24 bool isWin32Path(QString &fullPath)
25 {
26    if (fullPath.size()<2) {
27       return false;
28    }
29
30    bool toret = fullPath[1].toAscii() == ':' && fullPath[0].isLetter();
31    if (mainWin->m_miscDebug) {
32       if (toret)
33          Pmsg1(000, "returning from isWin32Path true %s\n", fullPath.toUtf8().data());
34       else
35          Pmsg1(000, "returning from isWin32Path false %s\n", fullPath.toUtf8().data());
36    }
37    return toret;
38 }
39
40 /* Need to initialize variables here */
41 Pages::Pages() : QWidget()
42 {
43    m_docked = false;
44    m_onceDocked = false;
45    m_closeable = true;
46    m_dockOnFirstUse = true;
47    m_console = NULL;
48    m_parent = NULL;
49 }
50
51 /* first Use Dock */
52 void Pages::firstUseDock()
53 {
54    if (!m_onceDocked && m_dockOnFirstUse) {
55       dockPage();
56    }
57 }
58
59 /*
60  * dockPage
61  * This function is intended to be called from within the Pages class to pull
62  * a window from floating to in the stack widget.
63  */
64
65 void Pages::dockPage()
66 {
67    if (isDocked()) {
68       return;
69    }
70
71    /* These two lines are for making sure if it is being changed from a window
72     * that it has the proper window flag and parent.
73     */
74    setWindowFlags(Qt::Widget);
75
76    /* calculate the index that the tab should be inserted into */
77    int tabPos = 0;
78    QTreeWidgetItemIterator it(mainWin->treeWidget);
79    while (*it) {
80       Pages *somepage = mainWin->getFromHash(*it);
81       if (this == somepage) {
82          tabPos += 1;
83          break;
84       }
85       int pageindex = mainWin->tabWidget->indexOf(somepage);
86       if (pageindex != -1) { tabPos = pageindex; }
87       ++it;
88    }
89
90    /* This was being done already */
91    m_parent->insertTab(tabPos, this, m_name);
92
93    /* Set docked flag */
94    m_docked = true;
95    m_onceDocked = true;
96    mainWin->tabWidget->setCurrentWidget(this);
97    /* lets set the page selectors action for docking or undocking */
98    setContextMenuDockText();
99 }
100
101 /*
102  * undockPage
103  * This function is intended to be called from within the Pages class to put
104  * a window from the stack widget to a floating window.
105  */
106
107 void Pages::undockPage()
108 {
109    if (!isDocked()) {
110       return;
111    }
112
113    /* Change from a stacked widget to a normal window */
114    m_parent->removeTab(m_parent->indexOf(this));
115    setWindowFlags(Qt::Window);
116    show();
117    /* Clear docked flag */
118    m_docked = false;
119    /* The window has been undocked, lets change the context menu */
120    setContextMenuDockText();
121 }
122
123 /*
124  * This function is intended to be called with the subclasses.  When it is
125  * called the specific sublclass does not have to be known to Pages.  When it
126  * is called this function will change the page from it's current state of being
127  * docked or undocked and change it to the other.
128  */
129
130 void Pages::togglePageDocking()
131 {
132    if (m_docked) {
133       undockPage();
134    } else {
135       dockPage();
136    }
137 }
138
139 /*
140  * This function is because I wanted for some reason to keep it protected but still
141  * give any subclasses the ability to find out if it is currently stacked or not.
142  */
143 bool Pages::isDocked()
144 {
145    return m_docked;
146 }
147
148 /*
149  * This function is because after the tabbed widget was added I could not tell
150  * from is docked if it had been docked yet.  To prevent status pages from requesting
151  * status from the director
152  */
153 bool Pages::isOnceDocked()
154 {
155    return m_onceDocked;
156 }
157
158
159 /*
160  * To keep m_closeable protected as well
161  */
162 bool Pages::isCloseable()
163 {
164    return m_closeable;
165 }
166
167 void Pages::hidePage()
168 {
169    if (!m_parent || (m_parent->indexOf(this) <= 0)) {
170       return;
171    }
172    /* Remove any tab that may exist */
173    m_parent->removeTab(m_parent->indexOf(this));
174    hide();
175    /* Clear docked flag */
176    m_docked = false;
177    /* The window has been undocked, lets change the context menu */
178    setContextMenuDockText();
179 }
180
181 /*
182  * When a window is closed, this slot is called.  The idea is to put it back in the
183  * stack here, and it works.  I wanted to get it to the top of the stack so that the
184  * user immediately sees where his window went.  Also, if he undocks the window, then
185  * closes it with the tree item highlighted, it may be confusing that the highlighted
186  * treewidgetitem is not the stack item in the front.
187  */
188
189 void Pages::closeEvent(QCloseEvent* event)
190 {
191    /* A Widget was closed, lets toggle it back into the window, and set it in front. */
192    dockPage();
193
194    /* this fixes my woes of getting the widget to show up on top when closed */
195    event->ignore();
196
197    /* Set the current tree widget item in the Page Selector window to the item
198     * which represents "this"
199     * Which will also bring "this" to the top of the stacked widget */
200    setCurrent();
201 }
202
203 /*
204  * The next three are virtual functions.  The idea here is that each subclass will have the
205  * built in virtual function to override if the programmer wants to populate the window
206  * when it it is first clicked.
207  */
208 void Pages::PgSeltreeWidgetClicked()
209 {
210 }
211
212 /*
213  *  Virtual function which is called when this page is visible on the stack.
214  *  This will be overridden by classes that want to populate if they are on the
215  *  top.
216  */
217 void Pages::currentStackItem()
218 {
219 }
220
221 /*
222  * Function to close the stacked page and remove the widget from the
223  * Page selector window
224  */
225 void Pages::closeStackPage()
226 {
227    /* First get the tree widget item and destroy it */
228    QTreeWidgetItem *item=mainWin->getFromHash(this);
229    /* remove the QTreeWidgetItem <-> page from the hash */
230    if (item) {
231       mainWin->hashRemove(item, this);
232       /* remove the item from the page selector by destroying it */
233       delete item;
234    }
235    /* remove this */
236    delete this;
237 }
238
239 /*
240  * Function to set members from the external mainwin and it's overload being
241  * passed a specific QTreeWidgetItem to be it's parent on the tree
242  */
243 void Pages::pgInitialize()
244 {
245    pgInitialize(QString(), NULL);
246 }
247
248 void Pages::pgInitialize(const QString &name)
249 {
250    pgInitialize(name, NULL);
251 }
252
253 void Pages::pgInitialize(const QString &tname, QTreeWidgetItem *parentTreeWidgetItem)
254 {
255    m_docked = false;
256    m_onceDocked = false;
257    if (tname.size()) {
258       m_name = tname;
259    }
260    m_parent = mainWin->tabWidget;
261    m_console = mainWin->currentConsole();
262
263    if (!parentTreeWidgetItem) {
264       parentTreeWidgetItem = m_console->directorTreeItem();
265    }
266
267    QTreeWidgetItem *item = new QTreeWidgetItem(parentTreeWidgetItem);
268    QString name;
269    treeWidgetName(name);
270    item->setText(0, name);
271    mainWin->hashInsert(item, this);
272    setTitle();
273 }
274
275 /*
276  * Virtual Function to return a name
277  * All subclasses should override this function
278  */
279 void Pages::treeWidgetName(QString &name)
280 {
281    name = m_name;
282 }
283
284 /*
285  * Function to simplify executing a console command and bringing the
286  * console to the front of the stack
287  */
288 void Pages::consoleCommand(QString &command)
289 {
290    consoleCommand(command, true);
291 }
292
293 void Pages::consoleCommand(QString &command, bool setCurrent)
294 {
295    int conn;
296    if (m_console->getDirComm(conn)) {
297       consoleCommand(command, conn, setCurrent, true);
298    }
299 }
300
301 /*
302  * Lowest level of console command method.
303  * "notify" parameter default is set to true by higher level console command call.
304  * In most cases "notify" parameter should be set to true value because after console
305  * command sent, notifier should be always enabled for catch all Director responses.
306  */
307 void Pages::consoleCommand(QString &command, int conn, bool setCurrent, bool notify)
308 {
309    if (notify) {
310       m_console->notify(conn, true);
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 }