2 Bacula® - The Network Backup Solution
4 Copyright (C) 2007-2007 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 John Walker.
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 = "Version Browser";
47 QTreeWidgetItem* thisitem = mainWin->getFromHash(this);
48 thisitem->setIcon(0, QIcon(QString::fromUtf8(":images/browse.png")));
54 m_winRegExpDrive.setPattern("^[a-z]:/$");
55 m_winRegExpPath.setPattern("^[a-z]:/");
56 m_slashregex.setPattern("/");
60 QGridLayout *gridLayout = new QGridLayout(this);
61 gridLayout->setSpacing(6);
62 gridLayout->setMargin(9);
63 gridLayout->setObjectName(QString::fromUtf8("gridLayout"));
65 m_splitter = new QSplitter(Qt::Vertical, this);
66 QScrollArea *area = new QScrollArea();
67 area->setObjectName(QString::fromUtf8("area"));
68 area->setWidget(widget);
69 area->setWidgetResizable(true);
70 m_splitter->addWidget(splitter);
71 m_splitter->addWidget(area);
73 gridLayout->addWidget(m_splitter, 0, 0, 1, 1);
75 /* progress widgets */
76 prBar1->setVisible(false);
77 prBar2->setVisible(false);
78 prLabel1->setVisible(false);
79 prLabel2->setVisible(false);
81 /* Set Defaults for check and spin for limits */
82 limitCheckBox->setCheckState(mainWin->m_recordLimitCheck ? Qt::Checked : Qt::Unchecked);
83 limitSpinBox->setValue(mainWin->m_recordLimitVal);
84 daysCheckBox->setCheckState(mainWin->m_daysLimitCheck ? Qt::Checked : Qt::Unchecked);
85 daysSpinBox->setValue(mainWin->m_daysLimitVal);
89 restoreTree::~restoreTree()
95 * Called from the constructor to set up the page widgets and connections.
97 void restoreTree::setupPage()
99 connect(refreshButton, SIGNAL(pressed()), this, SLOT(refreshButtonPushed()));
100 connect(restoreButton, SIGNAL(pressed()), this, SLOT(restoreButtonPushed()));
101 connect(jobCombo, SIGNAL(currentIndexChanged(int)), this, SLOT(jobComboChanged(int)));
102 connect(jobCombo, SIGNAL(currentIndexChanged(int)), this, SLOT(updateRefresh()));
103 connect(clientCombo, SIGNAL(currentIndexChanged(int)), this, SLOT(updateRefresh()));
104 connect(fileSetCombo, SIGNAL(currentIndexChanged(int)), this, SLOT(updateRefresh()));
105 connect(limitCheckBox, SIGNAL(stateChanged(int)), this, SLOT(updateRefresh()));
106 connect(daysCheckBox, SIGNAL(stateChanged(int)), this, SLOT(updateRefresh()));
107 connect(daysSpinBox, SIGNAL(valueChanged(int)), this, SLOT(updateRefresh()));
108 connect(limitSpinBox, SIGNAL(valueChanged(int)), this, SLOT(updateRefresh()));
109 connect(directoryTree, SIGNAL(currentItemChanged(QTreeWidgetItem *, QTreeWidgetItem *)),
110 this, SLOT(directoryCurrentItemChanged(QTreeWidgetItem *, QTreeWidgetItem *)));
111 connect(directoryTree, SIGNAL(itemExpanded(QTreeWidgetItem *)),
112 this, SLOT(directoryItemExpanded(QTreeWidgetItem *)));
113 connect(directoryTree, SIGNAL(itemChanged(QTreeWidgetItem *, int)),
114 this, SLOT(directoryItemChanged(QTreeWidgetItem *, int)));
115 connect(fileTable, SIGNAL(currentItemChanged(QTableWidgetItem *, QTableWidgetItem *)),
116 this, SLOT(fileCurrentItemChanged(QTableWidgetItem *, QTableWidgetItem *)));
117 connect(jobTable, SIGNAL(cellClicked(int, int)),
118 this, SLOT(jobTableCellClicked(int, int)));
120 QStringList titles = QStringList() << "Directories";
121 directoryTree->setHeaderLabels(titles);
122 clientCombo->addItems(m_console->client_list);
123 fileSetCombo->addItem("Any");
124 fileSetCombo->addItems(m_console->fileset_list);
125 jobCombo->addItem("Any");
126 jobCombo->addItems(m_console->job_list);
128 directoryTree->setContextMenuPolicy(Qt::ActionsContextMenu);
131 void restoreTree::updateRefresh()
133 if (mainWin->m_rtPopDirDebug) Pmsg2(000, "testing prev=\"%s\" current=\"%s\"\n", m_prevJobCombo.toUtf8().data(), jobCombo->currentText().toUtf8().data());
134 m_dropdownChanged = (m_prevJobCombo != jobCombo->currentText())
135 || (m_prevClientCombo != clientCombo->currentText())
136 || (m_prevFileSetCombo != fileSetCombo->currentText()
137 || (m_prevLimitSpinBox != limitSpinBox->value())
138 || (m_prevDaysSpinBox != daysSpinBox->value())
139 || (m_prevLimitCheckState != limitCheckBox->checkState())
140 || (m_prevDaysCheckState != daysCheckBox->checkState())
142 if (m_dropdownChanged) {
143 if (mainWin->m_rtPopDirDebug) Pmsg0(000, "In restoreTree::updateRefresh Is CHANGED\n");
144 refreshLabel->setText("Refresh From Re-Select");
146 if (mainWin->m_rtPopDirDebug) Pmsg0(000, "In restoreTree::updateRefresh Is not Changed\n");
147 refreshLabel->setText("Refresh From JobChecks");
152 * When refresh button is pushed, perform a query getting the directories and
153 * use parseDirectory and addDirectory to populate the directory tree with items.
155 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("Task " + QString("%1").arg(ontask)+ " of " + QString("%1").arg(taskcount));
180 prLabel1->setVisible(true);
181 prBar2->setVisible(true);
182 prBar2->setRange(0,0);
183 prLabel2->setText("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("Task " + QString("%1").arg(ontask)+ " of " + QString("%1").arg(taskcount));
199 prBar2->setRange(0,0);
200 prLabel2->setText("Querying Jobs");
203 setJobsCheckedList();
205 if (mainWin->m_rtPopDirDebug) Pmsg0(000, "Repopulating from checks in Job Table\n");
206 setJobsCheckedList();
209 if (m_checkedJobs != "") {
211 "SELECT DISTINCT Path.Path AS Path, Path.PathId AS PathId"
213 " INNER JOIN File ON (File.PathId=Path.PathId)"
214 " INNER JOIN Job ON (File.JobId=Job.JobId)"
215 " WHERE Job.Jobid IN (" + m_checkedJobs + ")"
217 if (mainWin->m_sqlDebug) {
218 Pmsg1(000, "Query cmd : %s\n", cmd.toUtf8().data());
220 prBar1->setValue(ontask++);
221 prLabel1->setText("Task " + QString("%1").arg(ontask)+ " of " + QString("%1").arg(taskcount));
223 prBar2->setRange(0,0);
224 prLabel2->setText("Querying for Directories");
227 m_directoryPathIdHash.clear();
228 bool querydone = false;
229 if (m_console->sql_cmd(cmd, results)) {
232 prLabel2->setText("Processing Directories");
233 prBar2->setRange(0,results.count());
236 if (mainWin->m_miscDebug)
237 Pmsg1(000, "Done with query %i results\n", results.count());
238 QStringList fieldlist;
239 foreach(QString resultline, results) {
241 prBar2->setValue(m_debugCnt);
242 fieldlist = resultline.split("\t");
245 /* Iterate through fields in the record */
246 foreach (field, fieldlist) {
247 if (fieldcnt == 0 ) {
248 parseDirectory(field);
249 } else if (fieldcnt == 1) {
251 int pathid = field.toInt(&ok, 10);
253 m_directoryPathIdHash.insert(fieldlist[0], pathid);
260 QMessageBox::warning(this, tr("Bat"),
261 tr("No jobs were selected in the job query !!!.\n"
262 "Press OK to continue?"),
265 prBar1->setVisible(false);
266 prBar2->setVisible(false);
267 prLabel1->setVisible(false);
268 prLabel2->setVisible(false);
272 * Function to set m_checkedJobs from the jobs that are checked in the table
275 void restoreTree::setJobsCheckedList()
277 m_JobsCheckedList = "";
279 /* Update the items in the version table */
280 int cnt = jobTable->rowCount();
281 for (int row=0; row<cnt; row++) {
282 QTableWidgetItem* jobItem = jobTable->item(row, 0);
283 if (jobItem->checkState() == Qt::Checked) {
285 m_JobsCheckedList += ",";
286 m_JobsCheckedList += jobItem->text();
288 jobItem->setBackground(Qt::green);
290 if (jobItem->flags())
291 jobItem->setBackground(Qt::gray);
293 jobItem->setBackground(Qt::darkYellow);
296 m_checkedJobs = m_JobsCheckedList;
300 * Function to parse a directory into all possible subdirectories, then add to
303 void restoreTree::parseDirectory(QString &dir_in)
305 /* m_debugTrap is to only print debugs for a few occurances of calling parseDirectory
306 * instead of printing out what could potentially a whole bunch */
309 /* Clean up the directory string remove some funny char after last '/' */
310 QRegExp rgx("[^/]$");
311 int lastslash = rgx.indexIn(dir_in);
313 dir_in.replace(lastslash, dir_in.length()-lastslash, "");
314 if ((mainWin->m_miscDebug) && (m_debugTrap))
315 Pmsg1(000, "parsing %s\n", dir_in.toUtf8().data());
317 /* split and add if not in yet */
318 QString direct, path;
321 QStringList pathAfter, dirAfter;
322 /* start from the end, turn /etc/somedir/subdir/ into /etc/somedir and subdir/
323 * if not added into tree, then try /etc/ and somedir/ if not added, then try
324 * / and etc/ . That should succeed, then add the ones that failed in reverse */
325 while (((index = m_slashregex.lastIndexIn(dir_in, -2)) != -1) && (!done)) {
326 direct = path = dir_in;
327 path.replace(index+1, dir_in.length()-index-1,"");
328 direct.replace(0, index+1, "");
329 if ((mainWin->m_miscDebug) && (m_debugTrap)) {
330 QString msg = QString("length = \"%1\" index = \"%2\" Adding \"%3\" \"%4\"\n")
331 .arg(dir_in.length()).arg(index).arg(path).arg(direct);
332 Pmsg0(000, msg.toUtf8().data());
334 if (addDirectory(path, direct)) done = true;
336 if ((mainWin->m_miscDebug) && (m_debugTrap))
337 Pmsg0(000, "Saving for later\n");
338 pathAfter.prepend(path);
339 dirAfter.prepend(direct);
344 for (int k=0; k<pathAfter.count(); k++) {
345 if (addDirectory(pathAfter[k], dirAfter[k]))
346 if ((mainWin->m_miscDebug) && (m_debugTrap))
347 Pmsg2(000, "Adding After %s %s\n", pathAfter[k].toUtf8().data(), dirAfter[k].toUtf8().data());
349 if ((mainWin->m_miscDebug) && (m_debugTrap))
350 Pmsg2(000, "Error Adding %s %s\n", pathAfter[k].toUtf8().data(), dirAfter[k].toUtf8().data());
355 * Function called from fill directory when a directory is found to see if this
356 * directory exists in the directory pane and then add it to the directory pane
358 bool restoreTree::addDirectory(QString &m_cwd, QString &newdirr)
360 QString newdir = newdirr;
361 QString fullPath = m_cwd + newdirr;
362 bool ok = true, added = false;
364 if ((mainWin->m_miscDebug) && (m_debugTrap)) {
365 QString msg = QString("In addDirectory cwd \"%1\" newdir \"%2\"\n")
368 Pmsg0(000, msg.toUtf8().data());
372 /* add unix '/' directory first */
373 if (m_dirPaths.empty() && (m_winRegExpPath.indexIn(fullPath, 0) == -1)) {
375 QTreeWidgetItem *item = new QTreeWidgetItem(directoryTree);
377 item->setText(0, text.toUtf8().data());
378 item->setData(0, Qt::UserRole, QVariant(text));
379 item->setData(1, Qt::UserRole, QVariant(Qt::Unchecked));
380 item->setIcon(0, QIcon(QString::fromUtf8(":images/folder.png")));
381 if ((mainWin->m_miscDebug) && (m_debugTrap)) {
382 Pmsg1(000, "Pre Inserting %s\n", text.toUtf8().data());
384 m_dirPaths.insert(text, item);
386 /* no need to check for windows drive if unix */
387 if (m_winRegExpDrive.indexIn(m_cwd, 0) == 0) {
388 if (!m_dirPaths.contains(m_cwd)) {
389 /* this is a windows drive add the base widget */
390 QTreeWidgetItem *item = new QTreeWidgetItem(directoryTree);
391 item->setText(0, m_cwd);
392 item->setData(0, Qt::UserRole, QVariant(fullPath));
393 item->setData(1, Qt::UserRole, QVariant(Qt::Unchecked));
394 item->setIcon(0, QIcon(QString::fromUtf8(":images/folder.png")));
395 if ((mainWin->m_miscDebug) && (m_debugTrap)) {
396 Pmsg0(000, "Added Base \"letter\":/\n");
398 m_dirPaths.insert(m_cwd, item);
403 /* is it already existent ?? */
404 if (!m_dirPaths.contains(fullPath)) {
405 QTreeWidgetItem *item = NULL;
406 QTreeWidgetItem *parent = m_dirPaths.value(m_cwd);
408 /* new directories to add */
409 item = new QTreeWidgetItem(parent);
410 item->setText(0, newdir.toUtf8().data());
411 item->setData(0, Qt::UserRole, QVariant(fullPath));
412 item->setCheckState(0, Qt::Unchecked);
413 /* Store the current state of the check status in column 1, which at
414 * this point has no text*/
415 item->setData(1, Qt::UserRole, QVariant(Qt::Unchecked));
418 if ((mainWin->m_miscDebug) && (m_debugTrap)) {
419 QString msg = QString("In else of if parent cwd \"%1\" newdir \"%2\"\n")
422 Pmsg0(000, msg.toUtf8().data());
425 /* insert into hash */
427 if ((mainWin->m_miscDebug) && (m_debugTrap)) {
428 Pmsg1(000, "Inserting %s\n", fullPath.toUtf8().data());
430 m_dirPaths.insert(fullPath, item);
438 * Virtual function which is called when this page is visible on the stack
440 void restoreTree::currentStackItem()
443 if (!m_console->preventInUseConnect())
451 * Populate the tree when refresh button pushed.
453 void restoreTree::refreshButtonPushed()
455 populateDirectoryTree();
459 * Set the values of non-job combo boxes to the job defaults
461 void restoreTree::jobComboChanged(int)
463 if (jobCombo->currentText() == "Any") {
464 fileSetCombo->setCurrentIndex(fileSetCombo->findText("Any", Qt::MatchExactly));
467 job_defaults job_defs;
470 job_defs.job_name = jobCombo->currentText();
471 if (m_console->get_job_defaults(job_defs)) {
472 fileSetCombo->setCurrentIndex(fileSetCombo->findText(job_defs.fileset_name, Qt::MatchExactly));
473 clientCombo->setCurrentIndex(clientCombo->findText(job_defs.client_name, Qt::MatchExactly));
478 * Function to populate the file list table
480 void restoreTree::directoryCurrentItemChanged(QTreeWidgetItem *item, QTreeWidgetItem *)
486 /* Also clear the version table here */
487 versionTable->clear();
488 versionFileLabel->setText("");
489 versionTable->setRowCount(0);
490 versionTable->setColumnCount(0);
492 QStringList headerlist = (QStringList() << "File Name" << "File Id");
493 fileTable->setColumnCount(headerlist.size());
494 fileTable->setHorizontalHeaderLabels(headerlist);
495 fileTable->setRowCount(0);
497 m_fileCheckStateList.clear();
498 disconnect(fileTable, SIGNAL(itemChanged(QTableWidgetItem *)),
499 this, SLOT(fileTableItemChanged(QTableWidgetItem *)));
500 QBrush blackBrush(Qt::black);
501 QString directory = item->data(0, Qt::UserRole).toString();
502 directoryLabel->setText("Present Working Directory : " + directory);
503 int pathid = m_directoryPathIdHash.value(directory, -1);
506 "SELECT DISTINCT Filename.Name AS FileName, Filename.FilenameId AS FilenameId"
508 " INNER JOIN Filename on (Filename.FilenameId=File.FilenameId)"
509 " INNER JOIN Path ON (Path.PathId=File.PathId)"
510 " INNER JOIN Job ON (File.JobId=Job.JobId)"
511 " WHERE Path.PathId=" + QString("%1").arg(pathid) + " AND Filename.Name!=''"
512 " AND Job.Jobid IN (" + m_checkedJobs + ")"
513 " ORDER BY FileName";
515 if (mainWin->m_sqlDebug) {
516 Pmsg1(000, "Query cmd : %s\n", cmd.toUtf8().data());
519 if (m_console->sql_cmd(cmd, results)) {
521 QTableWidgetItem* tableItem;
523 QStringList fieldlist;
524 fileTable->setRowCount(results.size());
527 /* Iterate through the record returned from the query */
528 foreach (QString resultline, results) {
529 /* Iterate through fields in the record */
531 fieldlist = resultline.split("\t");
532 foreach (field, fieldlist) {
533 field = field.trimmed(); /* strip leading & trailing spaces */
534 tableItem = new QTableWidgetItem(field, 1);
535 /* Possible flags are Qt::ItemFlags flag = Qt::ItemIsSelectable | Qt::ItemIsEditablex
536 * | Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled | Qt::ItemIsUserCheckable
537 * | Qt::ItemIsEnabled | Qt::ItemIsTristate; */
538 tableItem->setForeground(blackBrush);
539 /* Just in case a column ever gets added */
541 Qt::ItemFlags flag = Qt::ItemIsUserCheckable | Qt::ItemIsEnabled | Qt::ItemIsTristate;
542 tableItem->setFlags(flag);
543 tableItem->setData(Qt::UserRole, QVariant(directory));
544 fileTable->setItem(row, column, tableItem);
545 m_fileCheckStateList.append(Qt::Unchecked);
546 tableItem->setCheckState(Qt::Unchecked);
547 } else if (column == 1) {
548 Qt::ItemFlags flag = Qt::ItemIsEnabled;
549 tableItem->setFlags(flag);
551 int filenameid = field.toInt(&ok, 10);
552 if (!ok) filenameid = -1;
553 tableItem->setData(Qt::UserRole, QVariant(filenameid));
554 fileTable->setItem(row, column, tableItem);
560 fileTable->setRowCount(row);
562 fileTable->resizeColumnsToContents();
563 fileTable->resizeRowsToContents();
564 fileTable->verticalHeader()->hide();
565 if (mainWin->m_rtDirCurICDebug) Pmsg0(000, "will update file table checks\n");
566 updateFileTableChecks();
567 } else if (mainWin->m_sqlDebug)
568 Pmsg1(000, "did not perform query, pathid=%i not found\n", pathid);
569 connect(fileTable, SIGNAL(itemChanged(QTableWidgetItem *)),
570 this, SLOT(fileTableItemChanged(QTableWidgetItem *)));
574 * Function to populate the version table
576 void restoreTree::fileCurrentItemChanged(QTableWidgetItem *currentFileTableItem, QTableWidgetItem *)
578 if (currentFileTableItem == NULL)
581 int currentRow = fileTable->row(currentFileTableItem);
582 QTableWidgetItem *fileTableItem = fileTable->item(currentRow, 0);
583 QTableWidgetItem *fileNameIdTableItem = fileTable->item(currentRow, 1);
584 int fileNameId = fileNameIdTableItem->data(Qt::UserRole).toInt();
586 m_versionCheckStateList.clear();
587 disconnect(versionTable, SIGNAL(itemChanged(QTableWidgetItem *)),
588 this, SLOT(versionTableItemChanged(QTableWidgetItem *)));
590 QString file = fileTableItem->text();
591 versionFileLabel->setText(file);
592 QString directory = fileTableItem->data(Qt::UserRole).toString();
594 QBrush blackBrush(Qt::black);
596 QStringList headerlist = (QStringList() << "Job Id" << "Type" << "End Time" << "Md5" << "FileId");
597 versionTable->clear();
598 versionTable->setColumnCount(headerlist.size());
599 versionTable->setHorizontalHeaderLabels(headerlist);
600 versionTable->setRowCount(0);
602 int pathid = m_directoryPathIdHash.value(directory, -1);
603 if ((pathid != -1) && (fileNameId != -1)) {
605 "SELECT Job.JobId AS JobId, Job.Level AS Type, Job.EndTime AS EndTime, File.Md5 AS MD5, File.FileId AS FileId"
607 " INNER JOIN Filename on (Filename.FilenameId=File.FilenameId)"
608 " INNER JOIN Path ON (Path.PathId=File.PathId)"
609 " INNER JOIN Job ON (File.JobId=Job.JobId)"
610 " WHERE Path.PathId=" + QString("%1").arg(pathid) +
611 //" AND Filename.Name='" + file + "'"
612 " AND Filename.FilenameId=" + QString("%1").arg(fileNameId) +
613 " AND Job.Jobid IN (" + m_checkedJobs + ")"
614 " ORDER BY Job.EndTime DESC";
616 if (mainWin->m_sqlDebug)
617 Pmsg1(000, "Query cmd : %s\n", cmd.toUtf8().data());
619 if (m_console->sql_cmd(cmd, results)) {
621 QTableWidgetItem* tableItem;
623 QStringList fieldlist;
624 versionTable->setRowCount(results.size());
627 /* Iterate through the record returned from the query */
628 foreach (QString resultline, results) {
629 fieldlist = resultline.split("\t");
631 /* remove directory */
632 if (fieldlist[0].trimmed() != "") {
633 /* Iterate through fields in the record */
634 foreach (field, fieldlist) {
635 field = field.trimmed(); /* strip leading & trailing spaces */
636 tableItem = new QTableWidgetItem(field, 1);
637 tableItem->setFlags(0);
638 tableItem->setForeground(blackBrush);
639 tableItem->setData(Qt::UserRole, QVariant(directory));
640 versionTable->setItem(row, column, tableItem);
643 Qt::ItemFlags flag = Qt::ItemIsUserCheckable | Qt::ItemIsEnabled | Qt::ItemIsTristate;
644 tableItem->setFlags(flag);
645 m_versionCheckStateList.append(Qt::Unchecked);
646 tableItem->setCheckState(Qt::Unchecked);
654 versionTable->resizeColumnsToContents();
655 versionTable->resizeRowsToContents();
656 versionTable->verticalHeader()->hide();
657 updateVersionTableChecks();
659 if (mainWin->m_sqlDebug)
660 Pmsg2(000, "not querying : pathid=%i fileNameId=%i\n", pathid, fileNameId);
662 connect(versionTable, SIGNAL(itemChanged(QTableWidgetItem *)),
663 this, SLOT(versionTableItemChanged(QTableWidgetItem *)));
667 * Save user settings associated with this page
669 void restoreTree::writeSettings()
671 QSettings settings(m_console->m_dir->name(), "bat");
672 settings.beginGroup(m_groupText);
673 settings.setValue(m_splitText, m_splitter->saveState());
678 * Read and restore user settings associated with this page
680 void restoreTree::readSettings()
682 m_groupText = "RestoreTreePage";
683 m_splitText = "splitterSizes_1";
684 QSettings settings(m_console->m_dir->name(), "bat");
685 settings.beginGroup(m_groupText);
686 m_splitter->restoreState(settings.value(m_splitText).toByteArray());
691 * This is a funcion to accomplish the one thing I struggled to figure out what
692 * was taking so long. It add the icons, but after the tree is made. Seemed to
693 * work fast after changing from png to png file for graphic.
695 void restoreTree::directoryItemExpanded(QTreeWidgetItem *item)
697 int childCount = item->childCount();
698 for (int i=0; i<childCount; i++) {
699 QTreeWidgetItem *child = item->child(i);
700 if (child->icon(0).isNull())
701 child->setIcon(0, QIcon(QString::fromUtf8(":images/folder.png")));
706 * I wanted a table to show what jobs meet the criterion and are being used to
707 * populate the directory tree and file and version tables.
709 void restoreTree::populateJobTable()
711 QBrush blackBrush(Qt::black);
713 if (mainWin->m_rtPopDirDebug) Pmsg0(000, "Repopulating the Job Table\n");
714 QStringList headerlist = (QStringList() << "Job Id" << "End Time" << "Level" << "Name" << "Purged" << "TU" << "TD");
715 m_toggleUpIndex = headerlist.indexOf("TU");
716 m_toggleDownIndex = headerlist.indexOf("TD");
717 int purgedIndex = headerlist.indexOf("Purged");
719 jobTable->setColumnCount(headerlist.size());
720 jobTable->setHorizontalHeaderLabels(headerlist);
722 "SELECT Job.Jobid AS Id, Job.EndTime AS EndTime, Job.Level AS Level, Job.Name AS JobName, Job.purgedfiles AS Purged"
724 /* INNER JOIN FileSet eliminates all restore jobs */
725 " INNER JOIN Client ON (Job.ClientId=Client.ClientId)"
726 " INNER JOIN FileSet ON (Job.FileSetId=FileSet.FileSetId)"
728 " Client.Name='" + clientCombo->currentText() + "'";
729 if ((jobCombo->currentIndex() >= 0) && (jobCombo->currentText() != "Any")) {
730 jobQuery += " AND Job.name = '" + jobCombo->currentText() + "'";
732 if ((fileSetCombo->currentIndex() >= 0) && (fileSetCombo->currentText() != "Any")) {
733 jobQuery += " AND FileSet.FileSet='" + fileSetCombo->currentText() + "'";
735 /* If Limit check box For limit by days is checked */
736 if (daysCheckBox->checkState() == Qt::Checked) {
737 QDateTime stamp = QDateTime::currentDateTime().addDays(-daysSpinBox->value());
738 QString since = stamp.toString(Qt::ISODate);
739 jobQuery += " AND Job.Starttime>'" + since + "'";
741 //jobQuery += " AND Job.purgedfiles=0";
742 jobQuery += " ORDER BY Job.EndTime DESC";
743 /* If Limit check box for limit records returned is checked */
744 if (limitCheckBox->checkState() == Qt::Checked) {
746 limit.setNum(limitSpinBox->value());
747 jobQuery += " LIMIT " + limit;
749 if (mainWin->m_sqlDebug)
750 Pmsg1(000, "Query cmd : %s\n", jobQuery.toUtf8().data());
753 if (m_console->sql_cmd(jobQuery, results)) {
755 QTableWidgetItem* tableItem;
757 QStringList fieldlist;
758 jobTable->setRowCount(results.size());
761 /* Iterate through the record returned from the query */
762 foreach (QString resultline, results) {
763 fieldlist = resultline.split("\t");
765 /* remove directory */
766 if (fieldlist[0].trimmed() != "") {
767 /* Iterate through fields in the record */
768 foreach (field, fieldlist) {
769 field = field.trimmed(); /* strip leading & trailing spaces */
771 tableItem = new QTableWidgetItem(field, 1);
772 tableItem->setFlags(0);
773 tableItem->setForeground(blackBrush);
774 jobTable->setItem(row, column, tableItem);
777 int purged = fieldlist[purgedIndex].toInt(&ok, 10);
778 if (!((ok) && (purged == 1))) {
779 Qt::ItemFlags flag = Qt::ItemIsUserCheckable | Qt::ItemIsEnabled | Qt::ItemIsTristate;
780 tableItem->setFlags(flag);
781 tableItem->setCheckState(Qt::Checked);
782 tableItem->setBackground(Qt::green);
784 tableItem->setFlags(0);
785 tableItem->setCheckState(Qt::Unchecked);
791 tableItem = new QTableWidgetItem(QIcon(QString::fromUtf8(":images/go-up.png")), "", 1);
792 tableItem->setFlags(0);
793 tableItem->setForeground(blackBrush);
794 jobTable->setItem(row, column, tableItem);
796 tableItem = new QTableWidgetItem(QIcon(QString::fromUtf8(":images/go-down.png")), "", 1);
797 tableItem->setFlags(0);
798 tableItem->setForeground(blackBrush);
799 jobTable->setItem(row, column, tableItem);
804 jobTable->resizeColumnsToContents();
805 jobTable->resizeRowsToContents();
806 jobTable->verticalHeader()->hide();
807 jobTable->hideColumn(purgedIndex);
810 void restoreTree::jobTableCellClicked(int row, int column)
812 if (column == m_toggleUpIndex){
814 for (cnt=0; cnt<row+1; cnt++) {
815 QTableWidgetItem *item = jobTable->item(cnt, 0);
817 Qt::CheckState state = item->checkState();
818 if (state == Qt::Checked)
819 item->setCheckState(Qt::Unchecked);
820 else if (state == Qt::Unchecked)
821 item->setCheckState(Qt::Checked);
825 if (column == m_toggleDownIndex){
826 int cnt, max = jobTable->rowCount();
827 for (cnt=row; cnt<max; cnt++) {
828 QTableWidgetItem *item = jobTable->item(cnt, 0);
830 Qt::CheckState state = item->checkState();
831 if (state == Qt::Checked)
832 item->setCheckState(Qt::Unchecked);
833 else if (state == Qt::Unchecked)
834 item->setCheckState(Qt::Checked);
841 * When a directory item is "changed" check the state of the checkable item
842 * to see if it is different than what it was which is stored in Qt::UserRole
843 * of the 2nd column, column 1, of the tree widget.
845 void restoreTree::directoryItemChanged(QTreeWidgetItem *item, int /*column*/)
847 Qt::CheckState prevState = (Qt::CheckState)item->data(1, Qt::UserRole).toInt();
848 Qt::CheckState curState = item->checkState(0);
849 QTreeWidgetItem* parent = item->parent();
850 Qt::CheckState parState;
851 if (parent) parState = parent->checkState(0);
852 else parState = (Qt::CheckState)3;
853 if (mainWin->m_rtDirICDebug) {
854 QString msg = QString("directory item OBJECT has changed prev=%1 cur=%2 par=%3 dir=%4\n")
855 .arg(prevState).arg(curState).arg(parState).arg(item->text(0));
856 Pmsg1(000, "%s", msg.toUtf8().data()); }
857 /* I only care when the check state changes */
858 if (prevState == curState) {
859 if (mainWin->m_rtDirICDebug) Pmsg0(000, "Returning Early\n");
863 if ((prevState == Qt::Unchecked) && (curState == Qt::Checked) && (parState != Qt::Unchecked)) {
864 if (mainWin->m_rtDirICDebug) Pmsg0(000, "Disconnected Setting to Qt::PartiallyChecked\n");
865 directoryTreeDisconnectedSet(item, Qt::PartiallyChecked);
866 curState = Qt::PartiallyChecked;
868 if ((prevState == Qt::PartiallyChecked) && (curState == Qt::Checked)) {
869 if (mainWin->m_rtDirICDebug) Pmsg0(000, "Disconnected Setting to Qt::Unchecked\n");
870 directoryTreeDisconnectedSet(item, Qt::Unchecked);
871 curState = Qt::Unchecked;
873 if (mainWin->m_rtDirICDebug) {
874 QString msg = QString("directory item CHECKSTATE has changed prev=%1 cur=%2 par=%3 dir=%4\n")
875 .arg(prevState).arg(curState).arg(parState).arg(item->text(0));
876 Pmsg1(000, "%s", msg.toUtf8().data()); }
878 item->setData(1, Qt::UserRole, QVariant(curState));
879 Qt::CheckState childState = curState;
880 if (childState == Qt::Checked)
881 childState = Qt::PartiallyChecked;
882 setCheckofChildren(item, childState);
884 /* Remove items from the exception lists. The multi exception list is my index
885 * of what exceptions can be removed when the directory is known*/
886 QString directory = item->data(0, Qt::UserRole).toString();
887 QStringList fullPathList = m_fileExceptionMulti.values(directory);
888 int fullPathListCount = fullPathList.count();
889 if ((mainWin->m_rtDirICDebug) && fullPathListCount) Pmsg2(000, "Will attempt to remove file exceptions for %s count %i\n", directory.toUtf8().data(), fullPathListCount);
890 foreach (QString fullPath, fullPathList) {
891 /* If there is no value in the hash for the key fullPath a value of 3 will be returned
892 * which will match no Qt::xxx values */
893 Qt::CheckState hashState = m_fileExceptionHash.value(fullPath, (Qt::CheckState)3);
894 if (mainWin->m_rtDirICDebug) Pmsg2(000, "hashState=%i childState=%i\n", hashState, childState);
895 if (hashState == Qt::Unchecked) {
896 fileExceptionRemove(fullPath, directory);
897 m_versionExceptionHash.remove(fullPath);
898 if (mainWin->m_rtDirICDebug) Pmsg0(000, "Attempted Removal A\n");
900 if (hashState == Qt::Checked) {
901 fileExceptionRemove(fullPath, directory);
902 m_versionExceptionHash.remove(fullPath);
903 if (mainWin->m_rtDirICDebug) Pmsg0(000, "Attempted Removal B\n");
907 if (item == directoryTree->currentItem()) {
908 if (mainWin->m_rtDirICDebug) Pmsg0(000, "Will attempt to update File Table Checks\n");
909 updateFileTableChecks();
910 versionTable->clear();
911 versionTable->setRowCount(0);
912 versionTable->setColumnCount(0);
914 if (mainWin->m_rtDirICDebug) Pmsg0(000, "Returning At End\n");
918 * When a directory item check state is changed, this function iterates through
919 * all subdirectories and sets all to the passed state, which is either partially
920 * checked or unchecked.
922 void restoreTree::setCheckofChildren(QTreeWidgetItem *item, Qt::CheckState state)
925 childCount = item->childCount();
926 for (int i=0; i<childCount; i++) {
927 QTreeWidgetItem *child = item->child(i);
928 child->setData(1, Qt::UserRole, QVariant(state));
929 child->setCheckState(0, state);
930 setCheckofChildren(child, state);
935 * When a File Table Item is "changed" check to see if the state of the checkable
936 * item has changed which is stored in m_fileCheckStateList
937 * If changed store in a hash m_fileExceptionHash that whether this file should be
939 * Called as a slot, connected after populated (after directory current changed called)
941 void restoreTree::fileTableItemChanged(QTableWidgetItem *item)
943 /* get the previous and current check states */
944 int row = fileTable->row(item);
945 Qt::CheckState prevState;
946 /* prevent a segfault */
947 prevState = m_fileCheckStateList[row];
948 Qt::CheckState curState = item->checkState();
950 /* deterimine the default state from the state of the directory */
951 QTreeWidgetItem *dirTreeItem = directoryTree->currentItem();
952 Qt::CheckState dirState = (Qt::CheckState)dirTreeItem->data(1, Qt::UserRole).toInt();
953 Qt::CheckState defState = Qt::PartiallyChecked;
954 if (dirState == Qt::Unchecked) defState = Qt::Unchecked;
956 /* determine if it is already in the m_fileExceptionHash */
957 QString directory = directoryTree->currentItem()->data(0, Qt::UserRole).toString();
958 QString file = item->text();
959 QString fullPath = directory + file;
960 Qt::CheckState hashState = m_fileExceptionHash.value(fullPath, (Qt::CheckState)3);
961 int verJobNum = m_versionExceptionHash.value(fullPath, 0);
963 if (mainWin->m_rtFileTabICDebug) {
964 QString msg = QString("filerow=%1 prev=%2 cur=%3 def=%4 hash=%5 dir=%6 verJobNum=%7\n")
965 .arg(row).arg(prevState).arg(curState).arg(defState).arg(hashState).arg(dirState).arg(verJobNum);
966 Pmsg1(000, "%s", msg.toUtf8().data()); }
968 /* Remove the hash if currently checked previously unchecked and directory is checked or partial */
969 if ((prevState == Qt::Checked) && (curState == Qt::Unchecked) && (dirState == Qt::Unchecked)) {
970 /* it can behave as defaulted so current of unchecked is fine */
971 if (mainWin->m_rtFileTabICDebug) Pmsg0(000, "Will fileExceptionRemove and m_versionExceptionHash.remove here\n");
972 fileExceptionRemove(fullPath, directory);
973 m_versionExceptionHash.remove(fullPath);
974 } else if ((prevState == Qt::PartiallyChecked) && (curState == Qt::Checked) && (dirState != Qt::Unchecked) && (verJobNum == 0)) {
975 if (mainWin->m_rtFileTabICDebug) Pmsg0(000, "Will fileExceptionInsert here\n");
976 fileExceptionInsert(fullPath, directory, Qt::Unchecked);
977 } else if ((prevState == Qt::Unchecked) && (curState == Qt::Checked) && (dirState != Qt::Unchecked) && (verJobNum == 0) && (defState == Qt::PartiallyChecked)) {
978 /* filerow=2 prev=0 cur=2 def=1 hash=0 dir=2 verJobNum=0 */
979 if (mainWin->m_rtFileTabICDebug) Pmsg0(000, "Will fileExceptionRemove here\n");
980 fileExceptionRemove(fullPath, directory);
981 } else if ((prevState == Qt::Checked) && (curState == Qt::Unchecked) && (defState == Qt::PartiallyChecked) && (verJobNum != 0) && (hashState == Qt::Checked)) {
982 /* Check dir, check version, attempt uncheck in file
983 * filerow=4 prev=2 cur=0 def=1 hash=2 dir=2 verJobNum=53 */
984 if (mainWin->m_rtFileTabICDebug) Pmsg0(000, "Will fileExceptionRemove and m_versionExceptionHash.remove here\n");
985 fileExceptionRemove(fullPath, directory);
986 m_versionExceptionHash.remove(fullPath);
987 } else if ((prevState == Qt::Unchecked) && (curState == Qt::Checked) && (dirState != Qt::Unchecked) && (verJobNum == 0)) {
988 /* filerow=0 prev=0 cur=2 def=1 hash=0 dirState=2 verJobNum */
989 if (mainWin->m_rtFileTabICDebug) Pmsg0(000, "Will Not remove here\n");
990 } else if (prevState != curState) {
991 if (mainWin->m_rtFileTabICDebug) Pmsg2(000, " THE STATE OF THE Check has changed, Setting StateList[%i] to %i\n", row, curState);
992 /* A user did not set the check state to Partially checked, ignore if so */
993 if (curState != Qt::PartiallyChecked) {
994 if ((defState == Qt::Unchecked) && (prevState == Qt::PartiallyChecked) && (curState == Qt::Unchecked)) {
995 if (mainWin->m_rtFileTabICDebug) Pmsg0(000, " got here\n");
997 if (mainWin->m_rtFileTabICDebug) Pmsg2(000, " Inserting into m_fileExceptionHash %s, %i\n", fullPath.toUtf8().data(), curState);
998 fileExceptionInsert(fullPath, directory, curState);
1001 if (mainWin->m_rtFileTabICDebug) Pmsg1(000, "Removing version hash for %s\n", fullPath.toUtf8().data());
1002 /* programattically been changed back to a default state of Qt::PartiallyChecked remove the version hash here */
1003 m_versionExceptionHash.remove(fullPath);
1007 updateFileTableChecks();
1008 updateVersionTableChecks();
1012 * function to insert keys and values to both m_fileExceptionHash and m_fileExceptionMulti
1014 void restoreTree::fileExceptionInsert(QString &fullPath, QString &direcotry, Qt::CheckState state)
1016 m_fileExceptionHash.insert(fullPath, state);
1017 m_fileExceptionMulti.insert(direcotry, fullPath);
1018 directoryIconStateInsert(fullPath, state);
1022 * function to remove keys from both m_fileExceptionHash and m_fileExceptionMulti
1024 void restoreTree::fileExceptionRemove(QString &fullPath, QString &directory)
1026 m_fileExceptionHash.remove(fullPath);
1027 /* pull the list of values in the multi */
1028 QStringList fullPathList = m_fileExceptionMulti.values(directory);
1029 /* get the index of the fullpath to remove */
1030 int index = fullPathList.indexOf(fullPath);
1032 /* remove the desired item in the list */
1033 fullPathList.removeAt(index);
1034 /* remove the entire list from the multi */
1035 m_fileExceptionMulti.remove(directory);
1036 /* readd the remaining */
1037 foreach (QString fp, fullPathList) {
1038 m_fileExceptionMulti.insert(directory, fp);
1041 directoryIconStateRemove();
1045 * Overloaded function to be called from the slot and from other places to set the state
1046 * of the check marks in the version table
1048 void restoreTree::versionTableItemChanged(QTableWidgetItem *item)
1050 /* get the previous and current check states */
1051 int row = versionTable->row(item);
1052 QTableWidgetItem *colZeroItem = versionTable->item(row, 0);
1053 Qt::CheckState prevState = m_versionCheckStateList[row];
1054 Qt::CheckState curState = (Qt::CheckState)colZeroItem->checkState();
1055 m_versionCheckStateList[row] = curState;
1057 /* deterimine the default state from the state of the file */
1058 QTableWidgetItem *fileTableItem = fileTable->currentItem();
1059 Qt::CheckState fileState = (Qt::CheckState)fileTableItem->checkState();
1061 /* determine the default state */
1062 Qt::CheckState defState;
1064 defState = Qt::PartiallyChecked;
1065 if (fileState == Qt::Unchecked)
1066 defState = Qt::Unchecked;
1069 defState = Qt::Unchecked;
1071 /* determine if it is already in the versionExceptionHash */
1072 QString directory = directoryTree->currentItem()->data(0, Qt::UserRole).toString();
1073 Qt::CheckState dirState = directoryTree->currentItem()->checkState(0);
1074 QString file = fileTableItem->text();
1075 QString fullPath = directory + file;
1076 int thisJobNum = colZeroItem->text().toInt();
1077 int hashJobNum = m_versionExceptionHash.value(fullPath, 0);
1079 if (mainWin->m_rtVerTabICDebug) {
1080 QString msg = QString("versrow=%1 prev=%2 cur=%3 def=%4 dir=%5 hashJobNum=%6 thisJobNum=%7 filestate=%8 fec=%9 vec=%10\n")
1081 .arg(row).arg(prevState).arg(curState).arg(defState).arg(dirState).arg(hashJobNum).arg(thisJobNum).arg(fileState)
1082 .arg(m_fileExceptionHash.count()).arg(m_versionExceptionHash.count());
1083 Pmsg1(000, "%s", msg.toUtf8().data()); }
1084 /* if changed from partially checked to checked, make it unchecked */
1085 if ((curState == Qt::Checked) && (row == 0) && (fileState == Qt::Unchecked)) {
1086 if (mainWin->m_rtVerTabICDebug) Pmsg0(000, "Setting to Qt::Checked\n");
1087 fileTableItem->setCheckState(Qt::Checked);
1088 } else if ((prevState == Qt::PartiallyChecked) && (curState == Qt::Checked) && (row == 0) && (fileState == Qt::Checked) && (dirState == Qt::Unchecked)) {
1089 //versrow=0 prev=1 cur=2 def=1 dir=0 hashJobNum=0 thisJobNum=64 filestate=2 fec=1 vec=0
1090 if (mainWin->m_rtVerTabICDebug) Pmsg1(000, "fileExceptionRemove %s, %i\n", fullPath.toUtf8().data());
1091 fileExceptionRemove(fullPath, directory);
1092 } else if ((curState == Qt::Checked) && (row == 0) && (hashJobNum != 0) && (dirState != Qt::Unchecked)) {
1093 //versrow=0 prev=0 cur=2 def=1 dir=2 hashJobNum=53 thisJobNum=64 filestate=2 fec=1 vec=1
1094 if (mainWin->m_rtVerTabICDebug) Pmsg1(000, "m_versionExceptionHash.remove %s\n", fullPath.toUtf8().data());
1095 m_versionExceptionHash.remove(fullPath);
1096 fileExceptionRemove(fullPath, directory);
1097 } else if ((curState == Qt::Checked) && (row == 0)) {
1098 if (mainWin->m_rtVerTabICDebug) Pmsg1(000, "m_versionExceptionHash.remove %s\n", fullPath.toUtf8().data());
1099 m_versionExceptionHash.remove(fullPath);
1100 } else if (prevState != curState) {
1101 if (mainWin->m_rtVerTabICDebug) Pmsg2(000, " THE STATE OF THE version Check has changed, Setting StateList[%i] to %i\n", row, curState);
1102 if ((curState == Qt::Checked) || (curState == Qt::PartiallyChecked) && (row != 0)) {
1103 if (mainWin->m_rtVerTabICDebug) Pmsg2(000, "Inserting into m_versionExceptionHash %s, %i\n", fullPath.toUtf8().data(), thisJobNum);
1104 m_versionExceptionHash.insert(fullPath, thisJobNum);
1105 if (fileState != Qt::Checked) {
1106 if (mainWin->m_rtVerTabICDebug) Pmsg2(000, "Inserting into m_fileExceptionHash %s, %i\n", fullPath.toUtf8().data(), curState);
1107 fileExceptionInsert(fullPath, directory, curState);
1110 if (mainWin->m_rtVerTabICDebug) Pmsg0(000, "got here\n");
1113 if (mainWin->m_rtVerTabICDebug) Pmsg0(000, "no conditions met\n");
1116 updateFileTableChecks();
1117 updateVersionTableChecks();
1121 * Simple function to set the check state in the file table by disconnecting the
1122 * signal/slot the setting then reconnecting the signal/slot
1124 void restoreTree::fileTableDisconnectedSet(QTableWidgetItem *item, Qt::CheckState state, bool color)
1126 disconnect(fileTable, SIGNAL(itemChanged(QTableWidgetItem *)),
1127 this, SLOT(fileTableItemChanged(QTableWidgetItem *)));
1128 item->setCheckState(state);
1129 if (color) item->setBackground(Qt::yellow);
1130 else item->setBackground(Qt::white);
1131 connect(fileTable, SIGNAL(itemChanged(QTableWidgetItem *)),
1132 this, SLOT(fileTableItemChanged(QTableWidgetItem *)));
1136 * Simple function to set the check state in the version table by disconnecting the
1137 * signal/slot the setting then reconnecting the signal/slot
1139 void restoreTree::versionTableDisconnectedSet(QTableWidgetItem *item, Qt::CheckState state)
1141 disconnect(versionTable, SIGNAL(itemChanged(QTableWidgetItem *)),
1142 this, SLOT(versionTableItemChanged(QTableWidgetItem *)));
1143 item->setCheckState(state);
1144 connect(versionTable, SIGNAL(itemChanged(QTableWidgetItem *)),
1145 this, SLOT(versionTableItemChanged(QTableWidgetItem *)));
1149 * Simple function to set the check state in the directory tree by disconnecting the
1150 * signal/slot the setting then reconnecting the signal/slot
1152 void restoreTree::directoryTreeDisconnectedSet(QTreeWidgetItem *item, Qt::CheckState state)
1154 disconnect(directoryTree, SIGNAL(itemChanged(QTreeWidgetItem *, int)),
1155 this, SLOT(directoryItemChanged(QTreeWidgetItem *, int)));
1156 item->setCheckState(0, state);
1157 connect(directoryTree, SIGNAL(itemChanged(QTreeWidgetItem *, int)),
1158 this, SLOT(directoryItemChanged(QTreeWidgetItem *, int)));
1162 * Simplify the updating of the check state in the File table by iterating through
1163 * each item in the file table to determine it's appropriate state.
1164 * !! Will probably want to concoct a way to do this without iterating for the possibility
1165 * of the very large directories.
1167 void restoreTree::updateFileTableChecks()
1169 /* deterimine the default state from the state of the directory */
1170 QTreeWidgetItem *dirTreeItem = directoryTree->currentItem();
1171 Qt::CheckState dirState = dirTreeItem->checkState(0);
1173 QString dirName = dirTreeItem->data(0, Qt::UserRole).toString();
1175 /* Update the items in the version table */
1176 int rcnt = fileTable->rowCount();
1177 for (int row=0; row<rcnt; row++) {
1178 QTableWidgetItem* item = fileTable->item(row, 0);
1180 Qt::CheckState curState = item->checkState();
1181 Qt::CheckState newState = Qt::PartiallyChecked;
1182 if (dirState == Qt::Unchecked) newState = Qt::Unchecked;
1184 /* determine if it is already in the m_fileExceptionHash */
1185 QString file = item->text();
1186 QString fullPath = dirName + file;
1187 Qt::CheckState hashState = m_fileExceptionHash.value(fullPath, (Qt::CheckState)3);
1188 int hashJobNum = m_versionExceptionHash.value(fullPath, 0);
1190 if (hashState != 3) newState = hashState;
1192 if (mainWin->m_rtUpdateFTDebug) {
1193 QString msg = QString("file row=%1 cur=%2 hash=%3 new=%4 dirState=%5\n")
1194 .arg(row).arg(curState).arg(hashState).arg(newState).arg(dirState);
1195 Pmsg1(000, "%s", msg.toUtf8().data());
1198 bool docolor = false;
1199 if (hashJobNum != 0) docolor = true;
1200 bool isyellow = item->background().color() == QColor(Qt::yellow);
1201 if ((newState != curState) || (hashState == 3) || ((isyellow && !docolor) || (!isyellow && docolor)))
1202 fileTableDisconnectedSet(item, newState, docolor);
1203 m_fileCheckStateList[row] = newState;
1208 * Simplify the updating of the check state in the Version table by iterating through
1209 * each item in the file table to determine it's appropriate state.
1211 void restoreTree::updateVersionTableChecks()
1213 /* deterimine the default state from the state of the directory */
1214 QTreeWidgetItem *dirTreeItem = directoryTree->currentItem();
1215 Qt::CheckState dirState = dirTreeItem->checkState(0);
1216 QString dirName = dirTreeItem->data(0, Qt::UserRole).toString();
1218 /* deterimine the default state from the state of the file */
1219 QTableWidgetItem *fileTableItem = fileTable->item(fileTable->currentRow(), 0);
1220 Qt::CheckState fileState = fileTableItem->checkState();
1221 QString file = fileTableItem->text();
1222 QString fullPath = dirName + file;
1223 int hashJobNum = m_versionExceptionHash.value(fullPath, 0);
1225 /* Update the items in the version table */
1226 int cnt = versionTable->rowCount();
1227 for (int row=0; row<cnt; row++) {
1228 QTableWidgetItem* item = versionTable->item(row, 0);
1230 Qt::CheckState curState = item->checkState();
1231 Qt::CheckState newState = Qt::Unchecked;
1233 if ((row == 0) && (fileState != Qt::Unchecked) && (hashJobNum == 0))
1234 newState = Qt::PartiallyChecked;
1235 /* determine if it is already in the versionExceptionHash */
1237 int thisJobNum = item->text().toInt();
1238 if (thisJobNum == hashJobNum)
1239 newState = Qt::Checked;
1241 if (mainWin->m_rtChecksDebug) {
1242 QString msg = QString("ver row=%1 cur=%2 hashJobNum=%3 new=%4 dirState=%5\n")
1243 .arg(row).arg(curState).arg(hashJobNum).arg(newState).arg(dirState);
1244 Pmsg1(000, "%s", msg.toUtf8().data());
1246 if (newState != curState)
1247 versionTableDisconnectedSet(item, newState);
1248 m_versionCheckStateList[row] = newState;
1253 * Quick subroutine to "return via subPaths" a list of subpaths when passed a fullPath
1255 void restoreTree::fullPathtoSubPaths(QStringList &subPaths, QString &fullPath_in)
1259 QString fullPath = fullPath_in;
1260 QString direct, path;
1261 while (((index = m_slashregex.lastIndexIn(fullPath, -2)) != -1) && (!done)) {
1262 direct = path = fullPath;
1263 path.replace(index+1, fullPath.length()-index-1, "");
1264 direct.replace(0, index+1, "");
1266 QString msg = QString("length = \"%1\" index = \"%2\" Considering \"%3\" \"%4\"\n")
1267 .arg(fullPath.length()).arg(index).arg(path).arg(direct);
1268 Pmsg0(000, msg.toUtf8().data());
1271 subPaths.append(fullPath);
1276 * A Function to set the icon state and insert a record into
1277 * m_directoryIconStateHash when an exception is added by the user
1279 void restoreTree::directoryIconStateInsert(QString &fullPath, Qt::CheckState excpState)
1282 fullPathtoSubPaths(paths, fullPath);
1283 /* an exception that causes the item in the file table to be "Checked" has occured */
1284 if (excpState == Qt::Checked) {
1285 bool foundAsUnChecked = false;
1286 QTreeWidgetItem *firstItem = m_dirPaths.value(paths[0]);
1288 if (firstItem->checkState(0) == Qt::Unchecked)
1289 foundAsUnChecked = true;
1291 if (foundAsUnChecked) {
1292 /* as long as directory item is Unchecked, set icon state to "green check" */
1294 QListIterator<QString> siter(paths);
1295 while (siter.hasNext() && !done) {
1296 QString path = siter.next();
1297 QTreeWidgetItem *item = m_dirPaths.value(path);
1299 if (item->checkState(0) != Qt::Unchecked)
1302 directorySetIcon(1, FolderGreenChecked, path, item);
1303 if (mainWin->m_rtIconStateDebug) Pmsg1(000, "In restoreTree::directoryIconStateInsert inserting %s\n", path.toUtf8().data());
1308 /* if it is partially checked or fully checked insert green Check until a unchecked is found in the path */
1309 if (mainWin->m_rtIconStateDebug) Pmsg1(000, "In restoreTree::directoryIconStateInsert Aqua %s\n", paths[0].toUtf8().data());
1311 QListIterator<QString> siter(paths);
1312 while (siter.hasNext() && !done) {
1313 QString path = siter.next();
1314 QTreeWidgetItem *item = m_dirPaths.value(path);
1315 if (item) { /* if the directory item is checked, set icon state to unchecked "green check" */
1316 if (item->checkState(0) == Qt::Checked)
1318 directorySetIcon(1, FolderGreenChecked, path, item);
1319 if (mainWin->m_rtIconStateDebug) Pmsg1(000, "In restoreTree::directoryIconStateInsert boogie %s\n", path.toUtf8().data());
1324 /* an exception that causes the item in the file table to be "Unchecked" has occured */
1325 if (excpState == Qt::Unchecked) {
1327 QListIterator<QString> siter(paths);
1328 while (siter.hasNext() && !done) {
1329 QString path = siter.next();
1330 QTreeWidgetItem *item = m_dirPaths.value(path);
1331 if (item) { /* if the directory item is checked, set icon state to unchecked "white check" */
1332 if (item->checkState(0) == Qt::Checked)
1334 directorySetIcon(1, FolderWhiteChecked, path, item);
1335 if (mainWin->m_rtIconStateDebug) Pmsg1(000, "In restoreTree::directoryIconStateInsert boogie %s\n", path.toUtf8().data());
1342 * A function to set the icon state back to "folder" and to remove a record from
1343 * m_directoryIconStateHash when an exception is removed by a user.
1345 void restoreTree::directoryIconStateRemove()
1347 QHash<QString, int> shouldBeIconStateHash;
1348 /* First determine all paths with icons that should be checked with m_fileExceptionHash */
1349 /* Use iterator tera to iterate through m_fileExceptionHash */
1350 QHashIterator<QString, Qt::CheckState> tera(m_fileExceptionHash);
1351 while (tera.hasNext()) {
1353 if (mainWin->m_rtIconStateDebug) Pmsg2(000, "Alpha Key %s value %i\n", tera.key().toUtf8().data(), tera.value());
1355 QString keyPath = tera.key();
1356 Qt::CheckState state = tera.value();
1359 fullPathtoSubPaths(paths, keyPath);
1360 /* if the state of the item in m_fileExceptionHash is checked
1361 * each of the subpaths should be "Checked Green" */
1362 if (state == Qt::Checked) {
1364 bool foundAsUnChecked = false;
1365 QTreeWidgetItem *firstItem = m_dirPaths.value(paths[0]);
1367 if (firstItem->checkState(0) == Qt::Unchecked)
1368 foundAsUnChecked = true;
1370 if (foundAsUnChecked) {
1371 /* The right most directory is Unchecked, iterate leftwards
1372 * as long as directory item is Unchecked, set icon state to "green check" */
1374 QListIterator<QString> siter(paths);
1375 while (siter.hasNext() && !done) {
1376 QString path = siter.next();
1377 QTreeWidgetItem *item = m_dirPaths.value(path);
1379 if (item->checkState(0) != Qt::Unchecked)
1382 shouldBeIconStateHash.insert(path, FolderGreenChecked);
1383 if (mainWin->m_rtIconStateDebug) Pmsg1(000, "In restoreTree::directoryIconStateInsert inserting %s\n", path.toUtf8().data());
1389 /* The right most directory is Unchecked, iterate leftwards
1390 * until directory item is Checked, set icon state to "green check" */
1392 QListIterator<QString> siter(paths);
1393 while (siter.hasNext() && !done) {
1394 QString path = siter.next();
1395 QTreeWidgetItem *item = m_dirPaths.value(path);
1397 if (item->checkState(0) == Qt::Checked)
1399 shouldBeIconStateHash.insert(path, FolderGreenChecked);
1404 /* if the state of the item in m_fileExceptionHash is UNChecked
1405 * each of the subpaths should be "Checked white" until the tree item
1406 * which represents that path is Qt::Checked */
1407 if (state == Qt::Unchecked) {
1409 QListIterator<QString> siter(paths);
1410 while (siter.hasNext() && !done) {
1411 QString path = siter.next();
1412 QTreeWidgetItem *item = m_dirPaths.value(path);
1414 if (item->checkState(0) == Qt::Checked)
1416 shouldBeIconStateHash.insert(path, FolderWhiteChecked);
1421 /* now iterate through m_directoryIconStateHash which are the items that are checked
1422 * and remove all of those that are not in shouldBeIconStateHash */
1423 QHashIterator<QString, int> iter(m_directoryIconStateHash);
1424 while (iter.hasNext()) {
1426 if (mainWin->m_rtIconStateDebug) Pmsg2(000, "Beta Key %s value %i\n", iter.key().toUtf8().data(), iter.value());
1428 QString keyPath = iter.key();
1429 if (shouldBeIconStateHash.value(keyPath)) {
1430 if (mainWin->m_rtIconStateDebug) Pmsg1(000, "WAS found in shouldBeStateHash %s\n", keyPath.toUtf8().data());
1431 //newval = m_directoryIconStateHash.value(path, FolderUnchecked) & (~change);
1432 int newval = shouldBeIconStateHash.value(keyPath);
1434 newval = newval & FolderBothChecked;
1435 QTreeWidgetItem *item = m_dirPaths.value(keyPath);
1437 directorySetIcon(0, newval, keyPath, item);
1439 if (mainWin->m_rtIconStateDebug) Pmsg1(000, "NOT found in shouldBeStateHash %s\n", keyPath.toUtf8().data());
1440 QTreeWidgetItem *item = m_dirPaths.value(keyPath);
1442 directorySetIcon(0, FolderBothChecked, keyPath, item);
1443 //item->setIcon(0,QIcon(QString::fromUtf8(":images/folder.png")));
1444 //m_directoryIconStateHash.remove(keyPath);
1449 void restoreTree::directorySetIcon(int operation, int change, QString &path, QTreeWidgetItem* item) {
1451 /* we are adding a check type white or green */
1452 if (operation > 0) {
1453 /* get the old val and "bitwise OR" with the change */
1454 newval = m_directoryIconStateHash.value(path, FolderUnchecked) | change;
1455 if (mainWin->m_rtIconStateDebug) Pmsg2(000, "Inserting into m_directoryIconStateHash path=%s newval=%i\n", path.toUtf8().data(), newval);
1456 m_directoryIconStateHash.insert(path, newval);
1458 /* we are removing a check type white or green */
1459 newval = m_directoryIconStateHash.value(path, FolderUnchecked) & (~change);
1461 if (mainWin->m_rtIconStateDebug) Pmsg2(000, "Removing from m_directoryIconStateHash path=%s newval=%i\n", path.toUtf8().data(), newval);
1462 m_directoryIconStateHash.remove(path);
1465 if (mainWin->m_rtIconStateDebug) Pmsg2(000, "Inserting into m_directoryIconStateHash path=%s newval=%i\n", path.toUtf8().data(), newval);
1466 m_directoryIconStateHash.insert(path, newval);
1469 if (newval == FolderUnchecked)
1470 item->setIcon(0, QIcon(QString::fromUtf8(":images/folder.png")));
1471 else if (newval == FolderGreenChecked)
1472 item->setIcon(0, QIcon(QString::fromUtf8(":images/folderchecked.png")));
1473 else if (newval == FolderWhiteChecked)
1474 item->setIcon(0, QIcon(QString::fromUtf8(":images/folderunchecked.png")));
1475 else if (newval == FolderBothChecked)
1476 item->setIcon(0, QIcon(QString::fromUtf8(":images/folderbothchecked.png")));
1482 void restoreTree::restoreButtonPushed()
1484 /* Set progress bars and repaint */
1485 prLabel1->setVisible(true);
1486 prLabel1->setText("Task 1 of 3");
1487 prLabel2->setVisible(true);
1488 prLabel2->setText("Processing Checked directories");
1489 prBar1->setVisible(true);
1490 prBar1->setRange(0, 3);
1491 prBar1->setValue(0);
1492 prBar2->setVisible(true);
1493 prBar2->setRange(0, 0);
1495 QMultiHash<int, QString> versionFilesMulti;
1497 QHash <QString, bool> fullPathDone;
1498 QHash <QString, int> fileIndexHash;
1499 if ((mainWin->m_rtRestore1Debug) || (mainWin->m_rtRestore2Debug) || (mainWin->m_rtRestore3Debug))
1500 Pmsg0(000, "In restoreTree::restoreButtonPushed\n");
1501 /* Use a tree widget item iterator to count directories for the progress bar */
1502 QTreeWidgetItemIterator diterc(directoryTree, QTreeWidgetItemIterator::Checked);
1507 } /* while (*diterc) */
1508 prBar2->setRange(0, ditcount);
1509 prBar2->setValue(0);
1511 /* Use a tree widget item iterator filtering for Checked Items */
1512 QTreeWidgetItemIterator diter(directoryTree, QTreeWidgetItemIterator::Checked);
1514 QString directory = (*diter)->data(0, Qt::UserRole).toString();
1515 if (mainWin->m_rtRestore1Debug)
1516 Pmsg1(000, "Directory Checked=\"%s\"\n", directory.toUtf8().data());
1517 /* With a checked directory, query for the files in the directory */
1520 "SELECT t1.Filename AS Filename, t1.JobId AS JobId, File.FileIndex AS FileIndex"
1522 " ( SELECT Filename.Name AS Filename, MAX(Job.JobId) AS JobId"
1524 " INNER JOIN Filename on (Filename.FilenameId=File.FilenameId)"
1525 " INNER JOIN Path ON (Path.PathId=File.PathId)"
1526 " INNER JOIN Job ON (Job.JobId=File.JobId)"
1527 " WHERE Path.Path='" + directory + "' AND Filename.Name!=''"
1528 " AND Job.Jobid IN (" + m_checkedJobs + ")"
1529 " GROUP BY Filename.Name"
1531 " INNER JOIN Filename on (Filename.FilenameId=File.FilenameId)"
1532 " INNER JOIN Path ON (Path.PathId=File.PathId)"
1533 " INNER JOIN Job ON (Job.JobId=File.JobId)"
1535 " Path.Path='" + directory + "'"
1536 " AND Filename.Name=t1.Filename"
1537 " AND Job.Jobid=t1.JobId"
1538 " ORDER BY Filename";
1540 if (mainWin->m_sqlDebug) Pmsg1(000, "Query cmd : %s\n", cmd.toUtf8().data());
1541 QStringList results;
1542 if (m_console->sql_cmd(cmd, results)) {
1543 QStringList fieldlist;
1546 /* Iterate through the record returned from the query */
1547 foreach (QString resultline, results) {
1548 /* Iterate through fields in the record */
1550 QString fullPath = "";
1551 Qt::CheckState fileExcpState = (Qt::CheckState)4;
1552 fieldlist = resultline.split("\t");
1555 foreach (QString field, fieldlist) {
1557 fullPath = directory + field;
1560 version = field.toInt();
1563 fileIndex = field.toInt();
1567 fileExcpState = m_fileExceptionHash.value(fullPath, (Qt::CheckState)3);
1569 int excpVersion = m_versionExceptionHash.value(fullPath, 0);
1570 if (fileExcpState != Qt::Unchecked) {
1572 if (excpVersion != 0) {
1573 debugtext = QString("*E* version=%1").arg(excpVersion);
1574 version = excpVersion;
1575 fileIndex = queryFileIndex(fullPath, excpVersion);
1577 debugtext = QString("___ version=%1").arg(version);
1578 if (mainWin->m_rtRestore1Debug)
1579 Pmsg2(000, "Restoring %s File %s\n", debugtext.toUtf8().data(), fullPath.toUtf8().data());
1580 fullPathDone.insert(fullPath, 1);
1581 fileIndexHash.insert(fullPath, fileIndex);
1582 versionFilesMulti.insert(version, fullPath);
1589 prBar2->setValue(ditcount);
1591 } /* while (*diter) */
1592 prBar1->setValue(1);
1593 prLabel1->setText("Task 2 of 3");
1594 prLabel2->setText("Processing Exceptions");
1595 prBar2->setRange(0, 0);
1598 /* There may be some exceptions not accounted for yet with fullPathDone */
1599 QHashIterator<QString, Qt::CheckState> ftera(m_fileExceptionHash);
1600 while (ftera.hasNext()) {
1602 QString fullPath = ftera.key();
1603 Qt::CheckState state = ftera.value();
1605 /* now we don't want the ones already done */
1606 if (fullPathDone.value(fullPath, 0) == 0) {
1607 int version = m_versionExceptionHash.value(fullPath, 0);
1609 QString debugtext = "";
1611 fileIndex = queryFileIndex(fullPath, version);
1612 debugtext = QString("E1* version=%1 fileid=%2").arg(version).arg(fileIndex);
1614 version = mostRecentVersionfromFullPath(fullPath);
1616 fileIndex = queryFileIndex(fullPath, version);
1617 debugtext = QString("E2* version=%1 fileid=%2").arg(version).arg(fileIndex);
1619 debugtext = QString("Error det vers").arg(version);
1621 if (mainWin->m_rtRestore1Debug)
1622 Pmsg2(000, "Restoring %s file %s\n", debugtext.toUtf8().data(), fullPath.toUtf8().data());
1623 versionFilesMulti.insert(version, fullPath);
1625 fileIndexHash.insert(fullPath, fileIndex);
1626 } /* if fullPathDone.value(fullPath, 0) == 0 */
1627 } /* if state != 0 */
1628 } /* while ftera.hasNext */
1629 /* The progress bars for the next step */
1630 prBar1->setValue(2);
1631 prLabel1->setText("Task 3 of 3");
1632 prLabel2->setText("Filling Database Table");
1633 prBar2->setRange(0, vFMCounter);
1635 prBar2->setValue(vFMCounter);
1638 /* now for the final spit out of the versions and lists of files for each version */
1639 QHash<int, int> doneKeys;
1640 QHashIterator<int, QString> vFMiter(versionFilesMulti);
1641 QString tempTable = "";
1643 while (vFMiter.hasNext()) {
1645 int fversion = vFMiter.key();
1646 /* did not succeed in getting an iterator to work as expected on versionFilesMulti so use doneKeys */
1647 if (doneKeys.value(fversion, 0) == 0) {
1648 if (tempTable == "") {
1649 QSettings settings("www.bacula.org", "bat");
1650 settings.beginGroup("Restore");
1651 int counter = settings.value("Counter", 1).toInt();
1652 settings.setValue("Counter", counter+1);
1653 settings.endGroup();
1654 tempTable = "restore_" + QString("%1").arg(qrand()) + "_" + QString("%1").arg(counter);
1655 QString sqlcmd = "CREATE TEMPORARY TABLE " + tempTable + " (JobId INTEGER, FileIndex INTEGER)";
1656 if (mainWin->m_sqlDebug)
1657 Pmsg1(000, "Query cmd : %s ;\n", sqlcmd.toUtf8().data());
1658 QStringList results;
1659 if (!m_console->sql_cmd(sqlcmd, results))
1660 Pmsg1(000, "CREATE TABLE FAILED!!!! %s\n", sqlcmd.toUtf8().data());
1663 if (mainWin->m_rtRestore2Debug) Pmsg1(000, "Version->%i\n", fversion);
1664 QStringList fullPathList = versionFilesMulti.values(fversion);
1665 /* create the command to perform the restore */
1666 foreach(QString ffullPath, fullPathList) {
1667 int fileIndex = fileIndexHash.value(ffullPath);
1668 if (mainWin->m_rtRestore2Debug) Pmsg2(000, " file->%s id %i\n", ffullPath.toUtf8().data(), fileIndex);
1669 QString sqlcmd = "INSERT INTO " + tempTable + " (JobId, FileIndex) VALUES (" + QString("%1").arg(fversion) + ", " + QString("%1").arg(fileIndex) + ")";
1670 if (mainWin->m_rtRestore3Debug)
1671 Pmsg1(000, "Insert cmd : %s\n", sqlcmd.toUtf8().data());
1672 QStringList results;
1673 if (!m_console->sql_cmd(sqlcmd, results))
1674 Pmsg1(000, "INSERT INTO FAILED!!!! %s\n", sqlcmd.toUtf8().data());
1675 prBar2->setValue(++vFMCounter);
1676 } /* foreach fullPathList */
1677 doneKeys.insert(fversion,1);
1678 jobList.append(fversion);
1679 } /* if (doneKeys.value(fversion, 0) == 0) */
1680 } /* while (vFMiter.hasNext()) */
1681 if (tempTable != "") {
1682 /* a table was made, lets run the job */
1683 QString jobOption = " jobid=\"";
1685 /* create a list of jobs comma separated */
1686 foreach (int job, jobList) {
1687 if (first) first = false;
1688 else jobOption += ",";
1689 jobOption += QString("%1").arg(job);
1692 QString cmd = QString("restore");
1694 " client=\"" + m_prevClientCombo + "\"" +
1695 " file=\"?" + tempTable + "\" done";
1696 if (mainWin->m_commandDebug)
1697 Pmsg1(000, "preRestore command \'%s\'\n", cmd.toUtf8().data());
1698 consoleCommand(cmd);
1700 /* turn off the progress widgets */
1701 prBar1->setVisible(false);
1702 prBar2->setVisible(false);
1703 prLabel1->setVisible(false);
1704 prLabel2->setVisible(false);
1707 int restoreTree::mostRecentVersionfromFullPath(QString &fullPath)
1710 QString directory, fileName;
1711 int index = m_slashregex.lastIndexIn(fullPath, -2);
1713 directory = fileName = fullPath;
1714 directory.replace(index+1, fullPath.length()-index-1, "");
1715 fileName.replace(0, index+1, "");
1717 QString msg = QString("length = \"%1\" index = \"%2\" Considering \"%3\" \"%4\"\n")
1718 .arg(fullPath.length()).arg(index).arg(fileName).arg(directory);
1719 Pmsg0(000, msg.toUtf8().data());
1721 /* so now we need the latest version from the database */
1723 "SELECT MAX(Job.JobId)"
1725 " INNER JOIN Filename on (Filename.FilenameId=File.FilenameId)"
1726 " INNER JOIN Path ON (Path.PathId=File.PathId)"
1727 " INNER JOIN Job ON (File.JobId=Job.JobId)"
1728 " WHERE Path.Path='" + directory + "' AND Filename.Name!=''"
1729 " AND Job.Jobid IN (" + m_checkedJobs + ")"
1730 " AND Filename.Name='" + fileName + "'"
1731 " GROUP BY Filename.Name";
1733 if (mainWin->m_sqlDebug) Pmsg1(000, "Query cmd : %s\n", cmd.toUtf8().data());
1734 QStringList results;
1735 if (m_console->sql_cmd(cmd, results)) {
1736 QStringList fieldlist;
1738 /* Iterate through the record returned from the query */
1739 foreach (QString resultline, results) {
1740 /* Iterate through fields in the record */
1742 fieldlist = resultline.split("\t");
1743 foreach (QString field, fieldlist) {
1745 qversion = field.toInt();
1752 } /* if (index != -1) */
1757 int restoreTree::queryFileIndex(QString &fullPath, int jobId)
1760 QString directory, fileName;
1761 int index = m_slashregex.lastIndexIn(fullPath, -2);
1763 directory = fileName = fullPath;
1764 directory.replace(index+1, fullPath.length()-index-1, "");
1765 fileName.replace(0, index+1, "");
1767 QString msg = QString("length = \"%1\" index = \"%2\" Considering \"%3\" \"%4\"\n")
1768 .arg(fullPath.length()).arg(index).arg(fileName).arg(directory);
1769 Pmsg0(000, msg.toUtf8().data());
1771 /* so now we need the latest version from the database */
1776 " INNER JOIN Filename on (Filename.FilenameId=File.FilenameId)"
1777 " INNER JOIN Path ON (Path.PathId=File.PathId)"
1778 " INNER JOIN Job ON (File.JobId=Job.JobId)"
1780 " Path.Path='" + directory + "'"
1781 " AND Filename.Name='" + fileName + "'"
1782 " AND Job.Jobid='" + QString("%1").arg(jobId) + "'"
1783 " GROUP BY File.FileIndex";
1785 if (mainWin->m_sqlDebug) Pmsg1(000, "Query cmd : %s\n", cmd.toUtf8().data());
1786 QStringList results;
1787 if (m_console->sql_cmd(cmd, results)) {
1788 QStringList fieldlist;
1790 /* Iterate through the record returned from the query */
1791 foreach (QString resultline, results) {
1792 /* Iterate through fields in the record */
1794 fieldlist = resultline.split("\t");
1795 foreach (QString field, fieldlist) {
1797 qfileIndex = field.toInt();
1804 } /* if (index != -1) */