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")));
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);
70 gridLayout->addWidget(m_splitter, 0, 0, 1, 1);
72 /* progress widgets */
73 prBar1->setVisible(false);
74 prBar2->setVisible(false);
75 prLabel1->setVisible(false);
76 prLabel2->setVisible(false);
78 /* Set Defaults for check and spin for limits */
79 limitCheckBox->setCheckState(mainWin->m_recordLimitCheck ? Qt::Checked : Qt::Unchecked);
80 limitSpinBox->setValue(mainWin->m_recordLimitVal);
81 daysCheckBox->setCheckState(mainWin->m_daysLimitCheck ? Qt::Checked : Qt::Unchecked);
82 daysSpinBox->setValue(mainWin->m_daysLimitVal);
84 m_nullFileNameId = -1;
87 restoreTree::~restoreTree()
93 * Called from the constructor to set up the page widgets and connections.
95 void restoreTree::setupPage()
97 connect(refreshButton, SIGNAL(pressed()), this, SLOT(refreshButtonPushed()));
98 connect(restoreButton, SIGNAL(pressed()), this, SLOT(restoreButtonPushed()));
99 connect(jobCombo, SIGNAL(currentIndexChanged(int)), this, SLOT(jobComboChanged(int)));
100 connect(jobCombo, SIGNAL(currentIndexChanged(int)), this, SLOT(updateRefresh()));
101 connect(clientCombo, SIGNAL(currentIndexChanged(int)), this, SLOT(updateRefresh()));
102 connect(fileSetCombo, SIGNAL(currentIndexChanged(int)), this, SLOT(updateRefresh()));
103 connect(limitCheckBox, SIGNAL(stateChanged(int)), this, SLOT(updateRefresh()));
104 connect(daysCheckBox, SIGNAL(stateChanged(int)), this, SLOT(updateRefresh()));
105 connect(daysSpinBox, SIGNAL(valueChanged(int)), this, SLOT(updateRefresh()));
106 connect(limitSpinBox, SIGNAL(valueChanged(int)), this, SLOT(updateRefresh()));
107 connect(directoryTree, SIGNAL(currentItemChanged(QTreeWidgetItem *, QTreeWidgetItem *)),
108 this, SLOT(directoryCurrentItemChanged(QTreeWidgetItem *, QTreeWidgetItem *)));
109 connect(directoryTree, SIGNAL(itemExpanded(QTreeWidgetItem *)),
110 this, SLOT(directoryItemExpanded(QTreeWidgetItem *)));
111 connect(directoryTree, SIGNAL(itemChanged(QTreeWidgetItem *, int)),
112 this, SLOT(directoryItemChanged(QTreeWidgetItem *, int)));
113 connect(fileTable, SIGNAL(currentItemChanged(QTableWidgetItem *, QTableWidgetItem *)),
114 this, SLOT(fileCurrentItemChanged(QTableWidgetItem *, QTableWidgetItem *)));
115 connect(jobTable, SIGNAL(cellClicked(int, int)),
116 this, SLOT(jobTableCellClicked(int, int)));
118 QStringList titles = QStringList() << "Directories";
119 directoryTree->setHeaderLabels(titles);
120 clientCombo->addItems(m_console->client_list);
121 fileSetCombo->addItem("Any");
122 fileSetCombo->addItems(m_console->fileset_list);
123 jobCombo->addItem("Any");
124 jobCombo->addItems(m_console->job_list);
126 directoryTree->setContextMenuPolicy(Qt::ActionsContextMenu);
129 void restoreTree::updateRefresh()
131 if (mainWin->m_rtPopDirDebug) Pmsg2(000, "testing prev=\"%s\" current=\"%s\"\n", m_prevJobCombo.toUtf8().data(), jobCombo->currentText().toUtf8().data());
132 m_dropdownChanged = (m_prevJobCombo != jobCombo->currentText())
133 || (m_prevClientCombo != clientCombo->currentText())
134 || (m_prevFileSetCombo != fileSetCombo->currentText()
135 || (m_prevLimitSpinBox != limitSpinBox->value())
136 || (m_prevDaysSpinBox != daysSpinBox->value())
137 || (m_prevLimitCheckState != limitCheckBox->checkState())
138 || (m_prevDaysCheckState != daysCheckBox->checkState())
140 if (m_dropdownChanged) {
141 if (mainWin->m_rtPopDirDebug) Pmsg0(000, "In restoreTree::updateRefresh Is CHANGED\n");
142 refreshLabel->setText("Refresh From Re-Select");
144 if (mainWin->m_rtPopDirDebug) Pmsg0(000, "In restoreTree::updateRefresh Is not Changed\n");
145 refreshLabel->setText("Refresh From JobChecks");
150 * When refresh button is pushed, perform a query getting the directories and
151 * use parseDirectory and addDirectory to populate the directory tree with items.
153 void restoreTree::populateDirectoryTree()
157 directoryTree->clear();
159 fileTable->setRowCount(0);
160 fileTable->setColumnCount(0);
161 versionTable->clear();
162 versionTable->setRowCount(0);
163 versionTable->setColumnCount(0);
164 m_fileExceptionHash.clear();
165 m_fileExceptionMulti.clear();
166 m_versionExceptionHash.clear();
167 m_directoryIconStateHash.clear();
170 int taskcount = 3, ontask = 1;
171 if (m_dropdownChanged) taskcount += 1;
173 /* Set progress bars and repaint */
174 prBar1->setVisible(true);
175 prBar1->setRange(0,taskcount);
177 prLabel1->setText("Task " + QString("%1").arg(ontask)+ " of " + QString("%1").arg(taskcount));
178 prLabel1->setVisible(true);
179 prBar2->setVisible(true);
180 prBar2->setRange(0,0);
181 prLabel2->setText("Querying Database");
182 prLabel2->setVisible(true);
185 if (m_dropdownChanged) {
186 m_prevJobCombo = jobCombo->currentText();
187 m_prevClientCombo = clientCombo->currentText();
188 m_prevFileSetCombo = fileSetCombo->currentText();
189 m_prevLimitSpinBox = limitSpinBox->value();
190 m_prevDaysSpinBox = daysSpinBox->value();
191 m_prevLimitCheckState = limitCheckBox->checkState();
192 m_prevDaysCheckState = daysCheckBox->checkState();
194 prBar1->setValue(ontask++);
195 prLabel1->setText("Task " + QString("%1").arg(ontask)+ " of " + QString("%1").arg(taskcount));
197 prBar2->setRange(0,0);
198 prLabel2->setText("Querying Jobs");
201 setJobsCheckedList();
203 if (mainWin->m_rtPopDirDebug) Pmsg0(000, "Repopulating from checks in Job Table\n");
204 setJobsCheckedList();
207 if (m_checkedJobs != "") {
208 /* First get the filenameid of where the nae is null. These will be the directories
209 * This could be done in a subquery but postgres's query analyzer won't do the right
210 * thing like I want */
211 if (m_nullFileNameId == -1) {
212 QString cmd = "SELECT FilenameId FROM Filename WHERE name=''";
213 if (mainWin->m_sqlDebug)
214 Pmsg1(000, "Query cmd : %s\n", cmd.toUtf8().data());
216 if (m_console->sql_cmd(cmd, qres)) {
218 QStringList fieldlist = qres[0].split("\t");
219 QString field = fieldlist[0];
221 int val = field.toInt(&ok, 10);
222 if (ok) m_nullFileNameId = val;
226 /* now create the query to get the list of paths */
228 "SELECT DISTINCT Path.Path AS Path, File.PathId AS PathId"
230 " INNER JOIN Path ON (File.PathId=Path.PathId)";
231 if (m_nullFileNameId != -1)
232 cmd += " WHERE File.FilenameId=" + QString("%1").arg(m_nullFileNameId);
234 cmd += " WHERE File.FilenameId IN (SELECT FilenameId FROM Filename WHERE Name='')";
235 cmd += " AND File.Jobid IN (" + m_checkedJobs + ")"
237 if (mainWin->m_sqlDebug)
238 Pmsg1(000, "Query cmd : %s\n", cmd.toUtf8().data());
239 prBar1->setValue(ontask++);
240 prLabel1->setText("Task " + QString("%1").arg(ontask) + " of " + QString("%1").arg(taskcount));
242 prBar2->setRange(0,0);
243 prLabel2->setText("Querying for Directories");
246 m_directoryPathIdHash.clear();
247 bool querydone = false;
248 if (m_console->sql_cmd(cmd, results)) {
251 prLabel2->setText("Processing Directories");
252 prBar2->setRange(0,results.count());
255 if (mainWin->m_miscDebug)
256 Pmsg1(000, "Done with query %i results\n", results.count());
257 QStringList fieldlist;
258 foreach(QString resultline, results) {
259 /* Update progress bar periodically */
260 if ((++m_debugCnt && 0x3FF) == 0) {
261 prBar2->setValue(m_debugCnt);
263 fieldlist = resultline.split("\t");
266 /* Iterate through fields in the record */
267 foreach (field, fieldlist) {
268 if (fieldcnt == 0 ) {
269 parseDirectory(field);
270 } else if (fieldcnt == 1) {
272 int pathid = field.toInt(&ok, 10);
274 m_directoryPathIdHash.insert(fieldlist[0], pathid);
281 QMessageBox::warning(this, tr("Bat"),
282 tr("No jobs were selected in the job query !!!.\n"
283 "Press OK to continue?"),
286 prBar1->setVisible(false);
287 prBar2->setVisible(false);
288 prLabel1->setVisible(false);
289 prLabel2->setVisible(false);
293 * Function to set m_checkedJobs from the jobs that are checked in the table
296 void restoreTree::setJobsCheckedList()
298 m_JobsCheckedList = "";
300 /* Update the items in the version table */
301 int cnt = jobTable->rowCount();
302 for (int row=0; row<cnt; row++) {
303 QTableWidgetItem* jobItem = jobTable->item(row, 0);
304 if (jobItem->checkState() == Qt::Checked) {
306 m_JobsCheckedList += ",";
307 m_JobsCheckedList += jobItem->text();
309 jobItem->setBackground(Qt::green);
311 if (jobItem->flags())
312 jobItem->setBackground(Qt::gray);
314 jobItem->setBackground(Qt::darkYellow);
317 m_checkedJobs = m_JobsCheckedList;
321 * Function to parse a directory into all possible subdirectories, then add to
324 void restoreTree::parseDirectory(QString &dir_in)
326 /* m_debugTrap is to only print debugs for a few occurennces of calling parseDirectory
327 * instead of printing out what could potentially a whole bunch */
330 /* Truncate everything after the last / */
331 if (dir_in.right(1) != "/") {
332 dir_in.truncate(dir_in.lastIndexOf("/") + 1);
334 if ((mainWin->m_miscDebug) && (m_debugTrap))
335 Pmsg1(000, "parsing %s\n", dir_in.toUtf8().data());
337 /* split and add if not in yet */
338 QString direct, path;
341 QStringList pathAfter, dirAfter;
342 /* start from the end, turn /etc/somedir/subdir/ into /etc/somedir and subdir/
343 * if not added into tree, then try /etc/ and somedir/ if not added, then try
344 * / and etc/ . That should succeed, then add the ones that failed in reverse */
345 while (((index = dir_in.lastIndexOf("/", -2)) != -1) && (!done)) {
346 direct = path = dir_in;
347 path.replace(index+1, dir_in.length()-index-1,"");
348 direct.replace(0, index+1, "");
349 if ((mainWin->m_miscDebug) && (m_debugTrap)) {
350 QString msg = QString("length = \"%1\" index = \"%2\" Adding \"%3\" \"%4\"\n")
351 .arg(dir_in.length()).arg(index).arg(path).arg(direct);
352 Pmsg0(000, msg.toUtf8().data());
354 if (addDirectory(path, direct)) done = true;
356 if ((mainWin->m_miscDebug) && (m_debugTrap))
357 Pmsg0(000, "Saving for later\n");
358 pathAfter.prepend(path);
359 dirAfter.prepend(direct);
364 for (int k=0; k<pathAfter.count(); k++) {
365 if (addDirectory(pathAfter[k], dirAfter[k]))
366 if ((mainWin->m_miscDebug) && (m_debugTrap))
367 Pmsg2(000, "Adding After %s %s\n", pathAfter[k].toUtf8().data(), dirAfter[k].toUtf8().data());
369 if ((mainWin->m_miscDebug) && (m_debugTrap))
370 Pmsg2(000, "Error Adding %s %s\n", pathAfter[k].toUtf8().data(), dirAfter[k].toUtf8().data());
376 * Function called from fill directory when a directory is found to see if this
377 * directory exists in the directory pane and then add it to the directory pane
379 bool restoreTree::addDirectory(QString &m_cwd, QString &newdirr)
381 QString newdir = newdirr;
382 QString fullPath = m_cwd + newdirr;
383 bool ok = true, added = false;
385 if ((mainWin->m_miscDebug) && (m_debugTrap)) {
386 QString msg = QString("In addDirectory cwd \"%1\" newdir \"%2\"\n")
389 Pmsg0(000, msg.toUtf8().data());
393 /* add unix '/' directory first */
394 if (m_dirPaths.empty() && isWin32Path(fullPath)) {
396 QTreeWidgetItem *item = new QTreeWidgetItem(directoryTree);
398 item->setText(0, text.toUtf8().data());
399 item->setData(0, Qt::UserRole, QVariant(text));
400 item->setData(1, Qt::UserRole, QVariant(Qt::Unchecked));
401 item->setIcon(0, QIcon(QString::fromUtf8(":images/folder.png")));
402 if ((mainWin->m_miscDebug) && (m_debugTrap)) {
403 Pmsg1(000, "Pre Inserting %s\n", text.toUtf8().data());
405 m_dirPaths.insert(text, item);
407 /* no need to check for windows drive if unix */
408 if (isWin32Path(m_cwd)) {
409 if (!m_dirPaths.contains(m_cwd)) {
410 /* this is a windows drive add the base widget */
411 QTreeWidgetItem *item = new QTreeWidgetItem(directoryTree);
412 item->setText(0, m_cwd);
413 item->setData(0, Qt::UserRole, QVariant(fullPath));
414 item->setData(1, Qt::UserRole, QVariant(Qt::Unchecked));
415 item->setIcon(0, QIcon(QString::fromUtf8(":images/folder.png")));
416 if ((mainWin->m_miscDebug) && (m_debugTrap)) {
417 Pmsg0(000, "Added Base \"letter\":/\n");
419 m_dirPaths.insert(m_cwd, item);
424 /* is it already existent ?? */
425 if (!m_dirPaths.contains(fullPath)) {
426 QTreeWidgetItem *item = NULL;
427 QTreeWidgetItem *parent = m_dirPaths.value(m_cwd);
429 /* new directories to add */
430 item = new QTreeWidgetItem(parent);
431 item->setText(0, newdir.toUtf8().data());
432 item->setData(0, Qt::UserRole, QVariant(fullPath));
433 item->setCheckState(0, Qt::Unchecked);
434 /* Store the current state of the check status in column 1, which at
435 * this point has no text*/
436 item->setData(1, Qt::UserRole, QVariant(Qt::Unchecked));
439 if ((mainWin->m_miscDebug) && (m_debugTrap)) {
440 QString msg = QString("In else of if parent cwd \"%1\" newdir \"%2\"\n")
443 Pmsg0(000, msg.toUtf8().data());
446 /* insert into hash */
448 if ((mainWin->m_miscDebug) && (m_debugTrap)) {
449 Pmsg1(000, "Inserting %s\n", fullPath.toUtf8().data());
451 m_dirPaths.insert(fullPath, item);
459 * Virtual function which is called when this page is visible on the stack
461 void restoreTree::currentStackItem()
464 if (!m_console->preventInUseConnect())
472 * Populate the tree when refresh button pushed.
474 void restoreTree::refreshButtonPushed()
476 populateDirectoryTree();
480 * Set the values of non-job combo boxes to the job defaults
482 void restoreTree::jobComboChanged(int)
484 if (jobCombo->currentText() == "Any") {
485 fileSetCombo->setCurrentIndex(fileSetCombo->findText("Any", Qt::MatchExactly));
488 job_defaults job_defs;
491 job_defs.job_name = jobCombo->currentText();
492 if (m_console->get_job_defaults(job_defs)) {
493 fileSetCombo->setCurrentIndex(fileSetCombo->findText(job_defs.fileset_name, Qt::MatchExactly));
494 clientCombo->setCurrentIndex(clientCombo->findText(job_defs.client_name, Qt::MatchExactly));
499 * Function to populate the file list table
501 void restoreTree::directoryCurrentItemChanged(QTreeWidgetItem *item, QTreeWidgetItem *)
507 /* Also clear the version table here */
508 versionTable->clear();
509 versionFileLabel->setText("");
510 versionTable->setRowCount(0);
511 versionTable->setColumnCount(0);
513 QStringList headerlist = (QStringList() << "File Name" << "Filename Id");
514 fileTable->setColumnCount(headerlist.size());
515 fileTable->setHorizontalHeaderLabels(headerlist);
516 fileTable->setRowCount(0);
518 m_fileCheckStateList.clear();
519 disconnect(fileTable, SIGNAL(itemChanged(QTableWidgetItem *)),
520 this, SLOT(fileTableItemChanged(QTableWidgetItem *)));
521 QBrush blackBrush(Qt::black);
522 QString directory = item->data(0, Qt::UserRole).toString();
523 directoryLabel->setText("Present Working Directory : " + directory);
524 int pathid = m_directoryPathIdHash.value(directory, -1);
527 "SELECT DISTINCT Filename.Name AS FileName, Filename.FilenameId AS FilenameId"
529 " INNER JOIN Filename on (Filename.FilenameId=File.FilenameId)"
530 " WHERE File.PathId=" + QString("%1").arg(pathid) +
531 " AND File.Jobid IN (" + m_checkedJobs + ")"
532 " AND Filename.Name!=''"
533 " ORDER BY FileName";
535 if (mainWin->m_sqlDebug) {
536 Pmsg1(000, "Query cmd : %s\n", cmd.toUtf8().data());
539 if (m_console->sql_cmd(cmd, results)) {
541 QTableWidgetItem* tableItem;
543 QStringList fieldlist;
544 fileTable->setRowCount(results.size());
547 /* Iterate through the record returned from the query */
548 foreach (QString resultline, results) {
549 /* Iterate through fields in the record */
551 fieldlist = resultline.split("\t");
552 foreach (field, fieldlist) {
553 field = field.trimmed(); /* strip leading & trailing spaces */
554 tableItem = new QTableWidgetItem(field, 1);
555 /* Possible flags are Qt::ItemFlags flag = Qt::ItemIsSelectable | Qt::ItemIsEditablex
556 * | Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled | Qt::ItemIsUserCheckable
557 * | Qt::ItemIsEnabled | Qt::ItemIsTristate; */
558 tableItem->setForeground(blackBrush);
559 /* Just in case a column ever gets added */
561 Qt::ItemFlags flag = Qt::ItemIsUserCheckable | Qt::ItemIsEnabled | Qt::ItemIsTristate;
562 tableItem->setFlags(flag);
563 tableItem->setData(Qt::UserRole, QVariant(directory));
564 fileTable->setItem(row, column, tableItem);
565 m_fileCheckStateList.append(Qt::Unchecked);
566 tableItem->setCheckState(Qt::Unchecked);
567 } else if (column == 1) {
568 Qt::ItemFlags flag = Qt::ItemIsEnabled;
569 tableItem->setFlags(flag);
571 int filenameid = field.toInt(&ok, 10);
572 if (!ok) filenameid = -1;
573 tableItem->setData(Qt::UserRole, QVariant(filenameid));
574 fileTable->setItem(row, column, tableItem);
580 fileTable->setRowCount(row);
582 fileTable->resizeColumnsToContents();
583 fileTable->resizeRowsToContents();
584 fileTable->verticalHeader()->hide();
585 fileTable->hideColumn(1);
586 if (mainWin->m_rtDirCurICDebug) Pmsg0(000, "will update file table checks\n");
587 updateFileTableChecks();
588 } else if (mainWin->m_sqlDebug)
589 Pmsg1(000, "did not perform query, pathid=%i not found\n", pathid);
590 connect(fileTable, SIGNAL(itemChanged(QTableWidgetItem *)),
591 this, SLOT(fileTableItemChanged(QTableWidgetItem *)));
595 * Function to populate the version table
597 void restoreTree::fileCurrentItemChanged(QTableWidgetItem *currentFileTableItem, QTableWidgetItem *)
599 if (currentFileTableItem == NULL)
602 int currentRow = fileTable->row(currentFileTableItem);
603 QTableWidgetItem *fileTableItem = fileTable->item(currentRow, 0);
604 QTableWidgetItem *fileNameIdTableItem = fileTable->item(currentRow, 1);
605 int fileNameId = fileNameIdTableItem->data(Qt::UserRole).toInt();
607 m_versionCheckStateList.clear();
608 disconnect(versionTable, SIGNAL(itemChanged(QTableWidgetItem *)),
609 this, SLOT(versionTableItemChanged(QTableWidgetItem *)));
611 QString file = fileTableItem->text();
612 versionFileLabel->setText(file);
613 QString directory = fileTableItem->data(Qt::UserRole).toString();
615 QBrush blackBrush(Qt::black);
617 QStringList headerlist = (QStringList() << "Job Id" << "Type" << "End Time" << "Md5" << "FileId");
618 versionTable->clear();
619 versionTable->setColumnCount(headerlist.size());
620 versionTable->setHorizontalHeaderLabels(headerlist);
621 versionTable->setRowCount(0);
623 int pathid = m_directoryPathIdHash.value(directory, -1);
624 if ((pathid != -1) && (fileNameId != -1)) {
626 "SELECT Job.JobId AS JobId, Job.Level AS Type, Job.EndTime AS EndTime, File.Md5 AS MD5, File.FileId AS FileId"
628 " INNER JOIN Filename on (Filename.FilenameId=File.FilenameId)"
629 " INNER JOIN Path ON (Path.PathId=File.PathId)"
630 " INNER JOIN Job ON (File.JobId=Job.JobId)"
631 " WHERE Path.PathId=" + QString("%1").arg(pathid) +
632 //" AND Filename.Name='" + file + "'"
633 " AND Filename.FilenameId=" + QString("%1").arg(fileNameId) +
634 " AND Job.Jobid IN (" + m_checkedJobs + ")"
635 " ORDER BY Job.EndTime DESC";
637 if (mainWin->m_sqlDebug)
638 Pmsg1(000, "Query cmd : %s\n", cmd.toUtf8().data());
640 if (m_console->sql_cmd(cmd, results)) {
642 QTableWidgetItem* tableItem;
644 QStringList fieldlist;
645 versionTable->setRowCount(results.size());
648 /* Iterate through the record returned from the query */
649 foreach (QString resultline, results) {
650 fieldlist = resultline.split("\t");
652 /* remove directory */
653 if (fieldlist[0].trimmed() != "") {
654 /* Iterate through fields in the record */
655 foreach (field, fieldlist) {
656 field = field.trimmed(); /* strip leading & trailing spaces */
657 tableItem = new QTableWidgetItem(field, 1);
658 tableItem->setFlags(0);
659 tableItem->setForeground(blackBrush);
660 tableItem->setData(Qt::UserRole, QVariant(directory));
661 versionTable->setItem(row, column, tableItem);
664 Qt::ItemFlags flag = Qt::ItemIsUserCheckable | Qt::ItemIsEnabled | Qt::ItemIsTristate;
665 tableItem->setFlags(flag);
666 m_versionCheckStateList.append(Qt::Unchecked);
667 tableItem->setCheckState(Qt::Unchecked);
675 versionTable->resizeColumnsToContents();
676 versionTable->resizeRowsToContents();
677 versionTable->verticalHeader()->hide();
678 updateVersionTableChecks();
680 if (mainWin->m_sqlDebug)
681 Pmsg2(000, "not querying : pathid=%i fileNameId=%i\n", pathid, fileNameId);
683 connect(versionTable, SIGNAL(itemChanged(QTableWidgetItem *)),
684 this, SLOT(versionTableItemChanged(QTableWidgetItem *)));
688 * Save user settings associated with this page
690 void restoreTree::writeSettings()
692 QSettings settings(m_console->m_dir->name(), "bat");
693 settings.beginGroup(m_groupText);
694 settings.setValue(m_splitText, m_splitter->saveState());
699 * Read and restore user settings associated with this page
701 void restoreTree::readSettings()
703 m_groupText = "RestoreTreePage";
704 m_splitText = "splitterSizes_1";
705 QSettings settings(m_console->m_dir->name(), "bat");
706 settings.beginGroup(m_groupText);
707 m_splitter->restoreState(settings.value(m_splitText).toByteArray());
712 * This is a funcion to accomplish the one thing I struggled to figure out what
713 * was taking so long. It add the icons, but after the tree is made. Seemed to
714 * work fast after changing from png to png file for graphic.
716 void restoreTree::directoryItemExpanded(QTreeWidgetItem *item)
718 int childCount = item->childCount();
719 for (int i=0; i<childCount; i++) {
720 QTreeWidgetItem *child = item->child(i);
721 if (child->icon(0).isNull())
722 child->setIcon(0, QIcon(QString::fromUtf8(":images/folder.png")));
727 * I wanted a table to show what jobs meet the criterion and are being used to
728 * populate the directory tree and file and version tables.
730 void restoreTree::populateJobTable()
732 QBrush blackBrush(Qt::black);
734 if (mainWin->m_rtPopDirDebug) Pmsg0(000, "Repopulating the Job Table\n");
735 QStringList headerlist = (QStringList() << "Job Id" << "End Time" << "Level" << "Name" << "Purged" << "TU" << "TD");
736 m_toggleUpIndex = headerlist.indexOf("TU");
737 m_toggleDownIndex = headerlist.indexOf("TD");
738 int purgedIndex = headerlist.indexOf("Purged");
740 jobTable->setColumnCount(headerlist.size());
741 jobTable->setHorizontalHeaderLabels(headerlist);
743 "SELECT Job.Jobid AS Id, Job.EndTime AS EndTime, Job.Level AS Level, Job.Name AS JobName, Job.purgedfiles AS Purged"
745 /* INNER JOIN FileSet eliminates all restore jobs */
746 " INNER JOIN Client ON (Job.ClientId=Client.ClientId)"
747 " INNER JOIN FileSet ON (Job.FileSetId=FileSet.FileSetId)"
749 " Client.Name='" + clientCombo->currentText() + "'";
750 if ((jobCombo->currentIndex() >= 0) && (jobCombo->currentText() != "Any")) {
751 jobQuery += " AND Job.name = '" + jobCombo->currentText() + "'";
753 if ((fileSetCombo->currentIndex() >= 0) && (fileSetCombo->currentText() != "Any")) {
754 jobQuery += " AND FileSet.FileSet='" + fileSetCombo->currentText() + "'";
756 /* If Limit check box For limit by days is checked */
757 if (daysCheckBox->checkState() == Qt::Checked) {
758 QDateTime stamp = QDateTime::currentDateTime().addDays(-daysSpinBox->value());
759 QString since = stamp.toString(Qt::ISODate);
760 jobQuery += " AND Job.Starttime>'" + since + "'";
762 //jobQuery += " AND Job.purgedfiles=0";
763 jobQuery += " ORDER BY Job.EndTime DESC";
764 /* If Limit check box for limit records returned is checked */
765 if (limitCheckBox->checkState() == Qt::Checked) {
767 limit.setNum(limitSpinBox->value());
768 jobQuery += " LIMIT " + limit;
770 if (mainWin->m_sqlDebug)
771 Pmsg1(000, "Query cmd : %s\n", jobQuery.toUtf8().data());
774 if (m_console->sql_cmd(jobQuery, results)) {
776 QTableWidgetItem* tableItem;
778 QStringList fieldlist;
779 jobTable->setRowCount(results.size());
782 /* Iterate through the record returned from the query */
783 foreach (QString resultline, results) {
784 fieldlist = resultline.split("\t");
786 /* remove directory */
787 if (fieldlist[0].trimmed() != "") {
788 /* Iterate through fields in the record */
789 foreach (field, fieldlist) {
790 field = field.trimmed(); /* strip leading & trailing spaces */
792 tableItem = new QTableWidgetItem(field, 1);
793 tableItem->setFlags(0);
794 tableItem->setForeground(blackBrush);
795 jobTable->setItem(row, column, tableItem);
798 int purged = fieldlist[purgedIndex].toInt(&ok, 10);
799 if (!((ok) && (purged == 1))) {
800 Qt::ItemFlags flag = Qt::ItemIsUserCheckable | Qt::ItemIsEnabled | Qt::ItemIsTristate;
801 tableItem->setFlags(flag);
802 tableItem->setCheckState(Qt::Checked);
803 tableItem->setBackground(Qt::green);
805 tableItem->setFlags(0);
806 tableItem->setCheckState(Qt::Unchecked);
812 tableItem = new QTableWidgetItem(QIcon(QString::fromUtf8(":images/go-up.png")), "", 1);
813 tableItem->setFlags(0);
814 tableItem->setForeground(blackBrush);
815 jobTable->setItem(row, column, tableItem);
817 tableItem = new QTableWidgetItem(QIcon(QString::fromUtf8(":images/go-down.png")), "", 1);
818 tableItem->setFlags(0);
819 tableItem->setForeground(blackBrush);
820 jobTable->setItem(row, column, tableItem);
825 jobTable->resizeColumnsToContents();
826 jobTable->resizeRowsToContents();
827 jobTable->verticalHeader()->hide();
828 jobTable->hideColumn(purgedIndex);
831 void restoreTree::jobTableCellClicked(int row, int column)
833 if (column == m_toggleUpIndex){
835 for (cnt=0; cnt<row+1; cnt++) {
836 QTableWidgetItem *item = jobTable->item(cnt, 0);
838 Qt::CheckState state = item->checkState();
839 if (state == Qt::Checked)
840 item->setCheckState(Qt::Unchecked);
841 else if (state == Qt::Unchecked)
842 item->setCheckState(Qt::Checked);
846 if (column == m_toggleDownIndex){
847 int cnt, max = jobTable->rowCount();
848 for (cnt=row; cnt<max; cnt++) {
849 QTableWidgetItem *item = jobTable->item(cnt, 0);
851 Qt::CheckState state = item->checkState();
852 if (state == Qt::Checked)
853 item->setCheckState(Qt::Unchecked);
854 else if (state == Qt::Unchecked)
855 item->setCheckState(Qt::Checked);
862 * When a directory item is "changed" check the state of the checkable item
863 * to see if it is different than what it was which is stored in Qt::UserRole
864 * of the 2nd column, column 1, of the tree widget.
866 void restoreTree::directoryItemChanged(QTreeWidgetItem *item, int /*column*/)
868 Qt::CheckState prevState = (Qt::CheckState)item->data(1, Qt::UserRole).toInt();
869 Qt::CheckState curState = item->checkState(0);
870 QTreeWidgetItem* parent = item->parent();
871 Qt::CheckState parState;
872 if (parent) parState = parent->checkState(0);
873 else parState = (Qt::CheckState)3;
874 if (mainWin->m_rtDirICDebug) {
875 QString msg = QString("directory item OBJECT has changed prev=%1 cur=%2 par=%3 dir=%4\n")
876 .arg(prevState).arg(curState).arg(parState).arg(item->text(0));
877 Pmsg1(000, "%s", msg.toUtf8().data()); }
878 /* I only care when the check state changes */
879 if (prevState == curState) {
880 if (mainWin->m_rtDirICDebug) Pmsg0(000, "Returning Early\n");
884 if ((prevState == Qt::Unchecked) && (curState == Qt::Checked) && (parState != Qt::Unchecked)) {
885 if (mainWin->m_rtDirICDebug) Pmsg0(000, "Disconnected Setting to Qt::PartiallyChecked\n");
886 directoryTreeDisconnectedSet(item, Qt::PartiallyChecked);
887 curState = Qt::PartiallyChecked;
889 if ((prevState == Qt::PartiallyChecked) && (curState == Qt::Checked)) {
890 if (mainWin->m_rtDirICDebug) Pmsg0(000, "Disconnected Setting to Qt::Unchecked\n");
891 directoryTreeDisconnectedSet(item, Qt::Unchecked);
892 curState = Qt::Unchecked;
894 if (mainWin->m_rtDirICDebug) {
895 QString msg = QString("directory item CHECKSTATE has changed prev=%1 cur=%2 par=%3 dir=%4\n")
896 .arg(prevState).arg(curState).arg(parState).arg(item->text(0));
897 Pmsg1(000, "%s", msg.toUtf8().data()); }
899 item->setData(1, Qt::UserRole, QVariant(curState));
900 Qt::CheckState childState = curState;
901 if (childState == Qt::Checked)
902 childState = Qt::PartiallyChecked;
903 setCheckofChildren(item, childState);
905 /* Remove items from the exception lists. The multi exception list is my index
906 * of what exceptions can be removed when the directory is known*/
907 QString directory = item->data(0, Qt::UserRole).toString();
908 QStringList fullPathList = m_fileExceptionMulti.values(directory);
909 int fullPathListCount = fullPathList.count();
910 if ((mainWin->m_rtDirICDebug) && fullPathListCount) Pmsg2(000, "Will attempt to remove file exceptions for %s count %i\n", directory.toUtf8().data(), fullPathListCount);
911 foreach (QString fullPath, fullPathList) {
912 /* If there is no value in the hash for the key fullPath a value of 3 will be returned
913 * which will match no Qt::xxx values */
914 Qt::CheckState hashState = m_fileExceptionHash.value(fullPath, (Qt::CheckState)3);
915 if (mainWin->m_rtDirICDebug) Pmsg2(000, "hashState=%i childState=%i\n", hashState, childState);
916 if (hashState == Qt::Unchecked) {
917 fileExceptionRemove(fullPath, directory);
918 m_versionExceptionHash.remove(fullPath);
919 if (mainWin->m_rtDirICDebug) Pmsg0(000, "Attempted Removal A\n");
921 if (hashState == Qt::Checked) {
922 fileExceptionRemove(fullPath, directory);
923 m_versionExceptionHash.remove(fullPath);
924 if (mainWin->m_rtDirICDebug) Pmsg0(000, "Attempted Removal B\n");
928 if (item == directoryTree->currentItem()) {
929 if (mainWin->m_rtDirICDebug) Pmsg0(000, "Will attempt to update File Table Checks\n");
930 updateFileTableChecks();
931 versionTable->clear();
932 versionTable->setRowCount(0);
933 versionTable->setColumnCount(0);
935 if (mainWin->m_rtDirICDebug) Pmsg0(000, "Returning At End\n");
939 * When a directory item check state is changed, this function iterates through
940 * all subdirectories and sets all to the passed state, which is either partially
941 * checked or unchecked.
943 void restoreTree::setCheckofChildren(QTreeWidgetItem *item, Qt::CheckState state)
946 childCount = item->childCount();
947 for (int i=0; i<childCount; i++) {
948 QTreeWidgetItem *child = item->child(i);
949 child->setData(1, Qt::UserRole, QVariant(state));
950 child->setCheckState(0, state);
951 setCheckofChildren(child, state);
956 * When a File Table Item is "changed" check to see if the state of the checkable
957 * item has changed which is stored in m_fileCheckStateList
958 * If changed store in a hash m_fileExceptionHash that whether this file should be
960 * Called as a slot, connected after populated (after directory current changed called)
962 void restoreTree::fileTableItemChanged(QTableWidgetItem *item)
964 /* get the previous and current check states */
965 int row = fileTable->row(item);
966 Qt::CheckState prevState;
967 /* prevent a segfault */
968 prevState = m_fileCheckStateList[row];
969 Qt::CheckState curState = item->checkState();
971 /* deterimine the default state from the state of the directory */
972 QTreeWidgetItem *dirTreeItem = directoryTree->currentItem();
973 Qt::CheckState dirState = (Qt::CheckState)dirTreeItem->data(1, Qt::UserRole).toInt();
974 Qt::CheckState defState = Qt::PartiallyChecked;
975 if (dirState == Qt::Unchecked) defState = Qt::Unchecked;
977 /* determine if it is already in the m_fileExceptionHash */
978 QString directory = directoryTree->currentItem()->data(0, Qt::UserRole).toString();
979 QString file = item->text();
980 QString fullPath = directory + file;
981 Qt::CheckState hashState = m_fileExceptionHash.value(fullPath, (Qt::CheckState)3);
982 int verJobNum = m_versionExceptionHash.value(fullPath, 0);
984 if (mainWin->m_rtFileTabICDebug) {
985 QString msg = QString("filerow=%1 prev=%2 cur=%3 def=%4 hash=%5 dir=%6 verJobNum=%7\n")
986 .arg(row).arg(prevState).arg(curState).arg(defState).arg(hashState).arg(dirState).arg(verJobNum);
987 Pmsg1(000, "%s", msg.toUtf8().data()); }
989 /* Remove the hash if currently checked previously unchecked and directory is checked or partial */
990 if ((prevState == Qt::Checked) && (curState == Qt::Unchecked) && (dirState == Qt::Unchecked)) {
991 /* it can behave as defaulted so current of unchecked is fine */
992 if (mainWin->m_rtFileTabICDebug) Pmsg0(000, "Will fileExceptionRemove and m_versionExceptionHash.remove here\n");
993 fileExceptionRemove(fullPath, directory);
994 m_versionExceptionHash.remove(fullPath);
995 } else if ((prevState == Qt::PartiallyChecked) && (curState == Qt::Checked) && (dirState != Qt::Unchecked) && (verJobNum == 0)) {
996 if (mainWin->m_rtFileTabICDebug) Pmsg0(000, "Will fileExceptionInsert here\n");
997 fileExceptionInsert(fullPath, directory, Qt::Unchecked);
998 } else if ((prevState == Qt::Unchecked) && (curState == Qt::Checked) && (dirState != Qt::Unchecked) && (verJobNum == 0) && (defState == Qt::PartiallyChecked)) {
999 /* filerow=2 prev=0 cur=2 def=1 hash=0 dir=2 verJobNum=0 */
1000 if (mainWin->m_rtFileTabICDebug) Pmsg0(000, "Will fileExceptionRemove here\n");
1001 fileExceptionRemove(fullPath, directory);
1002 } else if ((prevState == Qt::Checked) && (curState == Qt::Unchecked) && (defState == Qt::PartiallyChecked) && (verJobNum != 0) && (hashState == Qt::Checked)) {
1003 /* Check dir, check version, attempt uncheck in file
1004 * filerow=4 prev=2 cur=0 def=1 hash=2 dir=2 verJobNum=53 */
1005 if (mainWin->m_rtFileTabICDebug) Pmsg0(000, "Will fileExceptionRemove and m_versionExceptionHash.remove here\n");
1006 fileExceptionRemove(fullPath, directory);
1007 m_versionExceptionHash.remove(fullPath);
1008 } else if ((prevState == Qt::Unchecked) && (curState == Qt::Checked) && (dirState != Qt::Unchecked) && (verJobNum == 0)) {
1009 /* filerow=0 prev=0 cur=2 def=1 hash=0 dirState=2 verJobNum */
1010 if (mainWin->m_rtFileTabICDebug) Pmsg0(000, "Will Not remove here\n");
1011 } else if (prevState != curState) {
1012 if (mainWin->m_rtFileTabICDebug) Pmsg2(000, " THE STATE OF THE Check has changed, Setting StateList[%i] to %i\n", row, curState);
1013 /* A user did not set the check state to Partially checked, ignore if so */
1014 if (curState != Qt::PartiallyChecked) {
1015 if ((defState == Qt::Unchecked) && (prevState == Qt::PartiallyChecked) && (curState == Qt::Unchecked)) {
1016 if (mainWin->m_rtFileTabICDebug) Pmsg0(000, " got here\n");
1018 if (mainWin->m_rtFileTabICDebug) Pmsg2(000, " Inserting into m_fileExceptionHash %s, %i\n", fullPath.toUtf8().data(), curState);
1019 fileExceptionInsert(fullPath, directory, curState);
1022 if (mainWin->m_rtFileTabICDebug) Pmsg1(000, "Removing version hash for %s\n", fullPath.toUtf8().data());
1023 /* programattically been changed back to a default state of Qt::PartiallyChecked remove the version hash here */
1024 m_versionExceptionHash.remove(fullPath);
1028 updateFileTableChecks();
1029 updateVersionTableChecks();
1033 * function to insert keys and values to both m_fileExceptionHash and m_fileExceptionMulti
1035 void restoreTree::fileExceptionInsert(QString &fullPath, QString &direcotry, Qt::CheckState state)
1037 m_fileExceptionHash.insert(fullPath, state);
1038 m_fileExceptionMulti.insert(direcotry, fullPath);
1039 directoryIconStateInsert(fullPath, state);
1043 * function to remove keys from both m_fileExceptionHash and m_fileExceptionMulti
1045 void restoreTree::fileExceptionRemove(QString &fullPath, QString &directory)
1047 m_fileExceptionHash.remove(fullPath);
1048 /* pull the list of values in the multi */
1049 QStringList fullPathList = m_fileExceptionMulti.values(directory);
1050 /* get the index of the fullpath to remove */
1051 int index = fullPathList.indexOf(fullPath);
1053 /* remove the desired item in the list */
1054 fullPathList.removeAt(index);
1055 /* remove the entire list from the multi */
1056 m_fileExceptionMulti.remove(directory);
1057 /* readd the remaining */
1058 foreach (QString fp, fullPathList) {
1059 m_fileExceptionMulti.insert(directory, fp);
1062 directoryIconStateRemove();
1066 * Overloaded function to be called from the slot and from other places to set the state
1067 * of the check marks in the version table
1069 void restoreTree::versionTableItemChanged(QTableWidgetItem *item)
1071 /* get the previous and current check states */
1072 int row = versionTable->row(item);
1073 QTableWidgetItem *colZeroItem = versionTable->item(row, 0);
1074 Qt::CheckState prevState = m_versionCheckStateList[row];
1075 Qt::CheckState curState = (Qt::CheckState)colZeroItem->checkState();
1076 m_versionCheckStateList[row] = curState;
1078 /* deterimine the default state from the state of the file */
1079 QTableWidgetItem *fileTableItem = fileTable->currentItem();
1080 Qt::CheckState fileState = (Qt::CheckState)fileTableItem->checkState();
1082 /* determine the default state */
1083 Qt::CheckState defState;
1085 defState = Qt::PartiallyChecked;
1086 if (fileState == Qt::Unchecked)
1087 defState = Qt::Unchecked;
1090 defState = Qt::Unchecked;
1092 /* determine if it is already in the versionExceptionHash */
1093 QString directory = directoryTree->currentItem()->data(0, Qt::UserRole).toString();
1094 Qt::CheckState dirState = directoryTree->currentItem()->checkState(0);
1095 QString file = fileTableItem->text();
1096 QString fullPath = directory + file;
1097 int thisJobNum = colZeroItem->text().toInt();
1098 int hashJobNum = m_versionExceptionHash.value(fullPath, 0);
1100 if (mainWin->m_rtVerTabICDebug) {
1101 QString msg = QString("versrow=%1 prev=%2 cur=%3 def=%4 dir=%5 hashJobNum=%6 thisJobNum=%7 filestate=%8 fec=%9 vec=%10\n")
1102 .arg(row).arg(prevState).arg(curState).arg(defState).arg(dirState).arg(hashJobNum).arg(thisJobNum).arg(fileState)
1103 .arg(m_fileExceptionHash.count()).arg(m_versionExceptionHash.count());
1104 Pmsg1(000, "%s", msg.toUtf8().data()); }
1105 /* if changed from partially checked to checked, make it unchecked */
1106 if ((curState == Qt::Checked) && (row == 0) && (fileState == Qt::Unchecked)) {
1107 if (mainWin->m_rtVerTabICDebug) Pmsg0(000, "Setting to Qt::Checked\n");
1108 fileTableItem->setCheckState(Qt::Checked);
1109 } else if ((prevState == Qt::PartiallyChecked) && (curState == Qt::Checked) && (row == 0) && (fileState == Qt::Checked) && (dirState == Qt::Unchecked)) {
1110 //versrow=0 prev=1 cur=2 def=1 dir=0 hashJobNum=0 thisJobNum=64 filestate=2 fec=1 vec=0
1111 if (mainWin->m_rtVerTabICDebug) Pmsg1(000, "fileExceptionRemove %s, %i\n", fullPath.toUtf8().data());
1112 fileExceptionRemove(fullPath, directory);
1113 } else if ((curState == Qt::Checked) && (row == 0) && (hashJobNum != 0) && (dirState != Qt::Unchecked)) {
1114 //versrow=0 prev=0 cur=2 def=1 dir=2 hashJobNum=53 thisJobNum=64 filestate=2 fec=1 vec=1
1115 if (mainWin->m_rtVerTabICDebug) Pmsg1(000, "m_versionExceptionHash.remove %s\n", fullPath.toUtf8().data());
1116 m_versionExceptionHash.remove(fullPath);
1117 fileExceptionRemove(fullPath, directory);
1118 } else if ((curState == Qt::Checked) && (row == 0)) {
1119 if (mainWin->m_rtVerTabICDebug) Pmsg1(000, "m_versionExceptionHash.remove %s\n", fullPath.toUtf8().data());
1120 m_versionExceptionHash.remove(fullPath);
1121 } else if (prevState != curState) {
1122 if (mainWin->m_rtVerTabICDebug) Pmsg2(000, " THE STATE OF THE version Check has changed, Setting StateList[%i] to %i\n", row, curState);
1123 if ((curState == Qt::Checked) || (curState == Qt::PartiallyChecked) && (row != 0)) {
1124 if (mainWin->m_rtVerTabICDebug) Pmsg2(000, "Inserting into m_versionExceptionHash %s, %i\n", fullPath.toUtf8().data(), thisJobNum);
1125 m_versionExceptionHash.insert(fullPath, thisJobNum);
1126 if (fileState != Qt::Checked) {
1127 if (mainWin->m_rtVerTabICDebug) Pmsg2(000, "Inserting into m_fileExceptionHash %s, %i\n", fullPath.toUtf8().data(), curState);
1128 fileExceptionInsert(fullPath, directory, curState);
1131 if (mainWin->m_rtVerTabICDebug) Pmsg0(000, "got here\n");
1134 if (mainWin->m_rtVerTabICDebug) Pmsg0(000, "no conditions met\n");
1137 updateFileTableChecks();
1138 updateVersionTableChecks();
1142 * Simple function to set the check state in the file table by disconnecting the
1143 * signal/slot the setting then reconnecting the signal/slot
1145 void restoreTree::fileTableDisconnectedSet(QTableWidgetItem *item, Qt::CheckState state, bool color)
1147 disconnect(fileTable, SIGNAL(itemChanged(QTableWidgetItem *)),
1148 this, SLOT(fileTableItemChanged(QTableWidgetItem *)));
1149 item->setCheckState(state);
1150 if (color) item->setBackground(Qt::yellow);
1151 else item->setBackground(Qt::white);
1152 connect(fileTable, SIGNAL(itemChanged(QTableWidgetItem *)),
1153 this, SLOT(fileTableItemChanged(QTableWidgetItem *)));
1157 * Simple function to set the check state in the version table by disconnecting the
1158 * signal/slot the setting then reconnecting the signal/slot
1160 void restoreTree::versionTableDisconnectedSet(QTableWidgetItem *item, Qt::CheckState state)
1162 disconnect(versionTable, SIGNAL(itemChanged(QTableWidgetItem *)),
1163 this, SLOT(versionTableItemChanged(QTableWidgetItem *)));
1164 item->setCheckState(state);
1165 connect(versionTable, SIGNAL(itemChanged(QTableWidgetItem *)),
1166 this, SLOT(versionTableItemChanged(QTableWidgetItem *)));
1170 * Simple function to set the check state in the directory tree by disconnecting the
1171 * signal/slot the setting then reconnecting the signal/slot
1173 void restoreTree::directoryTreeDisconnectedSet(QTreeWidgetItem *item, Qt::CheckState state)
1175 disconnect(directoryTree, SIGNAL(itemChanged(QTreeWidgetItem *, int)),
1176 this, SLOT(directoryItemChanged(QTreeWidgetItem *, int)));
1177 item->setCheckState(0, state);
1178 connect(directoryTree, SIGNAL(itemChanged(QTreeWidgetItem *, int)),
1179 this, SLOT(directoryItemChanged(QTreeWidgetItem *, int)));
1183 * Simplify the updating of the check state in the File table by iterating through
1184 * each item in the file table to determine it's appropriate state.
1185 * !! Will probably want to concoct a way to do this without iterating for the possibility
1186 * of the very large directories.
1188 void restoreTree::updateFileTableChecks()
1190 /* deterimine the default state from the state of the directory */
1191 QTreeWidgetItem *dirTreeItem = directoryTree->currentItem();
1192 Qt::CheckState dirState = dirTreeItem->checkState(0);
1194 QString dirName = dirTreeItem->data(0, Qt::UserRole).toString();
1196 /* Update the items in the version table */
1197 int rcnt = fileTable->rowCount();
1198 for (int row=0; row<rcnt; row++) {
1199 QTableWidgetItem* item = fileTable->item(row, 0);
1201 Qt::CheckState curState = item->checkState();
1202 Qt::CheckState newState = Qt::PartiallyChecked;
1203 if (dirState == Qt::Unchecked) newState = Qt::Unchecked;
1205 /* determine if it is already in the m_fileExceptionHash */
1206 QString file = item->text();
1207 QString fullPath = dirName + file;
1208 Qt::CheckState hashState = m_fileExceptionHash.value(fullPath, (Qt::CheckState)3);
1209 int hashJobNum = m_versionExceptionHash.value(fullPath, 0);
1211 if (hashState != 3) newState = hashState;
1213 if (mainWin->m_rtUpdateFTDebug) {
1214 QString msg = QString("file row=%1 cur=%2 hash=%3 new=%4 dirState=%5\n")
1215 .arg(row).arg(curState).arg(hashState).arg(newState).arg(dirState);
1216 Pmsg1(000, "%s", msg.toUtf8().data());
1219 bool docolor = false;
1220 if (hashJobNum != 0) docolor = true;
1221 bool isyellow = item->background().color() == QColor(Qt::yellow);
1222 if ((newState != curState) || (hashState == 3) || ((isyellow && !docolor) || (!isyellow && docolor)))
1223 fileTableDisconnectedSet(item, newState, docolor);
1224 m_fileCheckStateList[row] = newState;
1229 * Simplify the updating of the check state in the Version table by iterating through
1230 * each item in the file table to determine it's appropriate state.
1232 void restoreTree::updateVersionTableChecks()
1234 /* deterimine the default state from the state of the directory */
1235 QTreeWidgetItem *dirTreeItem = directoryTree->currentItem();
1236 Qt::CheckState dirState = dirTreeItem->checkState(0);
1237 QString dirName = dirTreeItem->data(0, Qt::UserRole).toString();
1239 /* deterimine the default state from the state of the file */
1240 QTableWidgetItem *fileTableItem = fileTable->item(fileTable->currentRow(), 0);
1241 Qt::CheckState fileState = fileTableItem->checkState();
1242 QString file = fileTableItem->text();
1243 QString fullPath = dirName + file;
1244 int hashJobNum = m_versionExceptionHash.value(fullPath, 0);
1246 /* Update the items in the version table */
1247 int cnt = versionTable->rowCount();
1248 for (int row=0; row<cnt; row++) {
1249 QTableWidgetItem* item = versionTable->item(row, 0);
1251 Qt::CheckState curState = item->checkState();
1252 Qt::CheckState newState = Qt::Unchecked;
1254 if ((row == 0) && (fileState != Qt::Unchecked) && (hashJobNum == 0))
1255 newState = Qt::PartiallyChecked;
1256 /* determine if it is already in the versionExceptionHash */
1258 int thisJobNum = item->text().toInt();
1259 if (thisJobNum == hashJobNum)
1260 newState = Qt::Checked;
1262 if (mainWin->m_rtChecksDebug) {
1263 QString msg = QString("ver row=%1 cur=%2 hashJobNum=%3 new=%4 dirState=%5\n")
1264 .arg(row).arg(curState).arg(hashJobNum).arg(newState).arg(dirState);
1265 Pmsg1(000, "%s", msg.toUtf8().data());
1267 if (newState != curState)
1268 versionTableDisconnectedSet(item, newState);
1269 m_versionCheckStateList[row] = newState;
1274 * Quick subroutine to "return via subPaths" a list of subpaths when passed a fullPath
1276 void restoreTree::fullPathtoSubPaths(QStringList &subPaths, QString &fullPath_in)
1280 QString fullPath = fullPath_in;
1281 QString direct, path;
1282 while (((index = fullPath.lastIndexOf("/", -2)) != -1) && (!done)) {
1283 direct = path = fullPath;
1284 path.replace(index+1, fullPath.length()-index-1, "");
1285 direct.replace(0, index+1, "");
1287 QString msg = QString("length = \"%1\" index = \"%2\" Considering \"%3\" \"%4\"\n")
1288 .arg(fullPath.length()).arg(index).arg(path).arg(direct);
1289 Pmsg0(000, msg.toUtf8().data());
1292 subPaths.append(fullPath);
1297 * A Function to set the icon state and insert a record into
1298 * m_directoryIconStateHash when an exception is added by the user
1300 void restoreTree::directoryIconStateInsert(QString &fullPath, Qt::CheckState excpState)
1303 fullPathtoSubPaths(paths, fullPath);
1304 /* an exception that causes the item in the file table to be "Checked" has occured */
1305 if (excpState == Qt::Checked) {
1306 bool foundAsUnChecked = false;
1307 QTreeWidgetItem *firstItem = m_dirPaths.value(paths[0]);
1309 if (firstItem->checkState(0) == Qt::Unchecked)
1310 foundAsUnChecked = true;
1312 if (foundAsUnChecked) {
1313 /* as long as directory item is Unchecked, set icon state to "green check" */
1315 QListIterator<QString> siter(paths);
1316 while (siter.hasNext() && !done) {
1317 QString path = siter.next();
1318 QTreeWidgetItem *item = m_dirPaths.value(path);
1320 if (item->checkState(0) != Qt::Unchecked)
1323 directorySetIcon(1, FolderGreenChecked, path, item);
1324 if (mainWin->m_rtIconStateDebug) Pmsg1(000, "In restoreTree::directoryIconStateInsert inserting %s\n", path.toUtf8().data());
1329 /* if it is partially checked or fully checked insert green Check until a unchecked is found in the path */
1330 if (mainWin->m_rtIconStateDebug) Pmsg1(000, "In restoreTree::directoryIconStateInsert Aqua %s\n", paths[0].toUtf8().data());
1332 QListIterator<QString> siter(paths);
1333 while (siter.hasNext() && !done) {
1334 QString path = siter.next();
1335 QTreeWidgetItem *item = m_dirPaths.value(path);
1336 if (item) { /* if the directory item is checked, set icon state to unchecked "green check" */
1337 if (item->checkState(0) == Qt::Checked)
1339 directorySetIcon(1, FolderGreenChecked, path, item);
1340 if (mainWin->m_rtIconStateDebug) Pmsg1(000, "In restoreTree::directoryIconStateInsert boogie %s\n", path.toUtf8().data());
1345 /* an exception that causes the item in the file table to be "Unchecked" has occured */
1346 if (excpState == Qt::Unchecked) {
1348 QListIterator<QString> siter(paths);
1349 while (siter.hasNext() && !done) {
1350 QString path = siter.next();
1351 QTreeWidgetItem *item = m_dirPaths.value(path);
1352 if (item) { /* if the directory item is checked, set icon state to unchecked "white check" */
1353 if (item->checkState(0) == Qt::Checked)
1355 directorySetIcon(1, FolderWhiteChecked, path, item);
1356 if (mainWin->m_rtIconStateDebug) Pmsg1(000, "In restoreTree::directoryIconStateInsert boogie %s\n", path.toUtf8().data());
1363 * A function to set the icon state back to "folder" and to remove a record from
1364 * m_directoryIconStateHash when an exception is removed by a user.
1366 void restoreTree::directoryIconStateRemove()
1368 QHash<QString, int> shouldBeIconStateHash;
1369 /* First determine all paths with icons that should be checked with m_fileExceptionHash */
1370 /* Use iterator tera to iterate through m_fileExceptionHash */
1371 QHashIterator<QString, Qt::CheckState> tera(m_fileExceptionHash);
1372 while (tera.hasNext()) {
1374 if (mainWin->m_rtIconStateDebug) Pmsg2(000, "Alpha Key %s value %i\n", tera.key().toUtf8().data(), tera.value());
1376 QString keyPath = tera.key();
1377 Qt::CheckState state = tera.value();
1380 fullPathtoSubPaths(paths, keyPath);
1381 /* if the state of the item in m_fileExceptionHash is checked
1382 * each of the subpaths should be "Checked Green" */
1383 if (state == Qt::Checked) {
1385 bool foundAsUnChecked = false;
1386 QTreeWidgetItem *firstItem = m_dirPaths.value(paths[0]);
1388 if (firstItem->checkState(0) == Qt::Unchecked)
1389 foundAsUnChecked = true;
1391 if (foundAsUnChecked) {
1392 /* The right most directory is Unchecked, iterate leftwards
1393 * as long as directory item is Unchecked, set icon state to "green check" */
1395 QListIterator<QString> siter(paths);
1396 while (siter.hasNext() && !done) {
1397 QString path = siter.next();
1398 QTreeWidgetItem *item = m_dirPaths.value(path);
1400 if (item->checkState(0) != Qt::Unchecked)
1403 shouldBeIconStateHash.insert(path, FolderGreenChecked);
1404 if (mainWin->m_rtIconStateDebug) Pmsg1(000, "In restoreTree::directoryIconStateInsert inserting %s\n", path.toUtf8().data());
1410 /* The right most directory is Unchecked, iterate leftwards
1411 * until directory item is Checked, set icon state to "green check" */
1413 QListIterator<QString> siter(paths);
1414 while (siter.hasNext() && !done) {
1415 QString path = siter.next();
1416 QTreeWidgetItem *item = m_dirPaths.value(path);
1418 if (item->checkState(0) == Qt::Checked)
1420 shouldBeIconStateHash.insert(path, FolderGreenChecked);
1425 /* if the state of the item in m_fileExceptionHash is UNChecked
1426 * each of the subpaths should be "Checked white" until the tree item
1427 * which represents that path is Qt::Checked */
1428 if (state == Qt::Unchecked) {
1430 QListIterator<QString> siter(paths);
1431 while (siter.hasNext() && !done) {
1432 QString path = siter.next();
1433 QTreeWidgetItem *item = m_dirPaths.value(path);
1435 if (item->checkState(0) == Qt::Checked)
1437 shouldBeIconStateHash.insert(path, FolderWhiteChecked);
1442 /* now iterate through m_directoryIconStateHash which are the items that are checked
1443 * and remove all of those that are not in shouldBeIconStateHash */
1444 QHashIterator<QString, int> iter(m_directoryIconStateHash);
1445 while (iter.hasNext()) {
1447 if (mainWin->m_rtIconStateDebug) Pmsg2(000, "Beta Key %s value %i\n", iter.key().toUtf8().data(), iter.value());
1449 QString keyPath = iter.key();
1450 if (shouldBeIconStateHash.value(keyPath)) {
1451 if (mainWin->m_rtIconStateDebug) Pmsg1(000, "WAS found in shouldBeStateHash %s\n", keyPath.toUtf8().data());
1452 //newval = m_directoryIconStateHash.value(path, FolderUnchecked) & (~change);
1453 int newval = shouldBeIconStateHash.value(keyPath);
1455 newval = newval & FolderBothChecked;
1456 QTreeWidgetItem *item = m_dirPaths.value(keyPath);
1458 directorySetIcon(0, newval, keyPath, item);
1460 if (mainWin->m_rtIconStateDebug) Pmsg1(000, "NOT found in shouldBeStateHash %s\n", keyPath.toUtf8().data());
1461 QTreeWidgetItem *item = m_dirPaths.value(keyPath);
1463 directorySetIcon(0, FolderBothChecked, keyPath, item);
1464 //item->setIcon(0,QIcon(QString::fromUtf8(":images/folder.png")));
1465 //m_directoryIconStateHash.remove(keyPath);
1470 void restoreTree::directorySetIcon(int operation, int change, QString &path, QTreeWidgetItem* item) {
1472 /* we are adding a check type white or green */
1473 if (operation > 0) {
1474 /* get the old val and "bitwise OR" with the change */
1475 newval = m_directoryIconStateHash.value(path, FolderUnchecked) | change;
1476 if (mainWin->m_rtIconStateDebug) Pmsg2(000, "Inserting into m_directoryIconStateHash path=%s newval=%i\n", path.toUtf8().data(), newval);
1477 m_directoryIconStateHash.insert(path, newval);
1479 /* we are removing a check type white or green */
1480 newval = m_directoryIconStateHash.value(path, FolderUnchecked) & (~change);
1482 if (mainWin->m_rtIconStateDebug) Pmsg2(000, "Removing from m_directoryIconStateHash path=%s newval=%i\n", path.toUtf8().data(), newval);
1483 m_directoryIconStateHash.remove(path);
1486 if (mainWin->m_rtIconStateDebug) Pmsg2(000, "Inserting into m_directoryIconStateHash path=%s newval=%i\n", path.toUtf8().data(), newval);
1487 m_directoryIconStateHash.insert(path, newval);
1490 if (newval == FolderUnchecked)
1491 item->setIcon(0, QIcon(QString::fromUtf8(":images/folder.png")));
1492 else if (newval == FolderGreenChecked)
1493 item->setIcon(0, QIcon(QString::fromUtf8(":images/folderchecked.png")));
1494 else if (newval == FolderWhiteChecked)
1495 item->setIcon(0, QIcon(QString::fromUtf8(":images/folderunchecked.png")));
1496 else if (newval == FolderBothChecked)
1497 item->setIcon(0, QIcon(QString::fromUtf8(":images/folderbothchecked.png")));
1503 void restoreTree::restoreButtonPushed()
1505 /* Set progress bars and repaint */
1506 prLabel1->setVisible(true);
1507 prLabel1->setText("Task 1 of 3");
1508 prLabel2->setVisible(true);
1509 prLabel2->setText("Processing Checked directories");
1510 prBar1->setVisible(true);
1511 prBar1->setRange(0, 3);
1512 prBar1->setValue(0);
1513 prBar2->setVisible(true);
1514 prBar2->setRange(0, 0);
1516 QMultiHash<int, QString> versionFilesMulti;
1518 QHash <QString, bool> fullPathDone;
1519 QHash <QString, int> fileIndexHash;
1520 if ((mainWin->m_rtRestore1Debug) || (mainWin->m_rtRestore2Debug) || (mainWin->m_rtRestore3Debug))
1521 Pmsg0(000, "In restoreTree::restoreButtonPushed\n");
1522 /* Use a tree widget item iterator to count directories for the progress bar */
1523 QTreeWidgetItemIterator diterc(directoryTree, QTreeWidgetItemIterator::Checked);
1528 } /* while (*diterc) */
1529 prBar2->setRange(0, ditcount);
1530 prBar2->setValue(0);
1532 /* Use a tree widget item iterator filtering for Checked Items */
1533 QTreeWidgetItemIterator diter(directoryTree, QTreeWidgetItemIterator::Checked);
1535 QString directory = (*diter)->data(0, Qt::UserRole).toString();
1536 int pathid = m_directoryPathIdHash.value(directory, -1);
1538 if (mainWin->m_rtRestore1Debug)
1539 Pmsg1(000, "Directory Checked=\"%s\"\n", directory.toUtf8().data());
1540 /* With a checked directory, query for the files in the directory */
1543 "SELECT Filename.Name AS Filename, t1.JobId AS JobId, File.FileIndex AS FileIndex"
1545 " ( SELECT File.FilenameId AS FilenameId, MAX(Job.JobId) AS JobId"
1547 " INNER JOIN Job ON (Job.JobId=File.JobId)"
1548 " WHERE File.PathId=" + QString("%1").arg(pathid) +
1549 " AND Job.Jobid IN (" + m_checkedJobs + ")"
1550 " AND File.FilenameId!=" + QString("%1").arg(m_nullFileNameId) +
1551 " GROUP BY File.FilenameId"
1553 " INNER JOIN Filename on (Filename.FilenameId=File.FilenameId)"
1554 " INNER JOIN Job ON (Job.JobId=File.JobId)"
1555 " WHERE File.PathId=" + QString("%1").arg(pathid) +
1556 " AND File.FilenameId=t1.FilenameId"
1557 " AND Job.Jobid=t1.JobId"
1558 " ORDER BY Filename";
1560 if (mainWin->m_sqlDebug) Pmsg1(000, "Query cmd : %s\n", cmd.toUtf8().data());
1561 QStringList results;
1562 if (m_console->sql_cmd(cmd, results)) {
1563 QStringList fieldlist;
1566 /* Iterate through the record returned from the query */
1567 foreach (QString resultline, results) {
1568 /* Iterate through fields in the record */
1570 QString fullPath = "";
1571 Qt::CheckState fileExcpState = (Qt::CheckState)4;
1572 fieldlist = resultline.split("\t");
1575 foreach (QString field, fieldlist) {
1577 fullPath = directory + field;
1580 version = field.toInt();
1583 fileIndex = field.toInt();
1587 fileExcpState = m_fileExceptionHash.value(fullPath, (Qt::CheckState)3);
1589 int excpVersion = m_versionExceptionHash.value(fullPath, 0);
1590 if (fileExcpState != Qt::Unchecked) {
1592 if (excpVersion != 0) {
1593 debugtext = QString("*E* version=%1").arg(excpVersion);
1594 version = excpVersion;
1595 fileIndex = queryFileIndex(fullPath, excpVersion);
1597 debugtext = QString("___ version=%1").arg(version);
1598 if (mainWin->m_rtRestore1Debug)
1599 Pmsg2(000, "Restoring %s File %s\n", debugtext.toUtf8().data(), fullPath.toUtf8().data());
1600 fullPathDone.insert(fullPath, 1);
1601 fileIndexHash.insert(fullPath, fileIndex);
1602 versionFilesMulti.insert(version, fullPath);
1610 prBar2->setValue(ditcount);
1612 } /* while (*diter) */
1613 prBar1->setValue(1);
1614 prLabel1->setText("Task 2 of 3");
1615 prLabel2->setText("Processing Exceptions");
1616 prBar2->setRange(0, 0);
1619 /* There may be some exceptions not accounted for yet with fullPathDone */
1620 QHashIterator<QString, Qt::CheckState> ftera(m_fileExceptionHash);
1621 while (ftera.hasNext()) {
1623 QString fullPath = ftera.key();
1624 Qt::CheckState state = ftera.value();
1626 /* now we don't want the ones already done */
1627 if (fullPathDone.value(fullPath, 0) == 0) {
1628 int version = m_versionExceptionHash.value(fullPath, 0);
1630 QString debugtext = "";
1632 fileIndex = queryFileIndex(fullPath, version);
1633 debugtext = QString("E1* version=%1 fileid=%2").arg(version).arg(fileIndex);
1635 version = mostRecentVersionfromFullPath(fullPath);
1637 fileIndex = queryFileIndex(fullPath, version);
1638 debugtext = QString("E2* version=%1 fileid=%2").arg(version).arg(fileIndex);
1640 debugtext = QString("Error det vers").arg(version);
1642 if (mainWin->m_rtRestore1Debug)
1643 Pmsg2(000, "Restoring %s file %s\n", debugtext.toUtf8().data(), fullPath.toUtf8().data());
1644 versionFilesMulti.insert(version, fullPath);
1646 fileIndexHash.insert(fullPath, fileIndex);
1647 } /* if fullPathDone.value(fullPath, 0) == 0 */
1648 } /* if state != 0 */
1649 } /* while ftera.hasNext */
1650 /* The progress bars for the next step */
1651 prBar1->setValue(2);
1652 prLabel1->setText("Task 3 of 3");
1653 prLabel2->setText("Filling Database Table");
1654 prBar2->setRange(0, vFMCounter);
1656 prBar2->setValue(vFMCounter);
1659 /* now for the final spit out of the versions and lists of files for each version */
1660 QHash<int, int> doneKeys;
1661 QHashIterator<int, QString> vFMiter(versionFilesMulti);
1662 QString tempTable = "";
1664 while (vFMiter.hasNext()) {
1666 int fversion = vFMiter.key();
1667 /* did not succeed in getting an iterator to work as expected on versionFilesMulti so use doneKeys */
1668 if (doneKeys.value(fversion, 0) == 0) {
1669 if (tempTable == "") {
1670 QSettings settings("www.bacula.org", "bat");
1671 settings.beginGroup("Restore");
1672 int counter = settings.value("Counter", 1).toInt();
1673 settings.setValue("Counter", counter+1);
1674 settings.endGroup();
1675 tempTable = "restore_" + QString("%1").arg(qrand()) + "_" + QString("%1").arg(counter);
1676 QString sqlcmd = "CREATE TEMPORARY TABLE " + tempTable + " (JobId INTEGER, FileIndex INTEGER)";
1677 if (mainWin->m_sqlDebug)
1678 Pmsg1(000, "Query cmd : %s ;\n", sqlcmd.toUtf8().data());
1679 QStringList results;
1680 if (!m_console->sql_cmd(sqlcmd, results))
1681 Pmsg1(000, "CREATE TABLE FAILED!!!! %s\n", sqlcmd.toUtf8().data());
1684 if (mainWin->m_rtRestore2Debug) Pmsg1(000, "Version->%i\n", fversion);
1685 QStringList fullPathList = versionFilesMulti.values(fversion);
1686 /* create the command to perform the restore */
1687 foreach(QString ffullPath, fullPathList) {
1688 int fileIndex = fileIndexHash.value(ffullPath);
1689 if (mainWin->m_rtRestore2Debug) Pmsg2(000, " file->%s id %i\n", ffullPath.toUtf8().data(), fileIndex);
1690 QString sqlcmd = "INSERT INTO " + tempTable + " (JobId, FileIndex) VALUES (" + QString("%1").arg(fversion) + ", " + QString("%1").arg(fileIndex) + ")";
1691 if (mainWin->m_rtRestore3Debug)
1692 Pmsg1(000, "Insert cmd : %s\n", sqlcmd.toUtf8().data());
1693 QStringList results;
1694 if (!m_console->sql_cmd(sqlcmd, results))
1695 Pmsg1(000, "INSERT INTO FAILED!!!! %s\n", sqlcmd.toUtf8().data());
1696 prBar2->setValue(++vFMCounter);
1697 } /* foreach fullPathList */
1698 doneKeys.insert(fversion,1);
1699 jobList.append(fversion);
1700 } /* if (doneKeys.value(fversion, 0) == 0) */
1701 } /* while (vFMiter.hasNext()) */
1702 if (tempTable != "") {
1703 /* a table was made, lets run the job */
1704 QString jobOption = " jobid=\"";
1706 /* create a list of jobs comma separated */
1707 foreach (int job, jobList) {
1708 if (first) first = false;
1709 else jobOption += ",";
1710 jobOption += QString("%1").arg(job);
1713 QString cmd = QString("restore");
1715 " client=\"" + m_prevClientCombo + "\"" +
1716 " file=\"?" + tempTable + "\" done";
1717 if (mainWin->m_commandDebug)
1718 Pmsg1(000, "preRestore command \'%s\'\n", cmd.toUtf8().data());
1719 consoleCommand(cmd);
1721 /* turn off the progress widgets */
1722 prBar1->setVisible(false);
1723 prBar2->setVisible(false);
1724 prLabel1->setVisible(false);
1725 prLabel2->setVisible(false);
1728 int restoreTree::mostRecentVersionfromFullPath(QString &fullPath)
1731 QString directory, fileName;
1732 int index = fullPath.lastIndexOf("/", -2);
1734 directory = fileName = fullPath;
1735 directory.replace(index+1, fullPath.length()-index-1, "");
1736 fileName.replace(0, index+1, "");
1738 QString msg = QString("length = \"%1\" index = \"%2\" Considering \"%3\" \"%4\"\n")
1739 .arg(fullPath.length()).arg(index).arg(fileName).arg(directory);
1740 Pmsg0(000, msg.toUtf8().data());
1742 int pathid = m_directoryPathIdHash.value(directory, -1);
1744 /* so now we need the latest version from the database */
1746 "SELECT MAX(Job.JobId)"
1748 " INNER JOIN Filename on (Filename.FilenameId=File.FilenameId)"
1749 " INNER JOIN Job ON (File.JobId=Job.JobId)"
1750 " WHERE File.PathId=" + QString("%1").arg(pathid) +
1751 " AND Job.Jobid IN (" + m_checkedJobs + ")"
1752 " AND Filename.Name='" + fileName + "'"
1753 " AND File.FilenameId!=" + QString("%1").arg(m_nullFileNameId) +
1754 " GROUP BY Filename.Name";
1756 if (mainWin->m_sqlDebug) Pmsg1(000, "Query cmd : %s\n", cmd.toUtf8().data());
1757 QStringList results;
1758 if (m_console->sql_cmd(cmd, results)) {
1759 QStringList fieldlist;
1761 /* Iterate through the record returned from the query */
1762 foreach (QString resultline, results) {
1763 /* Iterate through fields in the record */
1765 fieldlist = resultline.split("\t");
1766 foreach (QString field, fieldlist) {
1768 qversion = field.toInt();
1776 } /* if (index != -1) */
1781 int restoreTree::queryFileIndex(QString &fullPath, int jobId)
1784 QString directory, fileName;
1785 int index = fullPath.lastIndexOf("/", -2);
1787 directory = fileName = fullPath;
1788 directory.replace(index+1, fullPath.length()-index-1, "");
1789 fileName.replace(0, index+1, "");
1791 QString msg = QString("length = \"%1\" index = \"%2\" Considering \"%3\" \"%4\"\n")
1792 .arg(fullPath.length()).arg(index).arg(fileName).arg(directory);
1793 Pmsg0(000, msg.toUtf8().data());
1795 int pathid = m_directoryPathIdHash.value(directory, -1);
1797 /* so now we need the latest version from the database */
1802 " INNER JOIN Filename on (Filename.FilenameId=File.FilenameId)"
1803 " INNER JOIN Job ON (File.JobId=Job.JobId)"
1804 " WHERE File.PathId=" + QString("%1").arg(pathid) +
1805 " AND Filename.Name='" + fileName + "'"
1806 " AND Job.Jobid='" + QString("%1").arg(jobId) + "'"
1807 " GROUP BY File.FileIndex";
1809 if (mainWin->m_sqlDebug) Pmsg1(000, "Query cmd : %s\n", cmd.toUtf8().data());
1810 QStringList results;
1811 if (m_console->sql_cmd(cmd, results)) {
1812 QStringList fieldlist;
1814 /* Iterate through the record returned from the query */
1815 foreach (QString resultline, results) {
1816 /* Iterate through fields in the record */
1818 fieldlist = resultline.split("\t");
1819 foreach (QString field, fieldlist) {
1821 qfileIndex = field.toInt();
1829 } /* if (index != -1) */