From: Dirk H Bartley Date: Tue, 8 May 2007 01:59:22 +0000 (+0000) Subject: The ability to right click on a job in joblist and select restore from job. X-Git-Tag: Release-7.0.0~6408 X-Git-Url: https://git.sur5r.net/?a=commitdiff_plain;h=509375e818b579c1a0352f2c9da957439e61e757;p=bacula%2Fbacula The ability to right click on a job in joblist and select restore from job. prerestore is "smart" enough not to allow the user to press ok with jobs from a different clients or jobnames. Added todo the ability to select multiple jobs in joblist for restoring from. git-svn-id: https://bacula.svn.sourceforge.net/svnroot/bacula/trunk@4723 91ce42f0-d328-0410-95d8-f526ca767f89 --- diff --git a/bacula/src/qt-console/TODO b/bacula/src/qt-console/TODO index 674a94dac9..35d90bd260 100644 --- a/bacula/src/qt-console/TODO +++ b/bacula/src/qt-console/TODO @@ -1,5 +1,12 @@ dhb ==================================================== +See if there is a solution to images fun with designer other than: +%s/[\.\/]*:images/images/g +%s/images/..\/images/g + +Allow for selecting multiple jobs to restore from in joblist. Right click +restore from job works, but not with multiple selected jobs. + Test left pane of restore with 2 windows drives in one backup job. Resolve issue of connection during restore selection. Could go with preempt of @@ -8,10 +15,6 @@ connections. User preferences. With log to stdout options. Have settings for defaults of limits on joblist -Create the ability to start a restore from joblist. Right click, select -"restore from Jobid=xx" create an instance of restore defaulting in the jobid -or a list of selected jobs. - Add numerous are you sure dialog boxes. Like are you sure you want to delete/purge that volume. Show a little of the documentation about what the consequences of delete or purging are. @@ -93,6 +96,10 @@ global one defined in the mainWin class (if I remember right). ============================================================ DONE: ============================================================ +Create the ability to start a restore from joblist. Right click, select +"restore from Jobid=xx" create an instance of restore defaulting in the jobid +or a list of selected jobs. + Update README describe bat.conf.example to bat.conf Test restore and get anything not working, working. diff --git a/bacula/src/qt-console/joblist/joblist.cpp b/bacula/src/qt-console/joblist/joblist.cpp index f98f56fcd8..1806f40b76 100644 --- a/bacula/src/qt-console/joblist/joblist.cpp +++ b/bacula/src/qt-console/joblist/joblist.cpp @@ -35,7 +35,7 @@ #include #include "bat.h" #include "joblist.h" - +#include "restore.h" /* * Constructor for the class @@ -276,6 +276,7 @@ void JobList::createConnections() mp_tableWidget->addAction(actionListVolumes); mp_tableWidget->addAction(actionDeleteJob); mp_tableWidget->addAction(actionPurgeFiles); + mp_tableWidget->addAction(actionRestoreFromJob); /* Make Connections */ connect(actionLongListJob, SIGNAL(triggered()), this, @@ -292,6 +293,8 @@ void JobList::createConnections() SLOT(consoleDeleteJob())); connect(actionPurgeFiles, SIGNAL(triggered()), this, SLOT(consolePurgeFiles())); + connect(actionRestoreFromJob, SIGNAL(triggered()), this, + SLOT(preRestoreFromJob())); } /* @@ -340,3 +343,11 @@ void JobList::consolePurgeFiles() cmd += m_currentJob; consoleCommand(cmd); } + +/* + * Subroutine to call preRestore to restore from a select job + */ +void JobList::preRestoreFromJob() +{ + new prerestorePage(m_currentJob); +} diff --git a/bacula/src/qt-console/joblist/joblist.h b/bacula/src/qt-console/joblist/joblist.h index 989f988f15..5d35d7e4ea 100644 --- a/bacula/src/qt-console/joblist/joblist.h +++ b/bacula/src/qt-console/joblist/joblist.h @@ -61,6 +61,7 @@ private slots: void consoleListVolumes(); void consoleDeleteJob(); void consolePurgeFiles(); + void preRestoreFromJob(); private: void createConnections(); diff --git a/bacula/src/qt-console/joblist/joblist.ui b/bacula/src/qt-console/joblist/joblist.ui index 605f666e06..faa15cbacd 100644 --- a/bacula/src/qt-console/joblist/joblist.ui +++ b/bacula/src/qt-console/joblist/joblist.ui @@ -142,7 +142,7 @@ - ../../../../../../../:images/run.png + ../images/run.png Refresh Job List @@ -153,7 +153,7 @@ - ../../../../../../../:images/unmark.png + ../images/unmark.png ListJobid @@ -161,7 +161,7 @@ - ../../../../../../../:images/unmark.png + ../images/unmark.png List Files On Job @@ -169,7 +169,7 @@ - ../../../../../../../:images/unmark.png + ../images/unmark.png ListJobMedia @@ -177,7 +177,7 @@ - ../../../../../../../:images/unmark.png + ../images/unmark.png ListVolumes @@ -185,7 +185,7 @@ - ../../../../../../../:images/unmark.png + ../images/unmark.png LongListJob @@ -193,7 +193,7 @@ - ../../../../../../../:images/unmark.png + ../images/unmark.png DeleteJob @@ -201,12 +201,20 @@ - ../../../../../../../:images/unmark.png + ../images/unmark.png PurgeFiles + + + ../images/unmark.png + + + Restore From Job + + diff --git a/bacula/src/qt-console/restore/prerestore.cpp b/bacula/src/qt-console/restore/prerestore.cpp index 22937db684..be7d85e7c1 100644 --- a/bacula/src/qt-console/restore/prerestore.cpp +++ b/bacula/src/qt-console/restore/prerestore.cpp @@ -38,8 +38,24 @@ #include "bat.h" #include "restore.h" +/* Constructor to have job id list default in */ +prerestorePage::prerestorePage(QString &jobIdString) +{ + m_jobIdListIn = jobIdString; + buildPage(); +} +/* Basic Constructor */ prerestorePage::prerestorePage() +{ + m_jobIdListIn = ""; + buildPage(); +} + +/* + * This is really the constructor + */ +void prerestorePage::buildPage() { m_dtformat = "yyyy-MM-dd HH:MM:ss"; m_name = "Restore"; @@ -60,23 +76,44 @@ prerestorePage::prerestorePage() beforeDateTime->setDateTime(QDateTime::currentDateTime()); beforeDateTime->setEnabled(false); selectFilesRadio->setChecked(true); - selectJobsRadio->setChecked(true); - jobIdEdit->setText("Comma separted list of jobs id's"); - jobIdEdit->setEnabled(false); + if (m_jobIdListIn == "") { + selectJobsRadio->setChecked(true); + jobIdEdit->setText("Comma separted list of jobs id's"); + jobIdEdit->setEnabled(false); + } else { + listJobsRadio->setChecked(true); + jobIdEdit->setText(m_jobIdListIn); + jobsRadioClicked(false); + QStringList fieldlist; + jobdefsFromJob(fieldlist,m_jobIdListIn); + filesetCombo->setCurrentIndex(filesetCombo->findText(fieldlist[2], Qt::MatchExactly)); + clientCombo->setCurrentIndex(clientCombo->findText(fieldlist[1], Qt::MatchExactly)); + jobCombo->setCurrentIndex(jobCombo->findText(fieldlist[0], Qt::MatchExactly)); + } job_name_change(0); connect(jobCombo, SIGNAL(currentIndexChanged(int)), this, SLOT(job_name_change(int))); connect(okButton, SIGNAL(pressed()), this, SLOT(okButtonPushed())); connect(cancelButton, SIGNAL(pressed()), this, SLOT(cancelButtonPushed())); connect(recentCheckBox, SIGNAL(stateChanged(int)), this, SLOT(recentChanged(int))); connect(selectJobsRadio, SIGNAL(toggled(bool)), this, SLOT(jobsRadioClicked(bool))); + connect(jobIdEdit, SIGNAL(editingFinished()), this, SLOT(jobIdEditFinished())); dockPage(); setCurrent(); this->show(); } + +/* + * Check to make sure all is ok then start either the select window or the restore + * run window + */ void prerestorePage::okButtonPushed() { + if (!selectJobsRadio->isChecked()) { + if (!checkJobIdList()) + return; + } QString cmd; this->hide(); @@ -88,8 +125,8 @@ void prerestorePage::okButtonPushed() cmd += "all done "; } cmd += "fileset=\"" + filesetCombo->currentText() + "\" "; + cmd += "client=\"" + clientCombo->currentText() + "\" "; if (selectJobsRadio->isChecked()) { - cmd += "client=\"" + clientCombo->currentText() + "\" "; if (poolCombo->currentText() != "Any" ){ cmd += "pool=\"" + poolCombo->currentText() + "\" "; } @@ -121,6 +158,9 @@ void prerestorePage::okButtonPushed() } +/* + * Destroy the instace of the class + */ void prerestorePage::cancelButtonPushed() { mainWin->set_status("Canceled"); @@ -130,6 +170,9 @@ void prerestorePage::cancelButtonPushed() } +/* + * Handle updating the other widget with job defaults when the job combo is changed. + */ void prerestorePage::job_name_change(int index) { job_defaults job_defs; @@ -144,6 +187,10 @@ void prerestorePage::job_name_change(int index) } } +/* + * Handle the change of enabled of input widgets when the recent checkbox state + * is changed. + */ void prerestorePage::recentChanged(int state) { if ((state == Qt::Unchecked) && (selectJobsRadio->isChecked())) { @@ -153,11 +200,15 @@ void prerestorePage::recentChanged(int state) } } +/* + * Handle the change of enabled of input widgets when the job radio buttons + * are changed. + */ void prerestorePage::jobsRadioClicked(bool checked) { if (checked) { jobCombo->setEnabled(true); -// filesetCombo->setEnabled(true); + filesetCombo->setEnabled(true); clientCombo->setEnabled(true); poolCombo->setEnabled(true); storageCombo->setEnabled(true); @@ -168,7 +219,7 @@ void prerestorePage::jobsRadioClicked(bool checked) jobIdEdit->setEnabled(false); } else { jobCombo->setEnabled(false); -// filesetCombo->setEnabled(false); + filesetCombo->setEnabled(false); clientCombo->setEnabled(false); poolCombo->setEnabled(false); storageCombo->setEnabled(false); @@ -177,3 +228,96 @@ void prerestorePage::jobsRadioClicked(bool checked) jobIdEdit->setEnabled(true); } } + +/* + * For when jobs list is to be used, return a list which is the needed items from + * the job record + */ +void prerestorePage::jobdefsFromJob(QStringList &fieldlist, QString jobId) +{ + QString job, client, fileset; + QString query(""); + query = "SELECT DISTINCT Job.Name AS JobName, Client.Name AS Client, Fileset.Fileset AS Fileset " + " From Job, Client, Fileset" + " WHERE Job.FilesetId=FileSet.FilesetId AND Job.ClientId=Client.ClientId" + " AND JobId=\'" + jobId + "\'"; + //printf("query = %s\n", query.toUtf8().data()); + QStringList results; + if (m_console->sql_cmd(query, results)) { + QString field; + + /* Iterate through the lines of results, there should only be one. */ + foreach (QString resultline, results) { + fieldlist = resultline.split("\t"); + } /* foreach resultline */ + } /* if results from query */ +} + +/* + * Function to handle when the jobidlist line edit input loses focus or is entered + */ +void prerestorePage::jobIdEditFinished() +{ + checkJobIdList(); +} + +bool prerestorePage::checkJobIdList() +{ + /* Need to check and make sure the text is a comma separated list of integers */ + QString line = jobIdEdit->text(); + if (line.contains(" ")) { + QMessageBox::warning(this, tr("Bat"), + tr("There can be no spaces in the text for the joblist.\n" + "Press OK to continue?"), QMessageBox::Ok ); + return false; + } + //printf("In prerestorePage::jobIdEditFinished %s\n",line.toUtf8().data()); + QStringList joblist = line.split(",", QString::SkipEmptyParts); + bool allintokay = true, alljobok = true, allisjob = true; + QString jobName(""), clientName(""); + foreach (QString job, joblist) { + bool intok; + job.toInt(&intok, 10); + if (intok) { + /* are the intergers representing a list of jobs all with the same job + * and client */ + QStringList fields; + jobdefsFromJob(fields, job); + int count = fields.count(); + if (count > 0) { + if (jobName == "") + jobName = fields[0]; + else if (jobName != fields[0]) + alljobok = false; + if (clientName == "") + clientName = fields[1]; + else if (clientName != fields[1]) + alljobok = false; + } else { + allisjob = false; + } + } else { + allintokay = false; + } + } + if (!allintokay){ + QMessageBox::warning(this, tr("Bat"), + tr("The string is not a comma separated list if integers.\n" + "Press OK to continue?"), QMessageBox::Ok ); + return false; + } + if (!allisjob){ + QMessageBox::warning(this, tr("Bat"), + tr("At least one of the jobs is not a valid job.\n" + "Press OK to continue?"), QMessageBox::Ok ); + return false; + } + if (!alljobok){ + QMessageBox::warning(this, tr("Bat"), + tr("All jobs in the list must be of the same jobName and same client.\n" + "Press OK to continue?"), QMessageBox::Ok ); + return false; + } + return true; +} + diff --git a/bacula/src/qt-console/restore/restore.h b/bacula/src/qt-console/restore/restore.h index f952b530df..f027e233e5 100644 --- a/bacula/src/qt-console/restore/restore.h +++ b/bacula/src/qt-console/restore/restore.h @@ -50,6 +50,7 @@ class prerestorePage : public Pages, public Ui::prerestoreForm public: prerestorePage(); + prerestorePage(QString &jobIdString); private slots: void okButtonPushed(); @@ -57,9 +58,14 @@ private slots: void job_name_change(int index); void recentChanged(int); void jobsRadioClicked(bool); + void jobIdEditFinished(); private: + void jobdefsFromJob(QStringList &, QString); + void buildPage(); + bool checkJobIdList(); QString m_dtformat; + QString m_jobIdListIn; }; /*