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")));
57 QGridLayout *gridLayout = new QGridLayout(this);
58 gridLayout->setSpacing(6);
59 gridLayout->setMargin(9);
60 gridLayout->setObjectName(QString::fromUtf8("gridLayout"));
62 m_splitter = new QSplitter(Qt::Vertical, this);
63 QScrollArea *area = new QScrollArea();
64 area->setObjectName(QString::fromUtf8("area"));
65 area->setWidget(widget);
66 area->setWidgetResizable(true);
67 m_splitter->addWidget(splitter);
68 m_splitter->addWidget(area);
69 splitter->setCollapsible(0, false);
71 gridLayout->addWidget(m_splitter, 0, 0, 1, 1);
73 /* progress widgets */
74 prBar1->setVisible(false);
75 prBar2->setVisible(false);
76 prLabel1->setVisible(false);
77 prLabel2->setVisible(false);
79 /* Set Defaults for check and spin for limits */
80 limitCheckBox->setCheckState(mainWin->m_recordLimitCheck ? Qt::Checked : Qt::Unchecked);
81 limitSpinBox->setValue(mainWin->m_recordLimitVal);
82 daysCheckBox->setCheckState(mainWin->m_daysLimitCheck ? Qt::Checked : Qt::Unchecked);
83 daysSpinBox->setValue(mainWin->m_daysLimitVal);
85 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);
282 QMessageBox::warning(this, "Bat",
283 tr("No jobs were selected in the job query !!!.\n"
284 "Press OK to continue"),
287 prBar1->setVisible(false);
288 prBar2->setVisible(false);
289 prLabel1->setVisible(false);
290 prLabel2->setVisible(false);
294 * Function to set m_checkedJobs from the jobs that are checked in the table
297 void restoreTree::setJobsCheckedList()
299 m_JobsCheckedList = "";
301 /* Update the items in the version table */
302 int cnt = jobTable->rowCount();
303 for (int row=0; row<cnt; row++) {
304 QTableWidgetItem* jobItem = jobTable->item(row, 0);
305 if (jobItem->checkState() == Qt::Checked) {
307 m_JobsCheckedList += ",";
308 m_JobsCheckedList += jobItem->text();
310 jobItem->setBackground(Qt::green);
312 if (jobItem->flags())
313 jobItem->setBackground(Qt::gray);
315 jobItem->setBackground(Qt::darkYellow);
318 m_checkedJobs = m_JobsCheckedList;
322 * Function to parse a directory into all possible subdirectories, then add to
325 void restoreTree::parseDirectory(QString &dir_in)
327 /* m_debugTrap is to only print debugs for a few occurennces of calling parseDirectory
328 * instead of printing out what could potentially a whole bunch */
331 /* Truncate everything after the last / */
332 if (dir_in.right(1) != "/") {
333 dir_in.truncate(dir_in.lastIndexOf("/") + 1);
335 if ((mainWin->m_miscDebug) && (m_debugTrap))
336 Pmsg1(000, "parsing %s\n", dir_in.toUtf8().data());
338 /* split and add if not in yet */
339 QString direct, path;
342 QStringList pathAfter, dirAfter;
343 /* start from the end, turn /etc/somedir/subdir/ into /etc/somedir and subdir/
344 * if not added into tree, then try /etc/ and somedir/ if not added, then try
345 * / and etc/ . That should succeed, then add the ones that failed in reverse */
346 while (((index = dir_in.lastIndexOf("/", -2)) != -1) && (!done)) {
347 direct = path = dir_in;
348 path.replace(index+1, dir_in.length()-index-1,"");
349 direct.replace(0, index+1, "");
350 if ((mainWin->m_miscDebug) && (m_debugTrap)) {
351 QString msg = QString("length = \"%1\" index = \"%2\" Adding \"%3\" \"%4\"\n")
352 .arg(dir_in.length()).arg(index).arg(path).arg(direct);
353 Pmsg0(000, msg.toUtf8().data());
355 if (addDirectory(path, direct)) { done = true; }
357 if ((mainWin->m_miscDebug) && (m_debugTrap)) {
358 Pmsg0(000, "Saving for later\n");
360 pathAfter.prepend(path);
361 dirAfter.prepend(direct);
366 for (int k=0; k<pathAfter.count(); k++) {
367 if (addDirectory(pathAfter[k], dirAfter[k])) {
368 if ((mainWin->m_miscDebug) && (m_debugTrap))
369 Pmsg2(000, "Adding After %s %s\n", pathAfter[k].toUtf8().data(), dirAfter[k].toUtf8().data());
371 if ((mainWin->m_miscDebug) && (m_debugTrap))
372 Pmsg2(000, "Error Adding %s %s\n", pathAfter[k].toUtf8().data(), dirAfter[k].toUtf8().data());
379 * Function called from fill directory when a directory is found to see if this
380 * directory exists in the directory pane and then add it to the directory pane
382 bool restoreTree::addDirectory(QString &m_cwd, QString &newdirr)
384 QString newdir = newdirr;
385 QString fullPath = m_cwd + newdirr;
386 bool ok = true, added = false;
388 if ((mainWin->m_miscDebug) && (m_debugTrap)) {
389 QString msg = QString("In addDirectory cwd \"%1\" newdir \"%2\"\n")
392 Pmsg0(000, msg.toUtf8().data());
396 /* add unix '/' directory first */
397 if (m_dirPaths.empty() && !isWin32Path(fullPath)) {
399 QTreeWidgetItem *item = new QTreeWidgetItem(directoryTree);
401 item->setText(0, text.toUtf8().data());
402 item->setData(0, Qt::UserRole, QVariant(text));
403 item->setData(1, Qt::UserRole, QVariant(Qt::Unchecked));
404 item->setIcon(0, QIcon(QString::fromUtf8(":images/folder.png")));
405 if ((mainWin->m_miscDebug) && (m_debugTrap)) {
406 Pmsg1(000, "Pre Inserting %s\n", text.toUtf8().data());
408 m_dirPaths.insert(text, item);
410 /* no need to check for windows drive if unix */
411 if (isWin32Path(m_cwd)) {
412 if (!m_dirPaths.contains(m_cwd)) {
413 if (m_cwd.count('/') > 1) { return false; }
414 /* this is a windows drive add the base widget */
415 QTreeWidgetItem *item = new QTreeWidgetItem(directoryTree);
416 item->setText(0, m_cwd);
417 item->setData(0, Qt::UserRole, QVariant(fullPath));
418 item->setData(1, Qt::UserRole, QVariant(Qt::Unchecked));
419 item->setIcon(0, QIcon(QString::fromUtf8(":images/folder.png")));
420 if ((mainWin->m_miscDebug) && (m_debugTrap)) {
421 Pmsg0(000, "Added Base \"letter\":/\n");
423 m_dirPaths.insert(m_cwd, item);
428 /* is it already existent ?? */
429 if (!m_dirPaths.contains(fullPath)) {
430 QTreeWidgetItem *item = NULL;
431 QTreeWidgetItem *parent = m_dirPaths.value(m_cwd);
433 /* new directories to add */
434 item = new QTreeWidgetItem(parent);
435 item->setText(0, newdir.toUtf8().data());
436 item->setData(0, Qt::UserRole, QVariant(fullPath));
437 item->setCheckState(0, Qt::Unchecked);
438 /* Store the current state of the check status in column 1, which at
439 * this point has no text*/
440 item->setData(1, Qt::UserRole, QVariant(Qt::Unchecked));
443 if ((mainWin->m_miscDebug) && (m_debugTrap)) {
444 QString msg = QString("In else of if parent cwd \"%1\" newdir \"%2\"\n")
447 Pmsg0(000, msg.toUtf8().data());
450 /* insert into hash */
452 if ((mainWin->m_miscDebug) && (m_debugTrap)) {
453 Pmsg1(000, "Inserting %s\n", fullPath.toUtf8().data());
455 m_dirPaths.insert(fullPath, item);
463 * Virtual function which is called when this page is visible on the stack
465 void restoreTree::currentStackItem()
474 * Populate the tree when refresh button pushed.
476 void restoreTree::refreshButtonPushed()
478 populateDirectoryTree();
482 * Set the values of non-job combo boxes to the job defaults
484 void restoreTree::jobComboChanged(int)
486 if (jobCombo->currentText() == tr("Any")) {
487 fileSetCombo->setCurrentIndex(fileSetCombo->findText(tr("Any"), Qt::MatchExactly));
490 job_defaults job_defs;
493 job_defs.job_name = jobCombo->currentText();
494 if (m_console->get_job_defaults(job_defs)) {
495 fileSetCombo->setCurrentIndex(fileSetCombo->findText(job_defs.fileset_name, Qt::MatchExactly));
496 clientCombo->setCurrentIndex(clientCombo->findText(job_defs.client_name, Qt::MatchExactly));
501 * Function to populate the file list table
503 void restoreTree::directoryCurrentItemChanged(QTreeWidgetItem *item, QTreeWidgetItem *)
509 /* Also clear the version table here */
510 versionTable->clear();
511 versionFileLabel->setText("");
512 versionTable->setRowCount(0);
513 versionTable->setColumnCount(0);
515 QStringList headerlist = (QStringList() << tr("File Name") << tr("Filename Id"));
516 fileTable->setColumnCount(headerlist.size());
517 fileTable->setHorizontalHeaderLabels(headerlist);
518 fileTable->setRowCount(0);
520 m_fileCheckStateList.clear();
521 disconnect(fileTable, SIGNAL(itemChanged(QTableWidgetItem *)),
522 this, SLOT(fileTableItemChanged(QTableWidgetItem *)));
523 QBrush blackBrush(Qt::black);
524 QString directory = item->data(0, Qt::UserRole).toString();
525 directoryLabel->setText(tr("Present Working Directory: %1").arg(directory));
526 int pathid = m_directoryPathIdHash.value(directory, -1);
529 "SELECT DISTINCT Filename.Name AS FileName, Filename.FilenameId AS FilenameId"
531 " INNER JOIN Filename on (Filename.FilenameId=File.FilenameId)"
532 " WHERE File.PathId=" + QString("%1").arg(pathid) +
533 " AND File.Jobid IN (" + m_checkedJobs + ")"
534 " AND Filename.Name!=''"
535 " ORDER BY FileName";
537 if (mainWin->m_sqlDebug) {
538 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 */
563 Qt::ItemFlags flag = Qt::ItemIsUserCheckable | Qt::ItemIsEnabled | Qt::ItemIsTristate;
564 tableItem->setFlags(flag);
565 tableItem->setData(Qt::UserRole, QVariant(directory));
566 fileTable->setItem(row, column, tableItem);
567 m_fileCheckStateList.append(Qt::Unchecked);
568 tableItem->setCheckState(Qt::Unchecked);
569 } else if (column == 1) {
570 Qt::ItemFlags flag = Qt::ItemIsEnabled;
571 tableItem->setFlags(flag);
573 int filenameid = field.toInt(&ok, 10);
574 if (!ok) filenameid = -1;
575 tableItem->setData(Qt::UserRole, QVariant(filenameid));
576 fileTable->setItem(row, column, tableItem);
582 fileTable->setRowCount(row);
584 fileTable->resizeColumnsToContents();
585 fileTable->resizeRowsToContents();
586 fileTable->verticalHeader()->hide();
587 fileTable->hideColumn(1);
588 if (mainWin->m_rtDirCurICDebug) Pmsg0(000, "will update file table checks\n");
589 updateFileTableChecks();
590 } else if (mainWin->m_sqlDebug)
591 Pmsg1(000, "did not perform query, pathid=%i not found\n", pathid);
592 connect(fileTable, SIGNAL(itemChanged(QTableWidgetItem *)),
593 this, SLOT(fileTableItemChanged(QTableWidgetItem *)));
597 * Function to populate the version table
599 void restoreTree::fileCurrentItemChanged(QTableWidgetItem *currentFileTableItem, QTableWidgetItem *)
601 if (currentFileTableItem == NULL)
604 int currentRow = fileTable->row(currentFileTableItem);
605 QTableWidgetItem *fileTableItem = fileTable->item(currentRow, 0);
606 QTableWidgetItem *fileNameIdTableItem = fileTable->item(currentRow, 1);
607 int fileNameId = fileNameIdTableItem->data(Qt::UserRole).toInt();
609 m_versionCheckStateList.clear();
610 disconnect(versionTable, SIGNAL(itemChanged(QTableWidgetItem *)),
611 this, SLOT(versionTableItemChanged(QTableWidgetItem *)));
613 QString file = fileTableItem->text();
614 versionFileLabel->setText(file);
615 QString directory = fileTableItem->data(Qt::UserRole).toString();
617 QBrush blackBrush(Qt::black);
619 QStringList headerlist = (QStringList()
620 << tr("Job Id") << tr("Type") << tr("End Time") << tr("Hash") << tr("FileId") << tr("Job Type") << tr("First Volume"));
621 versionTable->clear();
622 versionTable->setColumnCount(headerlist.size());
623 versionTable->setHorizontalHeaderLabels(headerlist);
624 versionTable->setRowCount(0);
626 int pathid = m_directoryPathIdHash.value(directory, -1);
627 if ((pathid != -1) && (fileNameId != -1)) {
629 "SELECT Job.JobId AS JobId, Job.Level AS Type,"
630 " Job.EndTime AS EndTime, File.MD5 AS MD5,"
631 " File.FileId AS FileId, Job.Type AS JobType,"
632 " (SELECT Media.VolumeName FROM JobMedia JOIN Media ON JobMedia.MediaId=Media.MediaId WHERE JobMedia.JobId=Job.JobId ORDER BY JobMediaId LIMIT 1) AS FirstVolume"
634 " INNER JOIN Filename on (Filename.FilenameId=File.FilenameId)"
635 " INNER JOIN Path ON (Path.PathId=File.PathId)"
636 " INNER JOIN Job ON (File.JobId=Job.JobId)"
637 " WHERE Path.PathId=" + QString("%1").arg(pathid) +
638 //" AND Filename.Name='" + file + "'"
639 " AND Filename.FilenameId=" + QString("%1").arg(fileNameId) +
640 " AND Job.Jobid IN (" + m_checkedJobs + ")"
641 " ORDER BY Job.EndTime DESC";
643 if (mainWin->m_sqlDebug)
644 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);
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_2";
718 m_splitText2 = "splitterSizes2_2";
719 QSettings settings(m_console->m_dir->name(), "bat");
720 settings.beginGroup(m_groupText);
721 m_splitter->restoreState(settings.value(m_splitText1).toByteArray());
722 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);
824 int purged = fieldlist[purgedIndex].toInt(&ok, 10);
825 if (!((ok) && (purged == 1))) {
826 Qt::ItemFlags flag = Qt::ItemIsUserCheckable | Qt::ItemIsEnabled | Qt::ItemIsTristate;
827 tableItem->setFlags(flag);
828 tableItem->setCheckState(Qt::Checked);
829 tableItem->setBackground(Qt::green);
831 tableItem->setFlags(0);
832 tableItem->setCheckState(Qt::Unchecked);
838 tableItem = new QTableWidgetItem(QIcon(QString::fromUtf8(":images/go-up.png")), "", 1);
839 tableItem->setFlags(0);
840 tableItem->setForeground(blackBrush);
841 jobTable->setItem(row, column, tableItem);
843 tableItem = new QTableWidgetItem(QIcon(QString::fromUtf8(":images/go-down.png")), "", 1);
844 tableItem->setFlags(0);
845 tableItem->setForeground(blackBrush);
846 jobTable->setItem(row, column, tableItem);
851 jobTable->resizeColumnsToContents();
852 jobTable->resizeRowsToContents();
853 jobTable->verticalHeader()->hide();
854 jobTable->hideColumn(purgedIndex);
857 void restoreTree::jobTableCellClicked(int row, int column)
859 if (column == m_toggleUpIndex){
861 for (cnt=0; cnt<row+1; cnt++) {
862 QTableWidgetItem *item = jobTable->item(cnt, 0);
864 Qt::CheckState state = item->checkState();
865 if (state == Qt::Checked)
866 item->setCheckState(Qt::Unchecked);
867 else if (state == Qt::Unchecked)
868 item->setCheckState(Qt::Checked);
872 if (column == m_toggleDownIndex){
873 int cnt, max = jobTable->rowCount();
874 for (cnt=row; cnt<max; cnt++) {
875 QTableWidgetItem *item = jobTable->item(cnt, 0);
877 Qt::CheckState state = item->checkState();
878 if (state == Qt::Checked)
879 item->setCheckState(Qt::Unchecked);
880 else if (state == Qt::Unchecked)
881 item->setCheckState(Qt::Checked);
888 * When a directory item is "changed" check the state of the checkable item
889 * to see if it is different than what it was which is stored in Qt::UserRole
890 * of the 2nd column, column 1, of the tree widget.
892 void restoreTree::directoryItemChanged(QTreeWidgetItem *item, int /*column*/)
894 Qt::CheckState prevState = (Qt::CheckState)item->data(1, Qt::UserRole).toInt();
895 Qt::CheckState curState = item->checkState(0);
896 QTreeWidgetItem* parent = item->parent();
897 Qt::CheckState parState;
898 if (parent) parState = parent->checkState(0);
899 else parState = (Qt::CheckState)3;
900 if (mainWin->m_rtDirICDebug) {
901 QString msg = QString("directory item OBJECT has changed prev=%1 cur=%2 par=%3 dir=%4\n")
902 .arg(prevState).arg(curState).arg(parState).arg(item->text(0));
903 Pmsg1(000, "%s", msg.toUtf8().data()); }
904 /* I only care when the check state changes */
905 if (prevState == curState) {
906 if (mainWin->m_rtDirICDebug) Pmsg0(000, "Returning Early\n");
910 if ((prevState == Qt::Unchecked) && (curState == Qt::Checked) && (parState != Qt::Unchecked)) {
911 if (mainWin->m_rtDirICDebug) Pmsg0(000, "Disconnected Setting to Qt::PartiallyChecked\n");
912 directoryTreeDisconnectedSet(item, Qt::PartiallyChecked);
913 curState = Qt::PartiallyChecked;
915 if ((prevState == Qt::PartiallyChecked) && (curState == Qt::Checked)) {
916 if (mainWin->m_rtDirICDebug) Pmsg0(000, "Disconnected Setting to Qt::Unchecked\n");
917 directoryTreeDisconnectedSet(item, Qt::Unchecked);
918 curState = Qt::Unchecked;
920 if (mainWin->m_rtDirICDebug) {
921 QString msg = QString("directory item CHECKSTATE has changed prev=%1 cur=%2 par=%3 dir=%4\n")
922 .arg(prevState).arg(curState).arg(parState).arg(item->text(0));
923 Pmsg1(000, "%s", msg.toUtf8().data()); }
925 item->setData(1, Qt::UserRole, QVariant(curState));
926 Qt::CheckState childState = curState;
927 if (childState == Qt::Checked)
928 childState = Qt::PartiallyChecked;
929 setCheckofChildren(item, childState);
931 /* Remove items from the exception lists. The multi exception list is my index
932 * of what exceptions can be removed when the directory is known*/
933 QString directory = item->data(0, Qt::UserRole).toString();
934 QStringList fullPathList = m_fileExceptionMulti.values(directory);
935 int fullPathListCount = fullPathList.count();
936 if ((mainWin->m_rtDirICDebug) && fullPathListCount) Pmsg2(000, "Will attempt to remove file exceptions for %s count %i\n", directory.toUtf8().data(), fullPathListCount);
937 foreach (QString fullPath, fullPathList) {
938 /* If there is no value in the hash for the key fullPath a value of 3 will be returned
939 * which will match no Qt::xxx values */
940 Qt::CheckState hashState = m_fileExceptionHash.value(fullPath, (Qt::CheckState)3);
941 if (mainWin->m_rtDirICDebug) Pmsg2(000, "hashState=%i childState=%i\n", hashState, childState);
942 if (hashState == Qt::Unchecked) {
943 fileExceptionRemove(fullPath, directory);
944 m_versionExceptionHash.remove(fullPath);
945 if (mainWin->m_rtDirICDebug) Pmsg0(000, "Attempted Removal A\n");
947 if (hashState == Qt::Checked) {
948 fileExceptionRemove(fullPath, directory);
949 m_versionExceptionHash.remove(fullPath);
950 if (mainWin->m_rtDirICDebug) Pmsg0(000, "Attempted Removal B\n");
954 if (item == directoryTree->currentItem()) {
955 if (mainWin->m_rtDirICDebug) Pmsg0(000, "Will attempt to update File Table Checks\n");
956 updateFileTableChecks();
957 versionTable->clear();
958 versionTable->setRowCount(0);
959 versionTable->setColumnCount(0);
961 if (mainWin->m_rtDirICDebug) Pmsg0(000, "Returning At End\n");
965 * When a directory item check state is changed, this function iterates through
966 * all subdirectories and sets all to the passed state, which is either partially
967 * checked or unchecked.
969 void restoreTree::setCheckofChildren(QTreeWidgetItem *item, Qt::CheckState state)
972 childCount = item->childCount();
973 for (int i=0; i<childCount; i++) {
974 QTreeWidgetItem *child = item->child(i);
975 child->setData(1, Qt::UserRole, QVariant(state));
976 child->setCheckState(0, state);
977 setCheckofChildren(child, state);
982 * When a File Table Item is "changed" check to see if the state of the checkable
983 * item has changed which is stored in m_fileCheckStateList
984 * If changed store in a hash m_fileExceptionHash that whether this file should be
986 * Called as a slot, connected after populated (after directory current changed called)
988 void restoreTree::fileTableItemChanged(QTableWidgetItem *item)
990 /* get the previous and current check states */
991 int row = fileTable->row(item);
992 Qt::CheckState prevState;
993 /* prevent a segfault */
994 prevState = m_fileCheckStateList[row];
995 Qt::CheckState curState = item->checkState();
997 /* deterimine the default state from the state of the directory */
998 QTreeWidgetItem *dirTreeItem = directoryTree->currentItem();
999 Qt::CheckState dirState = (Qt::CheckState)dirTreeItem->data(1, Qt::UserRole).toInt();
1000 Qt::CheckState defState = Qt::PartiallyChecked;
1001 if (dirState == Qt::Unchecked) defState = Qt::Unchecked;
1003 /* determine if it is already in the m_fileExceptionHash */
1004 QString directory = directoryTree->currentItem()->data(0, Qt::UserRole).toString();
1005 QString file = item->text();
1006 QString fullPath = directory + file;
1007 Qt::CheckState hashState = m_fileExceptionHash.value(fullPath, (Qt::CheckState)3);
1008 int verJobNum = m_versionExceptionHash.value(fullPath, 0);
1010 if (mainWin->m_rtFileTabICDebug) {
1011 QString msg = QString("filerow=%1 prev=%2 cur=%3 def=%4 hash=%5 dir=%6 verJobNum=%7\n")
1012 .arg(row).arg(prevState).arg(curState).arg(defState).arg(hashState).arg(dirState).arg(verJobNum);
1013 Pmsg1(000, "%s", msg.toUtf8().data()); }
1015 /* Remove the hash if currently checked previously unchecked and directory is checked or partial */
1016 if ((prevState == Qt::Checked) && (curState == Qt::Unchecked) && (dirState == Qt::Unchecked)) {
1017 /* it can behave as defaulted so current of unchecked is fine */
1018 if (mainWin->m_rtFileTabICDebug) Pmsg0(000, "Will fileExceptionRemove and m_versionExceptionHash.remove here\n");
1019 fileExceptionRemove(fullPath, directory);
1020 m_versionExceptionHash.remove(fullPath);
1021 } else if ((prevState == Qt::PartiallyChecked) && (curState == Qt::Checked) && (dirState != Qt::Unchecked) && (verJobNum == 0)) {
1022 if (mainWin->m_rtFileTabICDebug) Pmsg0(000, "Will fileExceptionInsert here\n");
1023 fileExceptionInsert(fullPath, directory, Qt::Unchecked);
1024 } else if ((prevState == Qt::Unchecked) && (curState == Qt::Checked) && (dirState != Qt::Unchecked) && (verJobNum == 0) && (defState == Qt::PartiallyChecked)) {
1025 /* filerow=2 prev=0 cur=2 def=1 hash=0 dir=2 verJobNum=0 */
1026 if (mainWin->m_rtFileTabICDebug) Pmsg0(000, "Will fileExceptionRemove here\n");
1027 fileExceptionRemove(fullPath, directory);
1028 } else if ((prevState == Qt::Checked) && (curState == Qt::Unchecked) && (defState == Qt::PartiallyChecked) && (verJobNum != 0) && (hashState == Qt::Checked)) {
1029 /* Check dir, check version, attempt uncheck in file
1030 * filerow=4 prev=2 cur=0 def=1 hash=2 dir=2 verJobNum=53 */
1031 if (mainWin->m_rtFileTabICDebug) Pmsg0(000, "Will fileExceptionRemove and m_versionExceptionHash.remove here\n");
1032 fileExceptionRemove(fullPath, directory);
1033 m_versionExceptionHash.remove(fullPath);
1034 } else if ((prevState == Qt::Unchecked) && (curState == Qt::Checked) && (dirState != Qt::Unchecked) && (verJobNum == 0)) {
1035 /* filerow=0 prev=0 cur=2 def=1 hash=0 dirState=2 verJobNum */
1036 if (mainWin->m_rtFileTabICDebug) Pmsg0(000, "Will Not remove here\n");
1037 } else if (prevState != curState) {
1038 if (mainWin->m_rtFileTabICDebug) Pmsg2(000, " THE STATE OF THE Check has changed, Setting StateList[%i] to %i\n", row, curState);
1039 /* A user did not set the check state to Partially checked, ignore if so */
1040 if (curState != Qt::PartiallyChecked) {
1041 if ((defState == Qt::Unchecked) && (prevState == Qt::PartiallyChecked) && (curState == Qt::Unchecked)) {
1042 if (mainWin->m_rtFileTabICDebug) Pmsg0(000, " got here\n");
1044 if (mainWin->m_rtFileTabICDebug) Pmsg2(000, " Inserting into m_fileExceptionHash %s, %i\n", fullPath.toUtf8().data(), curState);
1045 fileExceptionInsert(fullPath, directory, curState);
1048 if (mainWin->m_rtFileTabICDebug) Pmsg1(000, "Removing version hash for %s\n", fullPath.toUtf8().data());
1049 /* programattically been changed back to a default state of Qt::PartiallyChecked remove the version hash here */
1050 m_versionExceptionHash.remove(fullPath);
1054 updateFileTableChecks();
1055 updateVersionTableChecks();
1059 * function to insert keys and values to both m_fileExceptionHash and m_fileExceptionMulti
1061 void restoreTree::fileExceptionInsert(QString &fullPath, QString &direcotry, Qt::CheckState state)
1063 m_fileExceptionHash.insert(fullPath, state);
1064 m_fileExceptionMulti.insert(direcotry, fullPath);
1065 directoryIconStateInsert(fullPath, state);
1069 * function to remove keys from both m_fileExceptionHash and m_fileExceptionMulti
1071 void restoreTree::fileExceptionRemove(QString &fullPath, QString &directory)
1073 m_fileExceptionHash.remove(fullPath);
1074 /* pull the list of values in the multi */
1075 QStringList fullPathList = m_fileExceptionMulti.values(directory);
1076 /* get the index of the fullpath to remove */
1077 int index = fullPathList.indexOf(fullPath);
1079 /* remove the desired item in the list */
1080 fullPathList.removeAt(index);
1081 /* remove the entire list from the multi */
1082 m_fileExceptionMulti.remove(directory);
1083 /* readd the remaining */
1084 foreach (QString fp, fullPathList) {
1085 m_fileExceptionMulti.insert(directory, fp);
1088 directoryIconStateRemove();
1092 * Overloaded function to be called from the slot and from other places to set the state
1093 * of the check marks in the version table
1095 void restoreTree::versionTableItemChanged(QTableWidgetItem *item)
1097 /* get the previous and current check states */
1098 int row = versionTable->row(item);
1099 QTableWidgetItem *colZeroItem = versionTable->item(row, 0);
1100 Qt::CheckState prevState = m_versionCheckStateList[row];
1101 Qt::CheckState curState = (Qt::CheckState)colZeroItem->checkState();
1102 m_versionCheckStateList[row] = curState;
1104 /* deterimine the default state from the state of the file */
1105 QTableWidgetItem *fileTableItem = fileTable->currentItem();
1106 Qt::CheckState fileState = (Qt::CheckState)fileTableItem->checkState();
1108 /* determine the default state */
1109 Qt::CheckState defState;
1111 defState = Qt::PartiallyChecked;
1112 if (fileState == Qt::Unchecked)
1113 defState = Qt::Unchecked;
1116 defState = Qt::Unchecked;
1118 /* determine if it is already in the versionExceptionHash */
1119 QString directory = directoryTree->currentItem()->data(0, Qt::UserRole).toString();
1120 Qt::CheckState dirState = directoryTree->currentItem()->checkState(0);
1121 QString file = fileTableItem->text();
1122 QString fullPath = directory + file;
1123 int thisJobNum = colZeroItem->text().toInt();
1124 int hashJobNum = m_versionExceptionHash.value(fullPath, 0);
1126 if (mainWin->m_rtVerTabICDebug) {
1127 QString msg = QString("versrow=%1 prev=%2 cur=%3 def=%4 dir=%5 hashJobNum=%6 thisJobNum=%7 filestate=%8 fec=%9 vec=%10\n")
1128 .arg(row).arg(prevState).arg(curState).arg(defState).arg(dirState).arg(hashJobNum).arg(thisJobNum).arg(fileState)
1129 .arg(m_fileExceptionHash.count()).arg(m_versionExceptionHash.count());
1130 Pmsg1(000, "%s", msg.toUtf8().data()); }
1131 /* if changed from partially checked to checked, make it unchecked */
1132 if ((curState == Qt::Checked) && (row == 0) && (fileState == Qt::Unchecked)) {
1133 if (mainWin->m_rtVerTabICDebug) Pmsg0(000, "Setting to Qt::Checked\n");
1134 fileTableItem->setCheckState(Qt::Checked);
1135 } else if ((prevState == Qt::PartiallyChecked) && (curState == Qt::Checked) && (row == 0) && (fileState == Qt::Checked) && (dirState == Qt::Unchecked)) {
1136 //versrow=0 prev=1 cur=2 def=1 dir=0 hashJobNum=0 thisJobNum=64 filestate=2 fec=1 vec=0
1137 if (mainWin->m_rtVerTabICDebug) Pmsg1(000, "fileExceptionRemove %s, %i\n", fullPath.toUtf8().data());
1138 fileExceptionRemove(fullPath, directory);
1139 } else if ((curState == Qt::Checked) && (row == 0) && (hashJobNum != 0) && (dirState != Qt::Unchecked)) {
1140 //versrow=0 prev=0 cur=2 def=1 dir=2 hashJobNum=53 thisJobNum=64 filestate=2 fec=1 vec=1
1141 if (mainWin->m_rtVerTabICDebug) Pmsg1(000, "m_versionExceptionHash.remove %s\n", fullPath.toUtf8().data());
1142 m_versionExceptionHash.remove(fullPath);
1143 fileExceptionRemove(fullPath, directory);
1144 } else if ((curState == Qt::Checked) && (row == 0)) {
1145 if (mainWin->m_rtVerTabICDebug) Pmsg1(000, "m_versionExceptionHash.remove %s\n", fullPath.toUtf8().data());
1146 m_versionExceptionHash.remove(fullPath);
1147 } else if (prevState != curState) {
1148 if (mainWin->m_rtVerTabICDebug) Pmsg2(000, " THE STATE OF THE version Check has changed, Setting StateList[%i] to %i\n", row, curState);
1149 if ((curState == Qt::Checked) || (curState == Qt::PartiallyChecked && row != 0)) {
1150 if (mainWin->m_rtVerTabICDebug) Pmsg2(000, "Inserting into m_versionExceptionHash %s, %i\n", fullPath.toUtf8().data(), thisJobNum);
1151 m_versionExceptionHash.insert(fullPath, thisJobNum);
1152 if (fileState != Qt::Checked) {
1153 if (mainWin->m_rtVerTabICDebug) Pmsg2(000, "Inserting into m_fileExceptionHash %s, %i\n", fullPath.toUtf8().data(), curState);
1154 fileExceptionInsert(fullPath, directory, curState);
1157 if (mainWin->m_rtVerTabICDebug) Pmsg0(000, "got here\n");
1160 if (mainWin->m_rtVerTabICDebug) Pmsg0(000, "no conditions met\n");
1163 updateFileTableChecks();
1164 updateVersionTableChecks();
1168 * Simple function to set the check state in the file table by disconnecting the
1169 * signal/slot the setting then reconnecting the signal/slot
1171 void restoreTree::fileTableDisconnectedSet(QTableWidgetItem *item, Qt::CheckState state, bool color)
1173 disconnect(fileTable, SIGNAL(itemChanged(QTableWidgetItem *)),
1174 this, SLOT(fileTableItemChanged(QTableWidgetItem *)));
1175 item->setCheckState(state);
1176 if (color) item->setBackground(Qt::yellow);
1177 else item->setBackground(Qt::white);
1178 connect(fileTable, SIGNAL(itemChanged(QTableWidgetItem *)),
1179 this, SLOT(fileTableItemChanged(QTableWidgetItem *)));
1183 * Simple function to set the check state in the version table by disconnecting the
1184 * signal/slot the setting then reconnecting the signal/slot
1186 void restoreTree::versionTableDisconnectedSet(QTableWidgetItem *item, Qt::CheckState state)
1188 disconnect(versionTable, SIGNAL(itemChanged(QTableWidgetItem *)),
1189 this, SLOT(versionTableItemChanged(QTableWidgetItem *)));
1190 item->setCheckState(state);
1191 connect(versionTable, SIGNAL(itemChanged(QTableWidgetItem *)),
1192 this, SLOT(versionTableItemChanged(QTableWidgetItem *)));
1196 * Simple function to set the check state in the directory tree by disconnecting the
1197 * signal/slot the setting then reconnecting the signal/slot
1199 void restoreTree::directoryTreeDisconnectedSet(QTreeWidgetItem *item, Qt::CheckState state)
1201 disconnect(directoryTree, SIGNAL(itemChanged(QTreeWidgetItem *, int)),
1202 this, SLOT(directoryItemChanged(QTreeWidgetItem *, int)));
1203 item->setCheckState(0, state);
1204 connect(directoryTree, SIGNAL(itemChanged(QTreeWidgetItem *, int)),
1205 this, SLOT(directoryItemChanged(QTreeWidgetItem *, int)));
1209 * Simplify the updating of the check state in the File table by iterating through
1210 * each item in the file table to determine it's appropriate state.
1211 * !! Will probably want to concoct a way to do this without iterating for the possibility
1212 * of the very large directories.
1214 void restoreTree::updateFileTableChecks()
1216 /* deterimine the default state from the state of the directory */
1217 QTreeWidgetItem *dirTreeItem = directoryTree->currentItem();
1218 Qt::CheckState dirState = dirTreeItem->checkState(0);
1220 QString dirName = dirTreeItem->data(0, Qt::UserRole).toString();
1222 /* Update the items in the version table */
1223 int rcnt = fileTable->rowCount();
1224 for (int row=0; row<rcnt; row++) {
1225 QTableWidgetItem* item = fileTable->item(row, 0);
1226 if (!item) { return; }
1228 Qt::CheckState curState = item->checkState();
1229 Qt::CheckState newState = Qt::PartiallyChecked;
1230 if (dirState == Qt::Unchecked) newState = Qt::Unchecked;
1232 /* determine if it is already in the m_fileExceptionHash */
1233 QString file = item->text();
1234 QString fullPath = dirName + file;
1235 Qt::CheckState hashState = m_fileExceptionHash.value(fullPath, (Qt::CheckState)3);
1236 int hashJobNum = m_versionExceptionHash.value(fullPath, 0);
1238 if (hashState != 3) newState = hashState;
1240 if (mainWin->m_rtUpdateFTDebug) {
1241 QString msg = QString("file row=%1 cur=%2 hash=%3 new=%4 dirState=%5\n")
1242 .arg(row).arg(curState).arg(hashState).arg(newState).arg(dirState);
1243 Pmsg1(000, "%s", msg.toUtf8().data());
1246 bool docolor = false;
1247 if (hashJobNum != 0) docolor = true;
1248 bool isyellow = item->background().color() == QColor(Qt::yellow);
1249 if ((newState != curState) || (hashState == 3) || ((isyellow && !docolor) || (!isyellow && docolor)))
1250 fileTableDisconnectedSet(item, newState, docolor);
1251 m_fileCheckStateList[row] = newState;
1256 * Simplify the updating of the check state in the Version table by iterating through
1257 * each item in the file table to determine it's appropriate state.
1259 void restoreTree::updateVersionTableChecks()
1261 /* deterimine the default state from the state of the directory */
1262 QTreeWidgetItem *dirTreeItem = directoryTree->currentItem();
1263 Qt::CheckState dirState = dirTreeItem->checkState(0);
1264 QString dirName = dirTreeItem->data(0, Qt::UserRole).toString();
1266 /* deterimine the default state from the state of the file */
1267 QTableWidgetItem *fileTableItem = fileTable->item(fileTable->currentRow(), 0);
1268 if (!fileTableItem) { return; }
1269 Qt::CheckState fileState = fileTableItem->checkState();
1270 QString file = fileTableItem->text();
1271 QString fullPath = dirName + file;
1272 int hashJobNum = m_versionExceptionHash.value(fullPath, 0);
1274 /* Update the items in the version table */
1275 int cnt = versionTable->rowCount();
1276 for (int row=0; row<cnt; row++) {
1277 QTableWidgetItem* item = versionTable->item(row, 0);
1278 if (!item) { break; }
1280 Qt::CheckState curState = item->checkState();
1281 Qt::CheckState newState = Qt::Unchecked;
1283 if ((row == 0) && (fileState != Qt::Unchecked) && (hashJobNum == 0))
1284 newState = Qt::PartiallyChecked;
1285 /* determine if it is already in the versionExceptionHash */
1287 int thisJobNum = item->text().toInt();
1288 if (thisJobNum == hashJobNum)
1289 newState = Qt::Checked;
1291 if (mainWin->m_rtChecksDebug) {
1292 QString msg = QString("ver row=%1 cur=%2 hashJobNum=%3 new=%4 dirState=%5\n")
1293 .arg(row).arg(curState).arg(hashJobNum).arg(newState).arg(dirState);
1294 Pmsg1(000, "%s", msg.toUtf8().data());
1296 if (newState != curState)
1297 versionTableDisconnectedSet(item, newState);
1298 m_versionCheckStateList[row] = newState;
1303 * Quick subroutine to "return via subPaths" a list of subpaths when passed a fullPath
1305 void restoreTree::fullPathtoSubPaths(QStringList &subPaths, QString &fullPath_in)
1309 QString fullPath = fullPath_in;
1310 QString direct, path;
1311 while (((index = fullPath.lastIndexOf("/", -2)) != -1) && (!done)) {
1312 direct = path = fullPath;
1313 path.replace(index+1, fullPath.length()-index-1, "");
1314 direct.replace(0, index+1, "");
1316 QString msg = QString("length = \"%1\" index = \"%2\" Considering \"%3\" \"%4\"\n")
1317 .arg(fullPath.length()).arg(index).arg(path).arg(direct);
1318 Pmsg0(000, msg.toUtf8().data());
1321 subPaths.append(fullPath);
1326 * A Function to set the icon state and insert a record into
1327 * m_directoryIconStateHash when an exception is added by the user
1329 void restoreTree::directoryIconStateInsert(QString &fullPath, Qt::CheckState excpState)
1332 fullPathtoSubPaths(paths, fullPath);
1333 /* an exception that causes the item in the file table to be "Checked" has occured */
1334 if (excpState == Qt::Checked) {
1335 bool foundAsUnChecked = false;
1336 QTreeWidgetItem *firstItem = m_dirPaths.value(paths[0]);
1338 if (firstItem->checkState(0) == Qt::Unchecked)
1339 foundAsUnChecked = true;
1341 if (foundAsUnChecked) {
1342 /* as long as directory item is Unchecked, set icon state to "green check" */
1344 QListIterator<QString> siter(paths);
1345 while (siter.hasNext() && !done) {
1346 QString path = siter.next();
1347 QTreeWidgetItem *item = m_dirPaths.value(path);
1349 if (item->checkState(0) != Qt::Unchecked)
1352 directorySetIcon(1, FolderGreenChecked, path, item);
1353 if (mainWin->m_rtIconStateDebug) Pmsg1(000, "In restoreTree::directoryIconStateInsert inserting %s\n", path.toUtf8().data());
1358 /* if it is partially checked or fully checked insert green Check until a unchecked is found in the path */
1359 if (mainWin->m_rtIconStateDebug) Pmsg1(000, "In restoreTree::directoryIconStateInsert Aqua %s\n", paths[0].toUtf8().data());
1361 QListIterator<QString> siter(paths);
1362 while (siter.hasNext() && !done) {
1363 QString path = siter.next();
1364 QTreeWidgetItem *item = m_dirPaths.value(path);
1365 if (item) { /* if the directory item is checked, set icon state to unchecked "green check" */
1366 if (item->checkState(0) == Qt::Checked)
1368 directorySetIcon(1, FolderGreenChecked, path, item);
1369 if (mainWin->m_rtIconStateDebug) Pmsg1(000, "In restoreTree::directoryIconStateInsert boogie %s\n", path.toUtf8().data());
1374 /* an exception that causes the item in the file table to be "Unchecked" has occured */
1375 if (excpState == Qt::Unchecked) {
1377 QListIterator<QString> siter(paths);
1378 while (siter.hasNext() && !done) {
1379 QString path = siter.next();
1380 QTreeWidgetItem *item = m_dirPaths.value(path);
1381 if (item) { /* if the directory item is checked, set icon state to unchecked "white check" */
1382 if (item->checkState(0) == Qt::Checked)
1384 directorySetIcon(1, FolderWhiteChecked, path, item);
1385 if (mainWin->m_rtIconStateDebug) Pmsg1(000, "In restoreTree::directoryIconStateInsert boogie %s\n", path.toUtf8().data());
1392 * A function to set the icon state back to "folder" and to remove a record from
1393 * m_directoryIconStateHash when an exception is removed by a user.
1395 void restoreTree::directoryIconStateRemove()
1397 QHash<QString, int> shouldBeIconStateHash;
1398 /* First determine all paths with icons that should be checked with m_fileExceptionHash */
1399 /* Use iterator tera to iterate through m_fileExceptionHash */
1400 QHashIterator<QString, Qt::CheckState> tera(m_fileExceptionHash);
1401 while (tera.hasNext()) {
1403 if (mainWin->m_rtIconStateDebug) Pmsg2(000, "Alpha Key %s value %i\n", tera.key().toUtf8().data(), tera.value());
1405 QString keyPath = tera.key();
1406 Qt::CheckState state = tera.value();
1409 fullPathtoSubPaths(paths, keyPath);
1410 /* if the state of the item in m_fileExceptionHash is checked
1411 * each of the subpaths should be "Checked Green" */
1412 if (state == Qt::Checked) {
1414 bool foundAsUnChecked = false;
1415 QTreeWidgetItem *firstItem = m_dirPaths.value(paths[0]);
1417 if (firstItem->checkState(0) == Qt::Unchecked)
1418 foundAsUnChecked = true;
1420 if (foundAsUnChecked) {
1421 /* The right most directory is Unchecked, iterate leftwards
1422 * as long as directory item is Unchecked, set icon state to "green check" */
1424 QListIterator<QString> siter(paths);
1425 while (siter.hasNext() && !done) {
1426 QString path = siter.next();
1427 QTreeWidgetItem *item = m_dirPaths.value(path);
1429 if (item->checkState(0) != Qt::Unchecked)
1432 shouldBeIconStateHash.insert(path, FolderGreenChecked);
1433 if (mainWin->m_rtIconStateDebug) Pmsg1(000, "In restoreTree::directoryIconStateInsert inserting %s\n", path.toUtf8().data());
1439 /* The right most directory is Unchecked, iterate leftwards
1440 * until directory item is Checked, set icon state to "green check" */
1442 QListIterator<QString> siter(paths);
1443 while (siter.hasNext() && !done) {
1444 QString path = siter.next();
1445 QTreeWidgetItem *item = m_dirPaths.value(path);
1447 if (item->checkState(0) == Qt::Checked)
1449 shouldBeIconStateHash.insert(path, FolderGreenChecked);
1454 /* if the state of the item in m_fileExceptionHash is UNChecked
1455 * each of the subpaths should be "Checked white" until the tree item
1456 * which represents that path is Qt::Checked */
1457 if (state == Qt::Unchecked) {
1459 QListIterator<QString> siter(paths);
1460 while (siter.hasNext() && !done) {
1461 QString path = siter.next();
1462 QTreeWidgetItem *item = m_dirPaths.value(path);
1464 if (item->checkState(0) == Qt::Checked)
1466 shouldBeIconStateHash.insert(path, FolderWhiteChecked);
1471 /* now iterate through m_directoryIconStateHash which are the items that are checked
1472 * and remove all of those that are not in shouldBeIconStateHash */
1473 QHashIterator<QString, int> iter(m_directoryIconStateHash);
1474 while (iter.hasNext()) {
1476 if (mainWin->m_rtIconStateDebug) Pmsg2(000, "Beta Key %s value %i\n", iter.key().toUtf8().data(), iter.value());
1478 QString keyPath = iter.key();
1479 if (shouldBeIconStateHash.value(keyPath)) {
1480 if (mainWin->m_rtIconStateDebug) Pmsg1(000, "WAS found in shouldBeStateHash %s\n", keyPath.toUtf8().data());
1481 //newval = m_directoryIconStateHash.value(path, FolderUnchecked) & (~change);
1482 int newval = shouldBeIconStateHash.value(keyPath);
1484 newval = newval & FolderBothChecked;
1485 QTreeWidgetItem *item = m_dirPaths.value(keyPath);
1487 directorySetIcon(0, newval, keyPath, item);
1489 if (mainWin->m_rtIconStateDebug) Pmsg1(000, "NOT found in shouldBeStateHash %s\n", keyPath.toUtf8().data());
1490 QTreeWidgetItem *item = m_dirPaths.value(keyPath);
1492 directorySetIcon(0, FolderBothChecked, keyPath, item);
1493 //item->setIcon(0,QIcon(QString::fromUtf8(":images/folder.png")));
1494 //m_directoryIconStateHash.remove(keyPath);
1499 void restoreTree::directorySetIcon(int operation, int change, QString &path, QTreeWidgetItem* item) {
1501 /* we are adding a check type white or green */
1502 if (operation > 0) {
1503 /* get the old val and "bitwise OR" with the change */
1504 newval = m_directoryIconStateHash.value(path, FolderUnchecked) | change;
1505 if (mainWin->m_rtIconStateDebug) Pmsg2(000, "Inserting into m_directoryIconStateHash path=%s newval=%i\n", path.toUtf8().data(), newval);
1506 m_directoryIconStateHash.insert(path, newval);
1508 /* we are removing a check type white or green */
1509 newval = m_directoryIconStateHash.value(path, FolderUnchecked) & (~change);
1511 if (mainWin->m_rtIconStateDebug) Pmsg2(000, "Removing from m_directoryIconStateHash path=%s newval=%i\n", path.toUtf8().data(), newval);
1512 m_directoryIconStateHash.remove(path);
1515 if (mainWin->m_rtIconStateDebug) Pmsg2(000, "Inserting into m_directoryIconStateHash path=%s newval=%i\n", path.toUtf8().data(), newval);
1516 m_directoryIconStateHash.insert(path, newval);
1519 if (newval == FolderUnchecked)
1520 item->setIcon(0, QIcon(QString::fromUtf8(":images/folder.png")));
1521 else if (newval == FolderGreenChecked)
1522 item->setIcon(0, QIcon(QString::fromUtf8(":images/folderchecked.png")));
1523 else if (newval == FolderWhiteChecked)
1524 item->setIcon(0, QIcon(QString::fromUtf8(":images/folderunchecked.png")));
1525 else if (newval == FolderBothChecked)
1526 item->setIcon(0, QIcon(QString::fromUtf8(":images/folderbothchecked.png")));
1532 void restoreTree::restoreButtonPushed()
1534 /* Set progress bars and repaint */
1535 prLabel1->setVisible(true);
1536 prLabel1->setText(tr("Task 1 of 3"));
1537 prLabel2->setVisible(true);
1538 prLabel2->setText(tr("Processing Checked directories"));
1539 prBar1->setVisible(true);
1540 prBar1->setRange(0, 3);
1541 prBar1->setValue(0);
1542 prBar2->setVisible(true);
1543 prBar2->setRange(0, 0);
1545 QMultiHash<int, QString> versionFilesMulti;
1547 QHash <QString, bool> fullPathDone;
1548 QHash <QString, int> fileIndexHash;
1549 if ((mainWin->m_rtRestore1Debug) || (mainWin->m_rtRestore2Debug) || (mainWin->m_rtRestore3Debug))
1550 Pmsg0(000, "In restoreTree::restoreButtonPushed\n");
1551 /* Use a tree widget item iterator to count directories for the progress bar */
1552 QTreeWidgetItemIterator diterc(directoryTree, QTreeWidgetItemIterator::Checked);
1557 } /* while (*diterc) */
1558 prBar2->setRange(0, ditcount);
1559 prBar2->setValue(0);
1561 /* Use a tree widget item iterator filtering for Checked Items */
1562 QTreeWidgetItemIterator diter(directoryTree, QTreeWidgetItemIterator::Checked);
1564 QString directory = (*diter)->data(0, Qt::UserRole).toString();
1565 int pathid = m_directoryPathIdHash.value(directory, -1);
1567 if (mainWin->m_rtRestore1Debug)
1568 Pmsg1(000, "Directory Checked=\"%s\"\n", directory.toUtf8().data());
1569 /* With a checked directory, query for the files in the directory */
1572 "SELECT Filename.Name AS Filename, t1.JobId AS JobId, File.FileIndex AS FileIndex"
1574 " ( SELECT File.FilenameId AS FilenameId, MAX(Job.JobId) AS JobId"
1576 " INNER JOIN Job ON (Job.JobId=File.JobId)"
1577 " WHERE File.PathId=" + QString("%1").arg(pathid) +
1578 " AND Job.Jobid IN (" + m_checkedJobs + ")"
1579 " GROUP BY File.FilenameId"
1581 " INNER JOIN Filename on (Filename.FilenameId=File.FilenameId)"
1582 " INNER JOIN Job ON (Job.JobId=File.JobId)"
1583 " WHERE File.PathId=" + QString("%1").arg(pathid) +
1584 " AND File.FilenameId=t1.FilenameId"
1585 " AND Job.Jobid=t1.JobId"
1586 " ORDER BY Filename";
1588 if (mainWin->m_sqlDebug) Pmsg1(000, "Query cmd : %s\n", cmd.toUtf8().data());
1589 QStringList results;
1590 if (m_console->sql_cmd(cmd, results)) {
1591 QStringList fieldlist;
1594 /* Iterate through the record returned from the query */
1595 foreach (QString resultline, results) {
1596 /* Iterate through fields in the record */
1598 QString fullPath = "";
1599 Qt::CheckState fileExcpState = (Qt::CheckState)4;
1600 fieldlist = resultline.split("\t");
1603 foreach (QString field, fieldlist) {
1605 fullPath = directory + field;
1608 version = field.toInt();
1611 fileIndex = field.toInt();
1615 fileExcpState = m_fileExceptionHash.value(fullPath, (Qt::CheckState)3);
1617 int excpVersion = m_versionExceptionHash.value(fullPath, 0);
1618 if (fileExcpState != Qt::Unchecked) {
1620 if (excpVersion != 0) {
1621 debugtext = QString("*E* version=%1").arg(excpVersion);
1622 version = excpVersion;
1623 fileIndex = queryFileIndex(fullPath, excpVersion);
1625 debugtext = QString("___ version=%1").arg(version);
1626 if (mainWin->m_rtRestore1Debug)
1627 Pmsg2(000, "Restoring %s File %s\n", debugtext.toUtf8().data(), fullPath.toUtf8().data());
1628 fullPathDone.insert(fullPath, 1);
1629 fileIndexHash.insert(fullPath, fileIndex);
1630 versionFilesMulti.insert(version, fullPath);
1638 prBar2->setValue(ditcount);
1640 } /* while (*diter) */
1641 prBar1->setValue(1);
1642 prLabel1->setText( tr("Task 2 of 3"));
1643 prLabel2->setText(tr("Processing Exceptions"));
1644 prBar2->setRange(0, 0);
1647 /* There may be some exceptions not accounted for yet with fullPathDone */
1648 QHashIterator<QString, Qt::CheckState> ftera(m_fileExceptionHash);
1649 while (ftera.hasNext()) {
1651 QString fullPath = ftera.key();
1652 Qt::CheckState state = ftera.value();
1654 /* now we don't want the ones already done */
1655 if (fullPathDone.value(fullPath, 0) == 0) {
1656 int version = m_versionExceptionHash.value(fullPath, 0);
1658 QString debugtext = "";
1660 fileIndex = queryFileIndex(fullPath, version);
1661 debugtext = QString("E1* version=%1 fileid=%2").arg(version).arg(fileIndex);
1663 version = mostRecentVersionfromFullPath(fullPath);
1665 fileIndex = queryFileIndex(fullPath, version);
1666 debugtext = QString("E2* version=%1 fileid=%2").arg(version).arg(fileIndex);
1668 debugtext = QString("Error det vers").arg(version);
1670 if (mainWin->m_rtRestore1Debug)
1671 Pmsg2(000, "Restoring %s file %s\n", debugtext.toUtf8().data(), fullPath.toUtf8().data());
1672 versionFilesMulti.insert(version, fullPath);
1674 fileIndexHash.insert(fullPath, fileIndex);
1675 } /* if fullPathDone.value(fullPath, 0) == 0 */
1676 } /* if state != 0 */
1677 } /* while ftera.hasNext */
1678 /* The progress bars for the next step */
1679 prBar1->setValue(2);
1680 prLabel1->setText(tr("Task 3 of 3"));
1681 prLabel2->setText(tr("Filling Database Table"));
1682 prBar2->setRange(0, vFMCounter);
1684 prBar2->setValue(vFMCounter);
1687 /* now for the final spit out of the versions and lists of files for each version */
1688 QHash<int, int> doneKeys;
1689 QHashIterator<int, QString> vFMiter(versionFilesMulti);
1690 QString tempTable = "";
1692 while (vFMiter.hasNext()) {
1694 int fversion = vFMiter.key();
1695 /* did not succeed in getting an iterator to work as expected on versionFilesMulti so use doneKeys */
1696 if (doneKeys.value(fversion, 0) == 0) {
1697 if (tempTable == "") {
1698 QSettings settings("www.bacula.org", "bat");
1699 settings.beginGroup("Restore");
1700 int counter = settings.value("Counter", 1).toInt();
1701 settings.setValue("Counter", counter+1);
1702 settings.endGroup();
1703 tempTable = "restore_" + QString("%1").arg(qrand()) + "_" + QString("%1").arg(counter);
1704 QString sqlcmd = "CREATE TEMPORARY TABLE " + tempTable + " (JobId INTEGER, FileIndex INTEGER)";
1705 if (mainWin->m_sqlDebug)
1706 Pmsg1(000, "Query cmd : %s ;\n", sqlcmd.toUtf8().data());
1707 QStringList results;
1708 if (!m_console->sql_cmd(sqlcmd, results))
1709 Pmsg1(000, "CREATE TABLE FAILED!!!! %s\n", sqlcmd.toUtf8().data());
1712 if (mainWin->m_rtRestore2Debug) Pmsg1(000, "Version->%i\n", fversion);
1713 QStringList fullPathList = versionFilesMulti.values(fversion);
1714 /* create the command to perform the restore */
1715 foreach(QString ffullPath, fullPathList) {
1716 int fileIndex = fileIndexHash.value(ffullPath);
1717 if (mainWin->m_rtRestore2Debug) Pmsg2(000, " file->%s id %i\n", ffullPath.toUtf8().data(), fileIndex);
1718 QString sqlcmd = "INSERT INTO " + tempTable + " (JobId, FileIndex) VALUES (" + QString("%1").arg(fversion) + ", " + QString("%1").arg(fileIndex) + ")";
1719 if (mainWin->m_rtRestore3Debug)
1720 Pmsg1(000, "Insert cmd : %s\n", sqlcmd.toUtf8().data());
1721 QStringList results;
1722 if (!m_console->sql_cmd(sqlcmd, results))
1723 Pmsg1(000, "INSERT INTO FAILED!!!! %s\n", sqlcmd.toUtf8().data());
1724 prBar2->setValue(++vFMCounter);
1725 } /* foreach fullPathList */
1726 doneKeys.insert(fversion,1);
1727 jobList.append(fversion);
1728 } /* if (doneKeys.value(fversion, 0) == 0) */
1729 } /* while (vFMiter.hasNext()) */
1730 if (tempTable != "") {
1731 /* a table was made, lets run the job */
1732 QString jobOption = " jobid=\"";
1734 /* create a list of jobs comma separated */
1735 foreach (int job, jobList) {
1736 if (first) first = false;
1737 else jobOption += ",";
1738 jobOption += QString("%1").arg(job);
1741 QString cmd = QString("restore");
1743 " client=\"" + m_prevClientCombo + "\"" +
1744 " file=\"?" + tempTable + "\" done";
1745 if (mainWin->m_commandDebug)
1746 Pmsg1(000, "preRestore command \'%s\'\n", cmd.toUtf8().data());
1747 consoleCommand(cmd);
1749 /* turn off the progress widgets */
1750 prBar1->setVisible(false);
1751 prBar2->setVisible(false);
1752 prLabel1->setVisible(false);
1753 prLabel2->setVisible(false);
1756 int restoreTree::mostRecentVersionfromFullPath(QString &fullPath)
1759 QString directory, fileName;
1760 int index = fullPath.lastIndexOf("/", -2);
1762 directory = fileName = fullPath;
1763 directory.replace(index+1, fullPath.length()-index-1, "");
1764 fileName.replace(0, index+1, "");
1766 QString msg = QString("length = \"%1\" index = \"%2\" Considering \"%3\" \"%4\"\n")
1767 .arg(fullPath.length()).arg(index).arg(fileName).arg(directory);
1768 Pmsg0(000, msg.toUtf8().data());
1770 int pathid = m_directoryPathIdHash.value(directory, -1);
1772 /* so now we need the latest version from the database */
1774 "SELECT MAX(Job.JobId)"
1776 " INNER JOIN Filename on (Filename.FilenameId=File.FilenameId)"
1777 " INNER JOIN Job ON (File.JobId=Job.JobId)"
1778 " WHERE File.PathId=" + QString("%1").arg(pathid) +
1779 " AND Job.Jobid IN (" + m_checkedJobs + ")"
1780 " AND Filename.Name='" + fileName + "'"
1781 " AND File.FilenameId!=" + QString("%1").arg(m_nullFileNameId) +
1782 " GROUP BY Filename.Name";
1784 if (mainWin->m_sqlDebug) Pmsg1(000, "Query cmd : %s\n", cmd.toUtf8().data());
1785 QStringList results;
1786 if (m_console->sql_cmd(cmd, results)) {
1787 QStringList fieldlist;
1789 /* Iterate through the record returned from the query */
1790 foreach (QString resultline, results) {
1791 /* Iterate through fields in the record */
1793 fieldlist = resultline.split("\t");
1794 foreach (QString field, fieldlist) {
1796 qversion = field.toInt();
1804 } /* if (index != -1) */
1809 int restoreTree::queryFileIndex(QString &fullPath, int jobId)
1812 QString directory, fileName;
1813 int index = fullPath.lastIndexOf("/", -2);
1815 directory = fileName = fullPath;
1816 directory.replace(index+1, fullPath.length()-index-1, "");
1817 fileName.replace(0, index+1, "");
1819 QString msg = QString("length = \"%1\" index = \"%2\" Considering \"%3\" \"%4\"\n")
1820 .arg(fullPath.length()).arg(index).arg(fileName).arg(directory);
1821 Pmsg0(000, msg.toUtf8().data());
1823 int pathid = m_directoryPathIdHash.value(directory, -1);
1825 /* so now we need the latest version from the database */
1830 " INNER JOIN Filename on (Filename.FilenameId=File.FilenameId)"
1831 " INNER JOIN Job ON (File.JobId=Job.JobId)"
1832 " WHERE File.PathId=" + QString("%1").arg(pathid) +
1833 " AND Filename.Name='" + fileName + "'"
1834 " AND Job.Jobid='" + QString("%1").arg(jobId) + "'"
1835 " GROUP BY File.FileIndex";
1837 if (mainWin->m_sqlDebug) Pmsg1(000, "Query cmd : %s\n", cmd.toUtf8().data());
1838 QStringList results;
1839 if (m_console->sql_cmd(cmd, results)) {
1840 QStringList fieldlist;
1842 /* Iterate through the record returned from the query */
1843 foreach (QString resultline, results) {
1844 /* Iterate through fields in the record */
1846 fieldlist = resultline.split("\t");
1847 foreach (QString field, fieldlist) {
1849 qfileIndex = field.toInt();
1857 } /* if (index != -1) */