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");
202 setJobsCheckedList();
203 if (mainWin->m_rtPopDirDebug) Pmsg0(000, "Repopulating from checks in Job Table\n");
205 if (m_checkedJobs != "") {
206 /* First get the filenameid of where the nae is null. These will be the directories
207 * This could be done in a subquery but postgres's query analyzer won't do the right
208 * thing like I want */
209 if (m_nullFileNameId == -1) {
210 QString cmd = "SELECT FilenameId FROM Filename WHERE name=''";
211 if (mainWin->m_sqlDebug)
212 Pmsg1(000, "Query cmd : %s\n", cmd.toUtf8().data());
214 if (m_console->sql_cmd(cmd, qres)) {
216 QStringList fieldlist = qres[0].split("\t");
217 QString field = fieldlist[0];
219 int val = field.toInt(&ok, 10);
220 if (ok) m_nullFileNameId = val;
224 /* now create the query to get the list of paths */
226 "SELECT DISTINCT Path.Path AS Path, File.PathId AS PathId"
228 " INNER JOIN Path ON (File.PathId=Path.PathId)";
229 if (m_nullFileNameId != -1)
230 cmd += " WHERE File.FilenameId=" + QString("%1").arg(m_nullFileNameId);
232 cmd += " WHERE File.FilenameId IN (SELECT FilenameId FROM Filename WHERE Name='')";
233 cmd += " AND File.Jobid IN (" + m_checkedJobs + ")"
235 if (mainWin->m_sqlDebug)
236 Pmsg1(000, "Query cmd : %s\n", cmd.toUtf8().data());
237 prBar1->setValue(ontask++);
238 prLabel1->setText("Task " + QString("%1").arg(ontask) + " of " + QString("%1").arg(taskcount));
240 prBar2->setRange(0,0);
241 prLabel2->setText("Querying for Directories");
244 m_directoryPathIdHash.clear();
245 bool querydone = false;
246 if (m_console->sql_cmd(cmd, results)) {
249 prLabel2->setText("Processing Directories");
250 prBar2->setRange(0,results.count());
253 if (mainWin->m_miscDebug)
254 Pmsg1(000, "Done with query %i results\n", results.count());
255 QStringList fieldlist;
256 foreach(QString resultline, results) {
257 /* Update progress bar periodically */
258 if ((++m_debugCnt && 0x3FF) == 0) {
259 prBar2->setValue(m_debugCnt);
261 fieldlist = resultline.split("\t");
264 /* Iterate through fields in the record */
265 foreach (field, fieldlist) {
266 if (fieldcnt == 0 ) {
267 parseDirectory(field);
268 } else if (fieldcnt == 1) {
270 int pathid = field.toInt(&ok, 10);
272 m_directoryPathIdHash.insert(fieldlist[0], pathid);
279 QMessageBox::warning(this, tr("Bat"),
280 tr("No jobs were selected in the job query !!!.\n"
281 "Press OK to continue?"),
284 prBar1->setVisible(false);
285 prBar2->setVisible(false);
286 prLabel1->setVisible(false);
287 prLabel2->setVisible(false);
291 * Function to set m_checkedJobs from the jobs that are checked in the table
294 void restoreTree::setJobsCheckedList()
296 m_JobsCheckedList = "";
298 /* Update the items in the version table */
299 int cnt = jobTable->rowCount();
300 for (int row=0; row<cnt; row++) {
301 QTableWidgetItem* jobItem = jobTable->item(row, 0);
302 if (jobItem->checkState() == Qt::Checked) {
304 m_JobsCheckedList += ",";
305 m_JobsCheckedList += jobItem->text();
307 jobItem->setBackground(Qt::green);
309 if (jobItem->flags())
310 jobItem->setBackground(Qt::gray);
312 jobItem->setBackground(Qt::darkYellow);
315 m_checkedJobs = m_JobsCheckedList;
319 * Function to parse a directory into all possible subdirectories, then add to
322 void restoreTree::parseDirectory(QString &dir_in)
324 /* m_debugTrap is to only print debugs for a few occurennces of calling parseDirectory
325 * instead of printing out what could potentially a whole bunch */
328 /* Truncate everything after the last / */
329 if (dir_in.right(1) != "/") {
330 dir_in.truncate(dir_in.lastIndexOf("/") + 1);
332 if ((mainWin->m_miscDebug) && (m_debugTrap))
333 Pmsg1(000, "parsing %s\n", dir_in.toUtf8().data());
335 /* split and add if not in yet */
336 QString direct, path;
339 QStringList pathAfter, dirAfter;
340 /* start from the end, turn /etc/somedir/subdir/ into /etc/somedir and subdir/
341 * if not added into tree, then try /etc/ and somedir/ if not added, then try
342 * / and etc/ . That should succeed, then add the ones that failed in reverse */
343 while (((index = dir_in.lastIndexOf("/", -2)) != -1) && (!done)) {
344 direct = path = dir_in;
345 path.replace(index+1, dir_in.length()-index-1,"");
346 direct.replace(0, index+1, "");
347 if ((mainWin->m_miscDebug) && (m_debugTrap)) {
348 QString msg = QString("length = \"%1\" index = \"%2\" Adding \"%3\" \"%4\"\n")
349 .arg(dir_in.length()).arg(index).arg(path).arg(direct);
350 Pmsg0(000, msg.toUtf8().data());
352 if (addDirectory(path, direct)) done = true;
354 if ((mainWin->m_miscDebug) && (m_debugTrap))
355 Pmsg0(000, "Saving for later\n");
356 pathAfter.prepend(path);
357 dirAfter.prepend(direct);
362 for (int k=0; k<pathAfter.count(); k++) {
363 if (addDirectory(pathAfter[k], dirAfter[k]))
364 if ((mainWin->m_miscDebug) && (m_debugTrap))
365 Pmsg2(000, "Adding After %s %s\n", pathAfter[k].toUtf8().data(), dirAfter[k].toUtf8().data());
367 if ((mainWin->m_miscDebug) && (m_debugTrap))
368 Pmsg2(000, "Error Adding %s %s\n", pathAfter[k].toUtf8().data(), dirAfter[k].toUtf8().data());
374 * Function called from fill directory when a directory is found to see if this
375 * directory exists in the directory pane and then add it to the directory pane
377 bool restoreTree::addDirectory(QString &m_cwd, QString &newdirr)
379 QString newdir = newdirr;
380 QString fullPath = m_cwd + newdirr;
381 bool ok = true, added = false;
383 if ((mainWin->m_miscDebug) && (m_debugTrap)) {
384 QString msg = QString("In addDirectory cwd \"%1\" newdir \"%2\"\n")
387 Pmsg0(000, msg.toUtf8().data());
391 /* add unix '/' directory first */
392 if (m_dirPaths.empty() && !isWin32Path(fullPath)) {
394 QTreeWidgetItem *item = new QTreeWidgetItem(directoryTree);
396 item->setText(0, text.toUtf8().data());
397 item->setData(0, Qt::UserRole, QVariant(text));
398 item->setData(1, Qt::UserRole, QVariant(Qt::Unchecked));
399 item->setIcon(0, QIcon(QString::fromUtf8(":images/folder.png")));
400 if ((mainWin->m_miscDebug) && (m_debugTrap)) {
401 Pmsg1(000, "Pre Inserting %s\n", text.toUtf8().data());
403 m_dirPaths.insert(text, item);
405 /* no need to check for windows drive if unix */
406 if (isWin32Path(m_cwd)) {
407 if (!m_dirPaths.contains(m_cwd)) {
408 /* this is a windows drive add the base widget */
409 QTreeWidgetItem *item = new QTreeWidgetItem(directoryTree);
410 item->setText(0, m_cwd);
411 item->setData(0, Qt::UserRole, QVariant(fullPath));
412 item->setData(1, Qt::UserRole, QVariant(Qt::Unchecked));
413 item->setIcon(0, QIcon(QString::fromUtf8(":images/folder.png")));
414 if ((mainWin->m_miscDebug) && (m_debugTrap)) {
415 Pmsg0(000, "Added Base \"letter\":/\n");
417 m_dirPaths.insert(m_cwd, item);
422 /* is it already existent ?? */
423 if (!m_dirPaths.contains(fullPath)) {
424 QTreeWidgetItem *item = NULL;
425 QTreeWidgetItem *parent = m_dirPaths.value(m_cwd);
427 /* new directories to add */
428 item = new QTreeWidgetItem(parent);
429 item->setText(0, newdir.toUtf8().data());
430 item->setData(0, Qt::UserRole, QVariant(fullPath));
431 item->setCheckState(0, Qt::Unchecked);
432 /* Store the current state of the check status in column 1, which at
433 * this point has no text*/
434 item->setData(1, Qt::UserRole, QVariant(Qt::Unchecked));
437 if ((mainWin->m_miscDebug) && (m_debugTrap)) {
438 QString msg = QString("In else of if parent cwd \"%1\" newdir \"%2\"\n")
441 Pmsg0(000, msg.toUtf8().data());
444 /* insert into hash */
446 if ((mainWin->m_miscDebug) && (m_debugTrap)) {
447 Pmsg1(000, "Inserting %s\n", fullPath.toUtf8().data());
449 m_dirPaths.insert(fullPath, item);
457 * Virtual function which is called when this page is visible on the stack
459 void restoreTree::currentStackItem()
462 if (!m_console->preventInUseConnect())
470 * Populate the tree when refresh button pushed.
472 void restoreTree::refreshButtonPushed()
474 populateDirectoryTree();
478 * Set the values of non-job combo boxes to the job defaults
480 void restoreTree::jobComboChanged(int)
482 if (jobCombo->currentText() == "Any") {
483 fileSetCombo->setCurrentIndex(fileSetCombo->findText("Any", Qt::MatchExactly));
486 job_defaults job_defs;
489 job_defs.job_name = jobCombo->currentText();
490 if (m_console->get_job_defaults(job_defs)) {
491 fileSetCombo->setCurrentIndex(fileSetCombo->findText(job_defs.fileset_name, Qt::MatchExactly));
492 clientCombo->setCurrentIndex(clientCombo->findText(job_defs.client_name, Qt::MatchExactly));
497 * Function to populate the file list table
499 void restoreTree::directoryCurrentItemChanged(QTreeWidgetItem *item, QTreeWidgetItem *)
505 /* Also clear the version table here */
506 versionTable->clear();
507 versionFileLabel->setText("");
508 versionTable->setRowCount(0);
509 versionTable->setColumnCount(0);
511 QStringList headerlist = (QStringList() << "File Name" << "Filename Id");
512 fileTable->setColumnCount(headerlist.size());
513 fileTable->setHorizontalHeaderLabels(headerlist);
514 fileTable->setRowCount(0);
516 m_fileCheckStateList.clear();
517 disconnect(fileTable, SIGNAL(itemChanged(QTableWidgetItem *)),
518 this, SLOT(fileTableItemChanged(QTableWidgetItem *)));
519 QBrush blackBrush(Qt::black);
520 QString directory = item->data(0, Qt::UserRole).toString();
521 directoryLabel->setText("Present Working Directory : " + directory);
522 int pathid = m_directoryPathIdHash.value(directory, -1);
525 "SELECT DISTINCT Filename.Name AS FileName, Filename.FilenameId AS FilenameId"
527 " INNER JOIN Filename on (Filename.FilenameId=File.FilenameId)"
528 " WHERE File.PathId=" + QString("%1").arg(pathid) +
529 " AND File.Jobid IN (" + m_checkedJobs + ")"
530 " AND Filename.Name!=''"
531 " ORDER BY FileName";
533 if (mainWin->m_sqlDebug) {
534 Pmsg1(000, "Query cmd : %s\n", cmd.toUtf8().data());
537 if (m_console->sql_cmd(cmd, results)) {
539 QTableWidgetItem* tableItem;
541 QStringList fieldlist;
542 fileTable->setRowCount(results.size());
545 /* Iterate through the record returned from the query */
546 foreach (QString resultline, results) {
547 /* Iterate through fields in the record */
549 fieldlist = resultline.split("\t");
550 foreach (field, fieldlist) {
551 field = field.trimmed(); /* strip leading & trailing spaces */
552 tableItem = new QTableWidgetItem(field, 1);
553 /* Possible flags are Qt::ItemFlags flag = Qt::ItemIsSelectable | Qt::ItemIsEditablex
554 * | Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled | Qt::ItemIsUserCheckable
555 * | Qt::ItemIsEnabled | Qt::ItemIsTristate; */
556 tableItem->setForeground(blackBrush);
557 /* Just in case a column ever gets added */
559 Qt::ItemFlags flag = Qt::ItemIsUserCheckable | Qt::ItemIsEnabled | Qt::ItemIsTristate;
560 tableItem->setFlags(flag);
561 tableItem->setData(Qt::UserRole, QVariant(directory));
562 fileTable->setItem(row, column, tableItem);
563 m_fileCheckStateList.append(Qt::Unchecked);
564 tableItem->setCheckState(Qt::Unchecked);
565 } else if (column == 1) {
566 Qt::ItemFlags flag = Qt::ItemIsEnabled;
567 tableItem->setFlags(flag);
569 int filenameid = field.toInt(&ok, 10);
570 if (!ok) filenameid = -1;
571 tableItem->setData(Qt::UserRole, QVariant(filenameid));
572 fileTable->setItem(row, column, tableItem);
578 fileTable->setRowCount(row);
580 fileTable->resizeColumnsToContents();
581 fileTable->resizeRowsToContents();
582 fileTable->verticalHeader()->hide();
583 fileTable->hideColumn(1);
584 if (mainWin->m_rtDirCurICDebug) Pmsg0(000, "will update file table checks\n");
585 updateFileTableChecks();
586 } else if (mainWin->m_sqlDebug)
587 Pmsg1(000, "did not perform query, pathid=%i not found\n", pathid);
588 connect(fileTable, SIGNAL(itemChanged(QTableWidgetItem *)),
589 this, SLOT(fileTableItemChanged(QTableWidgetItem *)));
593 * Function to populate the version table
595 void restoreTree::fileCurrentItemChanged(QTableWidgetItem *currentFileTableItem, QTableWidgetItem *)
597 if (currentFileTableItem == NULL)
600 int currentRow = fileTable->row(currentFileTableItem);
601 QTableWidgetItem *fileTableItem = fileTable->item(currentRow, 0);
602 QTableWidgetItem *fileNameIdTableItem = fileTable->item(currentRow, 1);
603 int fileNameId = fileNameIdTableItem->data(Qt::UserRole).toInt();
605 m_versionCheckStateList.clear();
606 disconnect(versionTable, SIGNAL(itemChanged(QTableWidgetItem *)),
607 this, SLOT(versionTableItemChanged(QTableWidgetItem *)));
609 QString file = fileTableItem->text();
610 versionFileLabel->setText(file);
611 QString directory = fileTableItem->data(Qt::UserRole).toString();
613 QBrush blackBrush(Qt::black);
615 QStringList headerlist = (QStringList() << "Job Id" << "Type" << "End Time" << "Hash" << "FileId");
616 versionTable->clear();
617 versionTable->setColumnCount(headerlist.size());
618 versionTable->setHorizontalHeaderLabels(headerlist);
619 versionTable->setRowCount(0);
621 int pathid = m_directoryPathIdHash.value(directory, -1);
622 if ((pathid != -1) && (fileNameId != -1)) {
624 "SELECT Job.JobId AS JobId,Job.Level AS Type,Job.EndTime AS EndTime,File.MD5 AS MD5,File.FileId AS FileId"
626 " INNER JOIN Filename on (Filename.FilenameId=File.FilenameId)"
627 " INNER JOIN Path ON (Path.PathId=File.PathId)"
628 " INNER JOIN Job ON (File.JobId=Job.JobId)"
629 " WHERE Path.PathId=" + QString("%1").arg(pathid) +
630 //" AND Filename.Name='" + file + "'"
631 " AND Filename.FilenameId=" + QString("%1").arg(fileNameId) +
632 " AND Job.Jobid IN (" + m_checkedJobs + ")"
633 " ORDER BY Job.EndTime DESC";
635 if (mainWin->m_sqlDebug)
636 Pmsg1(000, "Query cmd : %s\n", cmd.toUtf8().data());
638 if (m_console->sql_cmd(cmd, results)) {
640 QTableWidgetItem* tableItem;
642 QStringList fieldlist;
643 versionTable->setRowCount(results.size());
646 /* Iterate through the record returned from the query */
647 foreach (QString resultline, results) {
648 fieldlist = resultline.split("\t");
650 /* remove directory */
651 if (fieldlist[0].trimmed() != "") {
652 /* Iterate through fields in the record */
653 foreach (field, fieldlist) {
654 field = field.trimmed(); /* strip leading & trailing spaces */
655 tableItem = new QTableWidgetItem(field, 1);
656 tableItem->setFlags(0);
657 tableItem->setForeground(blackBrush);
658 tableItem->setData(Qt::UserRole, QVariant(directory));
659 versionTable->setItem(row, column, tableItem);
662 Qt::ItemFlags flag = Qt::ItemIsUserCheckable | Qt::ItemIsEnabled | Qt::ItemIsTristate;
663 tableItem->setFlags(flag);
664 m_versionCheckStateList.append(Qt::Unchecked);
665 tableItem->setCheckState(Qt::Unchecked);
673 versionTable->resizeColumnsToContents();
674 versionTable->resizeRowsToContents();
675 versionTable->verticalHeader()->hide();
676 updateVersionTableChecks();
678 if (mainWin->m_sqlDebug)
679 Pmsg2(000, "not querying : pathid=%i fileNameId=%i\n", pathid, fileNameId);
681 connect(versionTable, SIGNAL(itemChanged(QTableWidgetItem *)),
682 this, SLOT(versionTableItemChanged(QTableWidgetItem *)));
686 * Save user settings associated with this page
688 void restoreTree::writeSettings()
690 QSettings settings(m_console->m_dir->name(), "bat");
691 settings.beginGroup(m_groupText);
692 settings.setValue(m_splitText, m_splitter->saveState());
697 * Read and restore user settings associated with this page
699 void restoreTree::readSettings()
701 m_groupText = "RestoreTreePage";
702 m_splitText = "splitterSizes_1";
703 QSettings settings(m_console->m_dir->name(), "bat");
704 settings.beginGroup(m_groupText);
705 m_splitter->restoreState(settings.value(m_splitText).toByteArray());
710 * This is a funcion to accomplish the one thing I struggled to figure out what
711 * was taking so long. It add the icons, but after the tree is made. Seemed to
712 * work fast after changing from png to png file for graphic.
714 void restoreTree::directoryItemExpanded(QTreeWidgetItem *item)
716 int childCount = item->childCount();
717 for (int i=0; i<childCount; i++) {
718 QTreeWidgetItem *child = item->child(i);
719 if (child->icon(0).isNull())
720 child->setIcon(0, QIcon(QString::fromUtf8(":images/folder.png")));
725 * Show what jobs meet the criteria and are being used to
726 * populate the directory tree and file and version tables.
728 void restoreTree::populateJobTable()
730 QBrush blackBrush(Qt::black);
732 if (mainWin->m_rtPopDirDebug) Pmsg0(000, "Repopulating the Job Table\n");
733 QStringList headerlist = (QStringList() << "Job Id" << "End Time" << "Level" <<
734 "Name" << "Purged" << "TU" << "TD");
735 m_toggleUpIndex = headerlist.indexOf("TU");
736 m_toggleDownIndex = headerlist.indexOf("TD");
737 int purgedIndex = headerlist.indexOf("Purged");
739 jobTable->setColumnCount(headerlist.size());
740 jobTable->setHorizontalHeaderLabels(headerlist);
742 "SELECT Job.Jobid AS Id,Job.EndTime AS EndTime,Job.Level AS Level,"
743 "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) */