2 Bacula® - The Network Backup Solution
4 Copyright (C) 2007-2010 Free Software Foundation Europe e.V.
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
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.
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
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.
33 * Kern Sibbald, February MMVII
38 #include "restoretree.h"
41 restoreTree::restoreTree()
44 m_name = tr("Version Browser");
46 QTreeWidgetItem* thisitem = mainWin->getFromHash(this);
47 thisitem->setIcon(0, QIcon(QString::fromUtf8(":images/browse.png")));
54 QGridLayout *gridLayout = new QGridLayout(this);
55 gridLayout->setSpacing(6);
56 gridLayout->setMargin(9);
57 gridLayout->setObjectName(QString::fromUtf8("gridLayout"));
59 m_splitter = new QSplitter(Qt::Vertical, this);
60 QScrollArea *area = new QScrollArea();
61 area->setObjectName(QString::fromUtf8("area"));
62 area->setWidget(widget);
63 area->setWidgetResizable(true);
64 m_splitter->addWidget(area);
65 m_splitter->addWidget(splitter);
66 splitter->setChildrenCollapsible(false);
68 gridLayout->addWidget(m_splitter, 0, 0, 1, 1);
70 /* progress widgets */
71 prBar1->setVisible(false);
72 prBar2->setVisible(false);
73 prLabel1->setVisible(false);
74 prLabel2->setVisible(false);
76 /* Set Defaults for check and spin for limits */
77 limitCheckBox->setCheckState(mainWin->m_recordLimitCheck ? Qt::Checked : Qt::Unchecked);
78 limitSpinBox->setValue(mainWin->m_recordLimitVal);
79 daysCheckBox->setCheckState(mainWin->m_daysLimitCheck ? Qt::Checked : Qt::Unchecked);
80 daysSpinBox->setValue(mainWin->m_daysLimitVal);
82 m_nullFileNameId = -1;
87 restoreTree::~restoreTree()
93 * Called from the constructor to set up the page widgets and connections.
95 void restoreTree::setupPage()
97 connect(refreshButton, SIGNAL(pressed()), this, SLOT(refreshButtonPushed()));
98 connect(restoreButton, SIGNAL(pressed()), this, SLOT(restoreButtonPushed()));
99 connect(jobCombo, SIGNAL(currentIndexChanged(int)), this, SLOT(jobComboChanged(int)));
100 connect(jobCombo, SIGNAL(currentIndexChanged(int)), this, SLOT(updateRefresh()));
101 connect(clientCombo, SIGNAL(currentIndexChanged(int)), this, SLOT(updateRefresh()));
102 connect(fileSetCombo, SIGNAL(currentIndexChanged(int)), this, SLOT(updateRefresh()));
103 connect(limitCheckBox, SIGNAL(stateChanged(int)), this, SLOT(updateRefresh()));
104 connect(daysCheckBox, SIGNAL(stateChanged(int)), this, SLOT(updateRefresh()));
105 connect(daysSpinBox, SIGNAL(valueChanged(int)), this, SLOT(updateRefresh()));
106 connect(limitSpinBox, SIGNAL(valueChanged(int)), this, SLOT(updateRefresh()));
107 connect(directoryTree, SIGNAL(currentItemChanged(QTreeWidgetItem *, QTreeWidgetItem *)),
108 this, SLOT(directoryCurrentItemChanged(QTreeWidgetItem *, QTreeWidgetItem *)));
109 connect(directoryTree, SIGNAL(itemExpanded(QTreeWidgetItem *)),
110 this, SLOT(directoryItemExpanded(QTreeWidgetItem *)));
111 connect(directoryTree, SIGNAL(itemChanged(QTreeWidgetItem *, int)),
112 this, SLOT(directoryItemChanged(QTreeWidgetItem *, int)));
113 connect(fileTable, SIGNAL(currentItemChanged(QTableWidgetItem *, QTableWidgetItem *)),
114 this, SLOT(fileCurrentItemChanged(QTableWidgetItem *, QTableWidgetItem *)));
115 connect(jobTable, SIGNAL(cellClicked(int, int)),
116 this, SLOT(jobTableCellClicked(int, int)));
118 QStringList titles = QStringList() << tr("Directories");
119 directoryTree->setHeaderLabels(titles);
120 clientCombo->addItems(m_console->client_list);
121 fileSetCombo->addItem(tr("Any"));
122 fileSetCombo->addItems(m_console->fileset_list);
123 jobCombo->addItem(tr("Any"));
124 jobCombo->addItems(m_console->job_list);
126 directoryTree->setContextMenuPolicy(Qt::ActionsContextMenu);
129 void restoreTree::updateRefresh()
131 if (mainWin->m_rtPopDirDebug) Pmsg2(000, "testing prev=\"%s\" current=\"%s\"\n", m_prevJobCombo.toUtf8().data(), jobCombo->currentText().toUtf8().data());
132 m_dropdownChanged = (m_prevJobCombo != jobCombo->currentText())
133 || (m_prevClientCombo != clientCombo->currentText())
134 || (m_prevFileSetCombo != fileSetCombo->currentText()
135 || (m_prevLimitSpinBox != limitSpinBox->value())
136 || (m_prevDaysSpinBox != daysSpinBox->value())
137 || (m_prevLimitCheckState != limitCheckBox->checkState())
138 || (m_prevDaysCheckState != daysCheckBox->checkState())
140 if (m_dropdownChanged) {
141 if (mainWin->m_rtPopDirDebug) Pmsg0(000, "In restoreTree::updateRefresh Is CHANGED\n");
142 refreshLabel->setText(tr("Refresh From Re-Select"));
144 if (mainWin->m_rtPopDirDebug) Pmsg0(000, "In restoreTree::updateRefresh Is not Changed\n");
145 refreshLabel->setText(tr("Refresh From JobChecks"));
150 * When refresh button is pushed, perform a query getting the directories and
151 * use parseDirectory and addDirectory to populate the directory tree with items.
153 void restoreTree::populateDirectoryTree()
159 directoryTree->clear();
161 fileTable->setRowCount(0);
162 fileTable->setColumnCount(0);
163 versionTable->clear();
164 versionTable->setRowCount(0);
165 versionTable->setColumnCount(0);
166 m_fileExceptionHash.clear();
167 m_fileExceptionMulti.clear();
168 m_versionExceptionHash.clear();
169 m_directoryIconStateHash.clear();
172 int taskcount = 3, ontask = 1;
173 if (m_dropdownChanged) taskcount += 1;
175 /* Set progress bars and repaint */
176 prBar1->setVisible(true);
177 prBar1->setRange(0,taskcount);
179 prLabel1->setText(tr("Task %1 of %2").arg(ontask).arg(taskcount));
180 prLabel1->setVisible(true);
181 prBar2->setVisible(true);
182 prBar2->setRange(0,0);
183 prLabel2->setText(tr("Querying Database"));
184 prLabel2->setVisible(true);
187 if (m_dropdownChanged) {
188 m_prevJobCombo = jobCombo->currentText();
189 m_prevClientCombo = clientCombo->currentText();
190 m_prevFileSetCombo = fileSetCombo->currentText();
191 m_prevLimitSpinBox = limitSpinBox->value();
192 m_prevDaysSpinBox = daysSpinBox->value();
193 m_prevLimitCheckState = limitCheckBox->checkState();
194 m_prevDaysCheckState = daysCheckBox->checkState();
196 prBar1->setValue(ontask++);
197 prLabel1->setText(tr("Task %1 of %2").arg(ontask).arg(taskcount));
199 prBar2->setRange(0,0);
200 prLabel2->setText(tr("Querying Jobs"));
204 setJobsCheckedList();
205 if (mainWin->m_rtPopDirDebug) Pmsg0(000, "Repopulating from checks in Job Table\n");
207 if (m_checkedJobs != "") {
208 /* First get the filenameid of where the nae is null. These will be the directories
209 * This could be done in a subquery but postgres's query analyzer won't do the right
210 * thing like I want */
211 if (m_nullFileNameId == -1) {
212 QString cmd = "SELECT FilenameId FROM Filename WHERE name=''";
213 if (mainWin->m_sqlDebug)
214 Pmsg1(000, "Query cmd : %s\n", cmd.toUtf8().data());
216 if (m_console->sql_cmd(cmd, qres)) {
218 QStringList fieldlist = qres[0].split("\t");
219 QString field = fieldlist[0];
221 int val = field.toInt(&ok, 10);
222 if (ok) m_nullFileNameId = val;
226 /* now create the query to get the list of paths */
228 "SELECT DISTINCT Path.Path AS Path, File.PathId AS PathId"
230 " INNER JOIN Path ON (File.PathId=Path.PathId)";
231 if (m_nullFileNameId != -1)
232 cmd += " WHERE File.FilenameId=" + QString("%1").arg(m_nullFileNameId);
234 cmd += " WHERE File.FilenameId IN (SELECT FilenameId FROM Filename WHERE Name='')";
235 cmd += " AND File.Jobid IN (" + m_checkedJobs + ")"
237 if (mainWin->m_sqlDebug)
238 Pmsg1(000, "Query cmd : %s\n", cmd.toUtf8().data());
239 prBar1->setValue(ontask++);
240 prLabel1->setText(tr("Task %1 of %2").arg(ontask).arg(taskcount));
242 prBar2->setRange(0,0);
243 prLabel2->setText(tr("Querying for Directories"));
246 m_directoryPathIdHash.clear();
247 bool querydone = false;
248 if (m_console->sql_cmd(cmd, results)) {
251 prLabel2->setText(tr("Processing Directories"));
252 prBar2->setRange(0,results.count());
255 if (mainWin->m_miscDebug)
256 Pmsg1(000, "Done with query %i results\n", results.count());
257 QStringList fieldlist;
258 foreach(QString resultline, results) {
259 /* Update progress bar periodically */
260 if ((++m_debugCnt && 0x3FF) == 0) {
261 prBar2->setValue(m_debugCnt);
263 fieldlist = resultline.split("\t");
266 /* Iterate through fields in the record */
267 foreach (field, fieldlist) {
268 if (fieldcnt == 0 ) {
269 parseDirectory(field);
270 } else if (fieldcnt == 1) {
272 int pathid = field.toInt(&ok, 10);
274 m_directoryPathIdHash.insert(fieldlist[0], pathid);
283 QMessageBox::warning(this, "Bat",
284 tr("No jobs were selected in the job query !!!.\n"
285 "Press OK to continue"),
288 prBar1->setVisible(false);
289 prBar2->setVisible(false);
290 prLabel1->setVisible(false);
291 prLabel2->setVisible(false);
295 * Function to set m_checkedJobs from the jobs that are checked in the table
298 void restoreTree::setJobsCheckedList()
300 m_JobsCheckedList = "";
302 /* Update the items in the version table */
303 int cnt = jobTable->rowCount();
304 for (int row=0; row<cnt; row++) {
305 QTableWidgetItem* jobItem = jobTable->item(row, 0);
306 if (jobItem->checkState() == Qt::Checked) {
308 m_JobsCheckedList += ",";
309 m_JobsCheckedList += jobItem->text();
311 jobItem->setBackground(Qt::green);
313 if (jobItem->flags())
314 jobItem->setBackground(Qt::gray);
316 jobItem->setBackground(Qt::darkYellow);
319 m_checkedJobs = m_JobsCheckedList;
323 * Function to parse a directory into all possible subdirectories, then add to
326 void restoreTree::parseDirectory(QString &dir_in)
328 /* m_debugTrap is to only print debugs for a few occurennces of calling parseDirectory
329 * instead of printing out what could potentially a whole bunch */
332 /* Truncate everything after the last / */
333 if (dir_in.right(1) != "/") {
334 dir_in.truncate(dir_in.lastIndexOf("/") + 1);
336 if ((mainWin->m_miscDebug) && (m_debugTrap))
337 Pmsg1(000, "parsing %s\n", dir_in.toUtf8().data());
339 /* split and add if not in yet */
340 QString direct, path;
343 QStringList pathAfter, dirAfter;
344 /* start from the end, turn /etc/somedir/subdir/ into /etc/somedir and subdir/
345 * if not added into tree, then try /etc/ and somedir/ if not added, then try
346 * / and etc/ . That should succeed, then add the ones that failed in reverse */
347 while (((index = dir_in.lastIndexOf("/", -2)) != -1) && (!done)) {
348 direct = path = dir_in;
349 path.replace(index+1, dir_in.length()-index-1,"");
350 direct.replace(0, index+1, "");
351 if ((mainWin->m_miscDebug) && (m_debugTrap)) {
352 QString msg = QString("length = \"%1\" index = \"%2\" Adding \"%3\" \"%4\"\n")
353 .arg(dir_in.length()).arg(index).arg(path).arg(direct);
354 Pmsg0(000, msg.toUtf8().data());
356 if (addDirectory(path, direct)) { done = true; }
358 if ((mainWin->m_miscDebug) && (m_debugTrap)) {
359 Pmsg0(000, "Saving for later\n");
361 pathAfter.prepend(path);
362 dirAfter.prepend(direct);
367 for (int k=0; k<pathAfter.count(); k++) {
368 if (addDirectory(pathAfter[k], dirAfter[k])) {
369 if ((mainWin->m_miscDebug) && (m_debugTrap))
370 Pmsg2(000, "Adding After %s %s\n", pathAfter[k].toUtf8().data(), dirAfter[k].toUtf8().data());
372 if ((mainWin->m_miscDebug) && (m_debugTrap))
373 Pmsg2(000, "Error Adding %s %s\n", pathAfter[k].toUtf8().data(), dirAfter[k].toUtf8().data());
380 * Function called from fill directory when a directory is found to see if this
381 * directory exists in the directory pane and then add it to the directory pane
383 bool restoreTree::addDirectory(QString &m_cwd, QString &newdirr)
385 QString newdir = newdirr;
386 QString fullPath = m_cwd + newdirr;
387 bool ok = true, added = false;
389 if ((mainWin->m_miscDebug) && (m_debugTrap)) {
390 QString msg = QString("In addDirectory cwd \"%1\" newdir \"%2\"\n")
393 Pmsg0(000, msg.toUtf8().data());
397 /* add unix '/' directory first */
398 if (m_dirPaths.empty() && !isWin32Path(fullPath)) {
400 QTreeWidgetItem *item = new QTreeWidgetItem(directoryTree);
402 item->setText(0, text.toUtf8().data());
403 item->setData(0, Qt::UserRole, QVariant(text));
404 item->setData(1, Qt::UserRole, QVariant(Qt::Unchecked));
405 item->setIcon(0, QIcon(QString::fromUtf8(":images/folder.png")));
406 if ((mainWin->m_miscDebug) && (m_debugTrap)) {
407 Pmsg1(000, "Pre Inserting %s\n", text.toUtf8().data());
409 m_dirPaths.insert(text, item);
411 /* no need to check for windows drive if unix */
412 if (isWin32Path(m_cwd)) {
413 if (!m_dirPaths.contains(m_cwd)) {
414 if (m_cwd.count('/') > 1) { return false; }
415 /* this is a windows drive add the base widget */
416 QTreeWidgetItem *item = new QTreeWidgetItem(directoryTree);
417 item->setText(0, m_cwd);
418 item->setData(0, Qt::UserRole, QVariant(fullPath));
419 item->setData(1, Qt::UserRole, QVariant(Qt::Unchecked));
420 item->setIcon(0, QIcon(QString::fromUtf8(":images/folder.png")));
421 if ((mainWin->m_miscDebug) && (m_debugTrap)) {
422 Pmsg0(000, "Added Base \"letter\":/\n");
424 m_dirPaths.insert(m_cwd, item);
429 /* is it already existent ?? */
430 if (!m_dirPaths.contains(fullPath)) {
431 QTreeWidgetItem *item = NULL;
432 QTreeWidgetItem *parent = m_dirPaths.value(m_cwd);
434 /* new directories to add */
435 item = new QTreeWidgetItem(parent);
436 item->setText(0, newdir.toUtf8().data());
437 item->setData(0, Qt::UserRole, QVariant(fullPath));
438 item->setCheckState(0, Qt::Unchecked);
439 /* Store the current state of the check status in column 1, which at
440 * this point has no text*/
441 item->setData(1, Qt::UserRole, QVariant(Qt::Unchecked));
444 if ((mainWin->m_miscDebug) && (m_debugTrap)) {
445 QString msg = QString("In else of if parent cwd \"%1\" newdir \"%2\"\n")
448 Pmsg0(000, msg.toUtf8().data());
451 /* insert into hash */
453 if ((mainWin->m_miscDebug) && (m_debugTrap)) {
454 Pmsg1(000, "Inserting %s\n", fullPath.toUtf8().data());
456 m_dirPaths.insert(fullPath, item);
464 * Virtual function which is called when this page is visible on the stack
466 void restoreTree::currentStackItem()
475 * Populate the tree when refresh button pushed.
477 void restoreTree::refreshButtonPushed()
479 populateDirectoryTree();
483 * Set the values of non-job combo boxes to the job defaults
485 void restoreTree::jobComboChanged(int)
487 if (jobCombo->currentText() == tr("Any")) {
488 fileSetCombo->setCurrentIndex(fileSetCombo->findText(tr("Any"), Qt::MatchExactly));
491 job_defaults job_defs;
494 job_defs.job_name = jobCombo->currentText();
495 if (m_console->get_job_defaults(job_defs)) {
496 fileSetCombo->setCurrentIndex(fileSetCombo->findText(job_defs.fileset_name, Qt::MatchExactly));
497 clientCombo->setCurrentIndex(clientCombo->findText(job_defs.client_name, Qt::MatchExactly));
502 * Function to populate the file list table
504 void restoreTree::directoryCurrentItemChanged(QTreeWidgetItem *item, QTreeWidgetItem *)
510 /* Also clear the version table here */
511 versionTable->clear();
512 versionFileLabel->setText("");
513 versionTable->setRowCount(0);
514 versionTable->setColumnCount(0);
516 QStringList headerlist = (QStringList() << tr("File Name") << tr("Filename Id"));
517 fileTable->setColumnCount(headerlist.size());
518 fileTable->setHorizontalHeaderLabels(headerlist);
519 fileTable->setRowCount(0);
521 m_fileCheckStateList.clear();
522 disconnect(fileTable, SIGNAL(itemChanged(QTableWidgetItem *)),
523 this, SLOT(fileTableItemChanged(QTableWidgetItem *)));
524 QBrush blackBrush(Qt::black);
525 QString directory = item->data(0, Qt::UserRole).toString();
526 directoryLabel->setText(tr("Present Working Directory: %1").arg(directory));
527 int pathid = m_directoryPathIdHash.value(directory, -1);
530 "SELECT DISTINCT Filename.Name AS FileName, Filename.FilenameId AS FilenameId"
532 " INNER JOIN Filename on (Filename.FilenameId=File.FilenameId)"
533 " WHERE File.PathId=" + QString("%1").arg(pathid) +
534 " AND File.Jobid IN (" + m_checkedJobs + ")"
535 " AND Filename.Name!=''"
536 " ORDER BY FileName";
537 if (mainWin->m_sqlDebug) Pmsg1(000, "Query cmd : %s\n", cmd.toUtf8().data());
540 if (m_console->sql_cmd(cmd, results)) {
542 QTableWidgetItem* tableItem;
544 QStringList fieldlist;
545 fileTable->setRowCount(results.size());
548 /* Iterate through the record returned from the query */
549 foreach (QString resultline, results) {
550 /* Iterate through fields in the record */
552 fieldlist = resultline.split("\t");
553 foreach (field, fieldlist) {
554 field = field.trimmed(); /* strip leading & trailing spaces */
555 tableItem = new QTableWidgetItem(field, 1);
556 /* Possible flags are Qt::ItemFlags flag = Qt::ItemIsSelectable | Qt::ItemIsEditablex
557 * | Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled | Qt::ItemIsUserCheckable
558 * | Qt::ItemIsEnabled | Qt::ItemIsTristate; */
559 tableItem->setForeground(blackBrush);
560 /* Just in case a column ever gets added */
561 if (mainWin->m_sqlDebug) Pmsg1(000, "Column=%d\n", column);
563 Qt::ItemFlags flag = Qt::ItemIsUserCheckable | Qt::ItemIsEnabled | Qt::ItemIsTristate;
564 tableItem->setFlags(flag);
565 tableItem->setData(Qt::UserRole, QVariant(directory));
566 fileTable->setItem(row, column, tableItem);
567 m_fileCheckStateList.append(Qt::Unchecked);
568 tableItem->setCheckState(Qt::Unchecked);
569 } else if (column == 1) {
570 Qt::ItemFlags flag = Qt::ItemIsEnabled;
571 tableItem->setFlags(flag);
573 int filenameid = field.toInt(&ok, 10);
574 if (!ok) filenameid = -1;
575 tableItem->setData(Qt::UserRole, QVariant(filenameid));
576 fileTable->setItem(row, column, tableItem);
582 fileTable->setRowCount(row);
584 fileTable->resizeColumnsToContents();
585 fileTable->resizeRowsToContents();
586 fileTable->verticalHeader()->hide();
587 fileTable->hideColumn(1);
588 if (mainWin->m_rtDirCurICDebug) Pmsg0(000, "will update file table checks\n");
589 updateFileTableChecks();
590 } else if (mainWin->m_sqlDebug)
591 Pmsg1(000, "did not perform query, pathid=%i not found\n", pathid);
592 connect(fileTable, SIGNAL(itemChanged(QTableWidgetItem *)),
593 this, SLOT(fileTableItemChanged(QTableWidgetItem *)));
597 * Function to populate the version table
599 void restoreTree::fileCurrentItemChanged(QTableWidgetItem *currentFileTableItem, QTableWidgetItem *)
601 if (currentFileTableItem == NULL)
604 int currentRow = fileTable->row(currentFileTableItem);
605 QTableWidgetItem *fileTableItem = fileTable->item(currentRow, 0);
606 QTableWidgetItem *fileNameIdTableItem = fileTable->item(currentRow, 1);
607 int fileNameId = fileNameIdTableItem->data(Qt::UserRole).toInt();
609 m_versionCheckStateList.clear();
610 disconnect(versionTable, SIGNAL(itemChanged(QTableWidgetItem *)),
611 this, SLOT(versionTableItemChanged(QTableWidgetItem *)));
613 QString file = fileTableItem->text();
614 versionFileLabel->setText(file);
615 QString directory = fileTableItem->data(Qt::UserRole).toString();
617 QBrush blackBrush(Qt::black);
619 QStringList headerlist = (QStringList()
620 << tr("Job Id") << tr("Type") << tr("End Time") << tr("Hash") << tr("FileId") << tr("Job Type") << tr("First Volume"));
621 versionTable->clear();
622 versionTable->setColumnCount(headerlist.size());
623 versionTable->setHorizontalHeaderLabels(headerlist);
624 versionTable->setRowCount(0);
626 int pathid = m_directoryPathIdHash.value(directory, -1);
627 if ((pathid != -1) && (fileNameId != -1)) {
629 "SELECT Job.JobId AS JobId, Job.Level AS Type,"
630 " Job.EndTime AS EndTime, File.MD5 AS MD5,"
631 " File.FileId AS FileId, Job.Type AS JobType,"
632 " (SELECT Media.VolumeName FROM JobMedia JOIN Media ON JobMedia.MediaId=Media.MediaId WHERE JobMedia.JobId=Job.JobId ORDER BY JobMediaId LIMIT 1) AS FirstVolume"
634 " INNER JOIN Filename on (Filename.FilenameId=File.FilenameId)"
635 " INNER JOIN Path ON (Path.PathId=File.PathId)"
636 " INNER JOIN Job ON (File.JobId=Job.JobId)"
637 " WHERE Path.PathId=" + QString("%1").arg(pathid) +
638 //" AND Filename.Name='" + file + "'"
639 " AND Filename.FilenameId=" + QString("%1").arg(fileNameId) +
640 " AND Job.Jobid IN (" + m_checkedJobs + ")"
641 " ORDER BY Job.EndTime DESC";
643 if (mainWin->m_sqlDebug) Pmsg1(000, "Query cmd : %s\n", cmd.toUtf8().data());
645 if (m_console->sql_cmd(cmd, results)) {
647 QTableWidgetItem* tableItem;
649 QStringList fieldlist;
650 versionTable->setRowCount(results.size());
653 /* Iterate through the record returned from the query */
654 foreach (QString resultline, results) {
655 fieldlist = resultline.split("\t");
657 /* remove directory */
658 if (fieldlist[0].trimmed() != "") {
659 /* Iterate through fields in the record */
660 foreach (field, fieldlist) {
661 field = field.trimmed(); /* strip leading & trailing spaces */
663 QByteArray jtype(field.trimmed().toAscii());
665 field = job_type_to_str(jtype[0]);
668 tableItem = new QTableWidgetItem(field, 1);
669 tableItem->setFlags(0);
670 tableItem->setForeground(blackBrush);
671 tableItem->setData(Qt::UserRole, QVariant(directory));
672 versionTable->setItem(row, column, tableItem);
673 if (mainWin->m_sqlDebug) Pmsg1(000, "Column=%d\n", column);
675 Qt::ItemFlags flag = Qt::ItemIsUserCheckable | Qt::ItemIsEnabled | Qt::ItemIsTristate;
676 tableItem->setFlags(flag);
677 m_versionCheckStateList.append(Qt::Unchecked);
678 tableItem->setCheckState(Qt::Unchecked);
686 versionTable->resizeColumnsToContents();
687 versionTable->resizeRowsToContents();
688 versionTable->verticalHeader()->hide();
689 updateVersionTableChecks();
691 if (mainWin->m_sqlDebug)
692 Pmsg2(000, "not querying : pathid=%i fileNameId=%i\n", pathid, fileNameId);
694 connect(versionTable, SIGNAL(itemChanged(QTableWidgetItem *)),
695 this, SLOT(versionTableItemChanged(QTableWidgetItem *)));
699 * Save user settings associated with this page
701 void restoreTree::writeSettings()
703 QSettings settings(m_console->m_dir->name(), "bat");
704 settings.beginGroup(m_groupText);
705 settings.setValue(m_splitText1, m_splitter->saveState());
706 settings.setValue(m_splitText2, splitter->saveState());
711 * Read and restore user settings associated with this page
713 void restoreTree::readSettings()
715 m_groupText = tr("RestoreTreePage");
716 m_splitText1 = "splitterSizes1_3";
717 m_splitText2 = "splitterSizes2_3";
718 QSettings settings(m_console->m_dir->name(), "bat");
719 settings.beginGroup(m_groupText);
720 if (settings.contains(m_splitText1)) { m_splitter->restoreState(settings.value(m_splitText1).toByteArray()); }
721 if (settings.contains(m_splitText2)) { splitter->restoreState(settings.value(m_splitText2).toByteArray()); }
726 * This is a funcion to accomplish the one thing I struggled to figure out what
727 * was taking so long. It add the icons, but after the tree is made. Seemed to
728 * work fast after changing from png to png file for graphic.
730 void restoreTree::directoryItemExpanded(QTreeWidgetItem *item)
732 int childCount = item->childCount();
733 for (int i=0; i<childCount; i++) {
734 QTreeWidgetItem *child = item->child(i);
735 if (child->icon(0).isNull())
736 child->setIcon(0, QIcon(QString::fromUtf8(":images/folder.png")));
741 * Show what jobs meet the criteria and are being used to
742 * populate the directory tree and file and version tables.
744 void restoreTree::populateJobTable()
746 QBrush blackBrush(Qt::black);
748 if (mainWin->m_rtPopDirDebug) Pmsg0(000, "Repopulating the Job Table\n");
749 QStringList headerlist = (QStringList()
750 << tr("Job Id") << tr("End Time") << tr("Level") << tr("Type")
751 << tr("Name") << tr("Purged") << tr("TU") << tr("TD"));
752 m_toggleUpIndex = headerlist.indexOf(tr("TU"));
753 m_toggleDownIndex = headerlist.indexOf(tr("TD"));
754 int purgedIndex = headerlist.indexOf(tr("Purged"));
755 int typeIndex = headerlist.indexOf(tr("Type"));
757 jobTable->setColumnCount(headerlist.size());
758 jobTable->setHorizontalHeaderLabels(headerlist);
760 "SELECT Job.Jobid AS Id, Job.EndTime AS EndTime,"
761 " Job.Level AS Level, Job.Type AS Type,"
762 " Job.Name AS JobName, Job.purgedfiles AS Purged"
764 /* INNER JOIN FileSet eliminates all restore jobs */
765 " INNER JOIN Client ON (Job.ClientId=Client.ClientId)"
766 " INNER JOIN FileSet ON (Job.FileSetId=FileSet.FileSetId)"
768 " Job.JobStatus IN ('T','W') AND Job.Type='B' AND"
769 " Client.Name='" + clientCombo->currentText() + "'";
770 if ((jobCombo->currentIndex() >= 0) && (jobCombo->currentText() != tr("Any"))) {
771 jobQuery += " AND Job.name = '" + jobCombo->currentText() + "'";
773 if ((fileSetCombo->currentIndex() >= 0) && (fileSetCombo->currentText() != tr("Any"))) {
774 jobQuery += " AND FileSet.FileSet='" + fileSetCombo->currentText() + "'";
776 /* If Limit check box For limit by days is checked */
777 if (daysCheckBox->checkState() == Qt::Checked) {
778 QDateTime stamp = QDateTime::currentDateTime().addDays(-daysSpinBox->value());
779 QString since = stamp.toString(Qt::ISODate);
780 jobQuery += " AND Job.Starttime>'" + since + "'";
782 //jobQuery += " AND Job.purgedfiles=0";
783 jobQuery += " ORDER BY Job.EndTime DESC";
784 /* If Limit check box for limit records returned is checked */
785 if (limitCheckBox->checkState() == Qt::Checked) {
787 limit.setNum(limitSpinBox->value());
788 jobQuery += " LIMIT " + limit;
790 if (mainWin->m_sqlDebug) Pmsg1(000, "Query cmd : %s\n", jobQuery.toUtf8().data());
794 if (m_console->sql_cmd(jobQuery, results)) {
796 QTableWidgetItem* tableItem;
798 QStringList fieldlist;
799 jobTable->setRowCount(results.size());
802 /* Iterate through the record returned from the query */
803 foreach (QString resultline, results) {
804 fieldlist = resultline.split("\t");
806 /* remove directory */
807 if (fieldlist[0].trimmed() != "") {
808 /* Iterate through fields in the record */
809 foreach (field, fieldlist) {
810 field = field.trimmed(); /* strip leading & trailing spaces */
812 if (column == typeIndex) {
813 QByteArray jtype(field.trimmed().toAscii());
815 field = job_type_to_str(jtype[0]);
818 tableItem = new QTableWidgetItem(field, 1);
819 tableItem->setFlags(0);
820 tableItem->setForeground(blackBrush);
821 jobTable->setItem(row, column, tableItem);
822 if (mainWin->m_sqlDebug) Pmsg1(000, "Column=%d\n", column);
825 int purged = fieldlist[purgedIndex].toInt(&ok, 10);
826 if (!((ok) && (purged == 1))) {
827 Qt::ItemFlags flag = Qt::ItemIsUserCheckable | Qt::ItemIsEnabled | Qt::ItemIsTristate;
828 tableItem->setFlags(flag);
829 tableItem->setCheckState(Qt::Checked);
830 tableItem->setBackground(Qt::green);
832 tableItem->setFlags(0);
833 tableItem->setCheckState(Qt::Unchecked);
839 tableItem = new QTableWidgetItem(QIcon(QString::fromUtf8(":images/go-up.png")), "", 1);
840 tableItem->setFlags(0);
841 tableItem->setForeground(blackBrush);
842 jobTable->setItem(row, column, tableItem);
844 tableItem = new QTableWidgetItem(QIcon(QString::fromUtf8(":images/go-down.png")), "", 1);
845 tableItem->setFlags(0);
846 tableItem->setForeground(blackBrush);
847 jobTable->setItem(row, column, tableItem);
852 jobTable->resizeColumnsToContents();
853 jobTable->resizeRowsToContents();
854 jobTable->verticalHeader()->hide();
855 jobTable->hideColumn(purgedIndex);
858 void restoreTree::jobTableCellClicked(int row, int column)
860 if (column == m_toggleUpIndex){
862 for (cnt=0; cnt<row+1; cnt++) {
863 QTableWidgetItem *item = jobTable->item(cnt, 0);
865 Qt::CheckState state = item->checkState();
866 if (state == Qt::Checked)
867 item->setCheckState(Qt::Unchecked);
868 else if (state == Qt::Unchecked)
869 item->setCheckState(Qt::Checked);
873 if (column == m_toggleDownIndex){
874 int cnt, max = jobTable->rowCount();
875 for (cnt=row; cnt<max; cnt++) {
876 QTableWidgetItem *item = jobTable->item(cnt, 0);
878 Qt::CheckState state = item->checkState();
879 if (state == Qt::Checked)
880 item->setCheckState(Qt::Unchecked);
881 else if (state == Qt::Unchecked)
882 item->setCheckState(Qt::Checked);
889 * When a directory item is "changed" check the state of the checkable item
890 * to see if it is different than what it was which is stored in Qt::UserRole
891 * of the 2nd column, column 1, of the tree widget.
893 void restoreTree::directoryItemChanged(QTreeWidgetItem *item, int /*column*/)
895 Qt::CheckState prevState = (Qt::CheckState)item->data(1, Qt::UserRole).toInt();
896 Qt::CheckState curState = item->checkState(0);
897 QTreeWidgetItem* parent = item->parent();
898 Qt::CheckState parState;
899 if (parent) parState = parent->checkState(0);
900 else parState = (Qt::CheckState)3;
901 if (mainWin->m_rtDirICDebug) {
902 QString msg = QString("directory item OBJECT has changed prev=%1 cur=%2 par=%3 dir=%4\n")
903 .arg(prevState).arg(curState).arg(parState).arg(item->text(0));
904 Pmsg1(000, "%s", msg.toUtf8().data()); }
905 /* I only care when the check state changes */
906 if (prevState == curState) {
907 if (mainWin->m_rtDirICDebug) Pmsg0(000, "Returning Early\n");
911 if ((prevState == Qt::Unchecked) && (curState == Qt::Checked) && (parState != Qt::Unchecked)) {
912 if (mainWin->m_rtDirICDebug) Pmsg0(000, "Disconnected Setting to Qt::PartiallyChecked\n");
913 directoryTreeDisconnectedSet(item, Qt::PartiallyChecked);
914 curState = Qt::PartiallyChecked;
916 if ((prevState == Qt::PartiallyChecked) && (curState == Qt::Checked)) {
917 if (mainWin->m_rtDirICDebug) Pmsg0(000, "Disconnected Setting to Qt::Unchecked\n");
918 directoryTreeDisconnectedSet(item, Qt::Unchecked);
919 curState = Qt::Unchecked;
921 if (mainWin->m_rtDirICDebug) {
922 QString msg = QString("directory item CHECKSTATE has changed prev=%1 cur=%2 par=%3 dir=%4\n")
923 .arg(prevState).arg(curState).arg(parState).arg(item->text(0));
924 Pmsg1(000, "%s", msg.toUtf8().data()); }
926 item->setData(1, Qt::UserRole, QVariant(curState));
927 Qt::CheckState childState = curState;
928 if (childState == Qt::Checked)
929 childState = Qt::PartiallyChecked;
930 setCheckofChildren(item, childState);
932 /* Remove items from the exception lists. The multi exception list is my index
933 * of what exceptions can be removed when the directory is known*/
934 QString directory = item->data(0, Qt::UserRole).toString();
935 QStringList fullPathList = m_fileExceptionMulti.values(directory);
936 int fullPathListCount = fullPathList.count();
937 if ((mainWin->m_rtDirICDebug) && fullPathListCount) Pmsg2(000, "Will attempt to remove file exceptions for %s count %i\n", directory.toUtf8().data(), fullPathListCount);
938 foreach (QString fullPath, fullPathList) {
939 /* If there is no value in the hash for the key fullPath a value of 3 will be returned
940 * which will match no Qt::xxx values */
941 Qt::CheckState hashState = m_fileExceptionHash.value(fullPath, (Qt::CheckState)3);
942 if (mainWin->m_rtDirICDebug) Pmsg2(000, "hashState=%i childState=%i\n", hashState, childState);
943 if (hashState == Qt::Unchecked) {
944 fileExceptionRemove(fullPath, directory);
945 m_versionExceptionHash.remove(fullPath);
946 if (mainWin->m_rtDirICDebug) Pmsg0(000, "Attempted Removal A\n");
948 if (hashState == Qt::Checked) {
949 fileExceptionRemove(fullPath, directory);
950 m_versionExceptionHash.remove(fullPath);
951 if (mainWin->m_rtDirICDebug) Pmsg0(000, "Attempted Removal B\n");
955 if (item == directoryTree->currentItem()) {
956 if (mainWin->m_rtDirICDebug) Pmsg0(000, "Will attempt to update File Table Checks\n");
957 updateFileTableChecks();
958 versionTable->clear();
959 versionTable->setRowCount(0);
960 versionTable->setColumnCount(0);
962 if (mainWin->m_rtDirICDebug) Pmsg0(000, "Returning At End\n");
966 * When a directory item check state is changed, this function iterates through
967 * all subdirectories and sets all to the passed state, which is either partially
968 * checked or unchecked.
970 void restoreTree::setCheckofChildren(QTreeWidgetItem *item, Qt::CheckState state)
973 childCount = item->childCount();
974 for (int i=0; i<childCount; i++) {
975 QTreeWidgetItem *child = item->child(i);
976 child->setData(1, Qt::UserRole, QVariant(state));
977 child->setCheckState(0, state);
978 setCheckofChildren(child, state);
983 * When a File Table Item is "changed" check to see if the state of the checkable
984 * item has changed which is stored in m_fileCheckStateList
985 * If changed store in a hash m_fileExceptionHash that whether this file should be
987 * Called as a slot, connected after populated (after directory current changed called)
989 void restoreTree::fileTableItemChanged(QTableWidgetItem *item)
991 /* get the previous and current check states */
992 int row = fileTable->row(item);
993 Qt::CheckState prevState;
994 /* prevent a segfault */
995 prevState = m_fileCheckStateList[row];
996 Qt::CheckState curState = item->checkState();
998 /* deterimine the default state from the state of the directory */
999 QTreeWidgetItem *dirTreeItem = directoryTree->currentItem();
1000 Qt::CheckState dirState = (Qt::CheckState)dirTreeItem->data(1, Qt::UserRole).toInt();
1001 Qt::CheckState defState = Qt::PartiallyChecked;
1002 if (dirState == Qt::Unchecked) defState = Qt::Unchecked;
1004 /* determine if it is already in the m_fileExceptionHash */
1005 QString directory = directoryTree->currentItem()->data(0, Qt::UserRole).toString();
1006 QString file = item->text();
1007 QString fullPath = directory + file;
1008 Qt::CheckState hashState = m_fileExceptionHash.value(fullPath, (Qt::CheckState)3);
1009 int verJobNum = m_versionExceptionHash.value(fullPath, 0);
1011 if (mainWin->m_rtFileTabICDebug) {
1012 QString msg = QString("filerow=%1 prev=%2 cur=%3 def=%4 hash=%5 dir=%6 verJobNum=%7\n")
1013 .arg(row).arg(prevState).arg(curState).arg(defState).arg(hashState).arg(dirState).arg(verJobNum);
1014 Pmsg1(000, "%s", msg.toUtf8().data()); }
1016 /* Remove the hash if currently checked previously unchecked and directory is checked or partial */
1017 if ((prevState == Qt::Checked) && (curState == Qt::Unchecked) && (dirState == Qt::Unchecked)) {
1018 /* it can behave as defaulted so current of unchecked is fine */
1019 if (mainWin->m_rtFileTabICDebug) Pmsg0(000, "Will fileExceptionRemove and m_versionExceptionHash.remove here\n");
1020 fileExceptionRemove(fullPath, directory);
1021 m_versionExceptionHash.remove(fullPath);
1022 } else if ((prevState == Qt::PartiallyChecked) && (curState == Qt::Checked) && (dirState != Qt::Unchecked) && (verJobNum == 0)) {
1023 if (mainWin->m_rtFileTabICDebug) Pmsg0(000, "Will fileExceptionInsert here\n");
1024 fileExceptionInsert(fullPath, directory, Qt::Unchecked);
1025 } else if ((prevState == Qt::Unchecked) && (curState == Qt::Checked) && (dirState != Qt::Unchecked) && (verJobNum == 0) && (defState == Qt::PartiallyChecked)) {
1026 /* filerow=2 prev=0 cur=2 def=1 hash=0 dir=2 verJobNum=0 */
1027 if (mainWin->m_rtFileTabICDebug) Pmsg0(000, "Will fileExceptionRemove here\n");
1028 fileExceptionRemove(fullPath, directory);
1029 } else if ((prevState == Qt::Checked) && (curState == Qt::Unchecked) && (defState == Qt::PartiallyChecked) && (verJobNum != 0) && (hashState == Qt::Checked)) {
1030 /* Check dir, check version, attempt uncheck in file
1031 * filerow=4 prev=2 cur=0 def=1 hash=2 dir=2 verJobNum=53 */
1032 if (mainWin->m_rtFileTabICDebug) Pmsg0(000, "Will fileExceptionRemove and m_versionExceptionHash.remove here\n");
1033 fileExceptionRemove(fullPath, directory);
1034 m_versionExceptionHash.remove(fullPath);
1035 } else if ((prevState == Qt::Unchecked) && (curState == Qt::Checked) && (dirState != Qt::Unchecked) && (verJobNum == 0)) {
1036 /* filerow=0 prev=0 cur=2 def=1 hash=0 dirState=2 verJobNum */
1037 if (mainWin->m_rtFileTabICDebug) Pmsg0(000, "Will Not remove here\n");
1038 } else if (prevState != curState) {
1039 if (mainWin->m_rtFileTabICDebug) Pmsg2(000, " THE STATE OF THE Check has changed, Setting StateList[%i] to %i\n", row, curState);
1040 /* A user did not set the check state to Partially checked, ignore if so */
1041 if (curState != Qt::PartiallyChecked) {
1042 if ((defState == Qt::Unchecked) && (prevState == Qt::PartiallyChecked) && (curState == Qt::Unchecked)) {
1043 if (mainWin->m_rtFileTabICDebug) Pmsg0(000, " got here\n");
1045 if (mainWin->m_rtFileTabICDebug) Pmsg2(000, " Inserting into m_fileExceptionHash %s, %i\n", fullPath.toUtf8().data(), curState);
1046 fileExceptionInsert(fullPath, directory, curState);
1049 if (mainWin->m_rtFileTabICDebug) Pmsg1(000, "Removing version hash for %s\n", fullPath.toUtf8().data());
1050 /* programattically been changed back to a default state of Qt::PartiallyChecked remove the version hash here */
1051 m_versionExceptionHash.remove(fullPath);
1055 updateFileTableChecks();
1056 updateVersionTableChecks();
1060 * function to insert keys and values to both m_fileExceptionHash and m_fileExceptionMulti
1062 void restoreTree::fileExceptionInsert(QString &fullPath, QString &direcotry, Qt::CheckState state)
1064 m_fileExceptionHash.insert(fullPath, state);
1065 m_fileExceptionMulti.insert(direcotry, fullPath);
1066 directoryIconStateInsert(fullPath, state);
1070 * function to remove keys from both m_fileExceptionHash and m_fileExceptionMulti
1072 void restoreTree::fileExceptionRemove(QString &fullPath, QString &directory)
1074 m_fileExceptionHash.remove(fullPath);
1075 /* pull the list of values in the multi */
1076 QStringList fullPathList = m_fileExceptionMulti.values(directory);
1077 /* get the index of the fullpath to remove */
1078 int index = fullPathList.indexOf(fullPath);
1080 /* remove the desired item in the list */
1081 fullPathList.removeAt(index);
1082 /* remove the entire list from the multi */
1083 m_fileExceptionMulti.remove(directory);
1084 /* readd the remaining */
1085 foreach (QString fp, fullPathList) {
1086 m_fileExceptionMulti.insert(directory, fp);
1089 directoryIconStateRemove();
1093 * Overloaded function to be called from the slot and from other places to set the state
1094 * of the check marks in the version table
1096 void restoreTree::versionTableItemChanged(QTableWidgetItem *item)
1098 /* get the previous and current check states */
1099 int row = versionTable->row(item);
1100 QTableWidgetItem *colZeroItem = versionTable->item(row, 0);
1101 Qt::CheckState prevState = m_versionCheckStateList[row];
1102 Qt::CheckState curState = (Qt::CheckState)colZeroItem->checkState();
1103 m_versionCheckStateList[row] = curState;
1105 /* deterimine the default state from the state of the file */
1106 QTableWidgetItem *fileTableItem = fileTable->currentItem();
1107 Qt::CheckState fileState = (Qt::CheckState)fileTableItem->checkState();
1109 /* determine the default state */
1110 Qt::CheckState defState;
1111 if (mainWin->m_sqlDebug) Pmsg1(000, "row=%d\n", row);
1113 defState = Qt::PartiallyChecked;
1114 if (fileState == Qt::Unchecked)
1115 defState = Qt::Unchecked;
1117 defState = Qt::Unchecked;
1120 /* determine if it is already in the versionExceptionHash */
1121 QString directory = directoryTree->currentItem()->data(0, Qt::UserRole).toString();
1122 Qt::CheckState dirState = directoryTree->currentItem()->checkState(0);
1123 QString file = fileTableItem->text();
1124 QString fullPath = directory + file;
1125 int thisJobNum = colZeroItem->text().toInt();
1126 int hashJobNum = m_versionExceptionHash.value(fullPath, 0);
1128 if (mainWin->m_rtVerTabICDebug) {
1129 QString msg = QString("versrow=%1 prev=%2 cur=%3 def=%4 dir=%5 hashJobNum=%6 thisJobNum=%7 filestate=%8 fec=%9 vec=%10\n")
1130 .arg(row).arg(prevState).arg(curState).arg(defState).arg(dirState).arg(hashJobNum).arg(thisJobNum).arg(fileState)
1131 .arg(m_fileExceptionHash.count()).arg(m_versionExceptionHash.count());
1132 Pmsg1(000, "%s", msg.toUtf8().data()); }
1133 /* if changed from partially checked to checked, make it unchecked */
1134 if ((curState == Qt::Checked) && (row == 0) && (fileState == Qt::Unchecked)) {
1135 if (mainWin->m_rtVerTabICDebug) Pmsg0(000, "Setting to Qt::Checked\n");
1136 fileTableItem->setCheckState(Qt::Checked);
1137 } else if ((prevState == Qt::PartiallyChecked) && (curState == Qt::Checked) && (row == 0) && (fileState == Qt::Checked) && (dirState == Qt::Unchecked)) {
1138 //versrow=0 prev=1 cur=2 def=1 dir=0 hashJobNum=0 thisJobNum=64 filestate=2 fec=1 vec=0
1139 if (mainWin->m_rtVerTabICDebug) Pmsg1(000, "fileExceptionRemove %s, %i\n", fullPath.toUtf8().data());
1140 fileExceptionRemove(fullPath, directory);
1141 } else if ((curState == Qt::Checked) && (row == 0) && (hashJobNum != 0) && (dirState != Qt::Unchecked)) {
1142 //versrow=0 prev=0 cur=2 def=1 dir=2 hashJobNum=53 thisJobNum=64 filestate=2 fec=1 vec=1
1143 if (mainWin->m_rtVerTabICDebug) Pmsg1(000, "m_versionExceptionHash.remove %s\n", fullPath.toUtf8().data());
1144 m_versionExceptionHash.remove(fullPath);
1145 fileExceptionRemove(fullPath, directory);
1146 } else if ((curState == Qt::Checked) && (row == 0)) {
1147 if (mainWin->m_rtVerTabICDebug) Pmsg1(000, "m_versionExceptionHash.remove %s\n", fullPath.toUtf8().data());
1148 m_versionExceptionHash.remove(fullPath);
1149 } else if (prevState != curState) {
1150 if (mainWin->m_rtVerTabICDebug) Pmsg2(000, " THE STATE OF THE version Check has changed, Setting StateList[%i] to %i\n", row, curState);
1151 if ((curState == Qt::Checked) || (curState == Qt::PartiallyChecked)) {
1152 if (mainWin->m_rtVerTabICDebug) Pmsg2(000, "Inserting into m_versionExceptionHash %s, %i\n", fullPath.toUtf8().data(), thisJobNum);
1153 m_versionExceptionHash.insert(fullPath, thisJobNum);
1154 if (fileState != Qt::Checked) {
1155 if (mainWin->m_rtVerTabICDebug) Pmsg2(000, "Inserting into m_fileExceptionHash %s, %i\n", fullPath.toUtf8().data(), curState);
1156 fileExceptionInsert(fullPath, directory, curState);
1159 if (mainWin->m_rtVerTabICDebug) Pmsg0(000, "got here\n");
1162 if (mainWin->m_rtVerTabICDebug) Pmsg0(000, "no conditions met\n");
1165 updateFileTableChecks();
1166 updateVersionTableChecks();
1170 * Simple function to set the check state in the file table by disconnecting the
1171 * signal/slot the setting then reconnecting the signal/slot
1173 void restoreTree::fileTableDisconnectedSet(QTableWidgetItem *item, Qt::CheckState state, bool color)
1175 disconnect(fileTable, SIGNAL(itemChanged(QTableWidgetItem *)),
1176 this, SLOT(fileTableItemChanged(QTableWidgetItem *)));
1177 item->setCheckState(state);
1178 if (color) item->setBackground(Qt::yellow);
1179 else item->setBackground(Qt::white);
1180 connect(fileTable, SIGNAL(itemChanged(QTableWidgetItem *)),
1181 this, SLOT(fileTableItemChanged(QTableWidgetItem *)));
1185 * Simple function to set the check state in the version table by disconnecting the
1186 * signal/slot the setting then reconnecting the signal/slot
1188 void restoreTree::versionTableDisconnectedSet(QTableWidgetItem *item, Qt::CheckState state)
1190 disconnect(versionTable, SIGNAL(itemChanged(QTableWidgetItem *)),
1191 this, SLOT(versionTableItemChanged(QTableWidgetItem *)));
1192 item->setCheckState(state);
1193 connect(versionTable, SIGNAL(itemChanged(QTableWidgetItem *)),
1194 this, SLOT(versionTableItemChanged(QTableWidgetItem *)));
1198 * Simple function to set the check state in the directory tree by disconnecting the
1199 * signal/slot the setting then reconnecting the signal/slot
1201 void restoreTree::directoryTreeDisconnectedSet(QTreeWidgetItem *item, Qt::CheckState state)
1203 disconnect(directoryTree, SIGNAL(itemChanged(QTreeWidgetItem *, int)),
1204 this, SLOT(directoryItemChanged(QTreeWidgetItem *, int)));
1205 item->setCheckState(0, state);
1206 connect(directoryTree, SIGNAL(itemChanged(QTreeWidgetItem *, int)),
1207 this, SLOT(directoryItemChanged(QTreeWidgetItem *, int)));
1211 * Simplify the updating of the check state in the File table by iterating through
1212 * each item in the file table to determine it's appropriate state.
1213 * !! Will probably want to concoct a way to do this without iterating for the possibility
1214 * of the very large directories.
1216 void restoreTree::updateFileTableChecks()
1218 /* deterimine the default state from the state of the directory */
1219 QTreeWidgetItem *dirTreeItem = directoryTree->currentItem();
1220 Qt::CheckState dirState = dirTreeItem->checkState(0);
1222 QString dirName = dirTreeItem->data(0, Qt::UserRole).toString();
1224 /* Update the items in the version table */
1225 int rcnt = fileTable->rowCount();
1226 for (int row=0; row<rcnt; row++) {
1227 QTableWidgetItem* item = fileTable->item(row, 0);
1228 if (!item) { return; }
1230 Qt::CheckState curState = item->checkState();
1231 Qt::CheckState newState = Qt::PartiallyChecked;
1232 if (dirState == Qt::Unchecked) newState = Qt::Unchecked;
1234 /* determine if it is already in the m_fileExceptionHash */
1235 QString file = item->text();
1236 QString fullPath = dirName + file;
1237 Qt::CheckState hashState = m_fileExceptionHash.value(fullPath, (Qt::CheckState)3);
1238 int hashJobNum = m_versionExceptionHash.value(fullPath, 0);
1240 if (hashState != 3) newState = hashState;
1242 if (mainWin->m_rtUpdateFTDebug) {
1243 QString msg = QString("file row=%1 cur=%2 hash=%3 new=%4 dirState=%5\n")
1244 .arg(row).arg(curState).arg(hashState).arg(newState).arg(dirState);
1245 Pmsg1(000, "%s", msg.toUtf8().data());
1248 bool docolor = false;
1249 if (hashJobNum != 0) docolor = true;
1250 bool isyellow = item->background().color() == QColor(Qt::yellow);
1251 if ((newState != curState) || (hashState == 3) || ((isyellow && !docolor) || (!isyellow && docolor)))
1252 fileTableDisconnectedSet(item, newState, docolor);
1253 m_fileCheckStateList[row] = newState;
1258 * Simplify the updating of the check state in the Version table by iterating through
1259 * each item in the file table to determine it's appropriate state.
1261 void restoreTree::updateVersionTableChecks()
1263 /* deterimine the default state from the state of the directory */
1264 QTreeWidgetItem *dirTreeItem = directoryTree->currentItem();
1265 Qt::CheckState dirState = dirTreeItem->checkState(0);
1266 QString dirName = dirTreeItem->data(0, Qt::UserRole).toString();
1268 /* deterimine the default state from the state of the file */
1269 QTableWidgetItem *fileTableItem = fileTable->item(fileTable->currentRow(), 0);
1270 if (!fileTableItem) { return; }
1271 Qt::CheckState fileState = fileTableItem->checkState();
1272 QString file = fileTableItem->text();
1273 QString fullPath = dirName + file;
1274 int hashJobNum = m_versionExceptionHash.value(fullPath, 0);
1276 /* Update the items in the version table */
1277 int cnt = versionTable->rowCount();
1278 for (int row=0; row<cnt; row++) {
1279 QTableWidgetItem* item = versionTable->item(row, 0);
1280 if (!item) { break; }
1282 Qt::CheckState curState = item->checkState();
1283 Qt::CheckState newState = Qt::Unchecked;
1285 if ((row == 0) && (fileState != Qt::Unchecked) && (hashJobNum == 0))
1286 newState = Qt::PartiallyChecked;
1287 /* determine if it is already in the versionExceptionHash */
1289 int thisJobNum = item->text().toInt();
1290 if (thisJobNum == hashJobNum)
1291 newState = Qt::Checked;
1293 if (mainWin->m_rtChecksDebug) {
1294 QString msg = QString("ver row=%1 cur=%2 hashJobNum=%3 new=%4 dirState=%5\n")
1295 .arg(row).arg(curState).arg(hashJobNum).arg(newState).arg(dirState);
1296 Pmsg1(000, "%s", msg.toUtf8().data());
1298 if (newState != curState)
1299 versionTableDisconnectedSet(item, newState);
1300 m_versionCheckStateList[row] = newState;
1305 * Quick subroutine to "return via subPaths" a list of subpaths when passed a fullPath
1307 void restoreTree::fullPathtoSubPaths(QStringList &subPaths, QString &fullPath_in)
1311 QString fullPath = fullPath_in;
1312 QString direct, path;
1313 while (((index = fullPath.lastIndexOf("/", -2)) != -1) && (!done)) {
1314 direct = path = fullPath;
1315 path.replace(index+1, fullPath.length()-index-1, "");
1316 direct.replace(0, index+1, "");
1318 QString msg = QString("length = \"%1\" index = \"%2\" Considering \"%3\" \"%4\"\n")
1319 .arg(fullPath.length()).arg(index).arg(path).arg(direct);
1320 Pmsg0(000, msg.toUtf8().data());
1323 subPaths.append(fullPath);
1328 * A Function to set the icon state and insert a record into
1329 * m_directoryIconStateHash when an exception is added by the user
1331 void restoreTree::directoryIconStateInsert(QString &fullPath, Qt::CheckState excpState)
1334 fullPathtoSubPaths(paths, fullPath);
1335 /* an exception that causes the item in the file table to be "Checked" has occured */
1336 if (excpState == Qt::Checked) {
1337 bool foundAsUnChecked = false;
1338 QTreeWidgetItem *firstItem = m_dirPaths.value(paths[0]);
1340 if (firstItem->checkState(0) == Qt::Unchecked)
1341 foundAsUnChecked = true;
1343 if (foundAsUnChecked) {
1344 /* as long as directory item is Unchecked, set icon state to "green check" */
1346 QListIterator<QString> siter(paths);
1347 while (siter.hasNext() && !done) {
1348 QString path = siter.next();
1349 QTreeWidgetItem *item = m_dirPaths.value(path);
1351 if (item->checkState(0) != Qt::Unchecked)
1354 directorySetIcon(1, FolderGreenChecked, path, item);
1355 if (mainWin->m_rtIconStateDebug) Pmsg1(000, "In restoreTree::directoryIconStateInsert inserting %s\n", path.toUtf8().data());
1360 /* if it is partially checked or fully checked insert green Check until a unchecked is found in the path */
1361 if (mainWin->m_rtIconStateDebug) Pmsg1(000, "In restoreTree::directoryIconStateInsert Aqua %s\n", paths[0].toUtf8().data());
1363 QListIterator<QString> siter(paths);
1364 while (siter.hasNext() && !done) {
1365 QString path = siter.next();
1366 QTreeWidgetItem *item = m_dirPaths.value(path);
1367 if (item) { /* if the directory item is checked, set icon state to unchecked "green check" */
1368 if (item->checkState(0) == Qt::Checked)
1370 directorySetIcon(1, FolderGreenChecked, path, item);
1371 if (mainWin->m_rtIconStateDebug) Pmsg1(000, "In restoreTree::directoryIconStateInsert boogie %s\n", path.toUtf8().data());
1376 /* an exception that causes the item in the file table to be "Unchecked" has occured */
1377 if (excpState == Qt::Unchecked) {
1379 QListIterator<QString> siter(paths);
1380 while (siter.hasNext() && !done) {
1381 QString path = siter.next();
1382 QTreeWidgetItem *item = m_dirPaths.value(path);
1383 if (item) { /* if the directory item is checked, set icon state to unchecked "white check" */
1384 if (item->checkState(0) == Qt::Checked)
1386 directorySetIcon(1, FolderWhiteChecked, path, item);
1387 if (mainWin->m_rtIconStateDebug) Pmsg1(000, "In restoreTree::directoryIconStateInsert boogie %s\n", path.toUtf8().data());
1394 * A function to set the icon state back to "folder" and to remove a record from
1395 * m_directoryIconStateHash when an exception is removed by a user.
1397 void restoreTree::directoryIconStateRemove()
1399 QHash<QString, int> shouldBeIconStateHash;
1400 /* First determine all paths with icons that should be checked with m_fileExceptionHash */
1401 /* Use iterator tera to iterate through m_fileExceptionHash */
1402 QHashIterator<QString, Qt::CheckState> tera(m_fileExceptionHash);
1403 while (tera.hasNext()) {
1405 if (mainWin->m_rtIconStateDebug) Pmsg2(000, "Alpha Key %s value %i\n", tera.key().toUtf8().data(), tera.value());
1407 QString keyPath = tera.key();
1408 Qt::CheckState state = tera.value();
1411 fullPathtoSubPaths(paths, keyPath);
1412 /* if the state of the item in m_fileExceptionHash is checked
1413 * each of the subpaths should be "Checked Green" */
1414 if (state == Qt::Checked) {
1416 bool foundAsUnChecked = false;
1417 QTreeWidgetItem *firstItem = m_dirPaths.value(paths[0]);
1419 if (firstItem->checkState(0) == Qt::Unchecked)
1420 foundAsUnChecked = true;
1422 if (foundAsUnChecked) {
1423 /* The right most directory is Unchecked, iterate leftwards
1424 * as long as directory item is Unchecked, set icon state to "green check" */
1426 QListIterator<QString> siter(paths);
1427 while (siter.hasNext() && !done) {
1428 QString path = siter.next();
1429 QTreeWidgetItem *item = m_dirPaths.value(path);
1431 if (item->checkState(0) != Qt::Unchecked)
1434 shouldBeIconStateHash.insert(path, FolderGreenChecked);
1435 if (mainWin->m_rtIconStateDebug) Pmsg1(000, "In restoreTree::directoryIconStateInsert inserting %s\n", path.toUtf8().data());
1441 /* The right most directory is Unchecked, iterate leftwards
1442 * until directory item is Checked, set icon state to "green check" */
1444 QListIterator<QString> siter(paths);
1445 while (siter.hasNext() && !done) {
1446 QString path = siter.next();
1447 QTreeWidgetItem *item = m_dirPaths.value(path);
1449 if (item->checkState(0) == Qt::Checked)
1451 shouldBeIconStateHash.insert(path, FolderGreenChecked);
1456 /* if the state of the item in m_fileExceptionHash is UNChecked
1457 * each of the subpaths should be "Checked white" until the tree item
1458 * which represents that path is Qt::Checked */
1459 if (state == Qt::Unchecked) {
1461 QListIterator<QString> siter(paths);
1462 while (siter.hasNext() && !done) {
1463 QString path = siter.next();
1464 QTreeWidgetItem *item = m_dirPaths.value(path);
1466 if (item->checkState(0) == Qt::Checked)
1468 shouldBeIconStateHash.insert(path, FolderWhiteChecked);
1473 /* now iterate through m_directoryIconStateHash which are the items that are checked
1474 * and remove all of those that are not in shouldBeIconStateHash */
1475 QHashIterator<QString, int> iter(m_directoryIconStateHash);
1476 while (iter.hasNext()) {
1478 if (mainWin->m_rtIconStateDebug) Pmsg2(000, "Beta Key %s value %i\n", iter.key().toUtf8().data(), iter.value());
1480 QString keyPath = iter.key();
1481 if (shouldBeIconStateHash.value(keyPath)) {
1482 if (mainWin->m_rtIconStateDebug) Pmsg1(000, "WAS found in shouldBeStateHash %s\n", keyPath.toUtf8().data());
1483 //newval = m_directoryIconStateHash.value(path, FolderUnchecked) & (~change);
1484 int newval = shouldBeIconStateHash.value(keyPath);
1486 newval = newval & FolderBothChecked;
1487 QTreeWidgetItem *item = m_dirPaths.value(keyPath);
1489 directorySetIcon(0, newval, keyPath, item);
1491 if (mainWin->m_rtIconStateDebug) Pmsg1(000, "NOT found in shouldBeStateHash %s\n", keyPath.toUtf8().data());
1492 QTreeWidgetItem *item = m_dirPaths.value(keyPath);
1494 directorySetIcon(0, FolderBothChecked, keyPath, item);
1495 //item->setIcon(0,QIcon(QString::fromUtf8(":images/folder.png")));
1496 //m_directoryIconStateHash.remove(keyPath);
1501 void restoreTree::directorySetIcon(int operation, int change, QString &path, QTreeWidgetItem* item) {
1503 /* we are adding a check type white or green */
1504 if (operation > 0) {
1505 /* get the old val and "bitwise OR" with the change */
1506 newval = m_directoryIconStateHash.value(path, FolderUnchecked) | change;
1507 if (mainWin->m_rtIconStateDebug) Pmsg2(000, "Inserting into m_directoryIconStateHash path=%s newval=%i\n", path.toUtf8().data(), newval);
1508 m_directoryIconStateHash.insert(path, newval);
1510 /* we are removing a check type white or green */
1511 newval = m_directoryIconStateHash.value(path, FolderUnchecked) & (~change);
1513 if (mainWin->m_rtIconStateDebug) Pmsg2(000, "Removing from m_directoryIconStateHash path=%s newval=%i\n", path.toUtf8().data(), newval);
1514 m_directoryIconStateHash.remove(path);
1517 if (mainWin->m_rtIconStateDebug) Pmsg2(000, "Inserting into m_directoryIconStateHash path=%s newval=%i\n", path.toUtf8().data(), newval);
1518 m_directoryIconStateHash.insert(path, newval);
1521 if (newval == FolderUnchecked)
1522 item->setIcon(0, QIcon(QString::fromUtf8(":images/folder.png")));
1523 else if (newval == FolderGreenChecked)
1524 item->setIcon(0, QIcon(QString::fromUtf8(":images/folderchecked.png")));
1525 else if (newval == FolderWhiteChecked)
1526 item->setIcon(0, QIcon(QString::fromUtf8(":images/folderunchecked.png")));
1527 else if (newval == FolderBothChecked)
1528 item->setIcon(0, QIcon(QString::fromUtf8(":images/folderbothchecked.png")));
1534 void restoreTree::restoreButtonPushed()
1536 /* Set progress bars and repaint */
1537 prLabel1->setVisible(true);
1538 prLabel1->setText(tr("Task 1 of 3"));
1539 prLabel2->setVisible(true);
1540 prLabel2->setText(tr("Processing Checked directories"));
1541 prBar1->setVisible(true);
1542 prBar1->setRange(0, 3);
1543 prBar1->setValue(0);
1544 prBar2->setVisible(true);
1545 prBar2->setRange(0, 0);
1547 QMultiHash<int, QString> versionFilesMulti;
1549 QHash <QString, bool> fullPathDone;
1550 QHash <QString, int> fileIndexHash;
1551 if ((mainWin->m_rtRestore1Debug) || (mainWin->m_rtRestore2Debug) || (mainWin->m_rtRestore3Debug))
1552 Pmsg0(000, "In restoreTree::restoreButtonPushed\n");
1553 /* Use a tree widget item iterator to count directories for the progress bar */
1554 QTreeWidgetItemIterator diterc(directoryTree, QTreeWidgetItemIterator::Checked);
1559 } /* while (*diterc) */
1560 prBar2->setRange(0, ditcount);
1561 prBar2->setValue(0);
1563 /* Use a tree widget item iterator filtering for Checked Items */
1564 QTreeWidgetItemIterator diter(directoryTree, QTreeWidgetItemIterator::Checked);
1566 QString directory = (*diter)->data(0, Qt::UserRole).toString();
1567 int pathid = m_directoryPathIdHash.value(directory, -1);
1569 if (mainWin->m_rtRestore1Debug)
1570 Pmsg1(000, "Directory Checked=\"%s\"\n", directory.toUtf8().data());
1571 /* With a checked directory, query for the files in the directory */
1574 "SELECT Filename.Name AS Filename, t1.JobId AS JobId, File.FileIndex AS FileIndex"
1576 " ( SELECT File.FilenameId AS FilenameId, MAX(Job.JobId) AS JobId"
1578 " INNER JOIN Job ON (Job.JobId=File.JobId)"
1579 " WHERE File.PathId=" + QString("%1").arg(pathid) +
1580 " AND Job.Jobid IN (" + m_checkedJobs + ")"
1581 " GROUP BY File.FilenameId"
1583 " INNER JOIN Filename on (Filename.FilenameId=File.FilenameId)"
1584 " INNER JOIN Job ON (Job.JobId=File.JobId)"
1585 " WHERE File.PathId=" + QString("%1").arg(pathid) +
1586 " AND File.FilenameId=t1.FilenameId"
1587 " AND Job.Jobid=t1.JobId"
1588 " ORDER BY Filename";
1590 if (mainWin->m_sqlDebug) Pmsg1(000, "Query cmd : %s\n", cmd.toUtf8().data());
1591 QStringList results;
1592 if (m_console->sql_cmd(cmd, results)) {
1593 QStringList fieldlist;
1596 /* Iterate through the record returned from the query */
1597 foreach (QString resultline, results) {
1598 /* Iterate through fields in the record */
1600 QString fullPath = "";
1601 Qt::CheckState fileExcpState = (Qt::CheckState)4;
1602 fieldlist = resultline.split("\t");
1605 foreach (QString field, fieldlist) {
1607 fullPath = directory + field;
1610 version = field.toInt();
1613 fileIndex = field.toInt();
1617 fileExcpState = m_fileExceptionHash.value(fullPath, (Qt::CheckState)3);
1619 int excpVersion = m_versionExceptionHash.value(fullPath, 0);
1620 if (fileExcpState != Qt::Unchecked) {
1622 if (excpVersion != 0) {
1623 debugtext = QString("*E* version=%1").arg(excpVersion);
1624 version = excpVersion;
1625 fileIndex = queryFileIndex(fullPath, excpVersion);
1627 debugtext = QString("___ version=%1").arg(version);
1628 if (mainWin->m_rtRestore1Debug)
1629 Pmsg2(000, "Restoring %s File %s\n", debugtext.toUtf8().data(), fullPath.toUtf8().data());
1630 fullPathDone.insert(fullPath, 1);
1631 fileIndexHash.insert(fullPath, fileIndex);
1632 versionFilesMulti.insert(version, fullPath);
1640 prBar2->setValue(ditcount);
1642 } /* while (*diter) */
1643 prBar1->setValue(1);
1644 prLabel1->setText( tr("Task 2 of 3"));
1645 prLabel2->setText(tr("Processing Exceptions"));
1646 prBar2->setRange(0, 0);
1649 /* There may be some exceptions not accounted for yet with fullPathDone */
1650 QHashIterator<QString, Qt::CheckState> ftera(m_fileExceptionHash);
1651 while (ftera.hasNext()) {
1653 QString fullPath = ftera.key();
1654 Qt::CheckState state = ftera.value();
1656 /* now we don't want the ones already done */
1657 if (fullPathDone.value(fullPath, 0) == 0) {
1658 int version = m_versionExceptionHash.value(fullPath, 0);
1660 QString debugtext = "";
1662 fileIndex = queryFileIndex(fullPath, version);
1663 debugtext = QString("E1* version=%1 fileid=%2").arg(version).arg(fileIndex);
1665 version = mostRecentVersionfromFullPath(fullPath);
1667 fileIndex = queryFileIndex(fullPath, version);
1668 debugtext = QString("E2* version=%1 fileid=%2").arg(version).arg(fileIndex);
1670 debugtext = QString("Error det vers").arg(version);
1672 if (mainWin->m_rtRestore1Debug)
1673 Pmsg2(000, "Restoring %s file %s\n", debugtext.toUtf8().data(), fullPath.toUtf8().data());
1674 versionFilesMulti.insert(version, fullPath);
1676 fileIndexHash.insert(fullPath, fileIndex);
1677 } /* if fullPathDone.value(fullPath, 0) == 0 */
1678 } /* if state != 0 */
1679 } /* while ftera.hasNext */
1680 /* The progress bars for the next step */
1681 prBar1->setValue(2);
1682 prLabel1->setText(tr("Task 3 of 3"));
1683 prLabel2->setText(tr("Filling Database Table"));
1684 prBar2->setRange(0, vFMCounter);
1686 prBar2->setValue(vFMCounter);
1689 /* now for the final spit out of the versions and lists of files for each version */
1690 QHash<int, int> doneKeys;
1691 QHashIterator<int, QString> vFMiter(versionFilesMulti);
1692 QString tempTable = "";
1694 while (vFMiter.hasNext()) {
1696 int fversion = vFMiter.key();
1697 /* did not succeed in getting an iterator to work as expected on versionFilesMulti so use doneKeys */
1698 if (doneKeys.value(fversion, 0) == 0) {
1699 if (tempTable == "") {
1700 QSettings settings("www.bacula.org", "bat");
1701 settings.beginGroup("Restore");
1702 int counter = settings.value("Counter", 1).toInt();
1703 settings.setValue("Counter", counter+1);
1704 settings.endGroup();
1705 tempTable = "restore_" + QString("%1").arg(qrand()) + "_" + QString("%1").arg(counter);
1706 QString sqlcmd = "CREATE TEMPORARY TABLE " + tempTable + " (JobId INTEGER, FileIndex INTEGER)";
1707 if (mainWin->m_sqlDebug)
1708 Pmsg1(000, "Query cmd : %s ;\n", sqlcmd.toUtf8().data());
1709 QStringList results;
1710 if (!m_console->sql_cmd(sqlcmd, results))
1711 Pmsg1(000, "CREATE TABLE FAILED!!!! %s\n", sqlcmd.toUtf8().data());
1714 if (mainWin->m_rtRestore2Debug) Pmsg1(000, "Version->%i\n", fversion);
1715 QStringList fullPathList = versionFilesMulti.values(fversion);
1716 /* create the command to perform the restore */
1717 foreach(QString ffullPath, fullPathList) {
1718 int fileIndex = fileIndexHash.value(ffullPath);
1719 if (mainWin->m_rtRestore2Debug) Pmsg2(000, " file->%s id %i\n", ffullPath.toUtf8().data(), fileIndex);
1720 QString sqlcmd = "INSERT INTO " + tempTable + " (JobId, FileIndex) VALUES (" + QString("%1").arg(fversion) + ", " + QString("%1").arg(fileIndex) + ")";
1721 if (mainWin->m_rtRestore3Debug)
1722 Pmsg1(000, "Insert cmd : %s\n", sqlcmd.toUtf8().data());
1723 QStringList results;
1724 if (!m_console->sql_cmd(sqlcmd, results))
1725 Pmsg1(000, "INSERT INTO FAILED!!!! %s\n", sqlcmd.toUtf8().data());
1726 prBar2->setValue(++vFMCounter);
1727 } /* foreach fullPathList */
1728 doneKeys.insert(fversion,1);
1729 jobList.append(fversion);
1730 } /* if (doneKeys.value(fversion, 0) == 0) */
1731 } /* while (vFMiter.hasNext()) */
1732 if (tempTable != "") {
1733 /* a table was made, lets run the job */
1734 QString jobOption = " jobid=\"";
1736 /* create a list of jobs comma separated */
1737 foreach (int job, jobList) {
1738 if (first) first = false;
1739 else jobOption += ",";
1740 jobOption += QString("%1").arg(job);
1743 QString cmd = QString("restore");
1745 " client=\"" + m_prevClientCombo + "\"" +
1746 " file=\"?" + tempTable + "\" done";
1747 if (mainWin->m_commandDebug)
1748 Pmsg1(000, "preRestore command \'%s\'\n", cmd.toUtf8().data());
1749 consoleCommand(cmd);
1751 /* turn off the progress widgets */
1752 prBar1->setVisible(false);
1753 prBar2->setVisible(false);
1754 prLabel1->setVisible(false);
1755 prLabel2->setVisible(false);
1758 int restoreTree::mostRecentVersionfromFullPath(QString &fullPath)
1761 QString directory, fileName;
1762 int index = fullPath.lastIndexOf("/", -2);
1764 directory = fileName = fullPath;
1765 directory.replace(index+1, fullPath.length()-index-1, "");
1766 fileName.replace(0, index+1, "");
1768 QString msg = QString("length = \"%1\" index = \"%2\" Considering \"%3\" \"%4\"\n")
1769 .arg(fullPath.length()).arg(index).arg(fileName).arg(directory);
1770 Pmsg0(000, msg.toUtf8().data());
1772 int pathid = m_directoryPathIdHash.value(directory, -1);
1774 /* so now we need the latest version from the database */
1776 "SELECT MAX(Job.JobId)"
1778 " INNER JOIN Filename on (Filename.FilenameId=File.FilenameId)"
1779 " INNER JOIN Job ON (File.JobId=Job.JobId)"
1780 " WHERE File.PathId=" + QString("%1").arg(pathid) +
1781 " AND Job.Jobid IN (" + m_checkedJobs + ")"
1782 " AND Filename.Name='" + fileName + "'"
1783 " AND File.FilenameId!=" + QString("%1").arg(m_nullFileNameId) +
1784 " GROUP BY Filename.Name";
1786 if (mainWin->m_sqlDebug) Pmsg1(000, "Query cmd : %s\n", cmd.toUtf8().data());
1787 QStringList results;
1788 if (m_console->sql_cmd(cmd, results)) {
1789 QStringList fieldlist;
1791 /* Iterate through the record returned from the query */
1792 foreach (QString resultline, results) {
1793 /* Iterate through fields in the record */
1795 fieldlist = resultline.split("\t");
1796 foreach (QString field, fieldlist) {
1798 qversion = field.toInt();
1806 } /* if (index != -1) */
1811 int restoreTree::queryFileIndex(QString &fullPath, int jobId)
1814 QString directory, fileName;
1815 int index = fullPath.lastIndexOf("/", -2);
1816 if (mainWin->m_sqlDebug) Pmsg1(000, "Index=%d\n", index);
1818 directory = fileName = fullPath;
1819 directory.replace(index+1, fullPath.length()-index-1, "");
1820 fileName.replace(0, index+1, "");
1822 QString msg = QString("length = \"%1\" index = \"%2\" Considering \"%3\" \"%4\"\n")
1823 .arg(fullPath.length()).arg(index).arg(fileName).arg(directory);
1824 Pmsg0(000, msg.toUtf8().data());
1826 int pathid = m_directoryPathIdHash.value(directory, -1);
1828 /* so now we need the latest version from the database */
1833 " INNER JOIN Filename on (Filename.FilenameId=File.FilenameId)"
1834 " INNER JOIN Job ON (File.JobId=Job.JobId)"
1835 " WHERE File.PathId=" + QString("%1").arg(pathid) +
1836 " AND Filename.Name='" + fileName + "'"
1837 " AND Job.Jobid='" + QString("%1").arg(jobId) + "'"
1838 " GROUP BY File.FileIndex";
1839 if (mainWin->m_sqlDebug) Pmsg1(000, "Query cmd : %s\n", cmd.toUtf8().data());
1840 QStringList results;
1841 if (m_console->sql_cmd(cmd, results)) {
1842 QStringList fieldlist;
1844 /* Iterate through the record returned from the query */
1845 foreach (QString resultline, results) {
1846 /* Iterate through fields in the record */
1848 fieldlist = resultline.split("\t");
1849 foreach (QString field, fieldlist) {
1851 qfileIndex = field.toInt();
1859 } /* if (index != -1) */
1860 if (mainWin->m_sqlDebug) Pmsg1(000, "qfileIndex=%d\n", qfileIndex);
1865 void restoreTree::PgSeltreeWidgetClicked()
1867 if (!isOnceDocked()) {