]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/qt-console/storage/storage.cpp
Apply pane freezing during updates patch from Riccardo Ghetta.
[bacula/bacula] / bacula / src / qt-console / storage / storage.cpp
1 /*
2    Bacula® - The Network Backup Solution
3
4    Copyright (C) 2007-2008 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 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 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 /*
30  *   Version $Id$
31  *
32  *  Storage Class
33  *
34  *   Dirk Bartley, March 2007
35  *
36  */ 
37
38 #include <QAbstractEventDispatcher>
39 #include <QMenu>
40 #include "bat.h"
41 #include "storage.h"
42 #include "label/label.h"
43 #include "mount/mount.h"
44 #include "status/storstat.h"
45 #include "util/fmtwidgetitem.h"
46
47 Storage::Storage()
48 {
49    setupUi(this);
50    pgInitialize(tr("Storage"));
51    QTreeWidgetItem* thisitem = mainWin->getFromHash(this);
52    thisitem->setIcon(0,QIcon(QString::fromUtf8(":images/package-x-generic.png")));
53
54    /* mp_treeWidget, Storage Tree Tree Widget inherited from ui_storage.h */
55    m_populated = false;
56    m_checkcurwidget = true;
57    m_closeable = false;
58    m_currentStorage = "";
59    /* add context sensitive menu items specific to this classto the page
60     * selector tree. m_contextActions is QList of QActions */
61    m_contextActions.append(actionRefreshStorage);
62    dockPage();
63 }
64
65 Storage::~Storage()
66 {
67    if (m_populated)
68       writeExpandedSettings();
69 }
70
71 /*
72  * The main meat of the class!!  The function that querries the director and 
73  * creates the widgets with appropriate values.
74  */
75 void Storage::populateTree()
76 {
77    if (!m_console->preventInUseConnect())
78        return;
79
80    if (m_populated)
81       writeExpandedSettings();
82    m_populated = true;
83
84    Freeze frz(*mp_treeWidget); /* disable updating*/
85
86    m_checkcurwidget = false;
87    mp_treeWidget->clear();
88    m_checkcurwidget = true;
89
90    QStringList headerlist = (QStringList() << tr("Name") << tr("Id")
91         << tr("Changer") << tr("Slot") << tr("Status") << tr("Enabled") << tr("Pool") 
92         << tr("Media Type") );
93
94    m_topItem = new QTreeWidgetItem(mp_treeWidget);
95    m_topItem->setText(0, tr("Storage"));
96    m_topItem->setData(0, Qt::UserRole, 0);
97    m_topItem->setExpanded(true);
98
99    mp_treeWidget->setColumnCount(headerlist.count());
100    mp_treeWidget->setHeaderLabels(headerlist);
101
102    QSettings settings(m_console->m_dir->name(), "bat");
103    settings.beginGroup("StorageTreeExpanded");
104
105    foreach(QString storageName, m_console->storage_list){
106       TreeItemFormatter storageItem(*m_topItem, 1);
107       storageItem.setTextFld(0, storageName);
108       if(settings.contains(storageName)) {
109          storageItem.widget()->setExpanded(settings.value(storageName).toBool());
110       } else {
111          storageItem.widget()->setExpanded(true);
112       }
113
114       /* Set up query QString and header QStringList */
115       QString query("SELECT StorageId AS ID, AutoChanger AS Changer"
116                " FROM Storage WHERE");
117       query += " Name='" + storageName + "'"
118                " ORDER BY Name";
119
120       QStringList results;
121       /* This could be a log item */
122       if (mainWin->m_sqlDebug) {
123          Pmsg1(000, "Storage query cmd : %s\n",query.toUtf8().data());
124       }
125       if (m_console->sql_cmd(query, results)) {
126          int resultCount = results.count();
127          if (resultCount == 1){
128             QString resultline;
129             QString field;
130             QStringList fieldlist;
131             /* there will only be one of these */
132             foreach (resultline, results) {
133                fieldlist = resultline.split("\t");
134                int index = 1;
135                QStringListIterator fld(fieldlist);
136  
137                /* storage id */
138                storageItem.setNumericFld(index++, fld.next() );
139  
140                /* changer */
141                storageItem.setBoolFld(index++, fld.next() );
142  
143                mediaList(storageItem.widget(), fieldlist.first());
144             }
145          }
146       }
147    }
148    /* Resize the columns */
149    for(int cnter=0; cnter<headerlist.size(); cnter++) {
150       mp_treeWidget->resizeColumnToContents(cnter);
151    }
152 }
153 void Storage::mediaList(QTreeWidgetItem *parent, const QString &storageID)
154 {
155    QString query("SELECT Media.VolumeName AS Media, Media.Slot AS Slot,"
156                  " Media.VolStatus AS VolStatus, Media.Enabled AS Enabled,"
157                  " Pool.Name AS MediaPool, Media.MediaType AS MediaType" 
158                  " From Media"
159                  " JOIN Pool ON (Media.PoolId=Pool.PoolId)"
160                  " WHERE Media.StorageId='" + storageID + "'"
161                  " AND Media.InChanger<>0"
162                  " ORDER BY Media.Slot");
163
164    QStringList results;
165    /* This could be a log item */
166    if (mainWin->m_sqlDebug) {
167       Pmsg1(000, "Storage query cmd : %s\n",query.toUtf8().data());
168    }
169    if (m_console->sql_cmd(query, results)) {
170       QString resultline;
171       QString field;
172       QStringList fieldlist;
173  
174       foreach (resultline, results) {
175          fieldlist = resultline.split("\t");
176          if (fieldlist.size() < 6)
177             continue; 
178
179          /* Iterate through fields in the record */
180          QStringListIterator fld(fieldlist);
181          int index = 0;
182          TreeItemFormatter fmt(*parent, 2);
183
184          /* volname */
185          fmt.setTextFld(index++, fld.next()); 
186  
187          /* skip the next two columns, unused by media */
188          index += 2;
189
190          /* slot */
191          fmt.setNumericFld(index++, fld.next());
192
193          /* status */
194          fmt.setVolStatusFld(index++, fld.next());
195
196          /* enabled */
197          fmt.setBoolFld(index++, fld.next()); 
198
199          /* pool */
200          fmt.setTextFld(index++, fld.next()); 
201
202          /* media type */
203          fmt.setTextFld(index++, fld.next()); 
204
205       }
206    }
207 }
208
209 /*
210  * When the treeWidgetItem in the page selector tree is singleclicked, Make sure
211  * The tree has been populated.
212  */
213 void Storage::PgSeltreeWidgetClicked()
214 {
215    if(!m_populated) {
216       populateTree();
217       createContextMenu();
218    }
219 }
220
221 /*
222  * Added to set the context menu policy based on currently active treeWidgetItem
223  * signaled by currentItemChanged
224  */
225 void Storage::treeItemChanged(QTreeWidgetItem *currentwidgetitem, QTreeWidgetItem *previouswidgetitem )
226 {
227    /* m_checkcurwidget checks to see if this is during a refresh, which will segfault */
228    if (m_checkcurwidget) {
229       /* The Previous item */
230       if (previouswidgetitem) { /* avoid a segfault if first time */
231          int treedepth = previouswidgetitem->data(0, Qt::UserRole).toInt();
232          if (treedepth == 1){
233             mp_treeWidget->removeAction(actionStatusStorageInConsole);
234             mp_treeWidget->removeAction(actionStatusStorageWindow);
235             mp_treeWidget->removeAction(actionLabelStorage);
236             mp_treeWidget->removeAction(actionMountStorage);
237             mp_treeWidget->removeAction(actionUnMountStorage);
238             mp_treeWidget->removeAction(actionUpdateSlots);
239             mp_treeWidget->removeAction(actionUpdateSlotsScan);
240             mp_treeWidget->removeAction(actionRelease);
241          }
242       }
243
244       int treedepth = currentwidgetitem->data(0, Qt::UserRole).toInt();
245       if (treedepth == 1){
246          /* set a hold variable to the storage name in case the context sensitive
247           * menu is used */
248          m_currentStorage = currentwidgetitem->text(0);
249          m_currentAutoChanger = currentwidgetitem->text(2) == tr("Yes");
250          mp_treeWidget->addAction(actionStatusStorageInConsole);
251          mp_treeWidget->addAction(actionStatusStorageWindow);
252          mp_treeWidget->addAction(actionLabelStorage);
253          mp_treeWidget->addAction(actionMountStorage);
254          mp_treeWidget->addAction(actionUnMountStorage);
255          mp_treeWidget->addAction(actionRelease);
256          QString text;
257          text = tr("Status Storage \"%1\"").arg(m_currentStorage);;
258          actionStatusStorageInConsole->setText(text);
259          text = tr("Status Storage \"%1\" in Window").arg(m_currentStorage);;
260          actionStatusStorageWindow->setText(text);
261          text = tr("Label media in Storage \"%1\"").arg(m_currentStorage);
262          actionLabelStorage->setText(text);
263          text = tr("Mount media in Storage \"%1\"").arg(m_currentStorage);
264          actionMountStorage->setText(text);
265          text = tr("\"UN\" Mount media in Storage \"%1\"").arg(m_currentStorage);
266          text = tr("Release media in Storage \"%1\"").arg(m_currentStorage);
267          actionRelease->setText(text);
268          if (m_currentAutoChanger) {
269             mp_treeWidget->addAction(actionUpdateSlots);
270             mp_treeWidget->addAction(actionUpdateSlotsScan);
271             text = tr("Barcode Scan media in Storage \"%1\"").arg(m_currentStorage);
272             actionUpdateSlots->setText(text);
273             text = tr("Read scan media in Storage \"%1\"").arg( m_currentStorage);
274             actionUpdateSlotsScan->setText(text);
275          }
276       }
277    }
278 }
279
280 /* 
281  * Setup a context menu 
282  * Made separate from populate so that it would not create context menu over and
283  * over as the tree is repopulated.
284  */
285 void Storage::createContextMenu()
286 {
287    mp_treeWidget->setContextMenuPolicy(Qt::ActionsContextMenu);
288    mp_treeWidget->addAction(actionRefreshStorage);
289    connect(mp_treeWidget, SIGNAL(
290            currentItemChanged(QTreeWidgetItem *, QTreeWidgetItem *)),
291            this, SLOT(treeItemChanged(QTreeWidgetItem *, QTreeWidgetItem *)));
292    /* connect to the action specific to this pages class */
293    connect(actionRefreshStorage, SIGNAL(triggered()), this,
294                 SLOT(populateTree()));
295    connect(actionStatusStorageInConsole, SIGNAL(triggered()), this,
296                 SLOT(consoleStatusStorage()));
297    connect(actionLabelStorage, SIGNAL(triggered()), this,
298                 SLOT(consoleLabelStorage()));
299    connect(actionMountStorage, SIGNAL(triggered()), this,
300                 SLOT(consoleMountStorage()));
301    connect(actionUnMountStorage, SIGNAL(triggered()), this,
302                 SLOT(consoleUnMountStorage()));
303    connect(actionUpdateSlots, SIGNAL(triggered()), this,
304                 SLOT(consoleUpdateSlots()));
305    connect(actionUpdateSlotsScan, SIGNAL(triggered()), this,
306                 SLOT(consoleUpdateSlotsScan()));
307    connect(actionRelease, SIGNAL(triggered()), this,
308                 SLOT(consoleRelease()));
309    connect(actionStatusStorageWindow, SIGNAL(triggered()), this,
310                 SLOT(statusStorageWindow()));
311 }
312
313 /*
314  * Virtual function which is called when this page is visible on the stack
315  */
316 void Storage::currentStackItem()
317 {
318    if(!m_populated) {
319       populateTree();
320       /* Create the context menu for the storage tree */
321       createContextMenu();
322    }
323 }
324
325 /*
326  *  Functions to respond to local context sensitive menu sending console commands
327  *  If I could figure out how to make these one function passing a string, Yaaaaaa
328  */
329 void Storage::consoleStatusStorage()
330 {
331    QString cmd("status storage=");
332    cmd += m_currentStorage;
333    consoleCommand(cmd);
334 }
335
336 /* Label Media populating current storage by default */
337 void Storage::consoleLabelStorage()
338 {
339    new labelPage(m_currentStorage);
340 }
341
342 /* Mount currently selected storage */
343 void Storage::consoleMountStorage()
344 {
345    if (m_currentAutoChanger == 0){
346       /* no autochanger, just execute the command in the console */
347       QString cmd("mount storage=");
348       cmd += m_currentStorage;
349       consoleCommand(cmd);
350    } else {
351       setConsoleCurrent();
352       /* if this storage is an autochanger, lets ask for the slot */
353       new mountDialog(m_console, m_currentStorage);
354    }
355 }
356
357 /* Unmount Currently selected storage */
358 void Storage::consoleUnMountStorage()
359 {
360    QString cmd("umount storage=");
361    cmd += m_currentStorage;
362    consoleCommand(cmd);
363 }
364
365 /* Update Slots */
366 void Storage::consoleUpdateSlots()
367 {
368    QString cmd("update slots storage=");
369    cmd += m_currentStorage;
370    consoleCommand(cmd);
371 }
372
373 /* Update Slots Scan*/
374 void Storage::consoleUpdateSlotsScan()
375 {
376    QString cmd("update slots scan storage=");
377    cmd += m_currentStorage;
378    consoleCommand(cmd);
379 }
380
381 /* Release a tape in the drive */
382 void Storage::consoleRelease()
383 {
384    QString cmd("release storage=");
385    cmd += m_currentStorage;
386    consoleCommand(cmd);
387 }
388
389 /*
390  *  Open a status storage window
391  */
392 void Storage::statusStorageWindow()
393 {
394    QTreeWidgetItem *parentItem = mainWin->getFromHash(this);
395    new StorStat(m_currentStorage, parentItem);
396 }
397
398 /*
399  * Write settings to save expanded states of the pools
400  */
401 void Storage::writeExpandedSettings()
402 {
403    QSettings settings(m_console->m_dir->name(), "bat");
404    settings.beginGroup("StorageTreeExpanded");
405    int childcount = m_topItem->childCount();
406    for (int cnt=0; cnt<childcount; cnt++) {
407       QTreeWidgetItem *item = m_topItem->child(cnt);
408       settings.setValue(item->text(0), item->isExpanded());
409    }
410    settings.endGroup();
411 }