2 Bacula(R) - The Network Backup Solution
4 Copyright (C) 2000-2015 Kern Sibbald
5 Copyright (C) 2007-2010 Free Software Foundation Europe e.V.
7 The original author of Bacula is Kern Sibbald, with contributions
8 from many others, a complete list can be found in the file AUTHORS.
10 You may use this file and others of this release according to the
11 license defined in the LICENSE file, which includes the Affero General
12 Public License, v3.0 ("AGPLv3") and some additional permissions and
13 terms pursuant to its AGPLv3 Section 7.
15 This notice must be preserved when any source code is
16 conveyed and/or propagated.
18 Bacula(R) is a registered trademark of Kern Sibbald.
25 * Dirk Bartley, March 2007
30 #include <QAbstractEventDispatcher>
34 #include "label/label.h"
35 #include "mount/mount.h"
36 #include "status/storstat.h"
37 #include "util/fmtwidgetitem.h"
39 Storage::Storage() : Pages()
42 pgInitialize(tr("Storage"));
43 QTreeWidgetItem* thisitem = mainWin->getFromHash(this);
44 thisitem->setIcon(0,QIcon(QString::fromUtf8(":images/package-x-generic.png")));
46 /* mp_treeWidget, Storage Tree Tree Widget inherited from ui_storage.h */
48 m_firstpopulation = true;
49 m_checkcurwidget = true;
51 m_currentStorage = "";
52 /* add context sensitive menu items specific to this classto the page
53 * selector tree. m_contextActions is QList of QActions */
54 m_contextActions.append(actionRefreshStorage);
60 writeExpandedSettings();
64 * The main meat of the class!! The function that querries the director and
65 * creates the widgets with appropriate values.
67 void Storage::populateTree()
70 writeExpandedSettings();
73 Freeze frz(*mp_treeWidget); /* disable updating */
75 m_checkcurwidget = false;
76 mp_treeWidget->clear();
77 m_checkcurwidget = true;
79 QStringList headerlist = (QStringList() << tr("Name") << tr("Id")
80 << tr("Changer") << tr("Slot") << tr("Status") << tr("Enabled") << tr("Pool")
81 << tr("Media Type") );
83 m_topItem = new QTreeWidgetItem(mp_treeWidget);
84 m_topItem->setText(0, tr("Storage"));
85 m_topItem->setData(0, Qt::UserRole, 0);
86 m_topItem->setExpanded(true);
88 mp_treeWidget->setColumnCount(headerlist.count());
89 mp_treeWidget->setHeaderLabels(headerlist);
91 QSettings settings(m_console->m_dir->name(), "bat");
92 settings.beginGroup("StorageTreeExpanded");
95 QString storage_comsep("");
97 foreach(storageName, m_console->storage_list){
99 storage_comsep += "'" + storageName + "'";
103 storage_comsep += ",'" + storageName + "'";
105 if (storage_comsep != "") {
107 /* Set up query QString and header QStringList */
108 QString query("SELECT"
109 " Name AS StorageName,"
110 " StorageId AS ID, AutoChanger AS Changer"
112 " WHERE StorageId IN (SELECT MAX(StorageId) FROM Storage WHERE");
113 query += " Name IN (" + storage_comsep + ")";
114 query += " GROUP BY Name) ORDER BY Name";
117 /* This could be a log item */
118 if (mainWin->m_sqlDebug) {
119 Pmsg1(000, "Storage query cmd : %s\n",query.toUtf8().data());
121 if (m_console->sql_cmd(query, results)) {
123 QStringList fieldlist;
124 foreach (QString resultline, results) {
125 fieldlist = resultline.split("\t");
126 if (fieldlist.size() != 3) {
127 Pmsg1(000, "Unexpected line %s", resultline.toUtf8().data());
130 storageName = fieldlist.takeFirst();
131 if (m_firstpopulation) {
132 settingsOpenStatus(storageName);
134 TreeItemFormatter storageItem(*m_topItem, 1);
135 storageItem.setTextFld(0, storageName);
136 if(settings.contains(storageName))
137 storageItem.widget()->setExpanded(settings.value(storageName).toBool());
139 storageItem.widget()->setExpanded(true);
142 QStringListIterator fld(fieldlist);
145 storageItem.setNumericFld(index++, fld.next() );
148 QString changer = fld.next();
149 storageItem.setBoolFld(index++, changer);
152 mediaList(storageItem.widget(), fieldlist.first());
156 /* Resize the columns */
157 for(int cnter=0; cnter<headerlist.size(); cnter++) {
158 mp_treeWidget->resizeColumnToContents(cnter);
160 m_firstpopulation = false;
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()
232 if (!isOnceDocked()) {
238 * Added to set the context menu policy based on currently active treeWidgetItem
239 * signaled by currentItemChanged
241 void Storage::treeItemChanged(QTreeWidgetItem *currentwidgetitem, QTreeWidgetItem *previouswidgetitem )
243 /* m_checkcurwidget checks to see if this is during a refresh, which will segfault */
244 if (m_checkcurwidget) {
245 /* The Previous item */
246 if (previouswidgetitem) { /* avoid a segfault if first time */
247 int treedepth = previouswidgetitem->data(0, Qt::UserRole).toInt();
249 mp_treeWidget->removeAction(actionStatusStorageInConsole);
250 mp_treeWidget->removeAction(actionStatusStorageWindow);
251 mp_treeWidget->removeAction(actionLabelStorage);
252 mp_treeWidget->removeAction(actionMountStorage);
253 mp_treeWidget->removeAction(actionUnMountStorage);
254 mp_treeWidget->removeAction(actionUpdateSlots);
255 mp_treeWidget->removeAction(actionUpdateSlotsScan);
256 mp_treeWidget->removeAction(actionRelease);
260 int treedepth = currentwidgetitem->data(0, Qt::UserRole).toInt();
262 /* set a hold variable to the storage name in case the context sensitive
264 m_currentStorage = currentwidgetitem->text(0);
265 m_currentAutoChanger = currentwidgetitem->text(2) == tr("Yes");
266 mp_treeWidget->addAction(actionStatusStorageInConsole);
267 mp_treeWidget->addAction(actionStatusStorageWindow);
268 mp_treeWidget->addAction(actionLabelStorage);
269 mp_treeWidget->addAction(actionMountStorage);
270 mp_treeWidget->addAction(actionUnMountStorage);
271 mp_treeWidget->addAction(actionRelease);
273 text = tr("Status Storage \"%1\"").arg(m_currentStorage);;
274 actionStatusStorageInConsole->setText(text);
275 text = tr("Status Storage \"%1\" in Window").arg(m_currentStorage);;
276 actionStatusStorageWindow->setText(text);
277 text = tr("Label media in Storage \"%1\"").arg(m_currentStorage);
278 actionLabelStorage->setText(text);
279 text = tr("Mount media in Storage \"%1\"").arg(m_currentStorage);
280 actionMountStorage->setText(text);
281 text = tr("\"UN\" Mount media in Storage \"%1\"").arg(m_currentStorage);
282 text = tr("Release media in Storage \"%1\"").arg(m_currentStorage);
283 actionRelease->setText(text);
284 if (m_currentAutoChanger) {
285 mp_treeWidget->addAction(actionUpdateSlots);
286 mp_treeWidget->addAction(actionUpdateSlotsScan);
287 text = tr("Barcode Scan media in Storage \"%1\"").arg(m_currentStorage);
288 actionUpdateSlots->setText(text);
289 text = tr("Read scan media in Storage \"%1\"").arg( m_currentStorage);
290 actionUpdateSlotsScan->setText(text);
297 * Setup a context menu
298 * Made separate from populate so that it would not create context menu over and
299 * over as the tree is repopulated.
301 void Storage::createContextMenu()
303 mp_treeWidget->setContextMenuPolicy(Qt::ActionsContextMenu);
304 mp_treeWidget->addAction(actionRefreshStorage);
305 connect(mp_treeWidget, SIGNAL(
306 currentItemChanged(QTreeWidgetItem *, QTreeWidgetItem *)),
307 this, SLOT(treeItemChanged(QTreeWidgetItem *, QTreeWidgetItem *)));
308 /* connect to the action specific to this pages class */
309 connect(actionRefreshStorage, SIGNAL(triggered()), this,
310 SLOT(populateTree()));
311 connect(actionStatusStorageInConsole, SIGNAL(triggered()), this,
312 SLOT(consoleStatusStorage()));
313 connect(actionLabelStorage, SIGNAL(triggered()), this,
314 SLOT(consoleLabelStorage()));
315 connect(actionMountStorage, SIGNAL(triggered()), this,
316 SLOT(consoleMountStorage()));
317 connect(actionUnMountStorage, SIGNAL(triggered()), this,
318 SLOT(consoleUnMountStorage()));
319 connect(actionUpdateSlots, SIGNAL(triggered()), this,
320 SLOT(consoleUpdateSlots()));
321 connect(actionUpdateSlotsScan, SIGNAL(triggered()), this,
322 SLOT(consoleUpdateSlotsScan()));
323 connect(actionRelease, SIGNAL(triggered()), this,
324 SLOT(consoleRelease()));
325 connect(actionStatusStorageWindow, SIGNAL(triggered()), this,
326 SLOT(statusStorageWindow()));
327 connect(mp_treeWidget, SIGNAL(itemDoubleClicked(QTreeWidgetItem *, int)),
328 this, SLOT(contentWindow()));
332 void Storage::contentWindow()
334 if (m_currentStorage != "" && m_currentAutoChanger) {
335 QTreeWidgetItem *parentItem = mainWin->getFromHash(this);
336 new Content(m_currentStorage, parentItem);
341 * Virtual function which is called when this page is visible on the stack
343 void Storage::currentStackItem()
347 /* Create the context menu for the storage tree */
353 * Functions to respond to local context sensitive menu sending console commands
354 * If I could figure out how to make these one function passing a string, Yaaaaaa
356 void Storage::consoleStatusStorage()
358 QString cmd("status storage=");
359 cmd += m_currentStorage;
363 /* Label Media populating current storage by default */
364 void Storage::consoleLabelStorage()
366 new labelPage(m_currentStorage);
369 /* Mount currently selected storage */
370 void Storage::consoleMountStorage()
372 if (m_currentAutoChanger == 0){
373 /* no autochanger, just execute the command in the console */
374 QString cmd("mount storage=");
375 cmd += m_currentStorage;
379 /* if this storage is an autochanger, lets ask for the slot */
380 new mountDialog(m_console, m_currentStorage);
384 /* Unmount Currently selected storage */
385 void Storage::consoleUnMountStorage()
387 QString cmd("umount storage=");
388 cmd += m_currentStorage;
393 void Storage::consoleUpdateSlots()
395 QString cmd("update slots storage=");
396 cmd += m_currentStorage;
400 /* Update Slots Scan*/
401 void Storage::consoleUpdateSlotsScan()
403 QString cmd("update slots scan storage=");
404 cmd += m_currentStorage;
408 /* Release a tape in the drive */
409 void Storage::consoleRelease()
411 QString cmd("release storage=");
412 cmd += m_currentStorage;
417 * Open a status storage window
419 void Storage::statusStorageWindow()
421 /* if one exists, then just set it current */
423 foreach(Pages *page, mainWin->m_pagehash) {
424 if (mainWin->currentConsole() == page->console()) {
425 if (page->name() == tr("Storage Status %1").arg(m_currentStorage)) {
432 QTreeWidgetItem *parentItem = mainWin->getFromHash(this);
433 new StorStat(m_currentStorage, parentItem);
438 * Write settings to save expanded states of the pools
440 void Storage::writeExpandedSettings()
442 QSettings settings(m_console->m_dir->name(), "bat");
443 settings.beginGroup("StorageTreeExpanded");
444 int childcount = m_topItem->childCount();
445 for (int cnt=0; cnt<childcount; cnt++) {
446 QTreeWidgetItem *item = m_topItem->child(cnt);
447 settings.setValue(item->text(0), item->isExpanded());
453 * If first time, then check to see if there were status pages open the last time closed
456 void Storage::settingsOpenStatus(QString &storage)
458 QSettings settings(m_console->m_dir->name(), "bat");
460 settings.beginGroup("OpenOnExit");
461 QString toRead = "StorageStatus_" + storage;
462 if (settings.value(toRead) == 1) {
463 if (mainWin->m_sqlDebug) {
464 Pmsg1(000, "Do open Storage Status window for : %s\n", storage.toUtf8().data());
466 new StorStat(storage, mainWin->getFromHash(this));
468 mainWin->getFromHash(this)->setExpanded(true);
470 if (mainWin->m_sqlDebug) {
471 Pmsg1(000, "Do NOT open Storage Status window for : %s\n", storage.toUtf8().data());