]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/qt-console/storage/storage.cpp
This is the rather large commit of adding the feature to create multiple connections. I
[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 "bat.h"
39 #include <QAbstractEventDispatcher>
40 #include <QMenu>
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_populated)
78       writeExpandedSettings();
79    m_populated = true;
80
81    Freeze frz(*mp_treeWidget); /* disable updating*/
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    }
216 }
217
218 /*
219  * Added to set the context menu policy based on currently active treeWidgetItem
220  * signaled by currentItemChanged
221  */
222 void Storage::treeItemChanged(QTreeWidgetItem *currentwidgetitem, QTreeWidgetItem *previouswidgetitem )
223 {
224    /* m_checkcurwidget checks to see if this is during a refresh, which will segfault */
225    if (m_checkcurwidget) {
226       /* The Previous item */
227       if (previouswidgetitem) { /* avoid a segfault if first time */
228          int treedepth = previouswidgetitem->data(0, Qt::UserRole).toInt();
229          if (treedepth == 1){
230             mp_treeWidget->removeAction(actionStatusStorageInConsole);
231             mp_treeWidget->removeAction(actionStatusStorageWindow);
232             mp_treeWidget->removeAction(actionLabelStorage);
233             mp_treeWidget->removeAction(actionMountStorage);
234             mp_treeWidget->removeAction(actionUnMountStorage);
235             mp_treeWidget->removeAction(actionUpdateSlots);
236             mp_treeWidget->removeAction(actionUpdateSlotsScan);
237             mp_treeWidget->removeAction(actionRelease);
238          }
239       }
240
241       int treedepth = currentwidgetitem->data(0, Qt::UserRole).toInt();
242       if (treedepth == 1){
243          /* set a hold variable to the storage name in case the context sensitive
244           * menu is used */
245          m_currentStorage = currentwidgetitem->text(0);
246          m_currentAutoChanger = currentwidgetitem->text(2) == tr("Yes");
247          mp_treeWidget->addAction(actionStatusStorageInConsole);
248          mp_treeWidget->addAction(actionStatusStorageWindow);
249          mp_treeWidget->addAction(actionLabelStorage);
250          mp_treeWidget->addAction(actionMountStorage);
251          mp_treeWidget->addAction(actionUnMountStorage);
252          mp_treeWidget->addAction(actionRelease);
253          QString text;
254          text = tr("Status Storage \"%1\"").arg(m_currentStorage);;
255          actionStatusStorageInConsole->setText(text);
256          text = tr("Status Storage \"%1\" in Window").arg(m_currentStorage);;
257          actionStatusStorageWindow->setText(text);
258          text = tr("Label media in Storage \"%1\"").arg(m_currentStorage);
259          actionLabelStorage->setText(text);
260          text = tr("Mount media in Storage \"%1\"").arg(m_currentStorage);
261          actionMountStorage->setText(text);
262          text = tr("\"UN\" Mount media in Storage \"%1\"").arg(m_currentStorage);
263          text = tr("Release media in Storage \"%1\"").arg(m_currentStorage);
264          actionRelease->setText(text);
265          if (m_currentAutoChanger) {
266             mp_treeWidget->addAction(actionUpdateSlots);
267             mp_treeWidget->addAction(actionUpdateSlotsScan);
268             text = tr("Barcode Scan media in Storage \"%1\"").arg(m_currentStorage);
269             actionUpdateSlots->setText(text);
270             text = tr("Read scan media in Storage \"%1\"").arg( m_currentStorage);
271             actionUpdateSlotsScan->setText(text);
272          }
273       }
274    }
275 }
276
277 /* 
278  * Setup a context menu 
279  * Made separate from populate so that it would not create context menu over and
280  * over as the tree is repopulated.
281  */
282 void Storage::createContextMenu()
283 {
284    mp_treeWidget->setContextMenuPolicy(Qt::ActionsContextMenu);
285    mp_treeWidget->addAction(actionRefreshStorage);
286    connect(mp_treeWidget, SIGNAL(
287            currentItemChanged(QTreeWidgetItem *, QTreeWidgetItem *)),
288            this, SLOT(treeItemChanged(QTreeWidgetItem *, QTreeWidgetItem *)));
289    /* connect to the action specific to this pages class */
290    connect(actionRefreshStorage, SIGNAL(triggered()), this,
291                 SLOT(populateTree()));
292    connect(actionStatusStorageInConsole, SIGNAL(triggered()), this,
293                 SLOT(consoleStatusStorage()));
294    connect(actionLabelStorage, SIGNAL(triggered()), this,
295                 SLOT(consoleLabelStorage()));
296    connect(actionMountStorage, SIGNAL(triggered()), this,
297                 SLOT(consoleMountStorage()));
298    connect(actionUnMountStorage, SIGNAL(triggered()), this,
299                 SLOT(consoleUnMountStorage()));
300    connect(actionUpdateSlots, SIGNAL(triggered()), this,
301                 SLOT(consoleUpdateSlots()));
302    connect(actionUpdateSlotsScan, SIGNAL(triggered()), this,
303                 SLOT(consoleUpdateSlotsScan()));
304    connect(actionRelease, SIGNAL(triggered()), this,
305                 SLOT(consoleRelease()));
306    connect(actionStatusStorageWindow, SIGNAL(triggered()), this,
307                 SLOT(statusStorageWindow()));
308 }
309
310 /*
311  * Virtual function which is called when this page is visible on the stack
312  */
313 void Storage::currentStackItem()
314 {
315    if(!m_populated) {
316       populateTree();
317       /* Create the context menu for the storage tree */
318       createContextMenu();
319    }
320 }
321
322 /*
323  *  Functions to respond to local context sensitive menu sending console commands
324  *  If I could figure out how to make these one function passing a string, Yaaaaaa
325  */
326 void Storage::consoleStatusStorage()
327 {
328    QString cmd("status storage=");
329    cmd += m_currentStorage;
330    consoleCommand(cmd);
331 }
332
333 /* Label Media populating current storage by default */
334 void Storage::consoleLabelStorage()
335 {
336    new labelPage(m_currentStorage);
337 }
338
339 /* Mount currently selected storage */
340 void Storage::consoleMountStorage()
341 {
342    if (m_currentAutoChanger == 0){
343       /* no autochanger, just execute the command in the console */
344       QString cmd("mount storage=");
345       cmd += m_currentStorage;
346       consoleCommand(cmd);
347    } else {
348       setConsoleCurrent();
349       /* if this storage is an autochanger, lets ask for the slot */
350       new mountDialog(m_console, m_currentStorage);
351    }
352 }
353
354 /* Unmount Currently selected storage */
355 void Storage::consoleUnMountStorage()
356 {
357    QString cmd("umount storage=");
358    cmd += m_currentStorage;
359    consoleCommand(cmd);
360 }
361
362 /* Update Slots */
363 void Storage::consoleUpdateSlots()
364 {
365    QString cmd("update slots storage=");
366    cmd += m_currentStorage;
367    consoleCommand(cmd);
368 }
369
370 /* Update Slots Scan*/
371 void Storage::consoleUpdateSlotsScan()
372 {
373    QString cmd("update slots scan storage=");
374    cmd += m_currentStorage;
375    consoleCommand(cmd);
376 }
377
378 /* Release a tape in the drive */
379 void Storage::consoleRelease()
380 {
381    QString cmd("release storage=");
382    cmd += m_currentStorage;
383    consoleCommand(cmd);
384 }
385
386 /*
387  *  Open a status storage window
388  */
389 void Storage::statusStorageWindow()
390 {
391    QTreeWidgetItem *parentItem = mainWin->getFromHash(this);
392    new StorStat(m_currentStorage, parentItem);
393 }
394
395 /*
396  * Write settings to save expanded states of the pools
397  */
398 void Storage::writeExpandedSettings()
399 {
400    QSettings settings(m_console->m_dir->name(), "bat");
401    settings.beginGroup("StorageTreeExpanded");
402    int childcount = m_topItem->childCount();
403    for (int cnt=0; cnt<childcount; cnt++) {
404       QTreeWidgetItem *item = m_topItem->child(cnt);
405       settings.setValue(item->text(0), item->isExpanded());
406    }
407    settings.endGroup();
408 }