]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/qt-console/storage/storage.cpp
Commit of patch by Riccardo.
[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 John Walker.
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
83    m_checkcurwidget = false;
84    mp_treeWidget->clear();
85    m_checkcurwidget = true;
86
87    QStringList headerlist = (QStringList() << tr("Name") << tr("Id")
88         << tr("Changer") << tr("Slot") << tr("Status") << tr("Enabled") << tr("Pool") 
89         << tr("Media Type") );
90
91    m_topItem = new QTreeWidgetItem(mp_treeWidget);
92    m_topItem->setText(0, tr("Storage"));
93    m_topItem->setData(0, Qt::UserRole, 0);
94    m_topItem->setExpanded(true);
95
96    mp_treeWidget->setColumnCount(headerlist.count());
97    mp_treeWidget->setHeaderLabels(headerlist);
98
99    QSettings settings(m_console->m_dir->name(), "bat");
100    settings.beginGroup("StorageTreeExpanded");
101
102    foreach(QString storageName, m_console->storage_list){
103       TreeItemFormatter storageItem(*m_topItem, 1);
104       storageItem.setTextFld(0, storageName);
105       if(settings.contains(storageName)) {
106          storageItem.widget()->setExpanded(settings.value(storageName).toBool());
107       } else {
108          storageItem.widget()->setExpanded(true);
109       }
110
111       /* Set up query QString and header QStringList */
112       QString query("SELECT StorageId AS ID, AutoChanger AS Changer"
113                " FROM Storage WHERE");
114       query += " Name='" + storageName + "'"
115                " ORDER BY Name";
116
117       QStringList results;
118       /* This could be a log item */
119       if (mainWin->m_sqlDebug) {
120          Pmsg1(000, "Storage query cmd : %s\n",query.toUtf8().data());
121       }
122       if (m_console->sql_cmd(query, results)) {
123          int resultCount = results.count();
124          if (resultCount == 1){
125             QString resultline;
126             QString field;
127             QStringList fieldlist;
128             /* there will only be one of these */
129             foreach (resultline, results) {
130                fieldlist = resultline.split("\t");
131                int index = 1;
132                QStringListIterator fld(fieldlist);
133  
134                /* storage id */
135                storageItem.setNumericFld(index++, fld.next() );
136  
137                /* changer */
138                storageItem.setBoolFld(index++, fld.next() );
139  
140                mediaList(storageItem.widget(), fieldlist.first());
141             }
142          }
143       }
144    }
145    /* Resize the columns */
146    for(int cnter=0; cnter<headerlist.size(); cnter++) {
147       mp_treeWidget->resizeColumnToContents(cnter);
148    }
149 }
150 void Storage::mediaList(QTreeWidgetItem *parent, const QString &storageID)
151 {
152    QString query("SELECT Media.VolumeName AS Media, Media.Slot AS Slot,"
153                  " Media.VolStatus AS VolStatus, Media.Enabled AS Enabled,"
154                  " Pool.Name AS MediaPool, Media.MediaType AS MediaType" 
155                  " From Media"
156                  " JOIN Pool ON (Media.PoolId=Pool.PoolId)"
157                  " WHERE Media.StorageId='" + storageID + "'"
158                  " AND Media.InChanger<>0"
159                  " ORDER BY Media.Slot");
160
161    QStringList results;
162    /* This could be a log item */
163    if (mainWin->m_sqlDebug) {
164       Pmsg1(000, "Storage query cmd : %s\n",query.toUtf8().data());
165    }
166    if (m_console->sql_cmd(query, results)) {
167       QString resultline;
168       QString field;
169       QStringList fieldlist;
170  
171       foreach (resultline, results) {
172          fieldlist = resultline.split("\t");
173          if (fieldlist.size() < 6)
174             continue; 
175
176          /* Iterate through fields in the record */
177          QStringListIterator fld(fieldlist);
178          int index = 0;
179          TreeItemFormatter fmt(*parent, 2);
180
181          /* volname */
182          fmt.setTextFld(index++, fld.next()); 
183  
184          /* skip the next two columns, unused by media */
185          index += 2;
186
187          /* slot */
188          fmt.setNumericFld(index++, fld.next());
189
190          /* status */
191          fmt.setVolStatusFld(index++, fld.next());
192
193          /* enabled */
194          fmt.setBoolFld(index++, fld.next()); 
195
196          /* pool */
197          fmt.setTextFld(index++, fld.next()); 
198
199          /* media type */
200          fmt.setTextFld(index++, fld.next()); 
201
202       }
203    }
204 }
205
206 /*
207  * When the treeWidgetItem in the page selector tree is singleclicked, Make sure
208  * The tree has been populated.
209  */
210 void Storage::PgSeltreeWidgetClicked()
211 {
212    if(!m_populated) {
213       populateTree();
214       createContextMenu();
215       m_populated = true;
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       m_populated = true;
321    }
322 }
323
324 /*
325  *  Functions to respond to local context sensitive menu sending console commands
326  *  If I could figure out how to make these one function passing a string, Yaaaaaa
327  */
328 void Storage::consoleStatusStorage()
329 {
330    QString cmd("status storage=");
331    cmd += m_currentStorage;
332    consoleCommand(cmd);
333 }
334
335 /* Label Media populating current storage by default */
336 void Storage::consoleLabelStorage()
337 {
338    new labelPage(m_currentStorage);
339 }
340
341 /* Mount currently selected storage */
342 void Storage::consoleMountStorage()
343 {
344    if (m_currentAutoChanger == 0){
345       /* no autochanger, just execute the command in the console */
346       QString cmd("mount storage=");
347       cmd += m_currentStorage;
348       consoleCommand(cmd);
349    } else {
350       setConsoleCurrent();
351       /* if this storage is an autochanger, lets ask for the slot */
352       new mountDialog(m_console, m_currentStorage);
353    }
354 }
355
356 /* Unmount Currently selected storage */
357 void Storage::consoleUnMountStorage()
358 {
359    QString cmd("umount storage=");
360    cmd += m_currentStorage;
361    consoleCommand(cmd);
362 }
363
364 /* Update Slots */
365 void Storage::consoleUpdateSlots()
366 {
367    QString cmd("update slots storage=");
368    cmd += m_currentStorage;
369    consoleCommand(cmd);
370 }
371
372 /* Update Slots Scan*/
373 void Storage::consoleUpdateSlotsScan()
374 {
375    QString cmd("update slots scan storage=");
376    cmd += m_currentStorage;
377    consoleCommand(cmd);
378 }
379
380 /* Release a tape in the drive */
381 void Storage::consoleRelease()
382 {
383    QString cmd("release storage=");
384    cmd += m_currentStorage;
385    consoleCommand(cmd);
386 }
387
388 /*
389  *  Open a status storage window
390  */
391 void Storage::statusStorageWindow()
392 {
393    QTreeWidgetItem *parentItem = mainWin->getFromHash(this);
394    new StorStat(m_currentStorage, parentItem);
395 }
396
397 /*
398  * Write settings to save expanded states of the pools
399  */
400 void Storage::writeExpandedSettings()
401 {
402    QSettings settings(m_console->m_dir->name(), "bat");
403    settings.beginGroup("StorageTreeExpanded");
404    int childcount = m_topItem->childCount();
405    for (int cnt=0; cnt<childcount; cnt++) {
406       QTreeWidgetItem *item = m_topItem->child(cnt);
407       settings.setValue(item->text(0), item->isExpanded());
408    }
409    settings.endGroup();
410 }