2 Bacula® - The Network Backup Solution
4 Copyright (C) 2007-2008 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 = tr("Version Browser");
47 QTreeWidgetItem* thisitem = mainWin->getFromHash(this);
48 thisitem->setIcon(0, QIcon(QString::fromUtf8(":images/browse.png")));
57 QGridLayout *gridLayout = new QGridLayout(this);
58 gridLayout->setSpacing(6);
59 gridLayout->setMargin(9);
60 gridLayout->setObjectName(QString::fromUtf8("gridLayout"));
62 m_splitter = new QSplitter(Qt::Vertical, this);
63 QScrollArea *area = new QScrollArea();
64 area->setObjectName(QString::fromUtf8("area"));
65 area->setWidget(widget);
66 area->setWidgetResizable(true);
67 m_splitter->addWidget(splitter);
68 m_splitter->addWidget(area);
70 gridLayout->addWidget(m_splitter, 0, 0, 1, 1);
72 /* progress widgets */
73 prBar1->setVisible(false);
74 prBar2->setVisible(false);
75 prLabel1->setVisible(false);
76 prLabel2->setVisible(false);
78 /* Set Defaults for check and spin for limits */
79 limitCheckBox->setCheckState(mainWin->m_recordLimitCheck ? Qt::Checked : Qt::Unchecked);
80 limitSpinBox->setValue(mainWin->m_recordLimitVal);
81 daysCheckBox->setCheckState(mainWin->m_daysLimitCheck ? Qt::Checked : Qt::Unchecked);
82 daysSpinBox->setValue(mainWin->m_daysLimitVal);
84 m_nullFileNameId = -1;
87 restoreTree::~restoreTree()
93 * Called from the constructor to set up the page widgets and connections.
95 void restoreTree::setupPage()
97 connect(refreshButton, SIGNAL(pressed()), this, SLOT(refreshButtonPushed()));
98 connect(restoreButton, SIGNAL(pressed()), this, SLOT(restoreButtonPushed()));
99 connect(jobCombo, SIGNAL(currentIndexChanged(int)), this, SLOT(jobComboChanged(int)));
100 connect(jobCombo, SIGNAL(currentIndexChanged(int)), this, SLOT(updateRefresh()));
101 connect(clientCombo, SIGNAL(currentIndexChanged(int)), this, SLOT(updateRefresh()));
102 connect(fileSetCombo, SIGNAL(currentIndexChanged(int)), this, SLOT(updateRefresh()));
103 connect(limitCheckBox, SIGNAL(stateChanged(int)), this, SLOT(updateRefresh()));
104 connect(daysCheckBox, SIGNAL(stateChanged(int)), this, SLOT(updateRefresh()));
105 connect(daysSpinBox, SIGNAL(valueChanged(int)), this, SLOT(updateRefresh()));
106 connect(limitSpinBox, SIGNAL(valueChanged(int)), this, SLOT(updateRefresh()));
107 connect(directoryTree, SIGNAL(currentItemChanged(QTreeWidgetItem *, QTreeWidgetItem *)),
108 this, SLOT(directoryCurrentItemChanged(QTreeWidgetItem *, QTreeWidgetItem *)));
109 connect(directoryTree, SIGNAL(itemExpanded(QTreeWidgetItem *)),
110 this, SLOT(directoryItemExpanded(QTreeWidgetItem *)));
111 connect(directoryTree, SIGNAL(itemChanged(QTreeWidgetItem *, int)),
112 this, SLOT(directoryItemChanged(QTreeWidgetItem *, int)));
113 connect(fileTable, SIGNAL(currentItemChanged(QTableWidgetItem *, QTableWidgetItem *)),
114 this, SLOT(fileCurrentItemChanged(QTableWidgetItem *, QTableWidgetItem *)));
115 connect(jobTable, SIGNAL(cellClicked(int, int)),
116 this, SLOT(jobTableCellClicked(int, int)));
118 QStringList titles = QStringList() << tr("Directories");
119 directoryTree->setHeaderLabels(titles);
120 clientCombo->addItems(m_console->client_list);
121 fileSetCombo->addItem(tr("Any"));
122 fileSetCombo->addItems(m_console->fileset_list);
123 jobCombo->addItem(tr("Any"));
124 jobCombo->addItems(m_console->job_list);
126 directoryTree->setContextMenuPolicy(Qt::ActionsContextMenu);
129 void restoreTree::updateRefresh()
131 if (mainWin->m_rtPopDirDebug) Pmsg2(000, "testing prev=\"%s\" current=\"%s\"\n", m_prevJobCombo.toUtf8().data(), jobCombo->currentText().toUtf8().data());
132 m_dropdownChanged = (m_prevJobCombo != jobCombo->currentText())
133 || (m_prevClientCombo != clientCombo->currentText())
134 || (m_prevFileSetCombo != fileSetCombo->currentText()
135 || (m_prevLimitSpinBox != limitSpinBox->value())
136 || (m_prevDaysSpinBox != daysSpinBox->value())
137 || (m_prevLimitCheckState != limitCheckBox->checkState())
138 || (m_prevDaysCheckState != daysCheckBox->checkState())
140 if (m_dropdownChanged) {
141 if (mainWin->m_rtPopDirDebug) Pmsg0(000, "In restoreTree::updateRefresh Is CHANGED\n");
142 refreshLabel->setText(tr("Refresh From Re-Select"));
144 if (mainWin->m_rtPopDirDebug) Pmsg0(000, "In restoreTree::updateRefresh Is not Changed\n");
145 refreshLabel->setText(tr("Refresh From JobChecks"));
150 * When refresh button is pushed, perform a query getting the directories and
151 * use parseDirectory and addDirectory to populate the directory tree with items.
153 void restoreTree::populateDirectoryTree()
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(tr("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(tr("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(tr("Task ") + QString("%1").arg(ontask)+ " of " + QString("%1").arg(taskcount));
197 prBar2->setRange(0,0);
198 prLabel2->setText(tr("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(tr("Task ") + QString("%1").arg(ontask) + " of " + QString("%1").arg(taskcount));
240 prBar2->setRange(0,0);
241 prLabel2->setText(tr("Querying for Directories"));
244 m_directoryPathIdHash.clear();
245 bool querydone = false;
246 if (m_console->sql_cmd(cmd, results)) {
249 prLabel2->setText(tr("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, "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(tr("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(tr("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() == tr("Any")) {
483 fileSetCombo->setCurrentIndex(fileSetCombo->findText(tr("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() << tr("File Name") << tr("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(tr("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()
616 << tr("Job Id") << tr("Type") << tr("End Time") << tr("Hash") << tr("FileId"));
617 versionTable->clear();
618 versionTable->setColumnCount(headerlist.size());
619 versionTable->setHorizontalHeaderLabels(headerlist);
620 versionTable->setRowCount(0);
622 int pathid = m_directoryPathIdHash.value(directory, -1);
623 if ((pathid != -1) && (fileNameId != -1)) {
625 "SELECT Job.JobId AS JobId,Job.Level AS Type,Job.EndTime AS EndTime,File.MD5 AS MD5,File.FileId AS FileId"
627 " INNER JOIN Filename on (Filename.FilenameId=File.FilenameId)"
628 " INNER JOIN Path ON (Path.PathId=File.PathId)"
629 " INNER JOIN Job ON (File.JobId=Job.JobId)"
630 " WHERE Path.PathId=" + QString("%1").arg(pathid) +
631 //" AND Filename.Name='" + file + "'"
632 " AND Filename.FilenameId=" + QString("%1").arg(fileNameId) +
633 " AND Job.Jobid IN (" + m_checkedJobs + ")"
634 " ORDER BY Job.EndTime DESC";
636 if (mainWin->m_sqlDebug)
637 Pmsg1(000, "Query cmd : %s\n", cmd.toUtf8().data());
639 if (m_console->sql_cmd(cmd, results)) {
641 QTableWidgetItem* tableItem;
643 QStringList fieldlist;
644 versionTable->setRowCount(results.size());
647 /* Iterate through the record returned from the query */
648 foreach (QString resultline, results) {
649 fieldlist = resultline.split("\t");
651 /* remove directory */
652 if (fieldlist[0].trimmed() != "") {
653 /* Iterate through fields in the record */
654 foreach (field, fieldlist) {
655 field = field.trimmed(); /* strip leading & trailing spaces */
656 tableItem = new QTableWidgetItem(field, 1);
657 tableItem->setFlags(0);
658 tableItem->setForeground(blackBrush);
659 tableItem->setData(Qt::UserRole, QVariant(directory));
660 versionTable->setItem(row, column, tableItem);
663 Qt::ItemFlags flag = Qt::ItemIsUserCheckable | Qt::ItemIsEnabled | Qt::ItemIsTristate;
664 tableItem->setFlags(flag);
665 m_versionCheckStateList.append(Qt::Unchecked);
666 tableItem->setCheckState(Qt::Unchecked);
674 versionTable->resizeColumnsToContents();
675 versionTable->resizeRowsToContents();
676 versionTable->verticalHeader()->hide();
677 updateVersionTableChecks();
679 if (mainWin->m_sqlDebug)
680 Pmsg2(000, "not querying : pathid=%i fileNameId=%i\n", pathid, fileNameId);
682 connect(versionTable, SIGNAL(itemChanged(QTableWidgetItem *)),
683 this, SLOT(versionTableItemChanged(QTableWidgetItem *)));
687 * Save user settings associated with this page
689 void restoreTree::writeSettings()
691 QSettings settings(m_console->m_dir->name(), "bat");
692 settings.beginGroup(m_groupText);
693 settings.setValue(m_splitText, m_splitter->saveState());
698 * Read and restore user settings associated with this page
700 void restoreTree::readSettings()
702 m_groupText = tr("RestoreTreePage");
703 m_splitText = "splitterSizes_1";
704 QSettings settings(m_console->m_dir->name(), "bat");
705 settings.beginGroup(m_groupText);
706 m_splitter->restoreState(settings.value(m_splitText).toByteArray());
711 * This is a funcion to accomplish the one thing I struggled to figure out what
712 * was taking so long. It add the icons, but after the tree is made. Seemed to
713 * work fast after changing from png to png file for graphic.
715 void restoreTree::directoryItemExpanded(QTreeWidgetItem *item)
717 int childCount = item->childCount();
718 for (int i=0; i<childCount; i++) {
719 QTreeWidgetItem *child = item->child(i);
720 if (child->icon(0).isNull())
721 child->setIcon(0, QIcon(QString::fromUtf8(":images/folder.png")));
726 * Show what jobs meet the criteria and are being used to
727 * populate the directory tree and file and version tables.
729 void restoreTree::populateJobTable()
731 QBrush blackBrush(Qt::black);
733 if (mainWin->m_rtPopDirDebug) Pmsg0(000, "Repopulating the Job Table\n");
734 QStringList headerlist = (QStringList()
735 << tr("Job Id") << tr("End Time") << tr("Level")
736 << tr("Name") << tr("Purged") << tr("TU") << tr("TD"));
737 m_toggleUpIndex = headerlist.indexOf(tr("TU"));
738 m_toggleDownIndex = headerlist.indexOf(tr("TD"));
739 int purgedIndex = headerlist.indexOf(tr("Purged"));
741 jobTable->setColumnCount(headerlist.size());
742 jobTable->setHorizontalHeaderLabels(headerlist);
744 "SELECT Job.Jobid AS Id,Job.EndTime AS EndTime,Job.Level AS Level,"
745 "Job.Name AS JobName,Job.purgedfiles AS Purged"
747 /* INNER JOIN FileSet eliminates all restore jobs */
748 " INNER JOIN Client ON (Job.ClientId=Client.ClientId)"
749 " INNER JOIN FileSet ON (Job.FileSetId=FileSet.FileSetId)"
751 " Client.Name='" + clientCombo->currentText() + "'";
752 if ((jobCombo->currentIndex() >= 0) && (jobCombo->currentText() != tr("Any"))) {
753 jobQuery += " AND Job.name = '" + jobCombo->currentText() + "'";
755 if ((fileSetCombo->currentIndex() >= 0) && (fileSetCombo->currentText() != tr("Any"))) {
756 jobQuery += " AND FileSet.FileSet='" + fileSetCombo->currentText() + "'";
758 /* If Limit check box For limit by days is checked */
759 if (daysCheckBox->checkState() == Qt::Checked) {
760 QDateTime stamp = QDateTime::currentDateTime().addDays(-daysSpinBox->value());
761 QString since = stamp.toString(Qt::ISODate);
762 jobQuery += " AND Job.Starttime>'" + since + "'";
764 //jobQuery += " AND Job.purgedfiles=0";
765 jobQuery += " ORDER BY Job.EndTime DESC";
766 /* If Limit check box for limit records returned is checked */
767 if (limitCheckBox->checkState() == Qt::Checked) {
769 limit.setNum(limitSpinBox->value());
770 jobQuery += " LIMIT " + limit;
772 if (mainWin->m_sqlDebug)
773 Pmsg1(000, "Query cmd : %s\n", jobQuery.toUtf8().data());
776 if (m_console->sql_cmd(jobQuery, results)) {
778 QTableWidgetItem* tableItem;
780 QStringList fieldlist;
781 jobTable->setRowCount(results.size());
784 /* Iterate through the record returned from the query */
785 foreach (QString resultline, results) {
786 fieldlist = resultline.split("\t");
788 /* remove directory */
789 if (fieldlist[0].trimmed() != "") {
790 /* Iterate through fields in the record */
791 foreach (field, fieldlist) {
792 field = field.trimmed(); /* strip leading & trailing spaces */
794 tableItem = new QTableWidgetItem(field, 1);
795 tableItem->setFlags(0);
796 tableItem->setForeground(blackBrush);
797 jobTable->setItem(row, column, tableItem);
800 int purged = fieldlist[purgedIndex].toInt(&ok, 10);
801 if (!((ok) && (purged == 1))) {
802 Qt::ItemFlags flag = Qt::ItemIsUserCheckable | Qt::ItemIsEnabled | Qt::ItemIsTristate;
803 tableItem->setFlags(flag);
804 tableItem->setCheckState(Qt::Checked);
805 tableItem->setBackground(Qt::green);
807 tableItem->setFlags(0);
808 tableItem->setCheckState(Qt::Unchecked);
814 tableItem = new QTableWidgetItem(QIcon(QString::fromUtf8(":images/go-up.png")), "", 1);
815 tableItem->setFlags(0);
816 tableItem->setForeground(blackBrush);
817 jobTable->setItem(row, column, tableItem);
819 tableItem = new QTableWidgetItem(QIcon(QString::fromUtf8(":images/go-down.png")), "", 1);
820 tableItem->setFlags(0);
821 tableItem->setForeground(blackBrush);
822 jobTable->setItem(row, column, tableItem);
827 jobTable->resizeColumnsToContents();
828 jobTable->resizeRowsToContents();
829 jobTable->verticalHeader()->hide();
830 jobTable->hideColumn(purgedIndex);
833 void restoreTree::jobTableCellClicked(int row, int column)
835 if (column == m_toggleUpIndex){
837 for (cnt=0; cnt<row+1; cnt++) {
838 QTableWidgetItem *item = jobTable->item(cnt, 0);
840 Qt::CheckState state = item->checkState();
841 if (state == Qt::Checked)
842 item->setCheckState(Qt::Unchecked);
843 else if (state == Qt::Unchecked)
844 item->setCheckState(Qt::Checked);
848 if (column == m_toggleDownIndex){
849 int cnt, max = jobTable->rowCount();
850 for (cnt=row; cnt<max; cnt++) {
851 QTableWidgetItem *item = jobTable->item(cnt, 0);
853 Qt::CheckState state = item->checkState();
854 if (state == Qt::Checked)
855 item->setCheckState(Qt::Unchecked);
856 else if (state == Qt::Unchecked)
857 item->setCheckState(Qt::Checked);
864 * When a directory item is "changed" check the state of the checkable item
865 * to see if it is different than what it was which is stored in Qt::UserRole
866 * of the 2nd column, column 1, of the tree widget.
868 void restoreTree::directoryItemChanged(QTreeWidgetItem *item, int /*column*/)
870 Qt::CheckState prevState = (Qt::CheckState)item->data(1, Qt::UserRole).toInt();
871 Qt::CheckState curState = item->checkState(0);
872 QTreeWidgetItem* parent = item->parent();
873 Qt::CheckState parState;
874 if (parent) parState = parent->checkState(0);
875 else parState = (Qt::CheckState)3;
876 if (mainWin->m_rtDirICDebug) {
877 QString msg = QString("directory item OBJECT has changed prev=%1 cur=%2 par=%3 dir=%4\n")
878 .arg(prevState).arg(curState).arg(parState).arg(item->text(0));
879 Pmsg1(000, "%s", msg.toUtf8().data()); }
880 /* I only care when the check state changes */
881 if (prevState == curState) {
882 if (mainWin->m_rtDirICDebug) Pmsg0(000, "Returning Early\n");
886 if ((prevState == Qt::Unchecked) && (curState == Qt::Checked) && (parState != Qt::Unchecked)) {
887 if (mainWin->m_rtDirICDebug) Pmsg0(000, "Disconnected Setting to Qt::PartiallyChecked\n");
888 directoryTreeDisconnectedSet(item, Qt::PartiallyChecked);
889 curState = Qt::PartiallyChecked;
891 if ((prevState == Qt::PartiallyChecked) && (curState == Qt::Checked)) {
892 if (mainWin->m_rtDirICDebug) Pmsg0(000, "Disconnected Setting to Qt::Unchecked\n");
893 directoryTreeDisconnectedSet(item, Qt::Unchecked);
894 curState = Qt::Unchecked;
896 if (mainWin->m_rtDirICDebug) {
897 QString msg = QString("directory item CHECKSTATE has changed prev=%1 cur=%2 par=%3 dir=%4\n")
898 .arg(prevState).arg(curState).arg(parState).arg(item->text(0));
899 Pmsg1(000, "%s", msg.toUtf8().data()); }
901 item->setData(1, Qt::UserRole, QVariant(curState));
902 Qt::CheckState childState = curState;
903 if (childState == Qt::Checked)
904 childState = Qt::PartiallyChecked;
905 setCheckofChildren(item, childState);
907 /* Remove items from the exception lists. The multi exception list is my index
908 * of what exceptions can be removed when the directory is known*/
909 QString directory = item->data(0, Qt::UserRole).toString();
910 QStringList fullPathList = m_fileExceptionMulti.values(directory);
911 int fullPathListCount = fullPathList.count();
912 if ((mainWin->m_rtDirICDebug) && fullPathListCount) Pmsg2(000, "Will attempt to remove file exceptions for %s count %i\n", directory.toUtf8().data(), fullPathListCount);
913 foreach (QString fullPath, fullPathList) {
914 /* If there is no value in the hash for the key fullPath a value of 3 will be returned
915 * which will match no Qt::xxx values */
916 Qt::CheckState hashState = m_fileExceptionHash.value(fullPath, (Qt::CheckState)3);
917 if (mainWin->m_rtDirICDebug) Pmsg2(000, "hashState=%i childState=%i\n", hashState, childState);
918 if (hashState == Qt::Unchecked) {
919 fileExceptionRemove(fullPath, directory);
920 m_versionExceptionHash.remove(fullPath);
921 if (mainWin->m_rtDirICDebug) Pmsg0(000, "Attempted Removal A\n");
923 if (hashState == Qt::Checked) {
924 fileExceptionRemove(fullPath, directory);
925 m_versionExceptionHash.remove(fullPath);
926 if (mainWin->m_rtDirICDebug) Pmsg0(000, "Attempted Removal B\n");
930 if (item == directoryTree->currentItem()) {
931 if (mainWin->m_rtDirICDebug) Pmsg0(000, "Will attempt to update File Table Checks\n");
932 updateFileTableChecks();
933 versionTable->clear();
934 versionTable->setRowCount(0);
935 versionTable->setColumnCount(0);
937 if (mainWin->m_rtDirICDebug) Pmsg0(000, "Returning At End\n");
941 * When a directory item check state is changed, this function iterates through
942 * all subdirectories and sets all to the passed state, which is either partially
943 * checked or unchecked.
945 void restoreTree::setCheckofChildren(QTreeWidgetItem *item, Qt::CheckState state)
948 childCount = item->childCount();
949 for (int i=0; i<childCount; i++) {
950 QTreeWidgetItem *child = item->child(i);
951 child->setData(1, Qt::UserRole, QVariant(state));
952 child->setCheckState(0, state);
953 setCheckofChildren(child, state);
958 * When a File Table Item is "changed" check to see if the state of the checkable
959 * item has changed which is stored in m_fileCheckStateList
960 * If changed store in a hash m_fileExceptionHash that whether this file should be
962 * Called as a slot, connected after populated (after directory current changed called)
964 void restoreTree::fileTableItemChanged(QTableWidgetItem *item)
966 /* get the previous and current check states */
967 int row = fileTable->row(item);
968 Qt::CheckState prevState;
969 /* prevent a segfault */
970 prevState = m_fileCheckStateList[row];
971 Qt::CheckState curState = item->checkState();
973 /* deterimine the default state from the state of the directory */
974 QTreeWidgetItem *dirTreeItem = directoryTree->currentItem();
975 Qt::CheckState dirState = (Qt::CheckState)dirTreeItem->data(1, Qt::UserRole).toInt();
976 Qt::CheckState defState = Qt::PartiallyChecked;
977 if (dirState == Qt::Unchecked) defState = Qt::Unchecked;
979 /* determine if it is already in the m_fileExceptionHash */
980 QString directory = directoryTree->currentItem()->data(0, Qt::UserRole).toString();
981 QString file = item->text();
982 QString fullPath = directory + file;
983 Qt::CheckState hashState = m_fileExceptionHash.value(fullPath, (Qt::CheckState)3);
984 int verJobNum = m_versionExceptionHash.value(fullPath, 0);
986 if (mainWin->m_rtFileTabICDebug) {
987 QString msg = QString("filerow=%1 prev=%2 cur=%3 def=%4 hash=%5 dir=%6 verJobNum=%7\n")
988 .arg(row).arg(prevState).arg(curState).arg(defState).arg(hashState).arg(dirState).arg(verJobNum);
989 Pmsg1(000, "%s", msg.toUtf8().data()); }
991 /* Remove the hash if currently checked previously unchecked and directory is checked or partial */
992 if ((prevState == Qt::Checked) && (curState == Qt::Unchecked) && (dirState == Qt::Unchecked)) {
993 /* it can behave as defaulted so current of unchecked is fine */
994 if (mainWin->m_rtFileTabICDebug) Pmsg0(000, "Will fileExceptionRemove and m_versionExceptionHash.remove here\n");
995 fileExceptionRemove(fullPath, directory);
996 m_versionExceptionHash.remove(fullPath);
997 } else if ((prevState == Qt::PartiallyChecked) && (curState == Qt::Checked) && (dirState != Qt::Unchecked) && (verJobNum == 0)) {
998 if (mainWin->m_rtFileTabICDebug) Pmsg0(000, "Will fileExceptionInsert here\n");
999 fileExceptionInsert(fullPath, directory, Qt::Unchecked);
1000 } else if ((prevState == Qt::Unchecked) && (curState == Qt::Checked) && (dirState != Qt::Unchecked) && (verJobNum == 0) && (defState == Qt::PartiallyChecked)) {
1001 /* filerow=2 prev=0 cur=2 def=1 hash=0 dir=2 verJobNum=0 */
1002 if (mainWin->m_rtFileTabICDebug) Pmsg0(000, "Will fileExceptionRemove here\n");
1003 fileExceptionRemove(fullPath, directory);
1004 } else if ((prevState == Qt::Checked) && (curState == Qt::Unchecked) && (defState == Qt::PartiallyChecked) && (verJobNum != 0) && (hashState == Qt::Checked)) {
1005 /* Check dir, check version, attempt uncheck in file
1006 * filerow=4 prev=2 cur=0 def=1 hash=2 dir=2 verJobNum=53 */
1007 if (mainWin->m_rtFileTabICDebug) Pmsg0(000, "Will fileExceptionRemove and m_versionExceptionHash.remove here\n");
1008 fileExceptionRemove(fullPath, directory);
1009 m_versionExceptionHash.remove(fullPath);
1010 } else if ((prevState == Qt::Unchecked) && (curState == Qt::Checked) && (dirState != Qt::Unchecked) && (verJobNum == 0)) {
1011 /* filerow=0 prev=0 cur=2 def=1 hash=0 dirState=2 verJobNum */
1012 if (mainWin->m_rtFileTabICDebug) Pmsg0(000, "Will Not remove here\n");
1013 } else if (prevState != curState) {
1014 if (mainWin->m_rtFileTabICDebug) Pmsg2(000, " THE STATE OF THE Check has changed, Setting StateList[%i] to %i\n", row, curState);
1015 /* A user did not set the check state to Partially checked, ignore if so */
1016 if (curState != Qt::PartiallyChecked) {
1017 if ((defState == Qt::Unchecked) && (prevState == Qt::PartiallyChecked) && (curState == Qt::Unchecked)) {
1018 if (mainWin->m_rtFileTabICDebug) Pmsg0(000, " got here\n");
1020 if (mainWin->m_rtFileTabICDebug) Pmsg2(000, " Inserting into m_fileExceptionHash %s, %i\n", fullPath.toUtf8().data(), curState);
1021 fileExceptionInsert(fullPath, directory, curState);
1024 if (mainWin->m_rtFileTabICDebug) Pmsg1(000, "Removing version hash for %s\n", fullPath.toUtf8().data());
1025 /* programattically been changed back to a default state of Qt::PartiallyChecked remove the version hash here */
1026 m_versionExceptionHash.remove(fullPath);
1030 updateFileTableChecks();
1031 updateVersionTableChecks();
1035 * function to insert keys and values to both m_fileExceptionHash and m_fileExceptionMulti
1037 void restoreTree::fileExceptionInsert(QString &fullPath, QString &direcotry, Qt::CheckState state)
1039 m_fileExceptionHash.insert(fullPath, state);
1040 m_fileExceptionMulti.insert(direcotry, fullPath);
1041 directoryIconStateInsert(fullPath, state);
1045 * function to remove keys from both m_fileExceptionHash and m_fileExceptionMulti
1047 void restoreTree::fileExceptionRemove(QString &fullPath, QString &directory)
1049 m_fileExceptionHash.remove(fullPath);
1050 /* pull the list of values in the multi */
1051 QStringList fullPathList = m_fileExceptionMulti.values(directory);
1052 /* get the index of the fullpath to remove */
1053 int index = fullPathList.indexOf(fullPath);
1055 /* remove the desired item in the list */
1056 fullPathList.removeAt(index);
1057 /* remove the entire list from the multi */
1058 m_fileExceptionMulti.remove(directory);
1059 /* readd the remaining */
1060 foreach (QString fp, fullPathList) {
1061 m_fileExceptionMulti.insert(directory, fp);
1064 directoryIconStateRemove();
1068 * Overloaded function to be called from the slot and from other places to set the state
1069 * of the check marks in the version table
1071 void restoreTree::versionTableItemChanged(QTableWidgetItem *item)
1073 /* get the previous and current check states */
1074 int row = versionTable->row(item);
1075 QTableWidgetItem *colZeroItem = versionTable->item(row, 0);
1076 Qt::CheckState prevState = m_versionCheckStateList[row];
1077 Qt::CheckState curState = (Qt::CheckState)colZeroItem->checkState();
1078 m_versionCheckStateList[row] = curState;
1080 /* deterimine the default state from the state of the file */
1081 QTableWidgetItem *fileTableItem = fileTable->currentItem();
1082 Qt::CheckState fileState = (Qt::CheckState)fileTableItem->checkState();
1084 /* determine the default state */
1085 Qt::CheckState defState;
1087 defState = Qt::PartiallyChecked;
1088 if (fileState == Qt::Unchecked)
1089 defState = Qt::Unchecked;
1092 defState = Qt::Unchecked;
1094 /* determine if it is already in the versionExceptionHash */
1095 QString directory = directoryTree->currentItem()->data(0, Qt::UserRole).toString();
1096 Qt::CheckState dirState = directoryTree->currentItem()->checkState(0);
1097 QString file = fileTableItem->text();
1098 QString fullPath = directory + file;
1099 int thisJobNum = colZeroItem->text().toInt();
1100 int hashJobNum = m_versionExceptionHash.value(fullPath, 0);
1102 if (mainWin->m_rtVerTabICDebug) {
1103 QString msg = QString("versrow=%1 prev=%2 cur=%3 def=%4 dir=%5 hashJobNum=%6 thisJobNum=%7 filestate=%8 fec=%9 vec=%10\n")
1104 .arg(row).arg(prevState).arg(curState).arg(defState).arg(dirState).arg(hashJobNum).arg(thisJobNum).arg(fileState)
1105 .arg(m_fileExceptionHash.count()).arg(m_versionExceptionHash.count());
1106 Pmsg1(000, "%s", msg.toUtf8().data()); }
1107 /* if changed from partially checked to checked, make it unchecked */
1108 if ((curState == Qt::Checked) && (row == 0) && (fileState == Qt::Unchecked)) {
1109 if (mainWin->m_rtVerTabICDebug) Pmsg0(000, "Setting to Qt::Checked\n");
1110 fileTableItem->setCheckState(Qt::Checked);
1111 } else if ((prevState == Qt::PartiallyChecked) && (curState == Qt::Checked) && (row == 0) && (fileState == Qt::Checked) && (dirState == Qt::Unchecked)) {
1112 //versrow=0 prev=1 cur=2 def=1 dir=0 hashJobNum=0 thisJobNum=64 filestate=2 fec=1 vec=0
1113 if (mainWin->m_rtVerTabICDebug) Pmsg1(000, "fileExceptionRemove %s, %i\n", fullPath.toUtf8().data());
1114 fileExceptionRemove(fullPath, directory);
1115 } else if ((curState == Qt::Checked) && (row == 0) && (hashJobNum != 0) && (dirState != Qt::Unchecked)) {
1116 //versrow=0 prev=0 cur=2 def=1 dir=2 hashJobNum=53 thisJobNum=64 filestate=2 fec=1 vec=1
1117 if (mainWin->m_rtVerTabICDebug) Pmsg1(000, "m_versionExceptionHash.remove %s\n", fullPath.toUtf8().data());
1118 m_versionExceptionHash.remove(fullPath);
1119 fileExceptionRemove(fullPath, directory);
1120 } else if ((curState == Qt::Checked) && (row == 0)) {
1121 if (mainWin->m_rtVerTabICDebug) Pmsg1(000, "m_versionExceptionHash.remove %s\n", fullPath.toUtf8().data());
1122 m_versionExceptionHash.remove(fullPath);
1123 } else if (prevState != curState) {
1124 if (mainWin->m_rtVerTabICDebug) Pmsg2(000, " THE STATE OF THE version Check has changed, Setting StateList[%i] to %i\n", row, curState);
1125 if ((curState == Qt::Checked) || (curState == Qt::PartiallyChecked) && (row != 0)) {
1126 if (mainWin->m_rtVerTabICDebug) Pmsg2(000, "Inserting into m_versionExceptionHash %s, %i\n", fullPath.toUtf8().data(), thisJobNum);
1127 m_versionExceptionHash.insert(fullPath, thisJobNum);
1128 if (fileState != Qt::Checked) {
1129 if (mainWin->m_rtVerTabICDebug) Pmsg2(000, "Inserting into m_fileExceptionHash %s, %i\n", fullPath.toUtf8().data(), curState);
1130 fileExceptionInsert(fullPath, directory, curState);
1133 if (mainWin->m_rtVerTabICDebug) Pmsg0(000, "got here\n");
1136 if (mainWin->m_rtVerTabICDebug) Pmsg0(000, "no conditions met\n");
1139 updateFileTableChecks();
1140 updateVersionTableChecks();
1144 * Simple function to set the check state in the file table by disconnecting the
1145 * signal/slot the setting then reconnecting the signal/slot
1147 void restoreTree::fileTableDisconnectedSet(QTableWidgetItem *item, Qt::CheckState state, bool color)
1149 disconnect(fileTable, SIGNAL(itemChanged(QTableWidgetItem *)),
1150 this, SLOT(fileTableItemChanged(QTableWidgetItem *)));
1151 item->setCheckState(state);
1152 if (color) item->setBackground(Qt::yellow);
1153 else item->setBackground(Qt::white);
1154 connect(fileTable, SIGNAL(itemChanged(QTableWidgetItem *)),
1155 this, SLOT(fileTableItemChanged(QTableWidgetItem *)));
1159 * Simple function to set the check state in the version table by disconnecting the
1160 * signal/slot the setting then reconnecting the signal/slot
1162 void restoreTree::versionTableDisconnectedSet(QTableWidgetItem *item, Qt::CheckState state)
1164 disconnect(versionTable, SIGNAL(itemChanged(QTableWidgetItem *)),
1165 this, SLOT(versionTableItemChanged(QTableWidgetItem *)));
1166 item->setCheckState(state);
1167 connect(versionTable, SIGNAL(itemChanged(QTableWidgetItem *)),
1168 this, SLOT(versionTableItemChanged(QTableWidgetItem *)));
1172 * Simple function to set the check state in the directory tree by disconnecting the
1173 * signal/slot the setting then reconnecting the signal/slot
1175 void restoreTree::directoryTreeDisconnectedSet(QTreeWidgetItem *item, Qt::CheckState state)
1177 disconnect(directoryTree, SIGNAL(itemChanged(QTreeWidgetItem *, int)),
1178 this, SLOT(directoryItemChanged(QTreeWidgetItem *, int)));
1179 item->setCheckState(0, state);
1180 connect(directoryTree, SIGNAL(itemChanged(QTreeWidgetItem *, int)),
1181 this, SLOT(directoryItemChanged(QTreeWidgetItem *, int)));
1185 * Simplify the updating of the check state in the File table by iterating through
1186 * each item in the file table to determine it's appropriate state.
1187 * !! Will probably want to concoct a way to do this without iterating for the possibility
1188 * of the very large directories.
1190 void restoreTree::updateFileTableChecks()
1192 /* deterimine the default state from the state of the directory */
1193 QTreeWidgetItem *dirTreeItem = directoryTree->currentItem();
1194 Qt::CheckState dirState = dirTreeItem->checkState(0);
1196 QString dirName = dirTreeItem->data(0, Qt::UserRole).toString();
1198 /* Update the items in the version table */
1199 int rcnt = fileTable->rowCount();
1200 for (int row=0; row<rcnt; row++) {
1201 QTableWidgetItem* item = fileTable->item(row, 0);
1203 Qt::CheckState curState = item->checkState();
1204 Qt::CheckState newState = Qt::PartiallyChecked;
1205 if (dirState == Qt::Unchecked) newState = Qt::Unchecked;
1207 /* determine if it is already in the m_fileExceptionHash */
1208 QString file = item->text();
1209 QString fullPath = dirName + file;
1210 Qt::CheckState hashState = m_fileExceptionHash.value(fullPath, (Qt::CheckState)3);
1211 int hashJobNum = m_versionExceptionHash.value(fullPath, 0);
1213 if (hashState != 3) newState = hashState;
1215 if (mainWin->m_rtUpdateFTDebug) {
1216 QString msg = QString("file row=%1 cur=%2 hash=%3 new=%4 dirState=%5\n")
1217 .arg(row).arg(curState).arg(hashState).arg(newState).arg(dirState);
1218 Pmsg1(000, "%s", msg.toUtf8().data());
1221 bool docolor = false;
1222 if (hashJobNum != 0) docolor = true;
1223 bool isyellow = item->background().color() == QColor(Qt::yellow);
1224 if ((newState != curState) || (hashState == 3) || ((isyellow && !docolor) || (!isyellow && docolor)))
1225 fileTableDisconnectedSet(item, newState, docolor);
1226 m_fileCheckStateList[row] = newState;
1231 * Simplify the updating of the check state in the Version table by iterating through
1232 * each item in the file table to determine it's appropriate state.
1234 void restoreTree::updateVersionTableChecks()
1236 /* deterimine the default state from the state of the directory */
1237 QTreeWidgetItem *dirTreeItem = directoryTree->currentItem();
1238 Qt::CheckState dirState = dirTreeItem->checkState(0);
1239 QString dirName = dirTreeItem->data(0, Qt::UserRole).toString();
1241 /* deterimine the default state from the state of the file */
1242 QTableWidgetItem *fileTableItem = fileTable->item(fileTable->currentRow(), 0);
1243 Qt::CheckState fileState = fileTableItem->checkState();
1244 QString file = fileTableItem->text();
1245 QString fullPath = dirName + file;
1246 int hashJobNum = m_versionExceptionHash.value(fullPath, 0);
1248 /* Update the items in the version table */
1249 int cnt = versionTable->rowCount();
1250 for (int row=0; row<cnt; row++) {
1251 QTableWidgetItem* item = versionTable->item(row, 0);
1253 Qt::CheckState curState = item->checkState();
1254 Qt::CheckState newState = Qt::Unchecked;
1256 if ((row == 0) && (fileState != Qt::Unchecked) && (hashJobNum == 0))
1257 newState = Qt::PartiallyChecked;
1258 /* determine if it is already in the versionExceptionHash */
1260 int thisJobNum = item->text().toInt();
1261 if (thisJobNum == hashJobNum)
1262 newState = Qt::Checked;
1264 if (mainWin->m_rtChecksDebug) {
1265 QString msg = QString("ver row=%1 cur=%2 hashJobNum=%3 new=%4 dirState=%5\n")
1266 .arg(row).arg(curState).arg(hashJobNum).arg(newState).arg(dirState);
1267 Pmsg1(000, "%s", msg.toUtf8().data());
1269 if (newState != curState)
1270 versionTableDisconnectedSet(item, newState);
1271 m_versionCheckStateList[row] = newState;
1276 * Quick subroutine to "return via subPaths" a list of subpaths when passed a fullPath
1278 void restoreTree::fullPathtoSubPaths(QStringList &subPaths, QString &fullPath_in)
1282 QString fullPath = fullPath_in;
1283 QString direct, path;
1284 while (((index = fullPath.lastIndexOf("/", -2)) != -1) && (!done)) {
1285 direct = path = fullPath;
1286 path.replace(index+1, fullPath.length()-index-1, "");
1287 direct.replace(0, index+1, "");
1289 QString msg = QString("length = \"%1\" index = \"%2\" Considering \"%3\" \"%4\"\n")
1290 .arg(fullPath.length()).arg(index).arg(path).arg(direct);
1291 Pmsg0(000, msg.toUtf8().data());
1294 subPaths.append(fullPath);
1299 * A Function to set the icon state and insert a record into
1300 * m_directoryIconStateHash when an exception is added by the user
1302 void restoreTree::directoryIconStateInsert(QString &fullPath, Qt::CheckState excpState)
1305 fullPathtoSubPaths(paths, fullPath);
1306 /* an exception that causes the item in the file table to be "Checked" has occured */
1307 if (excpState == Qt::Checked) {
1308 bool foundAsUnChecked = false;
1309 QTreeWidgetItem *firstItem = m_dirPaths.value(paths[0]);
1311 if (firstItem->checkState(0) == Qt::Unchecked)
1312 foundAsUnChecked = true;
1314 if (foundAsUnChecked) {
1315 /* as long as directory item is Unchecked, set icon state to "green check" */
1317 QListIterator<QString> siter(paths);
1318 while (siter.hasNext() && !done) {
1319 QString path = siter.next();
1320 QTreeWidgetItem *item = m_dirPaths.value(path);
1322 if (item->checkState(0) != Qt::Unchecked)
1325 directorySetIcon(1, FolderGreenChecked, path, item);
1326 if (mainWin->m_rtIconStateDebug) Pmsg1(000, "In restoreTree::directoryIconStateInsert inserting %s\n", path.toUtf8().data());
1331 /* if it is partially checked or fully checked insert green Check until a unchecked is found in the path */
1332 if (mainWin->m_rtIconStateDebug) Pmsg1(000, "In restoreTree::directoryIconStateInsert Aqua %s\n", paths[0].toUtf8().data());
1334 QListIterator<QString> siter(paths);
1335 while (siter.hasNext() && !done) {
1336 QString path = siter.next();
1337 QTreeWidgetItem *item = m_dirPaths.value(path);
1338 if (item) { /* if the directory item is checked, set icon state to unchecked "green check" */
1339 if (item->checkState(0) == Qt::Checked)
1341 directorySetIcon(1, FolderGreenChecked, path, item);
1342 if (mainWin->m_rtIconStateDebug) Pmsg1(000, "In restoreTree::directoryIconStateInsert boogie %s\n", path.toUtf8().data());
1347 /* an exception that causes the item in the file table to be "Unchecked" has occured */
1348 if (excpState == Qt::Unchecked) {
1350 QListIterator<QString> siter(paths);
1351 while (siter.hasNext() && !done) {
1352 QString path = siter.next();
1353 QTreeWidgetItem *item = m_dirPaths.value(path);
1354 if (item) { /* if the directory item is checked, set icon state to unchecked "white check" */
1355 if (item->checkState(0) == Qt::Checked)
1357 directorySetIcon(1, FolderWhiteChecked, path, item);
1358 if (mainWin->m_rtIconStateDebug) Pmsg1(000, "In restoreTree::directoryIconStateInsert boogie %s\n", path.toUtf8().data());
1365 * A function to set the icon state back to "folder" and to remove a record from
1366 * m_directoryIconStateHash when an exception is removed by a user.
1368 void restoreTree::directoryIconStateRemove()
1370 QHash<QString, int> shouldBeIconStateHash;
1371 /* First determine all paths with icons that should be checked with m_fileExceptionHash */
1372 /* Use iterator tera to iterate through m_fileExceptionHash */
1373 QHashIterator<QString, Qt::CheckState> tera(m_fileExceptionHash);
1374 while (tera.hasNext()) {
1376 if (mainWin->m_rtIconStateDebug) Pmsg2(000, "Alpha Key %s value %i\n", tera.key().toUtf8().data(), tera.value());
1378 QString keyPath = tera.key();
1379 Qt::CheckState state = tera.value();
1382 fullPathtoSubPaths(paths, keyPath);
1383 /* if the state of the item in m_fileExceptionHash is checked
1384 * each of the subpaths should be "Checked Green" */
1385 if (state == Qt::Checked) {
1387 bool foundAsUnChecked = false;
1388 QTreeWidgetItem *firstItem = m_dirPaths.value(paths[0]);
1390 if (firstItem->checkState(0) == Qt::Unchecked)
1391 foundAsUnChecked = true;
1393 if (foundAsUnChecked) {
1394 /* The right most directory is Unchecked, iterate leftwards
1395 * as long as directory item is Unchecked, set icon state to "green check" */
1397 QListIterator<QString> siter(paths);
1398 while (siter.hasNext() && !done) {
1399 QString path = siter.next();
1400 QTreeWidgetItem *item = m_dirPaths.value(path);
1402 if (item->checkState(0) != Qt::Unchecked)
1405 shouldBeIconStateHash.insert(path, FolderGreenChecked);
1406 if (mainWin->m_rtIconStateDebug) Pmsg1(000, "In restoreTree::directoryIconStateInsert inserting %s\n", path.toUtf8().data());
1412 /* The right most directory is Unchecked, iterate leftwards
1413 * until directory item is Checked, set icon state to "green check" */
1415 QListIterator<QString> siter(paths);
1416 while (siter.hasNext() && !done) {
1417 QString path = siter.next();
1418 QTreeWidgetItem *item = m_dirPaths.value(path);
1420 if (item->checkState(0) == Qt::Checked)
1422 shouldBeIconStateHash.insert(path, FolderGreenChecked);
1427 /* if the state of the item in m_fileExceptionHash is UNChecked
1428 * each of the subpaths should be "Checked white" until the tree item
1429 * which represents that path is Qt::Checked */
1430 if (state == Qt::Unchecked) {
1432 QListIterator<QString> siter(paths);
1433 while (siter.hasNext() && !done) {
1434 QString path = siter.next();
1435 QTreeWidgetItem *item = m_dirPaths.value(path);
1437 if (item->checkState(0) == Qt::Checked)
1439 shouldBeIconStateHash.insert(path, FolderWhiteChecked);
1444 /* now iterate through m_directoryIconStateHash which are the items that are checked
1445 * and remove all of those that are not in shouldBeIconStateHash */
1446 QHashIterator<QString, int> iter(m_directoryIconStateHash);
1447 while (iter.hasNext()) {
1449 if (mainWin->m_rtIconStateDebug) Pmsg2(000, "Beta Key %s value %i\n", iter.key().toUtf8().data(), iter.value());
1451 QString keyPath = iter.key();
1452 if (shouldBeIconStateHash.value(keyPath)) {
1453 if (mainWin->m_rtIconStateDebug) Pmsg1(000, "WAS found in shouldBeStateHash %s\n", keyPath.toUtf8().data());
1454 //newval = m_directoryIconStateHash.value(path, FolderUnchecked) & (~change);
1455 int newval = shouldBeIconStateHash.value(keyPath);
1457 newval = newval & FolderBothChecked;
1458 QTreeWidgetItem *item = m_dirPaths.value(keyPath);
1460 directorySetIcon(0, newval, keyPath, item);
1462 if (mainWin->m_rtIconStateDebug) Pmsg1(000, "NOT found in shouldBeStateHash %s\n", keyPath.toUtf8().data());
1463 QTreeWidgetItem *item = m_dirPaths.value(keyPath);
1465 directorySetIcon(0, FolderBothChecked, keyPath, item);
1466 //item->setIcon(0,QIcon(QString::fromUtf8(":images/folder.png")));
1467 //m_directoryIconStateHash.remove(keyPath);
1472 void restoreTree::directorySetIcon(int operation, int change, QString &path, QTreeWidgetItem* item) {
1474 /* we are adding a check type white or green */
1475 if (operation > 0) {
1476 /* get the old val and "bitwise OR" with the change */
1477 newval = m_directoryIconStateHash.value(path, FolderUnchecked) | change;
1478 if (mainWin->m_rtIconStateDebug) Pmsg2(000, "Inserting into m_directoryIconStateHash path=%s newval=%i\n", path.toUtf8().data(), newval);
1479 m_directoryIconStateHash.insert(path, newval);
1481 /* we are removing a check type white or green */
1482 newval = m_directoryIconStateHash.value(path, FolderUnchecked) & (~change);
1484 if (mainWin->m_rtIconStateDebug) Pmsg2(000, "Removing from m_directoryIconStateHash path=%s newval=%i\n", path.toUtf8().data(), newval);
1485 m_directoryIconStateHash.remove(path);
1488 if (mainWin->m_rtIconStateDebug) Pmsg2(000, "Inserting into m_directoryIconStateHash path=%s newval=%i\n", path.toUtf8().data(), newval);
1489 m_directoryIconStateHash.insert(path, newval);
1492 if (newval == FolderUnchecked)
1493 item->setIcon(0, QIcon(QString::fromUtf8(":images/folder.png")));
1494 else if (newval == FolderGreenChecked)
1495 item->setIcon(0, QIcon(QString::fromUtf8(":images/folderchecked.png")));
1496 else if (newval == FolderWhiteChecked)
1497 item->setIcon(0, QIcon(QString::fromUtf8(":images/folderunchecked.png")));
1498 else if (newval == FolderBothChecked)
1499 item->setIcon(0, QIcon(QString::fromUtf8(":images/folderbothchecked.png")));
1505 void restoreTree::restoreButtonPushed()
1507 /* Set progress bars and repaint */
1508 prLabel1->setVisible(true);
1509 prLabel1->setText("Task 1 of 3");
1510 prLabel2->setVisible(true);
1511 prLabel2->setText("Processing Checked directories");
1512 prBar1->setVisible(true);
1513 prBar1->setRange(0, 3);
1514 prBar1->setValue(0);
1515 prBar2->setVisible(true);
1516 prBar2->setRange(0, 0);
1518 QMultiHash<int, QString> versionFilesMulti;
1520 QHash <QString, bool> fullPathDone;
1521 QHash <QString, int> fileIndexHash;
1522 if ((mainWin->m_rtRestore1Debug) || (mainWin->m_rtRestore2Debug) || (mainWin->m_rtRestore3Debug))
1523 Pmsg0(000, "In restoreTree::restoreButtonPushed\n");
1524 /* Use a tree widget item iterator to count directories for the progress bar */
1525 QTreeWidgetItemIterator diterc(directoryTree, QTreeWidgetItemIterator::Checked);
1530 } /* while (*diterc) */
1531 prBar2->setRange(0, ditcount);
1532 prBar2->setValue(0);
1534 /* Use a tree widget item iterator filtering for Checked Items */
1535 QTreeWidgetItemIterator diter(directoryTree, QTreeWidgetItemIterator::Checked);
1537 QString directory = (*diter)->data(0, Qt::UserRole).toString();
1538 int pathid = m_directoryPathIdHash.value(directory, -1);
1540 if (mainWin->m_rtRestore1Debug)
1541 Pmsg1(000, "Directory Checked=\"%s\"\n", directory.toUtf8().data());
1542 /* With a checked directory, query for the files in the directory */
1545 "SELECT Filename.Name AS Filename, t1.JobId AS JobId, File.FileIndex AS FileIndex"
1547 " ( SELECT File.FilenameId AS FilenameId, MAX(Job.JobId) AS JobId"
1549 " INNER JOIN Job ON (Job.JobId=File.JobId)"
1550 " WHERE File.PathId=" + QString("%1").arg(pathid) +
1551 " AND Job.Jobid IN (" + m_checkedJobs + ")"
1552 " AND File.FilenameId!=" + QString("%1").arg(m_nullFileNameId) +
1553 " GROUP BY File.FilenameId"
1555 " INNER JOIN Filename on (Filename.FilenameId=File.FilenameId)"
1556 " INNER JOIN Job ON (Job.JobId=File.JobId)"
1557 " WHERE File.PathId=" + QString("%1").arg(pathid) +
1558 " AND File.FilenameId=t1.FilenameId"
1559 " AND Job.Jobid=t1.JobId"
1560 " ORDER BY Filename";
1562 if (mainWin->m_sqlDebug) Pmsg1(000, "Query cmd : %s\n", cmd.toUtf8().data());
1563 QStringList results;
1564 if (m_console->sql_cmd(cmd, results)) {
1565 QStringList fieldlist;
1568 /* Iterate through the record returned from the query */
1569 foreach (QString resultline, results) {
1570 /* Iterate through fields in the record */
1572 QString fullPath = "";
1573 Qt::CheckState fileExcpState = (Qt::CheckState)4;
1574 fieldlist = resultline.split("\t");
1577 foreach (QString field, fieldlist) {
1579 fullPath = directory + field;
1582 version = field.toInt();
1585 fileIndex = field.toInt();
1589 fileExcpState = m_fileExceptionHash.value(fullPath, (Qt::CheckState)3);
1591 int excpVersion = m_versionExceptionHash.value(fullPath, 0);
1592 if (fileExcpState != Qt::Unchecked) {
1594 if (excpVersion != 0) {
1595 debugtext = QString("*E* version=%1").arg(excpVersion);
1596 version = excpVersion;
1597 fileIndex = queryFileIndex(fullPath, excpVersion);
1599 debugtext = QString("___ version=%1").arg(version);
1600 if (mainWin->m_rtRestore1Debug)
1601 Pmsg2(000, "Restoring %s File %s\n", debugtext.toUtf8().data(), fullPath.toUtf8().data());
1602 fullPathDone.insert(fullPath, 1);
1603 fileIndexHash.insert(fullPath, fileIndex);
1604 versionFilesMulti.insert(version, fullPath);
1612 prBar2->setValue(ditcount);
1614 } /* while (*diter) */
1615 prBar1->setValue(1);
1616 prLabel1->setText("Task 2 of 3");
1617 prLabel2->setText("Processing Exceptions");
1618 prBar2->setRange(0, 0);
1621 /* There may be some exceptions not accounted for yet with fullPathDone */
1622 QHashIterator<QString, Qt::CheckState> ftera(m_fileExceptionHash);
1623 while (ftera.hasNext()) {
1625 QString fullPath = ftera.key();
1626 Qt::CheckState state = ftera.value();
1628 /* now we don't want the ones already done */
1629 if (fullPathDone.value(fullPath, 0) == 0) {
1630 int version = m_versionExceptionHash.value(fullPath, 0);
1632 QString debugtext = "";
1634 fileIndex = queryFileIndex(fullPath, version);
1635 debugtext = QString("E1* version=%1 fileid=%2").arg(version).arg(fileIndex);
1637 version = mostRecentVersionfromFullPath(fullPath);
1639 fileIndex = queryFileIndex(fullPath, version);
1640 debugtext = QString("E2* version=%1 fileid=%2").arg(version).arg(fileIndex);
1642 debugtext = QString("Error det vers").arg(version);
1644 if (mainWin->m_rtRestore1Debug)
1645 Pmsg2(000, "Restoring %s file %s\n", debugtext.toUtf8().data(), fullPath.toUtf8().data());
1646 versionFilesMulti.insert(version, fullPath);
1648 fileIndexHash.insert(fullPath, fileIndex);
1649 } /* if fullPathDone.value(fullPath, 0) == 0 */
1650 } /* if state != 0 */
1651 } /* while ftera.hasNext */
1652 /* The progress bars for the next step */
1653 prBar1->setValue(2);
1654 prLabel1->setText("Task 3 of 3");
1655 prLabel2->setText("Filling Database Table");
1656 prBar2->setRange(0, vFMCounter);
1658 prBar2->setValue(vFMCounter);
1661 /* now for the final spit out of the versions and lists of files for each version */
1662 QHash<int, int> doneKeys;
1663 QHashIterator<int, QString> vFMiter(versionFilesMulti);
1664 QString tempTable = "";
1666 while (vFMiter.hasNext()) {
1668 int fversion = vFMiter.key();
1669 /* did not succeed in getting an iterator to work as expected on versionFilesMulti so use doneKeys */
1670 if (doneKeys.value(fversion, 0) == 0) {
1671 if (tempTable == "") {
1672 QSettings settings("www.bacula.org", "bat");
1673 settings.beginGroup("Restore");
1674 int counter = settings.value("Counter", 1).toInt();
1675 settings.setValue("Counter", counter+1);
1676 settings.endGroup();
1677 tempTable = "restore_" + QString("%1").arg(qrand()) + "_" + QString("%1").arg(counter);
1678 QString sqlcmd = "CREATE TEMPORARY TABLE " + tempTable + " (JobId INTEGER, FileIndex INTEGER)";
1679 if (mainWin->m_sqlDebug)
1680 Pmsg1(000, "Query cmd : %s ;\n", sqlcmd.toUtf8().data());
1681 QStringList results;
1682 if (!m_console->sql_cmd(sqlcmd, results))
1683 Pmsg1(000, "CREATE TABLE FAILED!!!! %s\n", sqlcmd.toUtf8().data());
1686 if (mainWin->m_rtRestore2Debug) Pmsg1(000, "Version->%i\n", fversion);
1687 QStringList fullPathList = versionFilesMulti.values(fversion);
1688 /* create the command to perform the restore */
1689 foreach(QString ffullPath, fullPathList) {
1690 int fileIndex = fileIndexHash.value(ffullPath);
1691 if (mainWin->m_rtRestore2Debug) Pmsg2(000, " file->%s id %i\n", ffullPath.toUtf8().data(), fileIndex);
1692 QString sqlcmd = "INSERT INTO " + tempTable + " (JobId, FileIndex) VALUES (" + QString("%1").arg(fversion) + ", " + QString("%1").arg(fileIndex) + ")";
1693 if (mainWin->m_rtRestore3Debug)
1694 Pmsg1(000, "Insert cmd : %s\n", sqlcmd.toUtf8().data());
1695 QStringList results;
1696 if (!m_console->sql_cmd(sqlcmd, results))
1697 Pmsg1(000, "INSERT INTO FAILED!!!! %s\n", sqlcmd.toUtf8().data());
1698 prBar2->setValue(++vFMCounter);
1699 } /* foreach fullPathList */
1700 doneKeys.insert(fversion,1);
1701 jobList.append(fversion);
1702 } /* if (doneKeys.value(fversion, 0) == 0) */
1703 } /* while (vFMiter.hasNext()) */
1704 if (tempTable != "") {
1705 /* a table was made, lets run the job */
1706 QString jobOption = " jobid=\"";
1708 /* create a list of jobs comma separated */
1709 foreach (int job, jobList) {
1710 if (first) first = false;
1711 else jobOption += ",";
1712 jobOption += QString("%1").arg(job);
1715 QString cmd = QString("restore");
1717 " client=\"" + m_prevClientCombo + "\"" +
1718 " file=\"?" + tempTable + "\" done";
1719 if (mainWin->m_commandDebug)
1720 Pmsg1(000, "preRestore command \'%s\'\n", cmd.toUtf8().data());
1721 consoleCommand(cmd);
1723 /* turn off the progress widgets */
1724 prBar1->setVisible(false);
1725 prBar2->setVisible(false);
1726 prLabel1->setVisible(false);
1727 prLabel2->setVisible(false);
1730 int restoreTree::mostRecentVersionfromFullPath(QString &fullPath)
1733 QString directory, fileName;
1734 int index = fullPath.lastIndexOf("/", -2);
1736 directory = fileName = fullPath;
1737 directory.replace(index+1, fullPath.length()-index-1, "");
1738 fileName.replace(0, index+1, "");
1740 QString msg = QString("length = \"%1\" index = \"%2\" Considering \"%3\" \"%4\"\n")
1741 .arg(fullPath.length()).arg(index).arg(fileName).arg(directory);
1742 Pmsg0(000, msg.toUtf8().data());
1744 int pathid = m_directoryPathIdHash.value(directory, -1);
1746 /* so now we need the latest version from the database */
1748 "SELECT MAX(Job.JobId)"
1750 " INNER JOIN Filename on (Filename.FilenameId=File.FilenameId)"
1751 " INNER JOIN Job ON (File.JobId=Job.JobId)"
1752 " WHERE File.PathId=" + QString("%1").arg(pathid) +
1753 " AND Job.Jobid IN (" + m_checkedJobs + ")"
1754 " AND Filename.Name='" + fileName + "'"
1755 " AND File.FilenameId!=" + QString("%1").arg(m_nullFileNameId) +
1756 " GROUP BY Filename.Name";
1758 if (mainWin->m_sqlDebug) Pmsg1(000, "Query cmd : %s\n", cmd.toUtf8().data());
1759 QStringList results;
1760 if (m_console->sql_cmd(cmd, results)) {
1761 QStringList fieldlist;
1763 /* Iterate through the record returned from the query */
1764 foreach (QString resultline, results) {
1765 /* Iterate through fields in the record */
1767 fieldlist = resultline.split("\t");
1768 foreach (QString field, fieldlist) {
1770 qversion = field.toInt();
1778 } /* if (index != -1) */
1783 int restoreTree::queryFileIndex(QString &fullPath, int jobId)
1786 QString directory, fileName;
1787 int index = fullPath.lastIndexOf("/", -2);
1789 directory = fileName = fullPath;
1790 directory.replace(index+1, fullPath.length()-index-1, "");
1791 fileName.replace(0, index+1, "");
1793 QString msg = QString("length = \"%1\" index = \"%2\" Considering \"%3\" \"%4\"\n")
1794 .arg(fullPath.length()).arg(index).arg(fileName).arg(directory);
1795 Pmsg0(000, msg.toUtf8().data());
1797 int pathid = m_directoryPathIdHash.value(directory, -1);
1799 /* so now we need the latest version from the database */
1804 " INNER JOIN Filename on (Filename.FilenameId=File.FilenameId)"
1805 " INNER JOIN Job ON (File.JobId=Job.JobId)"
1806 " WHERE File.PathId=" + QString("%1").arg(pathid) +
1807 " AND Filename.Name='" + fileName + "'"
1808 " AND Job.Jobid='" + QString("%1").arg(jobId) + "'"
1809 " GROUP BY File.FileIndex";
1811 if (mainWin->m_sqlDebug) Pmsg1(000, "Query cmd : %s\n", cmd.toUtf8().data());
1812 QStringList results;
1813 if (m_console->sql_cmd(cmd, results)) {
1814 QStringList fieldlist;
1816 /* Iterate through the record returned from the query */
1817 foreach (QString resultline, results) {
1818 /* Iterate through fields in the record */
1820 fieldlist = resultline.split("\t");
1821 foreach (QString field, fieldlist) {
1823 qfileIndex = field.toInt();
1831 } /* if (index != -1) */