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