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