2 Bacula® - The Network Backup Solution
4 Copyright (C) 2007-2009 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.
34 * Kern Sibbald, February MMVII
39 #include "restoretree.h"
42 restoreTree::restoreTree()
45 m_name = tr("Version Browser");
47 QTreeWidgetItem* thisitem = mainWin->getFromHash(this);
48 thisitem->setIcon(0, QIcon(QString::fromUtf8(":images/browse.png")));
55 QGridLayout *gridLayout = new QGridLayout(this);
56 gridLayout->setSpacing(6);
57 gridLayout->setMargin(9);
58 gridLayout->setObjectName(QString::fromUtf8("gridLayout"));
60 m_splitter = new QSplitter(Qt::Vertical, this);
61 QScrollArea *area = new QScrollArea();
62 area->setObjectName(QString::fromUtf8("area"));
63 area->setWidget(widget);
64 area->setWidgetResizable(true);
65 m_splitter->addWidget(area);
66 m_splitter->addWidget(splitter);
67 splitter->setChildrenCollapsible(false);
69 gridLayout->addWidget(m_splitter, 0, 0, 1, 1);
71 /* progress widgets */
72 prBar1->setVisible(false);
73 prBar2->setVisible(false);
74 prLabel1->setVisible(false);
75 prLabel2->setVisible(false);
77 /* Set Defaults for check and spin for limits */
78 limitCheckBox->setCheckState(mainWin->m_recordLimitCheck ? Qt::Checked : Qt::Unchecked);
79 limitSpinBox->setValue(mainWin->m_recordLimitVal);
80 daysCheckBox->setCheckState(mainWin->m_daysLimitCheck ? Qt::Checked : Qt::Unchecked);
81 daysSpinBox->setValue(mainWin->m_daysLimitVal);
83 m_nullFileNameId = -1;
88 restoreTree::~restoreTree()
94 * Called from the constructor to set up the page widgets and connections.
96 void restoreTree::setupPage()
98 connect(refreshButton, SIGNAL(pressed()), this, SLOT(refreshButtonPushed()));
99 connect(restoreButton, SIGNAL(pressed()), this, SLOT(restoreButtonPushed()));
100 connect(jobCombo, SIGNAL(currentIndexChanged(int)), this, SLOT(jobComboChanged(int)));
101 connect(jobCombo, SIGNAL(currentIndexChanged(int)), this, SLOT(updateRefresh()));
102 connect(clientCombo, SIGNAL(currentIndexChanged(int)), this, SLOT(updateRefresh()));
103 connect(fileSetCombo, SIGNAL(currentIndexChanged(int)), this, SLOT(updateRefresh()));
104 connect(limitCheckBox, SIGNAL(stateChanged(int)), this, SLOT(updateRefresh()));
105 connect(daysCheckBox, SIGNAL(stateChanged(int)), this, SLOT(updateRefresh()));
106 connect(daysSpinBox, SIGNAL(valueChanged(int)), this, SLOT(updateRefresh()));
107 connect(limitSpinBox, SIGNAL(valueChanged(int)), this, SLOT(updateRefresh()));
108 connect(directoryTree, SIGNAL(currentItemChanged(QTreeWidgetItem *, QTreeWidgetItem *)),
109 this, SLOT(directoryCurrentItemChanged(QTreeWidgetItem *, QTreeWidgetItem *)));
110 connect(directoryTree, SIGNAL(itemExpanded(QTreeWidgetItem *)),
111 this, SLOT(directoryItemExpanded(QTreeWidgetItem *)));
112 connect(directoryTree, SIGNAL(itemChanged(QTreeWidgetItem *, int)),
113 this, SLOT(directoryItemChanged(QTreeWidgetItem *, int)));
114 connect(fileTable, SIGNAL(currentItemChanged(QTableWidgetItem *, QTableWidgetItem *)),
115 this, SLOT(fileCurrentItemChanged(QTableWidgetItem *, QTableWidgetItem *)));
116 connect(jobTable, SIGNAL(cellClicked(int, int)),
117 this, SLOT(jobTableCellClicked(int, int)));
119 QStringList titles = QStringList() << tr("Directories");
120 directoryTree->setHeaderLabels(titles);
121 clientCombo->addItems(m_console->client_list);
122 fileSetCombo->addItem(tr("Any"));
123 fileSetCombo->addItems(m_console->fileset_list);
124 jobCombo->addItem(tr("Any"));
125 jobCombo->addItems(m_console->job_list);
127 directoryTree->setContextMenuPolicy(Qt::ActionsContextMenu);
130 void restoreTree::updateRefresh()
132 if (mainWin->m_rtPopDirDebug) Pmsg2(000, "testing prev=\"%s\" current=\"%s\"\n", m_prevJobCombo.toUtf8().data(), jobCombo->currentText().toUtf8().data());
133 m_dropdownChanged = (m_prevJobCombo != jobCombo->currentText())
134 || (m_prevClientCombo != clientCombo->currentText())
135 || (m_prevFileSetCombo != fileSetCombo->currentText()
136 || (m_prevLimitSpinBox != limitSpinBox->value())
137 || (m_prevDaysSpinBox != daysSpinBox->value())
138 || (m_prevLimitCheckState != limitCheckBox->checkState())
139 || (m_prevDaysCheckState != daysCheckBox->checkState())
141 if (m_dropdownChanged) {
142 if (mainWin->m_rtPopDirDebug) Pmsg0(000, "In restoreTree::updateRefresh Is CHANGED\n");
143 refreshLabel->setText(tr("Refresh From Re-Select"));
145 if (mainWin->m_rtPopDirDebug) Pmsg0(000, "In restoreTree::updateRefresh Is not Changed\n");
146 refreshLabel->setText(tr("Refresh From JobChecks"));
151 * When refresh button is pushed, perform a query getting the directories and
152 * use parseDirectory and addDirectory to populate the directory tree with items.
154 void restoreTree::populateDirectoryTree()
160 directoryTree->clear();
162 fileTable->setRowCount(0);
163 fileTable->setColumnCount(0);
164 versionTable->clear();
165 versionTable->setRowCount(0);
166 versionTable->setColumnCount(0);
167 m_fileExceptionHash.clear();
168 m_fileExceptionMulti.clear();
169 m_versionExceptionHash.clear();
170 m_directoryIconStateHash.clear();
173 int taskcount = 3, ontask = 1;
174 if (m_dropdownChanged) taskcount += 1;
176 /* Set progress bars and repaint */
177 prBar1->setVisible(true);
178 prBar1->setRange(0,taskcount);
180 prLabel1->setText(tr("Task %1 of %2").arg(ontask).arg(taskcount));
181 prLabel1->setVisible(true);
182 prBar2->setVisible(true);
183 prBar2->setRange(0,0);
184 prLabel2->setText(tr("Querying Database"));
185 prLabel2->setVisible(true);
188 if (m_dropdownChanged) {
189 m_prevJobCombo = jobCombo->currentText();
190 m_prevClientCombo = clientCombo->currentText();
191 m_prevFileSetCombo = fileSetCombo->currentText();
192 m_prevLimitSpinBox = limitSpinBox->value();
193 m_prevDaysSpinBox = daysSpinBox->value();
194 m_prevLimitCheckState = limitCheckBox->checkState();
195 m_prevDaysCheckState = daysCheckBox->checkState();
197 prBar1->setValue(ontask++);
198 prLabel1->setText(tr("Task %1 of %2").arg(ontask).arg(taskcount));
200 prBar2->setRange(0,0);
201 prLabel2->setText(tr("Querying Jobs"));
205 setJobsCheckedList();
206 if (mainWin->m_rtPopDirDebug) Pmsg0(000, "Repopulating from checks in Job Table\n");
208 if (m_checkedJobs != "") {
209 /* First get the filenameid of where the nae is null. These will be the directories
210 * This could be done in a subquery but postgres's query analyzer won't do the right
211 * thing like I want */
212 if (m_nullFileNameId == -1) {
213 QString cmd = "SELECT FilenameId FROM Filename WHERE name=''";
214 if (mainWin->m_sqlDebug)
215 Pmsg1(000, "Query cmd : %s\n", cmd.toUtf8().data());
217 if (m_console->sql_cmd(cmd, qres)) {
219 QStringList fieldlist = qres[0].split("\t");
220 QString field = fieldlist[0];
222 int val = field.toInt(&ok, 10);
223 if (ok) m_nullFileNameId = val;
227 /* now create the query to get the list of paths */
229 "SELECT DISTINCT Path.Path AS Path, File.PathId AS PathId"
231 " INNER JOIN Path ON (File.PathId=Path.PathId)";
232 if (m_nullFileNameId != -1)
233 cmd += " WHERE File.FilenameId=" + QString("%1").arg(m_nullFileNameId);
235 cmd += " WHERE File.FilenameId IN (SELECT FilenameId FROM Filename WHERE Name='')";
236 cmd += " AND File.Jobid IN (" + m_checkedJobs + ")"
238 if (mainWin->m_sqlDebug)
239 Pmsg1(000, "Query cmd : %s\n", cmd.toUtf8().data());
240 prBar1->setValue(ontask++);
241 prLabel1->setText(tr("Task %1 of %2").arg(ontask).arg(taskcount));
243 prBar2->setRange(0,0);
244 prLabel2->setText(tr("Querying for Directories"));
247 m_directoryPathIdHash.clear();
248 bool querydone = false;
249 if (m_console->sql_cmd(cmd, results)) {
252 prLabel2->setText(tr("Processing Directories"));
253 prBar2->setRange(0,results.count());
256 if (mainWin->m_miscDebug)
257 Pmsg1(000, "Done with query %i results\n", results.count());
258 QStringList fieldlist;
259 foreach(QString resultline, results) {
260 /* Update progress bar periodically */
261 if ((++m_debugCnt && 0x3FF) == 0) {
262 prBar2->setValue(m_debugCnt);
264 fieldlist = resultline.split("\t");
267 /* Iterate through fields in the record */
268 foreach (field, fieldlist) {
269 if (fieldcnt == 0 ) {
270 parseDirectory(field);
271 } else if (fieldcnt == 1) {
273 int pathid = field.toInt(&ok, 10);
275 m_directoryPathIdHash.insert(fieldlist[0], pathid);
284 QMessageBox::warning(this, "Bat",
285 tr("No jobs were selected in the job query !!!.\n"
286 "Press OK to continue"),
289 prBar1->setVisible(false);
290 prBar2->setVisible(false);
291 prLabel1->setVisible(false);
292 prLabel2->setVisible(false);
296 * Function to set m_checkedJobs from the jobs that are checked in the table
299 void restoreTree::setJobsCheckedList()
301 m_JobsCheckedList = "";
303 /* Update the items in the version table */
304 int cnt = jobTable->rowCount();
305 for (int row=0; row<cnt; row++) {
306 QTableWidgetItem* jobItem = jobTable->item(row, 0);
307 if (jobItem->checkState() == Qt::Checked) {
309 m_JobsCheckedList += ",";
310 m_JobsCheckedList += jobItem->text();
312 jobItem->setBackground(Qt::green);
314 if (jobItem->flags())
315 jobItem->setBackground(Qt::gray);
317 jobItem->setBackground(Qt::darkYellow);
320 m_checkedJobs = m_JobsCheckedList;
324 * Function to parse a directory into all possible subdirectories, then add to
327 void restoreTree::parseDirectory(QString &dir_in)
329 /* m_debugTrap is to only print debugs for a few occurennces of calling parseDirectory
330 * instead of printing out what could potentially a whole bunch */
333 /* Truncate everything after the last / */
334 if (dir_in.right(1) != "/") {
335 dir_in.truncate(dir_in.lastIndexOf("/") + 1);
337 if ((mainWin->m_miscDebug) && (m_debugTrap))
338 Pmsg1(000, "parsing %s\n", dir_in.toUtf8().data());
340 /* split and add if not in yet */
341 QString direct, path;
344 QStringList pathAfter, dirAfter;
345 /* start from the end, turn /etc/somedir/subdir/ into /etc/somedir and subdir/
346 * if not added into tree, then try /etc/ and somedir/ if not added, then try
347 * / and etc/ . That should succeed, then add the ones that failed in reverse */
348 while (((index = dir_in.lastIndexOf("/", -2)) != -1) && (!done)) {
349 direct = path = dir_in;
350 path.replace(index+1, dir_in.length()-index-1,"");
351 direct.replace(0, index+1, "");
352 if ((mainWin->m_miscDebug) && (m_debugTrap)) {
353 QString msg = QString("length = \"%1\" index = \"%2\" Adding \"%3\" \"%4\"\n")
354 .arg(dir_in.length()).arg(index).arg(path).arg(direct);
355 Pmsg0(000, msg.toUtf8().data());
357 if (addDirectory(path, direct)) { done = true; }
359 if ((mainWin->m_miscDebug) && (m_debugTrap)) {
360 Pmsg0(000, "Saving for later\n");
362 pathAfter.prepend(path);
363 dirAfter.prepend(direct);
368 for (int k=0; k<pathAfter.count(); k++) {
369 if (addDirectory(pathAfter[k], dirAfter[k])) {
370 if ((mainWin->m_miscDebug) && (m_debugTrap))
371 Pmsg2(000, "Adding After %s %s\n", pathAfter[k].toUtf8().data(), dirAfter[k].toUtf8().data());
373 if ((mainWin->m_miscDebug) && (m_debugTrap))
374 Pmsg2(000, "Error Adding %s %s\n", pathAfter[k].toUtf8().data(), dirAfter[k].toUtf8().data());
381 * Function called from fill directory when a directory is found to see if this
382 * directory exists in the directory pane and then add it to the directory pane
384 bool restoreTree::addDirectory(QString &m_cwd, QString &newdirr)
386 QString newdir = newdirr;
387 QString fullPath = m_cwd + newdirr;
388 bool ok = true, added = false;
390 if ((mainWin->m_miscDebug) && (m_debugTrap)) {
391 QString msg = QString("In addDirectory cwd \"%1\" newdir \"%2\"\n")
394 Pmsg0(000, msg.toUtf8().data());
398 /* add unix '/' directory first */
399 if (m_dirPaths.empty() && !isWin32Path(fullPath)) {
401 QTreeWidgetItem *item = new QTreeWidgetItem(directoryTree);
403 item->setText(0, text.toUtf8().data());
404 item->setData(0, Qt::UserRole, QVariant(text));
405 item->setData(1, Qt::UserRole, QVariant(Qt::Unchecked));
406 item->setIcon(0, QIcon(QString::fromUtf8(":images/folder.png")));
407 if ((mainWin->m_miscDebug) && (m_debugTrap)) {
408 Pmsg1(000, "Pre Inserting %s\n", text.toUtf8().data());
410 m_dirPaths.insert(text, item);
412 /* no need to check for windows drive if unix */
413 if (isWin32Path(m_cwd)) {
414 if (!m_dirPaths.contains(m_cwd)) {
415 if (m_cwd.count('/') > 1) { return false; }
416 /* this is a windows drive add the base widget */
417 QTreeWidgetItem *item = new QTreeWidgetItem(directoryTree);
418 item->setText(0, m_cwd);
419 item->setData(0, Qt::UserRole, QVariant(fullPath));
420 item->setData(1, Qt::UserRole, QVariant(Qt::Unchecked));
421 item->setIcon(0, QIcon(QString::fromUtf8(":images/folder.png")));
422 if ((mainWin->m_miscDebug) && (m_debugTrap)) {
423 Pmsg0(000, "Added Base \"letter\":/\n");
425 m_dirPaths.insert(m_cwd, item);
430 /* is it already existent ?? */
431 if (!m_dirPaths.contains(fullPath)) {
432 QTreeWidgetItem *item = NULL;
433 QTreeWidgetItem *parent = m_dirPaths.value(m_cwd);
435 /* new directories to add */
436 item = new QTreeWidgetItem(parent);
437 item->setText(0, newdir.toUtf8().data());
438 item->setData(0, Qt::UserRole, QVariant(fullPath));
439 item->setCheckState(0, Qt::Unchecked);
440 /* Store the current state of the check status in column 1, which at
441 * this point has no text*/
442 item->setData(1, Qt::UserRole, QVariant(Qt::Unchecked));
445 if ((mainWin->m_miscDebug) && (m_debugTrap)) {
446 QString msg = QString("In else of if parent cwd \"%1\" newdir \"%2\"\n")
449 Pmsg0(000, msg.toUtf8().data());
452 /* insert into hash */
454 if ((mainWin->m_miscDebug) && (m_debugTrap)) {
455 Pmsg1(000, "Inserting %s\n", fullPath.toUtf8().data());
457 m_dirPaths.insert(fullPath, item);
465 * Virtual function which is called when this page is visible on the stack
467 void restoreTree::currentStackItem()
476 * Populate the tree when refresh button pushed.
478 void restoreTree::refreshButtonPushed()
480 populateDirectoryTree();
484 * Set the values of non-job combo boxes to the job defaults
486 void restoreTree::jobComboChanged(int)
488 if (jobCombo->currentText() == tr("Any")) {
489 fileSetCombo->setCurrentIndex(fileSetCombo->findText(tr("Any"), Qt::MatchExactly));
492 job_defaults job_defs;
495 job_defs.job_name = jobCombo->currentText();
496 if (m_console->get_job_defaults(job_defs)) {
497 fileSetCombo->setCurrentIndex(fileSetCombo->findText(job_defs.fileset_name, Qt::MatchExactly));
498 clientCombo->setCurrentIndex(clientCombo->findText(job_defs.client_name, Qt::MatchExactly));
503 * Function to populate the file list table
505 void restoreTree::directoryCurrentItemChanged(QTreeWidgetItem *item, QTreeWidgetItem *)
511 /* Also clear the version table here */
512 versionTable->clear();
513 versionFileLabel->setText("");
514 versionTable->setRowCount(0);
515 versionTable->setColumnCount(0);
517 QStringList headerlist = (QStringList() << tr("File Name") << tr("Filename Id"));
518 fileTable->setColumnCount(headerlist.size());
519 fileTable->setHorizontalHeaderLabels(headerlist);
520 fileTable->setRowCount(0);
522 m_fileCheckStateList.clear();
523 disconnect(fileTable, SIGNAL(itemChanged(QTableWidgetItem *)),
524 this, SLOT(fileTableItemChanged(QTableWidgetItem *)));
525 QBrush blackBrush(Qt::black);
526 QString directory = item->data(0, Qt::UserRole).toString();
527 directoryLabel->setText(tr("Present Working Directory: %1").arg(directory));
528 int pathid = m_directoryPathIdHash.value(directory, -1);
531 "SELECT DISTINCT Filename.Name AS FileName, Filename.FilenameId AS FilenameId"
533 " INNER JOIN Filename on (Filename.FilenameId=File.FilenameId)"
534 " WHERE File.PathId=" + QString("%1").arg(pathid) +
535 " AND File.Jobid IN (" + m_checkedJobs + ")"
536 " AND Filename.Name!=''"
537 " ORDER BY FileName";
538 if (mainWin->m_sqlDebug) Pmsg1(000, "Query cmd : %s\n", cmd.toUtf8().data());
541 if (m_console->sql_cmd(cmd, results)) {
543 QTableWidgetItem* tableItem;
545 QStringList fieldlist;
546 fileTable->setRowCount(results.size());
549 /* Iterate through the record returned from the query */
550 foreach (QString resultline, results) {
551 /* Iterate through fields in the record */
553 fieldlist = resultline.split("\t");
554 foreach (field, fieldlist) {
555 field = field.trimmed(); /* strip leading & trailing spaces */
556 tableItem = new QTableWidgetItem(field, 1);
557 /* Possible flags are Qt::ItemFlags flag = Qt::ItemIsSelectable | Qt::ItemIsEditablex
558 * | Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled | Qt::ItemIsUserCheckable
559 * | Qt::ItemIsEnabled | Qt::ItemIsTristate; */
560 tableItem->setForeground(blackBrush);
561 /* Just in case a column ever gets added */
562 if (mainWin->m_sqlDebug) Pmsg1(000, "Column=%d\n", column);
564 Qt::ItemFlags flag = Qt::ItemIsUserCheckable | Qt::ItemIsEnabled | Qt::ItemIsTristate;
565 tableItem->setFlags(flag);
566 tableItem->setData(Qt::UserRole, QVariant(directory));
567 fileTable->setItem(row, column, tableItem);
568 m_fileCheckStateList.append(Qt::Unchecked);
569 tableItem->setCheckState(Qt::Unchecked);
570 } else if (column == 1) {
571 Qt::ItemFlags flag = Qt::ItemIsEnabled;
572 tableItem->setFlags(flag);
574 int filenameid = field.toInt(&ok, 10);
575 if (!ok) filenameid = -1;
576 tableItem->setData(Qt::UserRole, QVariant(filenameid));
577 fileTable->setItem(row, column, tableItem);
583 fileTable->setRowCount(row);
585 fileTable->resizeColumnsToContents();
586 fileTable->resizeRowsToContents();
587 fileTable->verticalHeader()->hide();
588 fileTable->hideColumn(1);
589 if (mainWin->m_rtDirCurICDebug) Pmsg0(000, "will update file table checks\n");
590 updateFileTableChecks();
591 } else if (mainWin->m_sqlDebug)
592 Pmsg1(000, "did not perform query, pathid=%i not found\n", pathid);
593 connect(fileTable, SIGNAL(itemChanged(QTableWidgetItem *)),
594 this, SLOT(fileTableItemChanged(QTableWidgetItem *)));
598 * Function to populate the version table
600 void restoreTree::fileCurrentItemChanged(QTableWidgetItem *currentFileTableItem, QTableWidgetItem *)
602 if (currentFileTableItem == NULL)
605 int currentRow = fileTable->row(currentFileTableItem);
606 QTableWidgetItem *fileTableItem = fileTable->item(currentRow, 0);
607 QTableWidgetItem *fileNameIdTableItem = fileTable->item(currentRow, 1);
608 int fileNameId = fileNameIdTableItem->data(Qt::UserRole).toInt();
610 m_versionCheckStateList.clear();
611 disconnect(versionTable, SIGNAL(itemChanged(QTableWidgetItem *)),
612 this, SLOT(versionTableItemChanged(QTableWidgetItem *)));
614 QString file = fileTableItem->text();
615 versionFileLabel->setText(file);
616 QString directory = fileTableItem->data(Qt::UserRole).toString();
618 QBrush blackBrush(Qt::black);
620 QStringList headerlist = (QStringList()
621 << tr("Job Id") << tr("Type") << tr("End Time") << tr("Hash") << tr("FileId") << tr("Job Type") << tr("First Volume"));
622 versionTable->clear();
623 versionTable->setColumnCount(headerlist.size());
624 versionTable->setHorizontalHeaderLabels(headerlist);
625 versionTable->setRowCount(0);
627 int pathid = m_directoryPathIdHash.value(directory, -1);
628 if ((pathid != -1) && (fileNameId != -1)) {
630 "SELECT Job.JobId AS JobId, Job.Level AS Type,"
631 " Job.EndTime AS EndTime, File.MD5 AS MD5,"
632 " File.FileId AS FileId, Job.Type AS JobType,"
633 " (SELECT Media.VolumeName FROM JobMedia JOIN Media ON JobMedia.MediaId=Media.MediaId WHERE JobMedia.JobId=Job.JobId ORDER BY JobMediaId LIMIT 1) AS FirstVolume"
635 " INNER JOIN Filename on (Filename.FilenameId=File.FilenameId)"
636 " INNER JOIN Path ON (Path.PathId=File.PathId)"
637 " INNER JOIN Job ON (File.JobId=Job.JobId)"
638 " WHERE Path.PathId=" + QString("%1").arg(pathid) +
639 //" AND Filename.Name='" + file + "'"
640 " AND Filename.FilenameId=" + QString("%1").arg(fileNameId) +
641 " AND Job.Jobid IN (" + m_checkedJobs + ")"
642 " ORDER BY Job.EndTime DESC";
644 if (mainWin->m_sqlDebug) Pmsg1(000, "Query cmd : %s\n", cmd.toUtf8().data());
646 if (m_console->sql_cmd(cmd, results)) {
648 QTableWidgetItem* tableItem;
650 QStringList fieldlist;
651 versionTable->setRowCount(results.size());
654 /* Iterate through the record returned from the query */
655 foreach (QString resultline, results) {
656 fieldlist = resultline.split("\t");
658 /* remove directory */
659 if (fieldlist[0].trimmed() != "") {
660 /* Iterate through fields in the record */
661 foreach (field, fieldlist) {
662 field = field.trimmed(); /* strip leading & trailing spaces */
664 QByteArray jtype(field.trimmed().toAscii());
666 field = job_type_to_str(jtype[0]);
669 tableItem = new QTableWidgetItem(field, 1);
670 tableItem->setFlags(0);
671 tableItem->setForeground(blackBrush);
672 tableItem->setData(Qt::UserRole, QVariant(directory));
673 versionTable->setItem(row, column, tableItem);
674 if (mainWin->m_sqlDebug) Pmsg1(000, "Column=%d\n", column);
676 Qt::ItemFlags flag = Qt::ItemIsUserCheckable | Qt::ItemIsEnabled | Qt::ItemIsTristate;
677 tableItem->setFlags(flag);
678 m_versionCheckStateList.append(Qt::Unchecked);
679 tableItem->setCheckState(Qt::Unchecked);
687 versionTable->resizeColumnsToContents();
688 versionTable->resizeRowsToContents();
689 versionTable->verticalHeader()->hide();
690 updateVersionTableChecks();
692 if (mainWin->m_sqlDebug)
693 Pmsg2(000, "not querying : pathid=%i fileNameId=%i\n", pathid, fileNameId);
695 connect(versionTable, SIGNAL(itemChanged(QTableWidgetItem *)),
696 this, SLOT(versionTableItemChanged(QTableWidgetItem *)));
700 * Save user settings associated with this page
702 void restoreTree::writeSettings()
704 QSettings settings(m_console->m_dir->name(), "bat");
705 settings.beginGroup(m_groupText);
706 settings.setValue(m_splitText1, m_splitter->saveState());
707 settings.setValue(m_splitText2, splitter->saveState());
712 * Read and restore user settings associated with this page
714 void restoreTree::readSettings()
716 m_groupText = tr("RestoreTreePage");
717 m_splitText1 = "splitterSizes1_3";
718 m_splitText2 = "splitterSizes2_3";
719 QSettings settings(m_console->m_dir->name(), "bat");
720 settings.beginGroup(m_groupText);
721 if (settings.contains(m_splitText1)) { m_splitter->restoreState(settings.value(m_splitText1).toByteArray()); }
722 if (settings.contains(m_splitText2)) { splitter->restoreState(settings.value(m_splitText2).toByteArray()); }
727 * This is a funcion to accomplish the one thing I struggled to figure out what
728 * was taking so long. It add the icons, but after the tree is made. Seemed to
729 * work fast after changing from png to png file for graphic.
731 void restoreTree::directoryItemExpanded(QTreeWidgetItem *item)
733 int childCount = item->childCount();
734 for (int i=0; i<childCount; i++) {
735 QTreeWidgetItem *child = item->child(i);
736 if (child->icon(0).isNull())
737 child->setIcon(0, QIcon(QString::fromUtf8(":images/folder.png")));
742 * Show what jobs meet the criteria and are being used to
743 * populate the directory tree and file and version tables.
745 void restoreTree::populateJobTable()
747 QBrush blackBrush(Qt::black);
749 if (mainWin->m_rtPopDirDebug) Pmsg0(000, "Repopulating the Job Table\n");
750 QStringList headerlist = (QStringList()
751 << tr("Job Id") << tr("End Time") << tr("Level") << tr("Type")
752 << tr("Name") << tr("Purged") << tr("TU") << tr("TD"));
753 m_toggleUpIndex = headerlist.indexOf(tr("TU"));
754 m_toggleDownIndex = headerlist.indexOf(tr("TD"));
755 int purgedIndex = headerlist.indexOf(tr("Purged"));
756 int typeIndex = headerlist.indexOf(tr("Type"));
758 jobTable->setColumnCount(headerlist.size());
759 jobTable->setHorizontalHeaderLabels(headerlist);
761 "SELECT Job.Jobid AS Id, Job.EndTime AS EndTime,"
762 " Job.Level AS Level, Job.Type AS Type,"
763 " Job.Name AS JobName, Job.purgedfiles AS Purged"
765 /* INNER JOIN FileSet eliminates all restore jobs */
766 " INNER JOIN Client ON (Job.ClientId=Client.ClientId)"
767 " INNER JOIN FileSet ON (Job.FileSetId=FileSet.FileSetId)"
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)
791 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()) {