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