2 Bacula® - The Network Backup Solution
4 Copyright (C) 2007-2008 Free Software Foundation Europe e.V.
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
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.
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
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.
34 * Dirk Bartley, March 2007
39 #include <QAbstractEventDispatcher>
42 #include "label/label.h"
43 #include "mount/mount.h"
44 #include "status/storstat.h"
45 #include "util/fmtwidgetitem.h"
50 pgInitialize(tr("Storage"));
51 QTreeWidgetItem* thisitem = mainWin->getFromHash(this);
52 thisitem->setIcon(0,QIcon(QString::fromUtf8(":images/package-x-generic.png")));
54 /* mp_treeWidget, Storage Tree Tree Widget inherited from ui_storage.h */
56 m_checkcurwidget = true;
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);
68 writeExpandedSettings();
72 * The main meat of the class!! The function that querries the director and
73 * creates the widgets with appropriate values.
75 void Storage::populateTree()
78 writeExpandedSettings();
81 Freeze frz(*mp_treeWidget); /* disable updating */
83 m_checkcurwidget = false;
84 mp_treeWidget->clear();
85 m_checkcurwidget = true;
87 QStringList headerlist = (QStringList() << tr("Name") << tr("Id")
88 << tr("Changer") << tr("Slot") << tr("Status") << tr("Enabled") << tr("Pool")
89 << tr("Media Type") );
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);
96 mp_treeWidget->setColumnCount(headerlist.count());
97 mp_treeWidget->setHeaderLabels(headerlist);
99 QSettings settings(m_console->m_dir->name(), "bat");
100 settings.beginGroup("StorageTreeExpanded");
103 QString storage_comsep("");
105 foreach(storageName, m_console->storage_list){
107 storage_comsep += "'" + storageName + "'";
111 storage_comsep += ",'" + storageName + "'";
113 if (storage_comsep != "") {
115 /* Set up query QString and header QStringList */
116 QString query("SELECT"
117 " Name AS StorageName,"
118 " StorageId AS ID, AutoChanger AS Changer"
120 " WHERE StorageId IN (SELECT MAX(StorageId) FROM Storage WHERE");
121 query += " Name IN (" + storage_comsep + ")";
122 query += " GROUP BY Name) ORDER BY Name";
125 /* This could be a log item */
126 if (mainWin->m_sqlDebug) {
127 Pmsg1(000, "Storage query cmd : %s\n",query.toUtf8().data());
129 if (m_console->sql_cmd(query, results)) {
131 QStringList fieldlist;
132 foreach (QString resultline, results) {
133 fieldlist = resultline.split("\t");
134 storageName = fieldlist.takeFirst();
135 TreeItemFormatter storageItem(*m_topItem, 1);
136 storageItem.setTextFld(0, storageName);
137 if(settings.contains(storageName))
138 storageItem.widget()->setExpanded(settings.value(storageName).toBool());
140 storageItem.widget()->setExpanded(true);
143 QStringListIterator fld(fieldlist);
146 storageItem.setNumericFld(index++, fld.next() );
149 QString changer = fld.next();
150 storageItem.setBoolFld(index++, changer);
153 mediaList(storageItem.widget(), fieldlist.first());
157 /* Resize the columns */
158 for(int cnter=0; cnter<headerlist.size(); cnter++) {
159 mp_treeWidget->resizeColumnToContents(cnter);
164 * For autochangers A query to show the tapes in the changer.
166 void Storage::mediaList(QTreeWidgetItem *parent, const QString &storageID)
168 QString query("SELECT Media.VolumeName AS Media, Media.Slot AS Slot,"
169 " Media.VolStatus AS VolStatus, Media.Enabled AS Enabled,"
170 " Pool.Name AS MediaPool, Media.MediaType AS MediaType"
172 " JOIN Pool ON (Media.PoolId=Pool.PoolId)"
173 " WHERE Media.StorageId='" + storageID + "'"
174 " AND Media.InChanger<>0"
175 " ORDER BY Media.Slot");
178 /* This could be a log item */
179 if (mainWin->m_sqlDebug) {
180 Pmsg1(000, "Storage query cmd : %s\n",query.toUtf8().data());
182 if (m_console->sql_cmd(query, results)) {
185 QStringList fieldlist;
187 foreach (resultline, results) {
188 fieldlist = resultline.split("\t");
189 if (fieldlist.size() < 6)
192 /* Iterate through fields in the record */
193 QStringListIterator fld(fieldlist);
195 TreeItemFormatter fmt(*parent, 2);
198 fmt.setTextFld(index++, fld.next());
200 /* skip the next two columns, unused by media */
204 fmt.setNumericFld(index++, fld.next());
207 fmt.setVolStatusFld(index++, fld.next());
210 fmt.setBoolFld(index++, fld.next());
213 fmt.setTextFld(index++, fld.next());
216 fmt.setTextFld(index++, fld.next());
223 * When the treeWidgetItem in the page selector tree is singleclicked, Make sure
224 * The tree has been populated.
226 void Storage::PgSeltreeWidgetClicked()
235 * Added to set the context menu policy based on currently active treeWidgetItem
236 * signaled by currentItemChanged
238 void Storage::treeItemChanged(QTreeWidgetItem *currentwidgetitem, QTreeWidgetItem *previouswidgetitem )
240 /* m_checkcurwidget checks to see if this is during a refresh, which will segfault */
241 if (m_checkcurwidget) {
242 /* The Previous item */
243 if (previouswidgetitem) { /* avoid a segfault if first time */
244 int treedepth = previouswidgetitem->data(0, Qt::UserRole).toInt();
246 mp_treeWidget->removeAction(actionStatusStorageInConsole);
247 mp_treeWidget->removeAction(actionStatusStorageWindow);
248 mp_treeWidget->removeAction(actionLabelStorage);
249 mp_treeWidget->removeAction(actionMountStorage);
250 mp_treeWidget->removeAction(actionUnMountStorage);
251 mp_treeWidget->removeAction(actionUpdateSlots);
252 mp_treeWidget->removeAction(actionUpdateSlotsScan);
253 mp_treeWidget->removeAction(actionRelease);
257 int treedepth = currentwidgetitem->data(0, Qt::UserRole).toInt();
259 /* set a hold variable to the storage name in case the context sensitive
261 m_currentStorage = currentwidgetitem->text(0);
262 m_currentAutoChanger = currentwidgetitem->text(2) == tr("Yes");
263 mp_treeWidget->addAction(actionStatusStorageInConsole);
264 mp_treeWidget->addAction(actionStatusStorageWindow);
265 mp_treeWidget->addAction(actionLabelStorage);
266 mp_treeWidget->addAction(actionMountStorage);
267 mp_treeWidget->addAction(actionUnMountStorage);
268 mp_treeWidget->addAction(actionRelease);
270 text = tr("Status Storage \"%1\"").arg(m_currentStorage);;
271 actionStatusStorageInConsole->setText(text);
272 text = tr("Status Storage \"%1\" in Window").arg(m_currentStorage);;
273 actionStatusStorageWindow->setText(text);
274 text = tr("Label media in Storage \"%1\"").arg(m_currentStorage);
275 actionLabelStorage->setText(text);
276 text = tr("Mount media in Storage \"%1\"").arg(m_currentStorage);
277 actionMountStorage->setText(text);
278 text = tr("\"UN\" Mount media in Storage \"%1\"").arg(m_currentStorage);
279 text = tr("Release media in Storage \"%1\"").arg(m_currentStorage);
280 actionRelease->setText(text);
281 if (m_currentAutoChanger) {
282 mp_treeWidget->addAction(actionUpdateSlots);
283 mp_treeWidget->addAction(actionUpdateSlotsScan);
284 text = tr("Barcode Scan media in Storage \"%1\"").arg(m_currentStorage);
285 actionUpdateSlots->setText(text);
286 text = tr("Read scan media in Storage \"%1\"").arg( m_currentStorage);
287 actionUpdateSlotsScan->setText(text);
294 * Setup a context menu
295 * Made separate from populate so that it would not create context menu over and
296 * over as the tree is repopulated.
298 void Storage::createContextMenu()
300 mp_treeWidget->setContextMenuPolicy(Qt::ActionsContextMenu);
301 mp_treeWidget->addAction(actionRefreshStorage);
302 connect(mp_treeWidget, SIGNAL(
303 currentItemChanged(QTreeWidgetItem *, QTreeWidgetItem *)),
304 this, SLOT(treeItemChanged(QTreeWidgetItem *, QTreeWidgetItem *)));
305 /* connect to the action specific to this pages class */
306 connect(actionRefreshStorage, SIGNAL(triggered()), this,
307 SLOT(populateTree()));
308 connect(actionStatusStorageInConsole, SIGNAL(triggered()), this,
309 SLOT(consoleStatusStorage()));
310 connect(actionLabelStorage, SIGNAL(triggered()), this,
311 SLOT(consoleLabelStorage()));
312 connect(actionMountStorage, SIGNAL(triggered()), this,
313 SLOT(consoleMountStorage()));
314 connect(actionUnMountStorage, SIGNAL(triggered()), this,
315 SLOT(consoleUnMountStorage()));
316 connect(actionUpdateSlots, SIGNAL(triggered()), this,
317 SLOT(consoleUpdateSlots()));
318 connect(actionUpdateSlotsScan, SIGNAL(triggered()), this,
319 SLOT(consoleUpdateSlotsScan()));
320 connect(actionRelease, SIGNAL(triggered()), this,
321 SLOT(consoleRelease()));
322 connect(actionStatusStorageWindow, SIGNAL(triggered()), this,
323 SLOT(statusStorageWindow()));
327 * Virtual function which is called when this page is visible on the stack
329 void Storage::currentStackItem()
333 /* Create the context menu for the storage tree */
339 * Functions to respond to local context sensitive menu sending console commands
340 * If I could figure out how to make these one function passing a string, Yaaaaaa
342 void Storage::consoleStatusStorage()
344 QString cmd("status storage=");
345 cmd += m_currentStorage;
349 /* Label Media populating current storage by default */
350 void Storage::consoleLabelStorage()
352 new labelPage(m_currentStorage);
355 /* Mount currently selected storage */
356 void Storage::consoleMountStorage()
358 if (m_currentAutoChanger == 0){
359 /* no autochanger, just execute the command in the console */
360 QString cmd("mount storage=");
361 cmd += m_currentStorage;
365 /* if this storage is an autochanger, lets ask for the slot */
366 new mountDialog(m_console, m_currentStorage);
370 /* Unmount Currently selected storage */
371 void Storage::consoleUnMountStorage()
373 QString cmd("umount storage=");
374 cmd += m_currentStorage;
379 void Storage::consoleUpdateSlots()
381 QString cmd("update slots storage=");
382 cmd += m_currentStorage;
386 /* Update Slots Scan*/
387 void Storage::consoleUpdateSlotsScan()
389 QString cmd("update slots scan storage=");
390 cmd += m_currentStorage;
394 /* Release a tape in the drive */
395 void Storage::consoleRelease()
397 QString cmd("release storage=");
398 cmd += m_currentStorage;
403 * Open a status storage window
405 void Storage::statusStorageWindow()
407 QTreeWidgetItem *parentItem = mainWin->getFromHash(this);
408 new StorStat(m_currentStorage, parentItem);
412 * Write settings to save expanded states of the pools
414 void Storage::writeExpandedSettings()
416 QSettings settings(m_console->m_dir->name(), "bat");
417 settings.beginGroup("StorageTreeExpanded");
418 int childcount = m_topItem->childCount();
419 for (int cnt=0; cnt<childcount; cnt++) {
420 QTreeWidgetItem *item = m_topItem->child(cnt);
421 settings.setValue(item->text(0), item->isExpanded());