1 /*
2 Bacula(R) - The Network Backup Solution
3
4 Copyright (C) 2000-2016 Kern Sibbald
5
6 The original author of Bacula is Kern Sibbald, with contributions
7 from many others, a complete list can be found in the file AUTHORS.
8
9 You may use this file and others of this release according to the
10 license defined in the LICENSE file, which includes the Affero General
11 Public License, v3.0 ("AGPLv3") and some additional permissions and
12 terms pursuant to its AGPLv3 Section 7.
13
14 This notice must be preserved when any source code is
15 conveyed and/or propagated.
16
17 Bacula(R) is a registered trademark of Kern Sibbald.
18 */
19 /*
20 * Dirk Bartley, March 2007
21 */
22
23 #include "bat.h"
24 #include <QAbstractEventDispatcher>
25 #include <QTableWidgetItem>
26 #include <QMessageBox>
27 #include "mediaedit.h"
28
29 /*
30 * A constructor
31 */
MediaEdit(QTreeWidgetItem * parentWidget,QString & mediaId)32 MediaEdit::MediaEdit(QTreeWidgetItem *parentWidget, QString &mediaId)
33 : Pages()
34 {
35 setupUi(this);
36 pgInitialize(tr("Media Edit"), parentWidget);
37 QTreeWidgetItem* thisitem = mainWin->getFromHash(this);
38 thisitem->setIcon(0,QIcon(QString::fromUtf8(":images/cartridge-edit.png")));
39 dockPage();
40 setCurrent();
41
42 connect(okButton, SIGNAL(pressed()), this, SLOT(okButtonPushed()));
43 connect(cancelButton, SIGNAL(pressed()), this, SLOT(cancelButtonPushed()));
44 connectSpins();
45 connect(retentionSpin, SIGNAL(valueChanged(int)), this, SLOT(retentionChanged()));
46 connect(useDurationSpin, SIGNAL(valueChanged(int)), this, SLOT(useDurationChanged()));
47 connect(retentionRadio, SIGNAL(pressed()), this, SLOT(retentionRadioPressed()));
48 connect(useDurationRadio, SIGNAL(pressed()), this, SLOT(useDurationRadioPressed()));
49
50 m_pool = "";
51 m_recyclePool = "";
52 m_status = "";
53 m_slot = 0;
54
55 /* The media's pool */
56 poolCombo->addItems(m_console->pool_list);
57
58 /* The media's Status */
59 QStringList statusList = (QStringList() << "Full" << "Used" << "Append"
60 << "Error" << "Purged" << "Recycle" << "Read-Only" << "Cleaning");
61 statusCombo->addItems(statusList);
62
63 /* Set up the query for the default values */
64 QStringList FieldList = (QStringList()
65 << "Media.VolumeName" << "Pool.Name" << "Media.VolStatus" << "Media.Slot"
66 << "Media.VolRetention" << "Media.VolUseDuration" << "Media.MaxVolJobs"
67 << "Media.MaxVolFiles" << "Media.MaxVolBytes" << "Media.Recycle" << "Media.Enabled"
68 << "Pol.Name");
69 QStringList AsList = (QStringList()
70 << "VolumeName" << "PoolName" << "Status" << "Slot"
71 << "Retention" << "UseDuration" << "MaxJobs"
72 << "MaxFiles" << "MaxBytes" << "Recycle" << "Enabled"
73 << "RecyclePool");
74 int i = 0;
75 QString query("SELECT ");
76 foreach (QString field, FieldList) {
77 if (i != 0) {
78 query += ", ";
79 }
80 query += field + " AS " + AsList[i];
81 i += 1;
82 }
83
84 QString where = " WHERE Media.VolumeName = '" + mediaId + "' ";
85 if (mediaId.contains(QRegExp("^[0-9]+$"))) {
86 where = " WHERE Media.MediaId=" + mediaId;
87 }
88 query += " FROM Media"
89 " JOIN Pool ON (Media.PoolId=Pool.PoolId)"
90 " LEFT OUTER JOIN Pool AS Pol ON (Media.RecyclePoolId=Pol.PoolId)"
91 + where;
92
93 if (mainWin->m_sqlDebug) {
94 Pmsg1(000, "MediaList query cmd : %s\n",query.toUtf8().data());
95 }
96 QStringList results;
97 if (m_console->sql_cmd(query, results)) {
98 QString field;
99 QStringList fieldlist;
100
101 /* Iterate through the lines of results, there should only be one. */
102 foreach (QString resultline, results) {
103 fieldlist = resultline.split("\t");
104 i = 0;
105
106 /* Iterate through fields in the record */
107 foreach (field, fieldlist) {
108 field = field.trimmed(); /* strip leading & trailing spaces */
109 bool ok;
110 if (i == 0) {
111 m_mediaName = field;
112 volumeLabel->setText(QString("Volume : %1").arg(m_mediaName));
113 } else if (i == 1) {
114 m_pool = field;
115 } else if (i == 2) {
116 m_status = field;
117 } else if (i == 3) {
118 m_slot = field.toInt(&ok, 10);
119 if (!ok){ m_slot = 0; }
120 } else if (i == 4) {
121 m_retention = field.toInt(&ok, 10);
122 if (!ok){ m_retention = 0; }
123 } else if (i == 5) {
124 m_useDuration = field.toInt(&ok, 10);
125 if (!ok){ m_useDuration = 0; }
126 } else if (i == 6) {
127 m_maxVolJobs = field.toInt(&ok, 10);
128 if (!ok){ m_maxVolJobs = 0; }
129 } else if (i == 7) {
130 m_maxVolFiles = field.toInt(&ok, 10);
131 if (!ok){ m_maxVolFiles = 0; }
132 } else if (i == 8) {
133 m_maxVolBytes = field.toInt(&ok, 10);
134 if (!ok){ m_maxVolBytes = 0; }
135 } else if (i == 9) {
136 if (field == "1") m_recycle = true;
137 else m_recycle = false;
138 } else if (i == 10) {
139 if (field == "1") m_enabled = true;
140 else m_enabled = false;
141 } else if (i == 11) {
142 m_recyclePool = field;
143 }
144 i++;
145 } /* foreach field */
146 } /* foreach resultline */
147 } /* if results from query */
148
149 if (m_mediaName != "") {
150 int index;
151 /* default value for pool */
152 index = poolCombo->findText(m_pool, Qt::MatchExactly);
153 if (index != -1) {
154 poolCombo->setCurrentIndex(index);
155 }
156
157 /* default value for status */
158 index = statusCombo->findText(m_status, Qt::MatchExactly);
159 if (index != -1) {
160 statusCombo->setCurrentIndex(index);
161 }
162 slotSpin->setValue(m_slot);
163 retentionSpin->setValue(m_retention);
164 useDurationSpin->setValue(m_useDuration);
165 setSpins(retentionSpin->value());
166 retentionRadio->setChecked(true);
167 maxJobsSpin->setValue(m_maxVolJobs);
168 maxFilesSpin->setValue(m_maxVolFiles);
169 maxBytesSpin->setValue(m_maxVolBytes);
170 if (m_recycle) recycleCheck->setCheckState(Qt::Checked);
171 else recycleCheck->setCheckState(Qt::Unchecked);
172 if (m_enabled) enabledCheck->setCheckState(Qt::Checked);
173 else enabledCheck->setCheckState(Qt::Unchecked);
174 /* default for recycle pool */
175 recyclePoolCombo->addItems(m_console->pool_list);
176 recyclePoolCombo->insertItem(0, "*None*");
177 index = recyclePoolCombo->findText(m_recyclePool, Qt::MatchExactly);
178 if (index == -1) {
179 index = 0;
180 }
181 recyclePoolCombo->setCurrentIndex(index);
182 } else {
183 QMessageBox::warning(this, tr("No Volume name"), tr("No Volume name given"),
184 QMessageBox::Ok, QMessageBox::Ok);
185 return;
186 }
187 }
188
189 /*
190 * Function to handle updating the record then closing the page
191 */
okButtonPushed()192 void MediaEdit::okButtonPushed()
193 {
194 QString scmd;
195 this->hide();
196 bool docmd = false;
197 scmd = QString("update volume=\"%1\"")
198 .arg(m_mediaName);
199 if (m_pool != poolCombo->currentText()) {
200 scmd += " pool=\"" + poolCombo->currentText() + "\"";
201 docmd = true;
202 }
203 if (m_status != statusCombo->currentText()) {
204 scmd += " volstatus=\"" + statusCombo->currentText() + "\"";
205 docmd = true;
206 }
207 if (m_slot != slotSpin->value()) {
208 scmd += " slot=" + QString().setNum(slotSpin->value());
209 docmd = true;
210 }
211 if (m_retention != retentionSpin->value()) {
212 scmd += " VolRetention=" + QString().setNum(retentionSpin->value());
213 docmd = true;
214 }
215 if (m_useDuration != useDurationSpin->value()) {
216 scmd += " VolUse=" + QString().setNum(useDurationSpin->value());
217 docmd = true;
218 }
219 if (m_maxVolJobs != maxJobsSpin->value()) {
220 scmd += " MaxVolJobs=" + QString().setNum(maxJobsSpin->value());
221 docmd = true;
222 }
223 if (m_maxVolFiles != maxFilesSpin->value()) {
224 scmd += " MaxVolFiles=" + QString().setNum(maxFilesSpin->value());
225 docmd = true;
226 }
227 if (m_maxVolBytes != maxBytesSpin->value()) {
228 scmd += " MaxVolBytes=" + QString().setNum(maxBytesSpin->value());
229 docmd = true;
230 }
231 if ((m_recycle) && (recycleCheck->checkState() == Qt::Unchecked)) {
232 scmd += " Recycle=no";
233 docmd = true;
234 }
235 if ((!m_recycle) && (recycleCheck->checkState() == Qt::Checked)) {
236 scmd += " Recycle=yes";
237 docmd = true;
238 }
239 if ((m_enabled) && (enabledCheck->checkState() == Qt::Unchecked)) {
240 scmd += " enabled=no";
241 docmd = true;
242 }
243 if ((!m_enabled) && (enabledCheck->checkState() == Qt::Checked)) {
244 scmd += " enabled=yes";
245 docmd = true;
246 }
247 if (m_recyclePool != recyclePoolCombo->currentText()) {
248 scmd += " recyclepool=\"";
249 if (recyclePoolCombo->currentText() != "*None*") {
250 scmd += recyclePoolCombo->currentText();
251 }
252 scmd += "\"";
253 docmd = true;
254 }
255 if (docmd) {
256 if (mainWin->m_commandDebug) {
257 Pmsg1(000, "sending command : %s\n",scmd.toUtf8().data());
258 }
259 consoleCommand(scmd);
260 }
261 closeStackPage();
262 }
263
264 /* close if cancel */
cancelButtonPushed()265 void MediaEdit::cancelButtonPushed()
266 {
267 closeStackPage();
268 }
269
270 /*
271 * Slot for user changed retention
272 */
retentionChanged()273 void MediaEdit::retentionChanged()
274 {
275 retentionRadio->setChecked(true);
276 setSpins(retentionSpin->value());
277 }
278
279 /*
280 * Slot for user changed the use duration
281 */
useDurationChanged()282 void MediaEdit::useDurationChanged()
283 {
284 useDurationRadio->setChecked(true);
285 setSpins(useDurationSpin->value());
286 }
287
288 /*
289 * Set the 5 duration spins from a known duration value
290 */
setSpins(int value)291 void MediaEdit::setSpins(int value)
292 {
293 int years, months, days, hours, minutes, seconds, left;
294
295 years = abs(value / 31536000);
296 left = value - years * 31536000;
297 months = abs(left / 2592000);
298 left = left - months * 2592000;
299 days = abs(left / 86400);
300 left = left - days * 86400;
301 hours = abs(left / 3600);
302 left = left - hours * 3600;
303 minutes = abs(left / 60);
304 seconds = left - minutes * 60;
305 disconnectSpins();
306 yearsSpin->setValue(years);
307 monthsSpin->setValue(months);
308 daysSpin->setValue(days);
309 hoursSpin->setValue(hours);
310 minutesSpin->setValue(minutes);
311 secondsSpin->setValue(seconds);
312 connectSpins();
313 }
314
315 /*
316 * This slot is called any time any one of the 5 duration spins a changed.
317 */
durationChanged()318 void MediaEdit::durationChanged()
319 {
320 disconnectSpins();
321 if (secondsSpin->value() == -1) {
322 secondsSpin->setValue(59);
323 minutesSpin->setValue(minutesSpin->value()-1);
324 }
325 if (minutesSpin->value() == -1) {
326 minutesSpin->setValue(59);
327 hoursSpin->setValue(hoursSpin->value()-1);
328 }
329 if (hoursSpin->value() == -1) {
330 hoursSpin->setValue(23);
331 daysSpin->setValue(daysSpin->value()-1);
332 }
333 if (daysSpin->value() == -1) {
334 daysSpin->setValue(29);
335 monthsSpin->setValue(monthsSpin->value()-1);
336 }
337 if (monthsSpin->value() == -1) {
338 monthsSpin->setValue(11);
339 yearsSpin->setValue(yearsSpin->value()-1);
340 }
341 if (yearsSpin->value() == -1) {
342 yearsSpin->setValue(0);
343 }
344
345 if (secondsSpin->value() == 60) {
346 secondsSpin->setValue(0);
347 minutesSpin->setValue(minutesSpin->value()+1);
348 }
349 if (minutesSpin->value() == 60) {
350 minutesSpin->setValue(0);
351 hoursSpin->setValue(hoursSpin->value()+1);
352 }
353 if (hoursSpin->value() == 24) {
354 hoursSpin->setValue(0);
355 daysSpin->setValue(daysSpin->value()+1);
356 }
357 if (daysSpin->value() == 30) {
358 daysSpin->setValue(0);
359 monthsSpin->setValue(monthsSpin->value()+1);
360 }
361 if (monthsSpin->value() == 12) {
362 monthsSpin->setValue(0);
363 yearsSpin->setValue(yearsSpin->value()+1);
364 }
365 connectSpins();
366 if (retentionRadio->isChecked()) {
367 int retention;
368 retention = secondsSpin->value() + minutesSpin->value() * 60 +
369 hoursSpin->value() * 3600 + daysSpin->value() * 86400 +
370 monthsSpin->value() * 2592000 +
371 yearsSpin->value() * 31536000;
372 disconnect(retentionSpin, SIGNAL(valueChanged(int)), this, SLOT(retentionChanged()));
373 retentionSpin->setValue(retention);
374 connect(retentionSpin, SIGNAL(valueChanged(int)), this, SLOT(retentionChanged()));
375 }
376 if (useDurationRadio->isChecked()) {
377 int useDuration;
378 useDuration = secondsSpin->value() + minutesSpin->value() * 60 +
379 hoursSpin->value() * 3600 + daysSpin->value() * 86400 +
380 monthsSpin->value() * 2592000 +
381 yearsSpin->value() * 31536000;
382 disconnect(useDurationSpin, SIGNAL(valueChanged(int)), this, SLOT(useDurationChanged()));
383 useDurationSpin->setValue(useDuration);
384 connect(useDurationSpin, SIGNAL(valueChanged(int)), this, SLOT(useDurationChanged()));
385 }
386 }
387
388 /* Connect the spins */
connectSpins()389 void MediaEdit::connectSpins()
390 {
391 connect(secondsSpin, SIGNAL(valueChanged(int)), this, SLOT(durationChanged()));
392 connect(minutesSpin, SIGNAL(valueChanged(int)), this, SLOT(durationChanged()));
393 connect(hoursSpin, SIGNAL(valueChanged(int)), this, SLOT(durationChanged()));
394 connect(daysSpin, SIGNAL(valueChanged(int)), this, SLOT(durationChanged()));
395 connect(monthsSpin, SIGNAL(valueChanged(int)), this, SLOT(durationChanged()));
396 connect(yearsSpin, SIGNAL(valueChanged(int)), this, SLOT(durationChanged()));
397 }
398
399 /* disconnect spins so that we can set the value of other spin from changed duration spin */
disconnectSpins()400 void MediaEdit::disconnectSpins()
401 {
402 disconnect(secondsSpin, SIGNAL(valueChanged(int)), this, SLOT(durationChanged()));
403 disconnect(minutesSpin, SIGNAL(valueChanged(int)), this, SLOT(durationChanged()));
404 disconnect(hoursSpin, SIGNAL(valueChanged(int)), this, SLOT(durationChanged()));
405 disconnect(daysSpin, SIGNAL(valueChanged(int)), this, SLOT(durationChanged()));
406 disconnect(monthsSpin, SIGNAL(valueChanged(int)), this, SLOT(durationChanged()));
407 disconnect(yearsSpin, SIGNAL(valueChanged(int)), this, SLOT(durationChanged()));
408 }
409
410 /* slot for setting spins when retention radio checked */
retentionRadioPressed()411 void MediaEdit::retentionRadioPressed()
412 {
413 setSpins(retentionSpin->value());
414 }
415
416 /* slot for setting spins when duration radio checked */
useDurationRadioPressed()417 void MediaEdit::useDurationRadioPressed()
418 {
419 setSpins(useDurationSpin->value());
420 }
421