]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/qt-console/restore/prerestore.cpp
bat: Add pattern filter and make restore to start from brestore
[bacula/bacula] / bacula / src / qt-console / restore / prerestore.cpp
1 /*
2    Bacula® - The Network Backup Solution
3
4    Copyright (C) 2007-2010 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 three of the GNU Affero 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 Affero 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  *  preRestore -> dialog put up to determine the restore type
31  *
32  *   Kern Sibbald, February MMVII
33  *
34  */ 
35
36 #include "bat.h"
37 #include "restore.h"
38
39 /* Constructor to have job id list default in */
40 prerestorePage::prerestorePage(QString &data, unsigned int datatype)
41 {
42    m_dataIn = data;
43    m_dataInType = datatype;
44    buildPage();
45 }
46
47 /* Basic Constructor */
48 prerestorePage::prerestorePage()
49 {
50    m_dataIn = "";
51    m_dataInType = R_NONE;
52    buildPage();
53 }
54
55 /*
56  * This is really the constructor
57  */
58 void prerestorePage::buildPage()
59 {
60    m_name = tr("Restore");
61    setupUi(this);
62    pgInitialize();
63    m_conn = m_console->notifyOff();
64    QTreeWidgetItem* thisitem = mainWin->getFromHash(this);
65    thisitem->setIcon(0,QIcon(QString::fromUtf8(":images/restore.png")));
66
67    jobCombo->addItems(m_console->job_list);
68    filesetCombo->addItems(m_console->fileset_list);
69    clientCombo->addItems(m_console->client_list);
70    poolCombo->addItem(tr("Any"));
71    poolCombo->addItems(m_console->pool_list);
72    storageCombo->addItems(m_console->storage_list);
73    /* current or before . .  Start out with current checked */
74    recentCheckBox->setCheckState(Qt::Checked);
75    beforeDateTime->setDisplayFormat(mainWin->m_dtformat);
76    beforeDateTime->setDateTime(QDateTime::currentDateTime());
77    beforeDateTime->setEnabled(false);
78    selectFilesRadio->setChecked(true);
79    if (m_dataInType == R_NONE) {
80       selectJobRadio->setChecked(true);
81       selectJobIdsRadio->setChecked(false);
82       jobIdEdit->setText(tr("Comma separted list of Job Ids"));
83       jobIdEdit->setEnabled(false);
84    } else if (m_dataInType == R_JOBIDLIST) {
85       selectJobIdsRadio->setChecked(true);
86       selectJobRadio->setChecked(false);
87       jobIdEdit->setText(m_dataIn);
88       jobRadioClicked(false);
89       QStringList fieldlist;
90       if (jobdefsFromJob(fieldlist, m_dataIn) == 1) {
91          filesetCombo->setCurrentIndex(filesetCombo->findText(fieldlist[2], Qt::MatchExactly));
92          clientCombo->setCurrentIndex(clientCombo->findText(fieldlist[1], Qt::MatchExactly));
93          jobCombo->setCurrentIndex(jobCombo->findText(fieldlist[0], Qt::MatchExactly));
94       }
95    } else if (m_dataInType == R_JOBDATETIME) {
96       selectJobRadio->setChecked(true);
97       selectJobIdsRadio->setChecked(false);
98       jobIdEdit->setText(tr("Comma separted list of Job Ids"));
99       jobIdEdit->setEnabled(false);
100       recentCheckBox->setCheckState(Qt::Unchecked);
101       jobRadioClicked(true);
102       QStringList fieldlist;
103       if (jobdefsFromJob(fieldlist, m_dataIn) == 1) {
104          filesetCombo->setCurrentIndex(filesetCombo->findText(fieldlist[2], Qt::MatchExactly));
105          clientCombo->setCurrentIndex(clientCombo->findText(fieldlist[1], Qt::MatchExactly));
106          jobCombo->setCurrentIndex(jobCombo->findText(fieldlist[0], Qt::MatchExactly));
107          beforeDateTime->setDateTime(QDateTime::fromString(fieldlist[3], mainWin->m_dtformat));
108      }
109    }
110    job_name_change(0);
111    connect(jobCombo, SIGNAL(currentIndexChanged(int)), this, SLOT(job_name_change(int)));
112    connect(okButton, SIGNAL(pressed()), this, SLOT(okButtonPushed()));
113    connect(cancelButton, SIGNAL(pressed()), this, SLOT(cancelButtonPushed()));
114    connect(recentCheckBox, SIGNAL(stateChanged(int)), this, SLOT(recentChanged(int)));
115    connect(selectJobRadio, SIGNAL(clicked(bool)), this, SLOT(jobRadioClicked(bool)));
116    connect(selectJobIdsRadio, SIGNAL(clicked(bool)), this, SLOT(jobidsRadioClicked(bool)));
117    connect(jobIdEdit, SIGNAL(editingFinished()), this, SLOT(jobIdEditFinished()));
118
119    dockPage();
120    setCurrent();
121    this->show();
122    if (mainWin->m_miscDebug) Pmsg0(000, "Leave preRestore\n");
123 }
124
125
126 /*
127  * Check to make sure all is ok then start either the select window or the restore
128  * run window
129  */
130 void prerestorePage::okButtonPushed()
131 {
132    if (!selectJobRadio->isChecked()) {
133       if (!checkJobIdList()) {
134          return;
135       }
136    }
137    QString cmd;
138
139    this->hide();
140
141
142    cmd = QString("restore");
143    cmd += " fileset=\"" + filesetCombo->currentText() + "\"";
144    cmd += " client=\"" + clientCombo->currentText() + "\"";
145    if (selectJobRadio->isChecked()) {
146       if (poolCombo->currentText() != tr("Any") ){
147          cmd += " pool=\"" + poolCombo->currentText() + "\"";
148       }
149       cmd += " storage=\"" + storageCombo->currentText() + "\"";
150       if (recentCheckBox->checkState() == Qt::Checked) {
151          cmd += " current";
152       } else {
153          QDateTime stamp = beforeDateTime->dateTime();
154          QString before = stamp.toString(mainWin->m_dtformat);
155          cmd += " before=\"" + before + "\"";
156       }
157    } else {
158       cmd += " jobid=\"" + jobIdEdit->text() + "\"";
159    }
160    if (selectFilesRadio->isChecked()) {
161       if (!selectJobIdsRadio->isChecked())
162          cmd += " select";
163    } else {
164       cmd += " all done";
165    }
166
167    if (mainWin->m_commandDebug) {
168       Pmsg1(000, "preRestore command \'%s\'\n", cmd.toUtf8().data());
169    }
170    /* 
171     * Send off command that looks something like:
172     *
173     * restore fileset="Full Set" client="timmy-fd" 
174     *        storage="File" current select
175     */
176    m_console->write_dir(m_conn, cmd.toUtf8().data());
177
178    /* Note, do not turn notifier back on here ... */
179    if (selectFilesRadio->isChecked()) {
180       setConsoleCurrent();
181       closeStackPage();
182       /* wait will be exited in the restore page constructor */
183       mainWin->waitEnter();
184    } else {
185       closeStackPage();
186       mainWin->resetFocus();
187    }
188    m_console->notify(m_conn, true);
189    if (mainWin->m_miscDebug) Pmsg0(000, "preRestore OK pressed\n");
190 }
191
192
193 /*
194  * Destroy the instace of the class
195  */
196 void prerestorePage::cancelButtonPushed()
197 {
198    mainWin->set_status(tr("Canceled"));
199    this->hide();
200    m_console->notify(m_conn, true);
201    closeStackPage();
202 }
203
204
205 /*
206  * Handle updating the other widget with job defaults when the job combo is changed.
207  */
208 void prerestorePage::job_name_change(int index)
209 {
210    job_defaults job_defs;
211
212    (void)index;
213    job_defs.job_name = jobCombo->currentText();
214    if (m_console->get_job_defaults(m_conn, job_defs)) {
215       filesetCombo->setCurrentIndex(filesetCombo->findText(job_defs.fileset_name, Qt::MatchExactly));
216       clientCombo->setCurrentIndex(clientCombo->findText(job_defs.client_name, Qt::MatchExactly));
217       poolCombo->setCurrentIndex(poolCombo->findText(tr("Any"), Qt::MatchExactly));
218       storageCombo->setCurrentIndex(storageCombo->findText(job_defs.store_name, Qt::MatchExactly));
219    }
220 }
221
222 /*
223  * Handle the change of enabled of input widgets when the recent checkbox state
224  * is changed.
225  */
226 void prerestorePage::recentChanged(int state)
227 {
228    if ((state == Qt::Unchecked) && (selectJobRadio->isChecked())) {
229       beforeDateTime->setEnabled(true);
230    } else {
231       beforeDateTime->setEnabled(false);
232    }
233 }
234
235
236 /*
237  * For when jobs list is to be used, return a list which is the needed items from
238  * the job record
239  */
240 int prerestorePage::jobdefsFromJob(QStringList &fieldlist, QString &jobId)
241 {
242    QString job, client, fileset;
243    QString query("");
244    query = "SELECT DISTINCT Job.Name AS JobName, Client.Name AS Client,"
245    " FileSet.FileSet AS FileSet, Job.EndTime AS JobEnd,"
246    " Job.Type AS JobType"
247    " From Job, Client, FileSet"
248    " WHERE Job.FileSetId=FileSet.FileSetId AND Job.ClientId=Client.ClientId"
249    " AND JobId=\'" + jobId + "\'";
250    if (mainWin->m_sqlDebug) { Pmsg1(000, "query = %s\n", query.toUtf8().data()); }
251    QStringList results;
252    if (m_console->sql_cmd(m_conn, query, results)) {
253       QString field;
254
255       /* Iterate through the lines of results, there should only be one. */
256       foreach (QString resultline, results) {
257          fieldlist = resultline.split("\t");
258       } /* foreach resultline */
259    } /* if results from query */
260
261    /* ***FIXME*** This should not ever be getting more than one */
262    return results.count() >= 1;
263 }
264
265 /*
266  * Function to handle when the jobidlist line edit input loses focus or is entered
267  */
268 void prerestorePage::jobIdEditFinished()
269 {
270    checkJobIdList();
271 }
272
273 bool prerestorePage::checkJobIdList()
274 {
275    /* Need to check and make sure the text is a comma separated list of integers */
276    QString line = jobIdEdit->text();
277    if (line.contains(" ")) {
278       QMessageBox::warning(this, "Bat",
279          tr("There can be no spaces in the text for the joblist.\n"
280          "Press OK to continue?"), QMessageBox::Ok );
281       return false;
282    }
283    QStringList joblist = line.split(",", QString::SkipEmptyParts);
284    bool allintokay = true, alljobok = true, allisjob = true;
285    QString jobName(""), clientName("");
286    foreach (QString job, joblist) {
287       bool intok;
288       job.toInt(&intok, 10);
289       if (intok) {
290          /* are the integers representing a list of jobs all with the same job
291           * and client */
292          QStringList fields;
293          if (jobdefsFromJob(fields, job) == 1) {
294             if (jobName == "")
295                jobName = fields[0];
296             else if (jobName != fields[0])
297                alljobok = false;
298             if (clientName == "")
299                clientName = fields[1];
300             else if (clientName != fields[1])
301                alljobok = false;
302          } else {
303             allisjob = false;
304          }
305       } else {
306          allintokay = false;
307       }
308    }
309    if (!allintokay){
310       QMessageBox::warning(this, "Bat",
311          tr("The string is not a comma separated list of integers.\n"
312          "Press OK to continue?"), QMessageBox::Ok );
313       return false;
314    }
315    if (!allisjob){
316       QMessageBox::warning(this, tr("Bat"),
317          tr("At least one of the jobs is not a valid job of type \"Backup\".\n"
318          "Press OK to continue?"), QMessageBox::Ok );
319       return false;
320    }
321    if (!alljobok){
322       QMessageBox::warning(this, "Bat",
323          tr("All jobs in the list must be of the same jobName and same client.\n"
324          "Press OK to continue?"), QMessageBox::Ok );
325       return false;
326    }
327    return true;
328 }
329
330 /*
331  * Handle the change of enabled of input widgets when the job radio buttons
332  * are changed.
333  */
334 void prerestorePage::jobRadioClicked(bool checked)
335 {
336    if (checked) {
337       jobCombo->setEnabled(true);
338       filesetCombo->setEnabled(true);
339       clientCombo->setEnabled(true);
340       poolCombo->setEnabled(true);
341       storageCombo->setEnabled(true);
342       recentCheckBox->setEnabled(true);
343       if (!recentCheckBox->isChecked()) {
344          beforeDateTime->setEnabled(true);
345       }
346       jobIdEdit->setEnabled(false);
347       selectJobRadio->setChecked(true);
348       selectJobIdsRadio->setChecked(false);
349    } else {
350       jobCombo->setEnabled(false);
351       filesetCombo->setEnabled(false);
352       clientCombo->setEnabled(false);
353       poolCombo->setEnabled(false);
354       storageCombo->setEnabled(false);
355       recentCheckBox->setEnabled(false);
356       beforeDateTime->setEnabled(false);
357       jobIdEdit->setEnabled(true);
358       selectJobRadio->setChecked(false);
359       selectJobIdsRadio->setChecked(true);
360    }
361    if (mainWin->m_miscDebug) {
362       Pmsg2(000, "jobRadio=%d jobidsRadio=%d\n", selectJobRadio->isChecked(), 
363          selectJobIdsRadio->isChecked());
364    }
365 }
366
367 void prerestorePage::jobidsRadioClicked(bool checked)
368 {
369    if (checked) {
370       jobCombo->setEnabled(false);
371       filesetCombo->setEnabled(false);
372       clientCombo->setEnabled(false);
373       poolCombo->setEnabled(false);
374       storageCombo->setEnabled(false);
375       recentCheckBox->setEnabled(false);
376       beforeDateTime->setEnabled(false);
377       jobIdEdit->setEnabled(true);
378       selectJobRadio->setChecked(false);
379       selectJobIdsRadio->setChecked(true);
380    } else {
381       jobCombo->setEnabled(true);
382       filesetCombo->setEnabled(true);
383       clientCombo->setEnabled(true);
384       poolCombo->setEnabled(true);
385       storageCombo->setEnabled(true);
386       recentCheckBox->setEnabled(true);
387       if (!recentCheckBox->isChecked()) {
388          beforeDateTime->setEnabled(true);
389       }
390       jobIdEdit->setEnabled(false);
391       selectJobRadio->setChecked(true);
392       selectJobIdsRadio->setChecked(false);
393    }
394    if (mainWin->m_miscDebug) {
395       Pmsg2(000, "jobRadio=%d jobidsRadio=%d\n", selectJobRadio->isChecked(), 
396          selectJobIdsRadio->isChecked());
397    }
398 }