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 two of the GNU 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 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")));
56 QGridLayout *gridLayout = new QGridLayout(this);
57 gridLayout->setSpacing(6);
58 gridLayout->setMargin(9);
59 gridLayout->setObjectName(QString::fromUtf8("gridLayout"));
61 m_splitter = new QSplitter(Qt::Vertical, this);
62 QScrollArea *area = new QScrollArea();
63 area->setObjectName(QString::fromUtf8("area"));
64 area->setWidget(widget);
65 area->setWidgetResizable(true);
66 m_splitter->addWidget(area);
67 m_splitter->addWidget(splitter);
68 splitter->setChildrenCollapsible(false);
70 gridLayout->addWidget(m_splitter, 0, 0, 1, 1);
72 /* progress widgets */
73 prBar1->setVisible(false);
74 prBar2->setVisible(false);
75 prLabel1->setVisible(false);
76 prLabel2->setVisible(false);
78 /* Set Defaults for check and spin for limits */
79 limitCheckBox->setCheckState(mainWin->m_recordLimitCheck ? Qt::Checked : Qt::Unchecked);
80 limitSpinBox->setValue(mainWin->m_recordLimitVal);
81 daysCheckBox->setCheckState(mainWin->m_daysLimitCheck ? Qt::Checked : Qt::Unchecked);
82 daysSpinBox->setValue(mainWin->m_daysLimitVal);
84 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);
281 QMessageBox::warning(this, "Bat",
282 tr("No jobs were selected in the job query !!!.\n"
283 "Press OK to continue"),
286 prBar1->setVisible(false);
287 prBar2->setVisible(false);
288 prLabel1->setVisible(false);
289 prLabel2->setVisible(false);
293 * Function to set m_checkedJobs from the jobs that are checked in the table
296 void restoreTree::setJobsCheckedList()
298 m_JobsCheckedList = "";
300 /* Update the items in the version table */
301 int cnt = jobTable->rowCount();
302 for (int row=0; row<cnt; row++) {
303 QTableWidgetItem* jobItem = jobTable->item(row, 0);
304 if (jobItem->checkState() == Qt::Checked) {
306 m_JobsCheckedList += ",";
307 m_JobsCheckedList += jobItem->text();
309 jobItem->setBackground(Qt::green);
311 if (jobItem->flags())
312 jobItem->setBackground(Qt::gray);
314 jobItem->setBackground(Qt::darkYellow);
317 m_checkedJobs = m_JobsCheckedList;
321 * Function to parse a directory into all possible subdirectories, then add to
324 void restoreTree::parseDirectory(QString &dir_in)
326 /* m_debugTrap is to only print debugs for a few occurennces of calling parseDirectory
327 * instead of printing out what could potentially a whole bunch */
330 /* Truncate everything after the last / */
331 if (dir_in.right(1) != "/") {
332 dir_in.truncate(dir_in.lastIndexOf("/") + 1);
334 if ((mainWin->m_miscDebug) && (m_debugTrap))
335 Pmsg1(000, "parsing %s\n", dir_in.toUtf8().data());
337 /* split and add if not in yet */
338 QString direct, path;
341 QStringList pathAfter, dirAfter;
342 /* start from the end, turn /etc/somedir/subdir/ into /etc/somedir and subdir/
343 * if not added into tree, then try /etc/ and somedir/ if not added, then try
344 * / and etc/ . That should succeed, then add the ones that failed in reverse */
345 while (((index = dir_in.lastIndexOf("/", -2)) != -1) && (!done)) {
346 direct = path = dir_in;
347 path.replace(index+1, dir_in.length()-index-1,"");
348 direct.replace(0, index+1, "");
349 if ((mainWin->m_miscDebug) && (m_debugTrap)) {
350 QString msg = QString("length = \"%1\" index = \"%2\" Adding \"%3\" \"%4\"\n")
351 .arg(dir_in.length()).arg(index).arg(path).arg(direct);
352 Pmsg0(000, msg.toUtf8().data());
354 if (addDirectory(path, direct)) { done = true; }
356 if ((mainWin->m_miscDebug) && (m_debugTrap)) {
357 Pmsg0(000, "Saving for later\n");
359 pathAfter.prepend(path);
360 dirAfter.prepend(direct);
365 for (int k=0; k<pathAfter.count(); k++) {
366 if (addDirectory(pathAfter[k], dirAfter[k])) {
367 if ((mainWin->m_miscDebug) && (m_debugTrap))
368 Pmsg2(000, "Adding After %s %s\n", pathAfter[k].toUtf8().data(), dirAfter[k].toUtf8().data());
370 if ((mainWin->m_miscDebug) && (m_debugTrap))
371 Pmsg2(000, "Error Adding %s %s\n", pathAfter[k].toUtf8().data(), dirAfter[k].toUtf8().data());
378 * Function called from fill directory when a directory is found to see if this
379 * directory exists in the directory pane and then add it to the directory pane
381 bool restoreTree::addDirectory(QString &m_cwd, QString &newdirr)
383 QString newdir = newdirr;
384 QString fullPath = m_cwd + newdirr;
385 bool ok = true, added = false;
387 if ((mainWin->m_miscDebug) && (m_debugTrap)) {
388 QString msg = QString("In addDirectory cwd \"%1\" newdir \"%2\"\n")
391 Pmsg0(000, msg.toUtf8().data());
395 /* add unix '/' directory first */
396 if (m_dirPaths.empty() && !isWin32Path(fullPath)) {
398 QTreeWidgetItem *item = new QTreeWidgetItem(directoryTree);
400 item->setText(0, text.toUtf8().data());
401 item->setData(0, Qt::UserRole, QVariant(text));
402 item->setData(1, Qt::UserRole, QVariant(Qt::Unchecked));
403 item->setIcon(0, QIcon(QString::fromUtf8(":images/folder.png")));
404 if ((mainWin->m_miscDebug) && (m_debugTrap)) {
405 Pmsg1(000, "Pre Inserting %s\n", text.toUtf8().data());
407 m_dirPaths.insert(text, item);
409 /* no need to check for windows drive if unix */
410 if (isWin32Path(m_cwd)) {
411 if (!m_dirPaths.contains(m_cwd)) {
412 if (m_cwd.count('/') > 1) { return false; }
413 /* this is a windows drive add the base widget */
414 QTreeWidgetItem *item = new QTreeWidgetItem(directoryTree);
415 item->setText(0, m_cwd);
416 item->setData(0, Qt::UserRole, QVariant(fullPath));
417 item->setData(1, Qt::UserRole, QVariant(Qt::Unchecked));
418 item->setIcon(0, QIcon(QString::fromUtf8(":images/folder.png")));
419 if ((mainWin->m_miscDebug) && (m_debugTrap)) {
420 Pmsg0(000, "Added Base \"letter\":/\n");
422 m_dirPaths.insert(m_cwd, item);
427 /* is it already existent ?? */
428 if (!m_dirPaths.contains(fullPath)) {
429 QTreeWidgetItem *item = NULL;
430 QTreeWidgetItem *parent = m_dirPaths.value(m_cwd);
432 /* new directories to add */
433 item = new QTreeWidgetItem(parent);
434 item->setText(0, newdir.toUtf8().data());
435 item->setData(0, Qt::UserRole, QVariant(fullPath));
436 item->setCheckState(0, Qt::Unchecked);
437 /* Store the current state of the check status in column 1, which at
438 * this point has no text*/
439 item->setData(1, Qt::UserRole, QVariant(Qt::Unchecked));
442 if ((mainWin->m_miscDebug) && (m_debugTrap)) {
443 QString msg = QString("In else of if parent cwd \"%1\" newdir \"%2\"\n")
446 Pmsg0(000, msg.toUtf8().data());
449 /* insert into hash */
451 if ((mainWin->m_miscDebug) && (m_debugTrap)) {
452 Pmsg1(000, "Inserting %s\n", fullPath.toUtf8().data());
454 m_dirPaths.insert(fullPath, item);
462 * Virtual function which is called when this page is visible on the stack
464 void restoreTree::currentStackItem()
473 * Populate the tree when refresh button pushed.
475 void restoreTree::refreshButtonPushed()
477 populateDirectoryTree();
481 * Set the values of non-job combo boxes to the job defaults
483 void restoreTree::jobComboChanged(int)
485 if (jobCombo->currentText() == tr("Any")) {
486 fileSetCombo->setCurrentIndex(fileSetCombo->findText(tr("Any"), Qt::MatchExactly));
489 job_defaults job_defs;
492 job_defs.job_name = jobCombo->currentText();
493 if (m_console->get_job_defaults(job_defs)) {
494 fileSetCombo->setCurrentIndex(fileSetCombo->findText(job_defs.fileset_name, Qt::MatchExactly));
495 clientCombo->setCurrentIndex(clientCombo->findText(job_defs.client_name, Qt::MatchExactly));
500 * Function to populate the file list table
502 void restoreTree::directoryCurrentItemChanged(QTreeWidgetItem *item, QTreeWidgetItem *)
508 /* Also clear the version table here */
509 versionTable->clear();
510 versionFileLabel->setText("");
511 versionTable->setRowCount(0);
512 versionTable->setColumnCount(0);
514 QStringList headerlist = (QStringList() << tr("File Name") << tr("Filename Id"));
515 fileTable->setColumnCount(headerlist.size());
516 fileTable->setHorizontalHeaderLabels(headerlist);
517 fileTable->setRowCount(0);
519 m_fileCheckStateList.clear();
520 disconnect(fileTable, SIGNAL(itemChanged(QTableWidgetItem *)),
521 this, SLOT(fileTableItemChanged(QTableWidgetItem *)));
522 QBrush blackBrush(Qt::black);
523 QString directory = item->data(0, Qt::UserRole).toString();
524 directoryLabel->setText(tr("Present Working Directory: %1").arg(directory));
525 int pathid = m_directoryPathIdHash.value(directory, -1);
528 "SELECT DISTINCT Filename.Name AS FileName, Filename.FilenameId AS FilenameId"
530 " INNER JOIN Filename on (Filename.FilenameId=File.FilenameId)"
531 " WHERE File.PathId=" + QString("%1").arg(pathid) +
532 " AND File.Jobid IN (" + m_checkedJobs + ")"
533 " AND Filename.Name!=''"
534 " ORDER BY FileName";
536 if (mainWin->m_sqlDebug) {
537 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 */
562 Qt::ItemFlags flag = Qt::ItemIsUserCheckable | Qt::ItemIsEnabled | Qt::ItemIsTristate;
563 tableItem->setFlags(flag);
564 tableItem->setData(Qt::UserRole, QVariant(directory));
565 fileTable->setItem(row, column, tableItem);
566 m_fileCheckStateList.append(Qt::Unchecked);
567 tableItem->setCheckState(Qt::Unchecked);
568 } else if (column == 1) {
569 Qt::ItemFlags flag = Qt::ItemIsEnabled;
570 tableItem->setFlags(flag);
572 int filenameid = field.toInt(&ok, 10);
573 if (!ok) filenameid = -1;
574 tableItem->setData(Qt::UserRole, QVariant(filenameid));
575 fileTable->setItem(row, column, tableItem);
581 fileTable->setRowCount(row);
583 fileTable->resizeColumnsToContents();
584 fileTable->resizeRowsToContents();
585 fileTable->verticalHeader()->hide();
586 fileTable->hideColumn(1);
587 if (mainWin->m_rtDirCurICDebug) Pmsg0(000, "will update file table checks\n");
588 updateFileTableChecks();
589 } else if (mainWin->m_sqlDebug)
590 Pmsg1(000, "did not perform query, pathid=%i not found\n", pathid);
591 connect(fileTable, SIGNAL(itemChanged(QTableWidgetItem *)),
592 this, SLOT(fileTableItemChanged(QTableWidgetItem *)));
596 * Function to populate the version table
598 void restoreTree::fileCurrentItemChanged(QTableWidgetItem *currentFileTableItem, QTableWidgetItem *)
600 if (currentFileTableItem == NULL)
603 int currentRow = fileTable->row(currentFileTableItem);
604 QTableWidgetItem *fileTableItem = fileTable->item(currentRow, 0);
605 QTableWidgetItem *fileNameIdTableItem = fileTable->item(currentRow, 1);
606 int fileNameId = fileNameIdTableItem->data(Qt::UserRole).toInt();
608 m_versionCheckStateList.clear();
609 disconnect(versionTable, SIGNAL(itemChanged(QTableWidgetItem *)),
610 this, SLOT(versionTableItemChanged(QTableWidgetItem *)));
612 QString file = fileTableItem->text();
613 versionFileLabel->setText(file);
614 QString directory = fileTableItem->data(Qt::UserRole).toString();
616 QBrush blackBrush(Qt::black);
618 QStringList headerlist = (QStringList()
619 << tr("Job Id") << tr("Type") << tr("End Time") << tr("Hash") << tr("FileId") << tr("Job Type") << tr("First Volume"));
620 versionTable->clear();
621 versionTable->setColumnCount(headerlist.size());
622 versionTable->setHorizontalHeaderLabels(headerlist);
623 versionTable->setRowCount(0);
625 int pathid = m_directoryPathIdHash.value(directory, -1);
626 if ((pathid != -1) && (fileNameId != -1)) {
628 "SELECT Job.JobId AS JobId, Job.Level AS Type,"
629 " Job.EndTime AS EndTime, File.MD5 AS MD5,"
630 " File.FileId AS FileId, Job.Type AS JobType,"
631 " (SELECT Media.VolumeName FROM JobMedia JOIN Media ON JobMedia.MediaId=Media.MediaId WHERE JobMedia.JobId=Job.JobId ORDER BY JobMediaId LIMIT 1) AS FirstVolume"
633 " INNER JOIN Filename on (Filename.FilenameId=File.FilenameId)"
634 " INNER JOIN Path ON (Path.PathId=File.PathId)"
635 " INNER JOIN Job ON (File.JobId=Job.JobId)"
636 " WHERE Path.PathId=" + QString("%1").arg(pathid) +
637 //" AND Filename.Name='" + file + "'"
638 " AND Filename.FilenameId=" + QString("%1").arg(fileNameId) +
639 " AND Job.Jobid IN (" + m_checkedJobs + ")"
640 " ORDER BY Job.EndTime DESC";
642 if (mainWin->m_sqlDebug)
643 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);
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 " Client.Name='" + clientCombo->currentText() + "'";
769 if ((jobCombo->currentIndex() >= 0) && (jobCombo->currentText() != tr("Any"))) {
770 jobQuery += " AND Job.name = '" + jobCombo->currentText() + "'";
772 if ((fileSetCombo->currentIndex() >= 0) && (fileSetCombo->currentText() != tr("Any"))) {
773 jobQuery += " AND FileSet.FileSet='" + fileSetCombo->currentText() + "'";
775 /* If Limit check box For limit by days is checked */
776 if (daysCheckBox->checkState() == Qt::Checked) {
777 QDateTime stamp = QDateTime::currentDateTime().addDays(-daysSpinBox->value());
778 QString since = stamp.toString(Qt::ISODate);
779 jobQuery += " AND Job.Starttime>'" + since + "'";
781 //jobQuery += " AND Job.purgedfiles=0";
782 jobQuery += " ORDER BY Job.EndTime DESC";
783 /* If Limit check box for limit records returned is checked */
784 if (limitCheckBox->checkState() == Qt::Checked) {
786 limit.setNum(limitSpinBox->value());
787 jobQuery += " LIMIT " + limit;
789 if (mainWin->m_sqlDebug)
790 Pmsg1(000, "Query cmd : %s\n", jobQuery.toUtf8().data());
793 if (m_console->sql_cmd(jobQuery, results)) {
795 QTableWidgetItem* tableItem;
797 QStringList fieldlist;
798 jobTable->setRowCount(results.size());
801 /* Iterate through the record returned from the query */
802 foreach (QString resultline, results) {
803 fieldlist = resultline.split("\t");
805 /* remove directory */
806 if (fieldlist[0].trimmed() != "") {
807 /* Iterate through fields in the record */
808 foreach (field, fieldlist) {
809 field = field.trimmed(); /* strip leading & trailing spaces */
811 if (column == typeIndex) {
812 QByteArray jtype(field.trimmed().toAscii());
814 field = job_type_to_str(jtype[0]);
817 tableItem = new QTableWidgetItem(field, 1);
818 tableItem->setFlags(0);
819 tableItem->setForeground(blackBrush);
820 jobTable->setItem(row, column, tableItem);
823 int purged = fieldlist[purgedIndex].toInt(&ok, 10);
824 if (!((ok) && (purged == 1))) {
825 Qt::ItemFlags flag = Qt::ItemIsUserCheckable | Qt::ItemIsEnabled | Qt::ItemIsTristate;
826 tableItem->setFlags(flag);
827 tableItem->setCheckState(Qt::Checked);
828 tableItem->setBackground(Qt::green);
830 tableItem->setFlags(0);
831 tableItem->setCheckState(Qt::Unchecked);
837 tableItem = new QTableWidgetItem(QIcon(QString::fromUtf8(":images/go-up.png")), "", 1);
838 tableItem->setFlags(0);
839 tableItem->setForeground(blackBrush);
840 jobTable->setItem(row, column, tableItem);
842 tableItem = new QTableWidgetItem(QIcon(QString::fromUtf8(":images/go-down.png")), "", 1);
843 tableItem->setFlags(0);
844 tableItem->setForeground(blackBrush);
845 jobTable->setItem(row, column, tableItem);
850 jobTable->resizeColumnsToContents();
851 jobTable->resizeRowsToContents();
852 jobTable->verticalHeader()->hide();
853 jobTable->hideColumn(purgedIndex);
856 void restoreTree::jobTableCellClicked(int row, int column)
858 if (column == m_toggleUpIndex){
860 for (cnt=0; cnt<row+1; cnt++) {
861 QTableWidgetItem *item = jobTable->item(cnt, 0);
863 Qt::CheckState state = item->checkState();
864 if (state == Qt::Checked)
865 item->setCheckState(Qt::Unchecked);
866 else if (state == Qt::Unchecked)
867 item->setCheckState(Qt::Checked);
871 if (column == m_toggleDownIndex){
872 int cnt, max = jobTable->rowCount();
873 for (cnt=row; cnt<max; cnt++) {
874 QTableWidgetItem *item = jobTable->item(cnt, 0);
876 Qt::CheckState state = item->checkState();
877 if (state == Qt::Checked)
878 item->setCheckState(Qt::Unchecked);
879 else if (state == Qt::Unchecked)
880 item->setCheckState(Qt::Checked);
887 * When a directory item is "changed" check the state of the checkable item
888 * to see if it is different than what it was which is stored in Qt::UserRole
889 * of the 2nd column, column 1, of the tree widget.
891 void restoreTree::directoryItemChanged(QTreeWidgetItem *item, int /*column*/)
893 Qt::CheckState prevState = (Qt::CheckState)item->data(1, Qt::UserRole).toInt();
894 Qt::CheckState curState = item->checkState(0);
895 QTreeWidgetItem* parent = item->parent();
896 Qt::CheckState parState;
897 if (parent) parState = parent->checkState(0);
898 else parState = (Qt::CheckState)3;
899 if (mainWin->m_rtDirICDebug) {
900 QString msg = QString("directory item OBJECT has changed prev=%1 cur=%2 par=%3 dir=%4\n")
901 .arg(prevState).arg(curState).arg(parState).arg(item->text(0));
902 Pmsg1(000, "%s", msg.toUtf8().data()); }
903 /* I only care when the check state changes */
904 if (prevState == curState) {
905 if (mainWin->m_rtDirICDebug) Pmsg0(000, "Returning Early\n");
909 if ((prevState == Qt::Unchecked) && (curState == Qt::Checked) && (parState != Qt::Unchecked)) {
910 if (mainWin->m_rtDirICDebug) Pmsg0(000, "Disconnected Setting to Qt::PartiallyChecked\n");
911 directoryTreeDisconnectedSet(item, Qt::PartiallyChecked);
912 curState = Qt::PartiallyChecked;
914 if ((prevState == Qt::PartiallyChecked) && (curState == Qt::Checked)) {
915 if (mainWin->m_rtDirICDebug) Pmsg0(000, "Disconnected Setting to Qt::Unchecked\n");
916 directoryTreeDisconnectedSet(item, Qt::Unchecked);
917 curState = Qt::Unchecked;
919 if (mainWin->m_rtDirICDebug) {
920 QString msg = QString("directory item CHECKSTATE has changed prev=%1 cur=%2 par=%3 dir=%4\n")
921 .arg(prevState).arg(curState).arg(parState).arg(item->text(0));
922 Pmsg1(000, "%s", msg.toUtf8().data()); }
924 item->setData(1, Qt::UserRole, QVariant(curState));
925 Qt::CheckState childState = curState;
926 if (childState == Qt::Checked)
927 childState = Qt::PartiallyChecked;
928 setCheckofChildren(item, childState);
930 /* Remove items from the exception lists. The multi exception list is my index
931 * of what exceptions can be removed when the directory is known*/
932 QString directory = item->data(0, Qt::UserRole).toString();
933 QStringList fullPathList = m_fileExceptionMulti.values(directory);
934 int fullPathListCount = fullPathList.count();
935 if ((mainWin->m_rtDirICDebug) && fullPathListCount) Pmsg2(000, "Will attempt to remove file exceptions for %s count %i\n", directory.toUtf8().data(), fullPathListCount);
936 foreach (QString fullPath, fullPathList) {
937 /* If there is no value in the hash for the key fullPath a value of 3 will be returned
938 * which will match no Qt::xxx values */
939 Qt::CheckState hashState = m_fileExceptionHash.value(fullPath, (Qt::CheckState)3);
940 if (mainWin->m_rtDirICDebug) Pmsg2(000, "hashState=%i childState=%i\n", hashState, childState);
941 if (hashState == Qt::Unchecked) {
942 fileExceptionRemove(fullPath, directory);
943 m_versionExceptionHash.remove(fullPath);
944 if (mainWin->m_rtDirICDebug) Pmsg0(000, "Attempted Removal A\n");
946 if (hashState == Qt::Checked) {
947 fileExceptionRemove(fullPath, directory);
948 m_versionExceptionHash.remove(fullPath);
949 if (mainWin->m_rtDirICDebug) Pmsg0(000, "Attempted Removal B\n");
953 if (item == directoryTree->currentItem()) {
954 if (mainWin->m_rtDirICDebug) Pmsg0(000, "Will attempt to update File Table Checks\n");
955 updateFileTableChecks();
956 versionTable->clear();
957 versionTable->setRowCount(0);
958 versionTable->setColumnCount(0);
960 if (mainWin->m_rtDirICDebug) Pmsg0(000, "Returning At End\n");
964 * When a directory item check state is changed, this function iterates through
965 * all subdirectories and sets all to the passed state, which is either partially
966 * checked or unchecked.
968 void restoreTree::setCheckofChildren(QTreeWidgetItem *item, Qt::CheckState state)
971 childCount = item->childCount();
972 for (int i=0; i<childCount; i++) {
973 QTreeWidgetItem *child = item->child(i);
974 child->setData(1, Qt::UserRole, QVariant(state));
975 child->setCheckState(0, state);
976 setCheckofChildren(child, state);
981 * When a File Table Item is "changed" check to see if the state of the checkable
982 * item has changed which is stored in m_fileCheckStateList
983 * If changed store in a hash m_fileExceptionHash that whether this file should be
985 * Called as a slot, connected after populated (after directory current changed called)
987 void restoreTree::fileTableItemChanged(QTableWidgetItem *item)
989 /* get the previous and current check states */
990 int row = fileTable->row(item);
991 Qt::CheckState prevState;
992 /* prevent a segfault */
993 prevState = m_fileCheckStateList[row];
994 Qt::CheckState curState = item->checkState();
996 /* deterimine the default state from the state of the directory */
997 QTreeWidgetItem *dirTreeItem = directoryTree->currentItem();
998 Qt::CheckState dirState = (Qt::CheckState)dirTreeItem->data(1, Qt::UserRole).toInt();
999 Qt::CheckState defState = Qt::PartiallyChecked;
1000 if (dirState == Qt::Unchecked) defState = Qt::Unchecked;
1002 /* determine if it is already in the m_fileExceptionHash */
1003 QString directory = directoryTree->currentItem()->data(0, Qt::UserRole).toString();
1004 QString file = item->text();
1005 QString fullPath = directory + file;
1006 Qt::CheckState hashState = m_fileExceptionHash.value(fullPath, (Qt::CheckState)3);
1007 int verJobNum = m_versionExceptionHash.value(fullPath, 0);
1009 if (mainWin->m_rtFileTabICDebug) {
1010 QString msg = QString("filerow=%1 prev=%2 cur=%3 def=%4 hash=%5 dir=%6 verJobNum=%7\n")
1011 .arg(row).arg(prevState).arg(curState).arg(defState).arg(hashState).arg(dirState).arg(verJobNum);
1012 Pmsg1(000, "%s", msg.toUtf8().data()); }
1014 /* Remove the hash if currently checked previously unchecked and directory is checked or partial */
1015 if ((prevState == Qt::Checked) && (curState == Qt::Unchecked) && (dirState == Qt::Unchecked)) {
1016 /* it can behave as defaulted so current of unchecked is fine */
1017 if (mainWin->m_rtFileTabICDebug) Pmsg0(000, "Will fileExceptionRemove and m_versionExceptionHash.remove here\n");
1018 fileExceptionRemove(fullPath, directory);
1019 m_versionExceptionHash.remove(fullPath);
1020 } else if ((prevState == Qt::PartiallyChecked) && (curState == Qt::Checked) && (dirState != Qt::Unchecked) && (verJobNum == 0)) {
1021 if (mainWin->m_rtFileTabICDebug) Pmsg0(000, "Will fileExceptionInsert here\n");
1022 fileExceptionInsert(fullPath, directory, Qt::Unchecked);
1023 } else if ((prevState == Qt::Unchecked) && (curState == Qt::Checked) && (dirState != Qt::Unchecked) && (verJobNum == 0) && (defState == Qt::PartiallyChecked)) {
1024 /* filerow=2 prev=0 cur=2 def=1 hash=0 dir=2 verJobNum=0 */
1025 if (mainWin->m_rtFileTabICDebug) Pmsg0(000, "Will fileExceptionRemove here\n");
1026 fileExceptionRemove(fullPath, directory);
1027 } else if ((prevState == Qt::Checked) && (curState == Qt::Unchecked) && (defState == Qt::PartiallyChecked) && (verJobNum != 0) && (hashState == Qt::Checked)) {
1028 /* Check dir, check version, attempt uncheck in file
1029 * filerow=4 prev=2 cur=0 def=1 hash=2 dir=2 verJobNum=53 */
1030 if (mainWin->m_rtFileTabICDebug) Pmsg0(000, "Will fileExceptionRemove and m_versionExceptionHash.remove here\n");
1031 fileExceptionRemove(fullPath, directory);
1032 m_versionExceptionHash.remove(fullPath);
1033 } else if ((prevState == Qt::Unchecked) && (curState == Qt::Checked) && (dirState != Qt::Unchecked) && (verJobNum == 0)) {
1034 /* filerow=0 prev=0 cur=2 def=1 hash=0 dirState=2 verJobNum */
1035 if (mainWin->m_rtFileTabICDebug) Pmsg0(000, "Will Not remove here\n");
1036 } else if (prevState != curState) {
1037 if (mainWin->m_rtFileTabICDebug) Pmsg2(000, " THE STATE OF THE Check has changed, Setting StateList[%i] to %i\n", row, curState);
1038 /* A user did not set the check state to Partially checked, ignore if so */
1039 if (curState != Qt::PartiallyChecked) {
1040 if ((defState == Qt::Unchecked) && (prevState == Qt::PartiallyChecked) && (curState == Qt::Unchecked)) {
1041 if (mainWin->m_rtFileTabICDebug) Pmsg0(000, " got here\n");
1043 if (mainWin->m_rtFileTabICDebug) Pmsg2(000, " Inserting into m_fileExceptionHash %s, %i\n", fullPath.toUtf8().data(), curState);
1044 fileExceptionInsert(fullPath, directory, curState);
1047 if (mainWin->m_rtFileTabICDebug) Pmsg1(000, "Removing version hash for %s\n", fullPath.toUtf8().data());
1048 /* programattically been changed back to a default state of Qt::PartiallyChecked remove the version hash here */
1049 m_versionExceptionHash.remove(fullPath);
1053 updateFileTableChecks();
1054 updateVersionTableChecks();
1058 * function to insert keys and values to both m_fileExceptionHash and m_fileExceptionMulti
1060 void restoreTree::fileExceptionInsert(QString &fullPath, QString &direcotry, Qt::CheckState state)
1062 m_fileExceptionHash.insert(fullPath, state);
1063 m_fileExceptionMulti.insert(direcotry, fullPath);
1064 directoryIconStateInsert(fullPath, state);
1068 * function to remove keys from both m_fileExceptionHash and m_fileExceptionMulti
1070 void restoreTree::fileExceptionRemove(QString &fullPath, QString &directory)
1072 m_fileExceptionHash.remove(fullPath);
1073 /* pull the list of values in the multi */
1074 QStringList fullPathList = m_fileExceptionMulti.values(directory);
1075 /* get the index of the fullpath to remove */
1076 int index = fullPathList.indexOf(fullPath);
1078 /* remove the desired item in the list */
1079 fullPathList.removeAt(index);
1080 /* remove the entire list from the multi */
1081 m_fileExceptionMulti.remove(directory);
1082 /* readd the remaining */
1083 foreach (QString fp, fullPathList) {
1084 m_fileExceptionMulti.insert(directory, fp);
1087 directoryIconStateRemove();
1091 * Overloaded function to be called from the slot and from other places to set the state
1092 * of the check marks in the version table
1094 void restoreTree::versionTableItemChanged(QTableWidgetItem *item)
1096 /* get the previous and current check states */
1097 int row = versionTable->row(item);
1098 QTableWidgetItem *colZeroItem = versionTable->item(row, 0);
1099 Qt::CheckState prevState = m_versionCheckStateList[row];
1100 Qt::CheckState curState = (Qt::CheckState)colZeroItem->checkState();
1101 m_versionCheckStateList[row] = curState;
1103 /* deterimine the default state from the state of the file */
1104 QTableWidgetItem *fileTableItem = fileTable->currentItem();
1105 Qt::CheckState fileState = (Qt::CheckState)fileTableItem->checkState();
1107 /* determine the default state */
1108 Qt::CheckState defState;
1110 defState = Qt::PartiallyChecked;
1111 if (fileState == Qt::Unchecked)
1112 defState = Qt::Unchecked;
1115 defState = Qt::Unchecked;
1117 /* determine if it is already in the versionExceptionHash */
1118 QString directory = directoryTree->currentItem()->data(0, Qt::UserRole).toString();
1119 Qt::CheckState dirState = directoryTree->currentItem()->checkState(0);
1120 QString file = fileTableItem->text();
1121 QString fullPath = directory + file;
1122 int thisJobNum = colZeroItem->text().toInt();
1123 int hashJobNum = m_versionExceptionHash.value(fullPath, 0);
1125 if (mainWin->m_rtVerTabICDebug) {
1126 QString msg = QString("versrow=%1 prev=%2 cur=%3 def=%4 dir=%5 hashJobNum=%6 thisJobNum=%7 filestate=%8 fec=%9 vec=%10\n")
1127 .arg(row).arg(prevState).arg(curState).arg(defState).arg(dirState).arg(hashJobNum).arg(thisJobNum).arg(fileState)
1128 .arg(m_fileExceptionHash.count()).arg(m_versionExceptionHash.count());
1129 Pmsg1(000, "%s", msg.toUtf8().data()); }
1130 /* if changed from partially checked to checked, make it unchecked */
1131 if ((curState == Qt::Checked) && (row == 0) && (fileState == Qt::Unchecked)) {
1132 if (mainWin->m_rtVerTabICDebug) Pmsg0(000, "Setting to Qt::Checked\n");
1133 fileTableItem->setCheckState(Qt::Checked);
1134 } else if ((prevState == Qt::PartiallyChecked) && (curState == Qt::Checked) && (row == 0) && (fileState == Qt::Checked) && (dirState == Qt::Unchecked)) {
1135 //versrow=0 prev=1 cur=2 def=1 dir=0 hashJobNum=0 thisJobNum=64 filestate=2 fec=1 vec=0
1136 if (mainWin->m_rtVerTabICDebug) Pmsg1(000, "fileExceptionRemove %s, %i\n", fullPath.toUtf8().data());
1137 fileExceptionRemove(fullPath, directory);
1138 } else if ((curState == Qt::Checked) && (row == 0) && (hashJobNum != 0) && (dirState != Qt::Unchecked)) {
1139 //versrow=0 prev=0 cur=2 def=1 dir=2 hashJobNum=53 thisJobNum=64 filestate=2 fec=1 vec=1
1140 if (mainWin->m_rtVerTabICDebug) Pmsg1(000, "m_versionExceptionHash.remove %s\n", fullPath.toUtf8().data());
1141 m_versionExceptionHash.remove(fullPath);
1142 fileExceptionRemove(fullPath, directory);
1143 } else if ((curState == Qt::Checked) && (row == 0)) {
1144 if (mainWin->m_rtVerTabICDebug) Pmsg1(000, "m_versionExceptionHash.remove %s\n", fullPath.toUtf8().data());
1145 m_versionExceptionHash.remove(fullPath);
1146 } else if (prevState != curState) {
1147 if (mainWin->m_rtVerTabICDebug) Pmsg2(000, " THE STATE OF THE version Check has changed, Setting StateList[%i] to %i\n", row, curState);
1148 if ((curState == Qt::Checked) || (curState == Qt::PartiallyChecked && row != 0)) {
1149 if (mainWin->m_rtVerTabICDebug) Pmsg2(000, "Inserting into m_versionExceptionHash %s, %i\n", fullPath.toUtf8().data(), thisJobNum);
1150 m_versionExceptionHash.insert(fullPath, thisJobNum);
1151 if (fileState != Qt::Checked) {
1152 if (mainWin->m_rtVerTabICDebug) Pmsg2(000, "Inserting into m_fileExceptionHash %s, %i\n", fullPath.toUtf8().data(), curState);
1153 fileExceptionInsert(fullPath, directory, curState);
1156 if (mainWin->m_rtVerTabICDebug) Pmsg0(000, "got here\n");
1159 if (mainWin->m_rtVerTabICDebug) Pmsg0(000, "no conditions met\n");
1162 updateFileTableChecks();
1163 updateVersionTableChecks();
1167 * Simple function to set the check state in the file table by disconnecting the
1168 * signal/slot the setting then reconnecting the signal/slot
1170 void restoreTree::fileTableDisconnectedSet(QTableWidgetItem *item, Qt::CheckState state, bool color)
1172 disconnect(fileTable, SIGNAL(itemChanged(QTableWidgetItem *)),
1173 this, SLOT(fileTableItemChanged(QTableWidgetItem *)));
1174 item->setCheckState(state);
1175 if (color) item->setBackground(Qt::yellow);
1176 else item->setBackground(Qt::white);
1177 connect(fileTable, SIGNAL(itemChanged(QTableWidgetItem *)),
1178 this, SLOT(fileTableItemChanged(QTableWidgetItem *)));
1182 * Simple function to set the check state in the version table by disconnecting the
1183 * signal/slot the setting then reconnecting the signal/slot
1185 void restoreTree::versionTableDisconnectedSet(QTableWidgetItem *item, Qt::CheckState state)
1187 disconnect(versionTable, SIGNAL(itemChanged(QTableWidgetItem *)),
1188 this, SLOT(versionTableItemChanged(QTableWidgetItem *)));
1189 item->setCheckState(state);
1190 connect(versionTable, SIGNAL(itemChanged(QTableWidgetItem *)),
1191 this, SLOT(versionTableItemChanged(QTableWidgetItem *)));
1195 * Simple function to set the check state in the directory tree by disconnecting the
1196 * signal/slot the setting then reconnecting the signal/slot
1198 void restoreTree::directoryTreeDisconnectedSet(QTreeWidgetItem *item, Qt::CheckState state)
1200 disconnect(directoryTree, SIGNAL(itemChanged(QTreeWidgetItem *, int)),
1201 this, SLOT(directoryItemChanged(QTreeWidgetItem *, int)));
1202 item->setCheckState(0, state);
1203 connect(directoryTree, SIGNAL(itemChanged(QTreeWidgetItem *, int)),
1204 this, SLOT(directoryItemChanged(QTreeWidgetItem *, int)));
1208 * Simplify the updating of the check state in the File table by iterating through
1209 * each item in the file table to determine it's appropriate state.
1210 * !! Will probably want to concoct a way to do this without iterating for the possibility
1211 * of the very large directories.
1213 void restoreTree::updateFileTableChecks()
1215 /* deterimine the default state from the state of the directory */
1216 QTreeWidgetItem *dirTreeItem = directoryTree->currentItem();
1217 Qt::CheckState dirState = dirTreeItem->checkState(0);
1219 QString dirName = dirTreeItem->data(0, Qt::UserRole).toString();
1221 /* Update the items in the version table */
1222 int rcnt = fileTable->rowCount();
1223 for (int row=0; row<rcnt; row++) {
1224 QTableWidgetItem* item = fileTable->item(row, 0);
1225 if (!item) { return; }
1227 Qt::CheckState curState = item->checkState();
1228 Qt::CheckState newState = Qt::PartiallyChecked;
1229 if (dirState == Qt::Unchecked) newState = Qt::Unchecked;
1231 /* determine if it is already in the m_fileExceptionHash */
1232 QString file = item->text();
1233 QString fullPath = dirName + file;
1234 Qt::CheckState hashState = m_fileExceptionHash.value(fullPath, (Qt::CheckState)3);
1235 int hashJobNum = m_versionExceptionHash.value(fullPath, 0);
1237 if (hashState != 3) newState = hashState;
1239 if (mainWin->m_rtUpdateFTDebug) {
1240 QString msg = QString("file row=%1 cur=%2 hash=%3 new=%4 dirState=%5\n")
1241 .arg(row).arg(curState).arg(hashState).arg(newState).arg(dirState);
1242 Pmsg1(000, "%s", msg.toUtf8().data());
1245 bool docolor = false;
1246 if (hashJobNum != 0) docolor = true;
1247 bool isyellow = item->background().color() == QColor(Qt::yellow);
1248 if ((newState != curState) || (hashState == 3) || ((isyellow && !docolor) || (!isyellow && docolor)))
1249 fileTableDisconnectedSet(item, newState, docolor);
1250 m_fileCheckStateList[row] = newState;
1255 * Simplify the updating of the check state in the Version table by iterating through
1256 * each item in the file table to determine it's appropriate state.
1258 void restoreTree::updateVersionTableChecks()
1260 /* deterimine the default state from the state of the directory */
1261 QTreeWidgetItem *dirTreeItem = directoryTree->currentItem();
1262 Qt::CheckState dirState = dirTreeItem->checkState(0);
1263 QString dirName = dirTreeItem->data(0, Qt::UserRole).toString();
1265 /* deterimine the default state from the state of the file */
1266 QTableWidgetItem *fileTableItem = fileTable->item(fileTable->currentRow(), 0);
1267 if (!fileTableItem) { return; }
1268 Qt::CheckState fileState = fileTableItem->checkState();
1269 QString file = fileTableItem->text();
1270 QString fullPath = dirName + file;
1271 int hashJobNum = m_versionExceptionHash.value(fullPath, 0);
1273 /* Update the items in the version table */
1274 int cnt = versionTable->rowCount();
1275 for (int row=0; row<cnt; row++) {
1276 QTableWidgetItem* item = versionTable->item(row, 0);
1277 if (!item) { break; }
1279 Qt::CheckState curState = item->checkState();
1280 Qt::CheckState newState = Qt::Unchecked;
1282 if ((row == 0) && (fileState != Qt::Unchecked) && (hashJobNum == 0))
1283 newState = Qt::PartiallyChecked;
1284 /* determine if it is already in the versionExceptionHash */
1286 int thisJobNum = item->text().toInt();
1287 if (thisJobNum == hashJobNum)
1288 newState = Qt::Checked;
1290 if (mainWin->m_rtChecksDebug) {
1291 QString msg = QString("ver row=%1 cur=%2 hashJobNum=%3 new=%4 dirState=%5\n")
1292 .arg(row).arg(curState).arg(hashJobNum).arg(newState).arg(dirState);
1293 Pmsg1(000, "%s", msg.toUtf8().data());
1295 if (newState != curState)
1296 versionTableDisconnectedSet(item, newState);
1297 m_versionCheckStateList[row] = newState;
1302 * Quick subroutine to "return via subPaths" a list of subpaths when passed a fullPath
1304 void restoreTree::fullPathtoSubPaths(QStringList &subPaths, QString &fullPath_in)
1308 QString fullPath = fullPath_in;
1309 QString direct, path;
1310 while (((index = fullPath.lastIndexOf("/", -2)) != -1) && (!done)) {
1311 direct = path = fullPath;
1312 path.replace(index+1, fullPath.length()-index-1, "");
1313 direct.replace(0, index+1, "");
1315 QString msg = QString("length = \"%1\" index = \"%2\" Considering \"%3\" \"%4\"\n")
1316 .arg(fullPath.length()).arg(index).arg(path).arg(direct);
1317 Pmsg0(000, msg.toUtf8().data());
1320 subPaths.append(fullPath);
1325 * A Function to set the icon state and insert a record into
1326 * m_directoryIconStateHash when an exception is added by the user
1328 void restoreTree::directoryIconStateInsert(QString &fullPath, Qt::CheckState excpState)
1331 fullPathtoSubPaths(paths, fullPath);
1332 /* an exception that causes the item in the file table to be "Checked" has occured */
1333 if (excpState == Qt::Checked) {
1334 bool foundAsUnChecked = false;
1335 QTreeWidgetItem *firstItem = m_dirPaths.value(paths[0]);
1337 if (firstItem->checkState(0) == Qt::Unchecked)
1338 foundAsUnChecked = true;
1340 if (foundAsUnChecked) {
1341 /* as long as directory item is Unchecked, set icon state to "green check" */
1343 QListIterator<QString> siter(paths);
1344 while (siter.hasNext() && !done) {
1345 QString path = siter.next();
1346 QTreeWidgetItem *item = m_dirPaths.value(path);
1348 if (item->checkState(0) != Qt::Unchecked)
1351 directorySetIcon(1, FolderGreenChecked, path, item);
1352 if (mainWin->m_rtIconStateDebug) Pmsg1(000, "In restoreTree::directoryIconStateInsert inserting %s\n", path.toUtf8().data());
1357 /* if it is partially checked or fully checked insert green Check until a unchecked is found in the path */
1358 if (mainWin->m_rtIconStateDebug) Pmsg1(000, "In restoreTree::directoryIconStateInsert Aqua %s\n", paths[0].toUtf8().data());
1360 QListIterator<QString> siter(paths);
1361 while (siter.hasNext() && !done) {
1362 QString path = siter.next();
1363 QTreeWidgetItem *item = m_dirPaths.value(path);
1364 if (item) { /* if the directory item is checked, set icon state to unchecked "green check" */
1365 if (item->checkState(0) == Qt::Checked)
1367 directorySetIcon(1, FolderGreenChecked, path, item);
1368 if (mainWin->m_rtIconStateDebug) Pmsg1(000, "In restoreTree::directoryIconStateInsert boogie %s\n", path.toUtf8().data());
1373 /* an exception that causes the item in the file table to be "Unchecked" has occured */
1374 if (excpState == Qt::Unchecked) {
1376 QListIterator<QString> siter(paths);
1377 while (siter.hasNext() && !done) {
1378 QString path = siter.next();
1379 QTreeWidgetItem *item = m_dirPaths.value(path);
1380 if (item) { /* if the directory item is checked, set icon state to unchecked "white check" */
1381 if (item->checkState(0) == Qt::Checked)
1383 directorySetIcon(1, FolderWhiteChecked, path, item);
1384 if (mainWin->m_rtIconStateDebug) Pmsg1(000, "In restoreTree::directoryIconStateInsert boogie %s\n", path.toUtf8().data());
1391 * A function to set the icon state back to "folder" and to remove a record from
1392 * m_directoryIconStateHash when an exception is removed by a user.
1394 void restoreTree::directoryIconStateRemove()
1396 QHash<QString, int> shouldBeIconStateHash;
1397 /* First determine all paths with icons that should be checked with m_fileExceptionHash */
1398 /* Use iterator tera to iterate through m_fileExceptionHash */
1399 QHashIterator<QString, Qt::CheckState> tera(m_fileExceptionHash);
1400 while (tera.hasNext()) {
1402 if (mainWin->m_rtIconStateDebug) Pmsg2(000, "Alpha Key %s value %i\n", tera.key().toUtf8().data(), tera.value());
1404 QString keyPath = tera.key();
1405 Qt::CheckState state = tera.value();
1408 fullPathtoSubPaths(paths, keyPath);
1409 /* if the state of the item in m_fileExceptionHash is checked
1410 * each of the subpaths should be "Checked Green" */
1411 if (state == Qt::Checked) {
1413 bool foundAsUnChecked = false;
1414 QTreeWidgetItem *firstItem = m_dirPaths.value(paths[0]);
1416 if (firstItem->checkState(0) == Qt::Unchecked)
1417 foundAsUnChecked = true;
1419 if (foundAsUnChecked) {
1420 /* The right most directory is Unchecked, iterate leftwards
1421 * as long as directory item is Unchecked, set icon state to "green check" */
1423 QListIterator<QString> siter(paths);
1424 while (siter.hasNext() && !done) {
1425 QString path = siter.next();
1426 QTreeWidgetItem *item = m_dirPaths.value(path);
1428 if (item->checkState(0) != Qt::Unchecked)
1431 shouldBeIconStateHash.insert(path, FolderGreenChecked);
1432 if (mainWin->m_rtIconStateDebug) Pmsg1(000, "In restoreTree::directoryIconStateInsert inserting %s\n", path.toUtf8().data());
1438 /* The right most directory is Unchecked, iterate leftwards
1439 * until directory item is Checked, set icon state to "green check" */
1441 QListIterator<QString> siter(paths);
1442 while (siter.hasNext() && !done) {
1443 QString path = siter.next();
1444 QTreeWidgetItem *item = m_dirPaths.value(path);
1446 if (item->checkState(0) == Qt::Checked)
1448 shouldBeIconStateHash.insert(path, FolderGreenChecked);
1453 /* if the state of the item in m_fileExceptionHash is UNChecked
1454 * each of the subpaths should be "Checked white" until the tree item
1455 * which represents that path is Qt::Checked */
1456 if (state == Qt::Unchecked) {
1458 QListIterator<QString> siter(paths);
1459 while (siter.hasNext() && !done) {
1460 QString path = siter.next();
1461 QTreeWidgetItem *item = m_dirPaths.value(path);
1463 if (item->checkState(0) == Qt::Checked)
1465 shouldBeIconStateHash.insert(path, FolderWhiteChecked);
1470 /* now iterate through m_directoryIconStateHash which are the items that are checked
1471 * and remove all of those that are not in shouldBeIconStateHash */
1472 QHashIterator<QString, int> iter(m_directoryIconStateHash);
1473 while (iter.hasNext()) {
1475 if (mainWin->m_rtIconStateDebug) Pmsg2(000, "Beta Key %s value %i\n", iter.key().toUtf8().data(), iter.value());
1477 QString keyPath = iter.key();
1478 if (shouldBeIconStateHash.value(keyPath)) {
1479 if (mainWin->m_rtIconStateDebug) Pmsg1(000, "WAS found in shouldBeStateHash %s\n", keyPath.toUtf8().data());
1480 //newval = m_directoryIconStateHash.value(path, FolderUnchecked) & (~change);
1481 int newval = shouldBeIconStateHash.value(keyPath);
1483 newval = newval & FolderBothChecked;
1484 QTreeWidgetItem *item = m_dirPaths.value(keyPath);
1486 directorySetIcon(0, newval, keyPath, item);
1488 if (mainWin->m_rtIconStateDebug) Pmsg1(000, "NOT found in shouldBeStateHash %s\n", keyPath.toUtf8().data());
1489 QTreeWidgetItem *item = m_dirPaths.value(keyPath);
1491 directorySetIcon(0, FolderBothChecked, keyPath, item);
1492 //item->setIcon(0,QIcon(QString::fromUtf8(":images/folder.png")));
1493 //m_directoryIconStateHash.remove(keyPath);
1498 void restoreTree::directorySetIcon(int operation, int change, QString &path, QTreeWidgetItem* item) {
1500 /* we are adding a check type white or green */
1501 if (operation > 0) {
1502 /* get the old val and "bitwise OR" with the change */
1503 newval = m_directoryIconStateHash.value(path, FolderUnchecked) | change;
1504 if (mainWin->m_rtIconStateDebug) Pmsg2(000, "Inserting into m_directoryIconStateHash path=%s newval=%i\n", path.toUtf8().data(), newval);
1505 m_directoryIconStateHash.insert(path, newval);
1507 /* we are removing a check type white or green */
1508 newval = m_directoryIconStateHash.value(path, FolderUnchecked) & (~change);
1510 if (mainWin->m_rtIconStateDebug) Pmsg2(000, "Removing from m_directoryIconStateHash path=%s newval=%i\n", path.toUtf8().data(), newval);
1511 m_directoryIconStateHash.remove(path);
1514 if (mainWin->m_rtIconStateDebug) Pmsg2(000, "Inserting into m_directoryIconStateHash path=%s newval=%i\n", path.toUtf8().data(), newval);
1515 m_directoryIconStateHash.insert(path, newval);
1518 if (newval == FolderUnchecked)
1519 item->setIcon(0, QIcon(QString::fromUtf8(":images/folder.png")));
1520 else if (newval == FolderGreenChecked)
1521 item->setIcon(0, QIcon(QString::fromUtf8(":images/folderchecked.png")));
1522 else if (newval == FolderWhiteChecked)
1523 item->setIcon(0, QIcon(QString::fromUtf8(":images/folderunchecked.png")));
1524 else if (newval == FolderBothChecked)
1525 item->setIcon(0, QIcon(QString::fromUtf8(":images/folderbothchecked.png")));
1531 void restoreTree::restoreButtonPushed()
1533 /* Set progress bars and repaint */
1534 prLabel1->setVisible(true);
1535 prLabel1->setText(tr("Task 1 of 3"));
1536 prLabel2->setVisible(true);
1537 prLabel2->setText(tr("Processing Checked directories"));
1538 prBar1->setVisible(true);
1539 prBar1->setRange(0, 3);
1540 prBar1->setValue(0);
1541 prBar2->setVisible(true);
1542 prBar2->setRange(0, 0);
1544 QMultiHash<int, QString> versionFilesMulti;
1546 QHash <QString, bool> fullPathDone;
1547 QHash <QString, int> fileIndexHash;
1548 if ((mainWin->m_rtRestore1Debug) || (mainWin->m_rtRestore2Debug) || (mainWin->m_rtRestore3Debug))
1549 Pmsg0(000, "In restoreTree::restoreButtonPushed\n");
1550 /* Use a tree widget item iterator to count directories for the progress bar */
1551 QTreeWidgetItemIterator diterc(directoryTree, QTreeWidgetItemIterator::Checked);
1556 } /* while (*diterc) */
1557 prBar2->setRange(0, ditcount);
1558 prBar2->setValue(0);
1560 /* Use a tree widget item iterator filtering for Checked Items */
1561 QTreeWidgetItemIterator diter(directoryTree, QTreeWidgetItemIterator::Checked);
1563 QString directory = (*diter)->data(0, Qt::UserRole).toString();
1564 int pathid = m_directoryPathIdHash.value(directory, -1);
1566 if (mainWin->m_rtRestore1Debug)
1567 Pmsg1(000, "Directory Checked=\"%s\"\n", directory.toUtf8().data());
1568 /* With a checked directory, query for the files in the directory */
1571 "SELECT Filename.Name AS Filename, t1.JobId AS JobId, File.FileIndex AS FileIndex"
1573 " ( SELECT File.FilenameId AS FilenameId, MAX(Job.JobId) AS JobId"
1575 " INNER JOIN Job ON (Job.JobId=File.JobId)"
1576 " WHERE File.PathId=" + QString("%1").arg(pathid) +
1577 " AND Job.Jobid IN (" + m_checkedJobs + ")"
1578 " GROUP BY File.FilenameId"
1580 " INNER JOIN Filename on (Filename.FilenameId=File.FilenameId)"
1581 " INNER JOIN Job ON (Job.JobId=File.JobId)"
1582 " WHERE File.PathId=" + QString("%1").arg(pathid) +
1583 " AND File.FilenameId=t1.FilenameId"
1584 " AND Job.Jobid=t1.JobId"
1585 " ORDER BY Filename";
1587 if (mainWin->m_sqlDebug) Pmsg1(000, "Query cmd : %s\n", cmd.toUtf8().data());
1588 QStringList results;
1589 if (m_console->sql_cmd(cmd, results)) {
1590 QStringList fieldlist;
1593 /* Iterate through the record returned from the query */
1594 foreach (QString resultline, results) {
1595 /* Iterate through fields in the record */
1597 QString fullPath = "";
1598 Qt::CheckState fileExcpState = (Qt::CheckState)4;
1599 fieldlist = resultline.split("\t");
1602 foreach (QString field, fieldlist) {
1604 fullPath = directory + field;
1607 version = field.toInt();
1610 fileIndex = field.toInt();
1614 fileExcpState = m_fileExceptionHash.value(fullPath, (Qt::CheckState)3);
1616 int excpVersion = m_versionExceptionHash.value(fullPath, 0);
1617 if (fileExcpState != Qt::Unchecked) {
1619 if (excpVersion != 0) {
1620 debugtext = QString("*E* version=%1").arg(excpVersion);
1621 version = excpVersion;
1622 fileIndex = queryFileIndex(fullPath, excpVersion);
1624 debugtext = QString("___ version=%1").arg(version);
1625 if (mainWin->m_rtRestore1Debug)
1626 Pmsg2(000, "Restoring %s File %s\n", debugtext.toUtf8().data(), fullPath.toUtf8().data());
1627 fullPathDone.insert(fullPath, 1);
1628 fileIndexHash.insert(fullPath, fileIndex);
1629 versionFilesMulti.insert(version, fullPath);
1637 prBar2->setValue(ditcount);
1639 } /* while (*diter) */
1640 prBar1->setValue(1);
1641 prLabel1->setText( tr("Task 2 of 3"));
1642 prLabel2->setText(tr("Processing Exceptions"));
1643 prBar2->setRange(0, 0);
1646 /* There may be some exceptions not accounted for yet with fullPathDone */
1647 QHashIterator<QString, Qt::CheckState> ftera(m_fileExceptionHash);
1648 while (ftera.hasNext()) {
1650 QString fullPath = ftera.key();
1651 Qt::CheckState state = ftera.value();
1653 /* now we don't want the ones already done */
1654 if (fullPathDone.value(fullPath, 0) == 0) {
1655 int version = m_versionExceptionHash.value(fullPath, 0);
1657 QString debugtext = "";
1659 fileIndex = queryFileIndex(fullPath, version);
1660 debugtext = QString("E1* version=%1 fileid=%2").arg(version).arg(fileIndex);
1662 version = mostRecentVersionfromFullPath(fullPath);
1664 fileIndex = queryFileIndex(fullPath, version);
1665 debugtext = QString("E2* version=%1 fileid=%2").arg(version).arg(fileIndex);
1667 debugtext = QString("Error det vers").arg(version);
1669 if (mainWin->m_rtRestore1Debug)
1670 Pmsg2(000, "Restoring %s file %s\n", debugtext.toUtf8().data(), fullPath.toUtf8().data());
1671 versionFilesMulti.insert(version, fullPath);
1673 fileIndexHash.insert(fullPath, fileIndex);
1674 } /* if fullPathDone.value(fullPath, 0) == 0 */
1675 } /* if state != 0 */
1676 } /* while ftera.hasNext */
1677 /* The progress bars for the next step */
1678 prBar1->setValue(2);
1679 prLabel1->setText(tr("Task 3 of 3"));
1680 prLabel2->setText(tr("Filling Database Table"));
1681 prBar2->setRange(0, vFMCounter);
1683 prBar2->setValue(vFMCounter);
1686 /* now for the final spit out of the versions and lists of files for each version */
1687 QHash<int, int> doneKeys;
1688 QHashIterator<int, QString> vFMiter(versionFilesMulti);
1689 QString tempTable = "";
1691 while (vFMiter.hasNext()) {
1693 int fversion = vFMiter.key();
1694 /* did not succeed in getting an iterator to work as expected on versionFilesMulti so use doneKeys */
1695 if (doneKeys.value(fversion, 0) == 0) {
1696 if (tempTable == "") {
1697 QSettings settings("www.bacula.org", "bat");
1698 settings.beginGroup("Restore");
1699 int counter = settings.value("Counter", 1).toInt();
1700 settings.setValue("Counter", counter+1);
1701 settings.endGroup();
1702 tempTable = "restore_" + QString("%1").arg(qrand()) + "_" + QString("%1").arg(counter);
1703 QString sqlcmd = "CREATE TEMPORARY TABLE " + tempTable + " (JobId INTEGER, FileIndex INTEGER)";
1704 if (mainWin->m_sqlDebug)
1705 Pmsg1(000, "Query cmd : %s ;\n", sqlcmd.toUtf8().data());
1706 QStringList results;
1707 if (!m_console->sql_cmd(sqlcmd, results))
1708 Pmsg1(000, "CREATE TABLE FAILED!!!! %s\n", sqlcmd.toUtf8().data());
1711 if (mainWin->m_rtRestore2Debug) Pmsg1(000, "Version->%i\n", fversion);
1712 QStringList fullPathList = versionFilesMulti.values(fversion);
1713 /* create the command to perform the restore */
1714 foreach(QString ffullPath, fullPathList) {
1715 int fileIndex = fileIndexHash.value(ffullPath);
1716 if (mainWin->m_rtRestore2Debug) Pmsg2(000, " file->%s id %i\n", ffullPath.toUtf8().data(), fileIndex);
1717 QString sqlcmd = "INSERT INTO " + tempTable + " (JobId, FileIndex) VALUES (" + QString("%1").arg(fversion) + ", " + QString("%1").arg(fileIndex) + ")";
1718 if (mainWin->m_rtRestore3Debug)
1719 Pmsg1(000, "Insert cmd : %s\n", sqlcmd.toUtf8().data());
1720 QStringList results;
1721 if (!m_console->sql_cmd(sqlcmd, results))
1722 Pmsg1(000, "INSERT INTO FAILED!!!! %s\n", sqlcmd.toUtf8().data());
1723 prBar2->setValue(++vFMCounter);
1724 } /* foreach fullPathList */
1725 doneKeys.insert(fversion,1);
1726 jobList.append(fversion);
1727 } /* if (doneKeys.value(fversion, 0) == 0) */
1728 } /* while (vFMiter.hasNext()) */
1729 if (tempTable != "") {
1730 /* a table was made, lets run the job */
1731 QString jobOption = " jobid=\"";
1733 /* create a list of jobs comma separated */
1734 foreach (int job, jobList) {
1735 if (first) first = false;
1736 else jobOption += ",";
1737 jobOption += QString("%1").arg(job);
1740 QString cmd = QString("restore");
1742 " client=\"" + m_prevClientCombo + "\"" +
1743 " file=\"?" + tempTable + "\" done";
1744 if (mainWin->m_commandDebug)
1745 Pmsg1(000, "preRestore command \'%s\'\n", cmd.toUtf8().data());
1746 consoleCommand(cmd);
1748 /* turn off the progress widgets */
1749 prBar1->setVisible(false);
1750 prBar2->setVisible(false);
1751 prLabel1->setVisible(false);
1752 prLabel2->setVisible(false);
1755 int restoreTree::mostRecentVersionfromFullPath(QString &fullPath)
1758 QString directory, fileName;
1759 int index = fullPath.lastIndexOf("/", -2);
1761 directory = fileName = fullPath;
1762 directory.replace(index+1, fullPath.length()-index-1, "");
1763 fileName.replace(0, index+1, "");
1765 QString msg = QString("length = \"%1\" index = \"%2\" Considering \"%3\" \"%4\"\n")
1766 .arg(fullPath.length()).arg(index).arg(fileName).arg(directory);
1767 Pmsg0(000, msg.toUtf8().data());
1769 int pathid = m_directoryPathIdHash.value(directory, -1);
1771 /* so now we need the latest version from the database */
1773 "SELECT MAX(Job.JobId)"
1775 " INNER JOIN Filename on (Filename.FilenameId=File.FilenameId)"
1776 " INNER JOIN Job ON (File.JobId=Job.JobId)"
1777 " WHERE File.PathId=" + QString("%1").arg(pathid) +
1778 " AND Job.Jobid IN (" + m_checkedJobs + ")"
1779 " AND Filename.Name='" + fileName + "'"
1780 " AND File.FilenameId!=" + QString("%1").arg(m_nullFileNameId) +
1781 " GROUP BY Filename.Name";
1783 if (mainWin->m_sqlDebug) Pmsg1(000, "Query cmd : %s\n", cmd.toUtf8().data());
1784 QStringList results;
1785 if (m_console->sql_cmd(cmd, results)) {
1786 QStringList fieldlist;
1788 /* Iterate through the record returned from the query */
1789 foreach (QString resultline, results) {
1790 /* Iterate through fields in the record */
1792 fieldlist = resultline.split("\t");
1793 foreach (QString field, fieldlist) {
1795 qversion = field.toInt();
1803 } /* if (index != -1) */
1808 int restoreTree::queryFileIndex(QString &fullPath, int jobId)
1811 QString directory, fileName;
1812 int index = fullPath.lastIndexOf("/", -2);
1814 directory = fileName = fullPath;
1815 directory.replace(index+1, fullPath.length()-index-1, "");
1816 fileName.replace(0, index+1, "");
1818 QString msg = QString("length = \"%1\" index = \"%2\" Considering \"%3\" \"%4\"\n")
1819 .arg(fullPath.length()).arg(index).arg(fileName).arg(directory);
1820 Pmsg0(000, msg.toUtf8().data());
1822 int pathid = m_directoryPathIdHash.value(directory, -1);
1824 /* so now we need the latest version from the database */
1829 " INNER JOIN Filename on (Filename.FilenameId=File.FilenameId)"
1830 " INNER JOIN Job ON (File.JobId=Job.JobId)"
1831 " WHERE File.PathId=" + QString("%1").arg(pathid) +
1832 " AND Filename.Name='" + fileName + "'"
1833 " AND Job.Jobid='" + QString("%1").arg(jobId) + "'"
1834 " GROUP BY File.FileIndex";
1836 if (mainWin->m_sqlDebug) Pmsg1(000, "Query cmd : %s\n", cmd.toUtf8().data());
1837 QStringList results;
1838 if (m_console->sql_cmd(cmd, results)) {
1839 QStringList fieldlist;
1841 /* Iterate through the record returned from the query */
1842 foreach (QString resultline, results) {
1843 /* Iterate through fields in the record */
1845 fieldlist = resultline.split("\t");
1846 foreach (QString field, fieldlist) {
1848 qfileIndex = field.toInt();
1856 } /* if (index != -1) */
1861 void restoreTree::PgSeltreeWidgetClicked()
1863 if (!isOnceDocked()) {