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