]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/qt-console/medialist/medialist.cpp
Add icons for the page selector.
[bacula/bacula] / bacula / src / qt-console / medialist / medialist.cpp
1 /*
2    Bacula® - The Network Backup Solution
3
4    Copyright (C) 2000-2007 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 plus additions
11    that are listed 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: medialist.cpp 4230 2007-02-21 20:07:37Z kerns $
31  *
32  *  MediaList Class
33  *
34  *   Dirk Bartley, March 2007
35  *
36  */ 
37
38 #include <QAbstractEventDispatcher>
39 #include <QMenu>
40 #include "bat.h"
41 #include "medialist.h"
42 #include "mediaedit/mediaedit.h"
43 #include "joblist/joblist.h"
44 #include "relabel/relabel.h"
45
46 MediaList::MediaList()
47 {
48    setupUi(this);
49    m_name = "Media";
50    pgInitialize();
51    QTreeWidgetItem* thisitem = mainWin->getFromHash(this);
52    thisitem->setIcon(0,QIcon(QString::fromUtf8(":images/cartridge.png")));
53
54    /* mp_treeWidget, Storage Tree Tree Widget inherited from ui_medialist.h */
55    m_populated = false;
56    m_checkcurwidget = true;
57    m_closeable = false;
58 }
59
60 MediaList::~MediaList()
61 {
62 }
63
64 /*
65  * The main meat of the class!!  The function that querries the director and 
66  * creates the widgets with appropriate values.
67  */
68 void MediaList::populateTree()
69 {
70    QTreeWidgetItem *mediatreeitem, *pooltreeitem, *topItem;
71
72    if (!m_console->preventInUseConnect())
73        return;
74
75    QStringList headerlist = (QStringList()
76       << "Volume Name" << "Id" << "Status" << "Enabled"
77       << "Bytes" << "Files" << "Jobs" << "Retention" 
78       << "Media Type" << "Slot" << "Last Written");
79    int statusIndex = headerlist.indexOf("Status");
80
81    m_checkcurwidget = false;
82    mp_treeWidget->clear();
83    m_checkcurwidget = true;
84    mp_treeWidget->setColumnCount(headerlist.count());
85    topItem = new QTreeWidgetItem(mp_treeWidget);
86    topItem->setText(0, "Pools");
87    topItem->setData(0, Qt::UserRole, 0);
88    topItem->setExpanded(true);
89    
90    mp_treeWidget->setHeaderLabels(headerlist);
91
92    QString query;
93
94    foreach (QString pool_listItem, m_console->pool_list) {
95       pooltreeitem = new QTreeWidgetItem(topItem);
96       pooltreeitem->setText(0, pool_listItem);
97       pooltreeitem->setData(0, Qt::UserRole, 1);
98       pooltreeitem->setExpanded(true);
99
100       query =  "SELECT Media.VolumeName AS Media, "
101          " Media.MediaId AS Id, Media.VolStatus AS VolStatus,"
102          " Media.Enabled AS Enabled, Media.VolBytes AS Bytes,"
103          " Media.VolFiles AS FileCount, Media.VolJobs AS JobCount,"
104          " Media.VolRetention AS VolumeRetention, Media.MediaType AS MediaType,"
105          " Media.Slot AS Slot, Media.LastWritten AS LastWritten"
106          " FROM Media, Pool"
107          " WHERE Media.PoolId=Pool.PoolId";
108       query += " AND Pool.Name='" + pool_listItem + "'";
109       query += " ORDER BY Media";
110    
111       if (mainWin->m_sqlDebug) {
112          Pmsg1(000, "MediaList query cmd : %s\n",query.toUtf8().data());
113       }
114       QStringList results;
115       if (m_console->sql_cmd(query, results)) {
116          QString field;
117          QStringList fieldlist;
118
119          /* Iterate through the lines of results. */
120          foreach (QString resultline, results) {
121             fieldlist = resultline.split("\t");
122             int index = 0;
123             mediatreeitem = new QTreeWidgetItem(pooltreeitem);
124
125             /* Iterate through fields in the record */
126             foreach (field, fieldlist) {
127                field = field.trimmed();  /* strip leading & trailing spaces */
128                if (field != "") {
129                   mediatreeitem->setData(index, Qt::UserRole, 2);
130                   mediatreeitem->setData(index, Qt::UserRole, 2);
131                   mediatreeitem->setText(index, field);
132                   if (index == statusIndex) {
133                      setStatusColor(mediatreeitem, field, index);
134                   }
135                }
136                index++;
137             } /* foreach field */
138          } /* foreach resultline */
139       } /* if results from query */
140    } /* foreach pool_listItem */
141    /* Resize the columns */
142    for(int cnter=0; cnter<headerlist.count(); cnter++) {
143       mp_treeWidget->resizeColumnToContents(cnter);
144    }
145 }
146
147 void MediaList::setStatusColor(QTreeWidgetItem *item, QString &field, int &index)
148 {
149    if (field == "Append" ) {
150       item->setBackground(index, Qt::green);
151    } else if (field == "Error") {
152       item->setBackground(index, Qt::red);
153    } else if ((field == "Used") || ("Full")){
154       item->setBackground(index, Qt::yellow);
155    }
156 }
157
158 /*
159  * Called from the signal of the context sensitive menu!
160  */
161 void MediaList::editVolume()
162 {
163    MediaEdit* edit = new MediaEdit(m_console, m_currentVolumeId);
164    connect(edit, SIGNAL(destroyed()), this, SLOT(populateTree()));
165 }
166
167 /*
168  * Called from the signal of the context sensitive menu!
169  */
170 void MediaList::showJobs()
171 {
172    QString emptyclient("");
173    QTreeWidgetItem *parentItem = mainWin->getFromHash(this);
174    mainWin->createPageJobList(m_currentVolumeName, emptyclient, parentItem);
175 }
176
177 /*
178  * When the treeWidgetItem in the page selector tree is singleclicked, Make sure
179  * The tree has been populated.
180  */
181 void MediaList::PgSeltreeWidgetClicked()
182 {
183    if (!m_populated) {
184       populateTree();
185       createContextMenu();
186       m_populated=true;
187    }
188 }
189
190 /*
191  * Added to set the context menu policy based on currently active treeWidgetItem
192  * signaled by currentItemChanged
193  */
194 void MediaList::treeItemChanged(QTreeWidgetItem *currentwidgetitem, QTreeWidgetItem *previouswidgetitem )
195 {
196    /* m_checkcurwidget checks to see if this is during a refresh, which will segfault */
197    if (m_checkcurwidget) {
198       /* The Previous item */
199       if (previouswidgetitem) { /* avoid a segfault if first time */
200          int treedepth = previouswidgetitem->data(0, Qt::UserRole).toInt();
201          if (treedepth == 2){
202             mp_treeWidget->removeAction(actionEditVolume);
203             mp_treeWidget->removeAction(actionListJobsOnVolume);
204             mp_treeWidget->removeAction(actionDeleteVolume);
205             mp_treeWidget->removeAction(actionPurgeVolume);
206             mp_treeWidget->removeAction(actionRelabelVolume);
207          }
208       }
209
210       int treedepth = currentwidgetitem->data(0, Qt::UserRole).toInt();
211       if (treedepth == 2){
212          m_currentVolumeName=currentwidgetitem->text(0);
213          m_currentVolumeId=currentwidgetitem->text(1);
214          mp_treeWidget->addAction(actionEditVolume);
215          mp_treeWidget->addAction(actionListJobsOnVolume);
216          mp_treeWidget->addAction(actionDeleteVolume);
217          mp_treeWidget->addAction(actionPurgeVolume);
218          mp_treeWidget->addAction(actionRelabelVolume);
219       }
220    }
221 }
222
223 /* 
224  * Setup a context menu 
225  * Made separate from populate so that it would not create context menu over and
226  * over as the tree is repopulated.
227  */
228 void MediaList::createContextMenu()
229 {
230    mp_treeWidget->setContextMenuPolicy(Qt::ActionsContextMenu);
231    mp_treeWidget->addAction(actionRefreshMediaList);
232    connect(actionEditVolume, SIGNAL(triggered()), this, SLOT(editVolume()));
233    connect(actionListJobsOnVolume, SIGNAL(triggered()), this, SLOT(showJobs()));
234    connect(actionDeleteVolume, SIGNAL(triggered()), this, SLOT(deleteVolume()));
235    connect(actionPurgeVolume, SIGNAL(triggered()), this, SLOT(purgeVolume()));
236    connect(actionRelabelVolume, SIGNAL(triggered()), this, SLOT(relabelVolume()));
237    connect(mp_treeWidget, SIGNAL(
238            currentItemChanged(QTreeWidgetItem *, QTreeWidgetItem *)),
239            this, SLOT(treeItemChanged(QTreeWidgetItem *, QTreeWidgetItem *)));
240    /* connect to the action specific to this pages class */
241    connect(actionRefreshMediaList, SIGNAL(triggered()), this,
242                 SLOT(populateTree()));
243 }
244
245 /*
246  * Virtual function which is called when this page is visible on the stack
247  */
248 void MediaList::currentStackItem()
249 {
250    if(!m_populated) {
251       populateTree();
252       /* add context sensitive menu items specific to this classto the page
253        * selector tree. m_contextActions is QList of QActions, so this is 
254        * only done once with the first population. */
255       m_contextActions.append(actionRefreshMediaList);
256       /* Create the context menu for the medialist tree */
257       createContextMenu();
258       m_populated=true;
259    }
260 }
261
262 /*
263  * Called from the signal of the context sensitive menu!
264  */
265 void MediaList::deleteVolume()
266 {
267    if (QMessageBox::warning(this, tr("Bat"),
268       tr("Are you sure you want to delete??  !!!.\n"
269 "This delete command is used to delete a Volume record and all associated catalog"
270 " records that were created. This command operates only on the Catalog"
271 " database and has no effect on the actual data written to a Volume. This"
272 " command can be dangerous and we strongly recommend that you do not use"
273 " it unless you know what you are doing.  All Jobs and all associated"
274 " records (File and JobMedia) will be deleted from the catalog."
275       "Press OK to proceed with delete operation.?"),
276       QMessageBox::Ok | QMessageBox::Cancel)
277       == QMessageBox::Cancel) { return; }
278
279    QString cmd("delete volume=");
280    cmd += m_currentVolumeName;
281    consoleCommand(cmd);
282 }
283 /*
284  * Called from the signal of the context sensitive menu!
285  */
286 void MediaList::purgeVolume()
287 {
288    if (QMessageBox::warning(this, tr("Bat"),
289       tr("Are you sure you want to purge ??  !!!.\n"
290 "The Purge command will delete associated Catalog database records from Jobs and"
291 " Volumes without considering the retention period. Purge  works only on the"
292 " Catalog database and does not affect data written to Volumes. This command can"
293 " be dangerous because you can delete catalog records associated with current"
294 " backups of files, and we recommend that you do not use it unless you know what"
295 " you are doing.\n"
296       "Press OK to proceed with the purge operation?"),
297       QMessageBox::Ok | QMessageBox::Cancel)
298       == QMessageBox::Cancel) { return; }
299
300    QString cmd("purge volume=");
301    cmd += m_currentVolumeName;
302    consoleCommand(cmd);
303    populateTree();
304 }
305 /*
306  * Called from the signal of the context sensitive menu!
307  */
308 void MediaList::relabelVolume()
309 {
310    setConsoleCurrent();
311    new relabelDialog(m_console, m_currentVolumeName);
312 }