2 Bacula® - The Network Backup Solution
4 Copyright (C) 2007-2007 Free Software Foundation Europe e.V.
6 The main author of Bacula is Kern Sibbald, with contributions from
7 many others, a complete list can be found in the file AUTHORS.
8 This program is Free Software; you can redistribute it and/or
9 modify it under the terms of version two of the GNU General Public
10 License as published by the Free Software Foundation and included
13 This program is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
23 Bacula® is a registered trademark of John Walker.
24 The licensor of Bacula is the Free Software Foundation Europe
25 (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich,
26 Switzerland, email:ftf@fsfeurope.org.
34 * Kern Sibbald, February MMVII
39 #include "restoretree.h"
42 restoreTree::restoreTree()
45 m_name = "Version Browser";
47 QTreeWidgetItem* thisitem = mainWin->getFromHash(this);
48 thisitem->setIcon(0, QIcon(QString::fromUtf8(":images/browse.png")));
54 m_winRegExpDrive.setPattern("^[a-z]:/$");
55 m_winRegExpPath.setPattern("^[a-z]:/");
56 m_slashregex.setPattern("/");
60 QGridLayout *gridLayout = new QGridLayout(this);
61 gridLayout->setSpacing(6);
62 gridLayout->setMargin(9);
63 gridLayout->setObjectName(QString::fromUtf8("gridLayout"));
65 m_splitter = new QSplitter(Qt::Vertical, this);
66 QScrollArea *area = new QScrollArea();
67 area->setObjectName(QString::fromUtf8("area"));
68 area->setWidget(widget);
69 area->setWidgetResizable(true);
70 m_splitter->addWidget(splitter);
71 m_splitter->addWidget(area);
73 gridLayout->addWidget(m_splitter, 0, 0, 1, 1);
75 /* progress widgets */
76 prBar1->setVisible(false);
77 prBar2->setVisible(false);
78 prLabel1->setVisible(false);
79 prLabel2->setVisible(false);
81 /* Set Defaults for check and spin for limits */
82 limitCheckBox->setCheckState(mainWin->m_recordLimitCheck ? Qt::Checked : Qt::Unchecked);
83 limitSpinBox->setValue(mainWin->m_recordLimitVal);
84 daysCheckBox->setCheckState(mainWin->m_daysLimitCheck ? Qt::Checked : Qt::Unchecked);
85 daysSpinBox->setValue(mainWin->m_daysLimitVal);
87 m_nullFileNameId = -1;
90 restoreTree::~restoreTree()
96 * Called from the constructor to set up the page widgets and connections.
98 void restoreTree::setupPage()
100 connect(refreshButton, SIGNAL(pressed()), this, SLOT(refreshButtonPushed()));
101 connect(restoreButton, SIGNAL(pressed()), this, SLOT(restoreButtonPushed()));
102 connect(jobCombo, SIGNAL(currentIndexChanged(int)), this, SLOT(jobComboChanged(int)));
103 connect(jobCombo, SIGNAL(currentIndexChanged(int)), this, SLOT(updateRefresh()));
104 connect(clientCombo, SIGNAL(currentIndexChanged(int)), this, SLOT(updateRefresh()));
105 connect(fileSetCombo, SIGNAL(currentIndexChanged(int)), this, SLOT(updateRefresh()));
106 connect(limitCheckBox, SIGNAL(stateChanged(int)), this, SLOT(updateRefresh()));
107 connect(daysCheckBox, SIGNAL(stateChanged(int)), this, SLOT(updateRefresh()));
108 connect(daysSpinBox, SIGNAL(valueChanged(int)), this, SLOT(updateRefresh()));
109 connect(limitSpinBox, SIGNAL(valueChanged(int)), this, SLOT(updateRefresh()));
110 connect(directoryTree, SIGNAL(currentItemChanged(QTreeWidgetItem *, QTreeWidgetItem *)),
111 this, SLOT(directoryCurrentItemChanged(QTreeWidgetItem *, QTreeWidgetItem *)));
112 connect(directoryTree, SIGNAL(itemExpanded(QTreeWidgetItem *)),
113 this, SLOT(directoryItemExpanded(QTreeWidgetItem *)));
114 connect(directoryTree, SIGNAL(itemChanged(QTreeWidgetItem *, int)),
115 this, SLOT(directoryItemChanged(QTreeWidgetItem *, int)));
116 connect(fileTable, SIGNAL(currentItemChanged(QTableWidgetItem *, QTableWidgetItem *)),
117 this, SLOT(fileCurrentItemChanged(QTableWidgetItem *, QTableWidgetItem *)));
118 connect(jobTable, SIGNAL(cellClicked(int, int)),
119 this, SLOT(jobTableCellClicked(int, int)));
121 QStringList titles = QStringList() << "Directories";
122 directoryTree->setHeaderLabels(titles);
123 clientCombo->addItems(m_console->client_list);
124 fileSetCombo->addItem("Any");
125 fileSetCombo->addItems(m_console->fileset_list);
126 jobCombo->addItem("Any");
127 jobCombo->addItems(m_console->job_list);
129 directoryTree->setContextMenuPolicy(Qt::ActionsContextMenu);
132 void restoreTree::updateRefresh()
134 if (mainWin->m_rtPopDirDebug) Pmsg2(000, "testing prev=\"%s\" current=\"%s\"\n", m_prevJobCombo.toUtf8().data(), jobCombo->currentText().toUtf8().data());
135 m_dropdownChanged = (m_prevJobCombo != jobCombo->currentText())
136 || (m_prevClientCombo != clientCombo->currentText())
137 || (m_prevFileSetCombo != fileSetCombo->currentText()
138 || (m_prevLimitSpinBox != limitSpinBox->value())
139 || (m_prevDaysSpinBox != daysSpinBox->value())
140 || (m_prevLimitCheckState != limitCheckBox->checkState())
141 || (m_prevDaysCheckState != daysCheckBox->checkState())
143 if (m_dropdownChanged) {
144 if (mainWin->m_rtPopDirDebug) Pmsg0(000, "In restoreTree::updateRefresh Is CHANGED\n");
145 refreshLabel->setText("Refresh From Re-Select");
147 if (mainWin->m_rtPopDirDebug) Pmsg0(000, "In restoreTree::updateRefresh Is not Changed\n");
148 refreshLabel->setText("Refresh From JobChecks");
153 * When refresh button is pushed, perform a query getting the directories and
154 * use parseDirectory and addDirectory to populate the directory tree with items.
156 void restoreTree::populateDirectoryTree()
160 directoryTree->clear();
162 fileTable->setRowCount(0);
163 fileTable->setColumnCount(0);
164 versionTable->clear();
165 versionTable->setRowCount(0);
166 versionTable->setColumnCount(0);
167 m_fileExceptionHash.clear();
168 m_fileExceptionMulti.clear();
169 m_versionExceptionHash.clear();
170 m_directoryIconStateHash.clear();
173 int taskcount = 3, ontask = 1;
174 if (m_dropdownChanged) taskcount += 1;
176 /* Set progress bars and repaint */
177 prBar1->setVisible(true);
178 prBar1->setRange(0,taskcount);
180 prLabel1->setText("Task " + QString("%1").arg(ontask)+ " of " + QString("%1").arg(taskcount));
181 prLabel1->setVisible(true);
182 prBar2->setVisible(true);
183 prBar2->setRange(0,0);
184 prLabel2->setText("Querying Database");
185 prLabel2->setVisible(true);
188 if (m_dropdownChanged) {
189 m_prevJobCombo = jobCombo->currentText();
190 m_prevClientCombo = clientCombo->currentText();
191 m_prevFileSetCombo = fileSetCombo->currentText();
192 m_prevLimitSpinBox = limitSpinBox->value();
193 m_prevDaysSpinBox = daysSpinBox->value();
194 m_prevLimitCheckState = limitCheckBox->checkState();
195 m_prevDaysCheckState = daysCheckBox->checkState();
197 prBar1->setValue(ontask++);
198 prLabel1->setText("Task " + QString("%1").arg(ontask)+ " of " + QString("%1").arg(taskcount));
200 prBar2->setRange(0,0);
201 prLabel2->setText("Querying Jobs");
204 setJobsCheckedList();
206 if (mainWin->m_rtPopDirDebug) Pmsg0(000, "Repopulating from checks in Job Table\n");
207 setJobsCheckedList();
210 if (m_checkedJobs != "") {
211 /* First get the filenameid of where the nae is null. These will be the directories
212 * This could be done in a subquery but postgres's query analyzer won't do the right
213 * thing like I want */
214 if (m_nullFileNameId == -1) {
215 QString cmd = "SELECT FilenameId FROM Filename WHERE name=''";
216 if (mainWin->m_sqlDebug)
217 Pmsg1(000, "Query cmd : %s\n", cmd.toUtf8().data());
219 if (m_console->sql_cmd(cmd, qres)) {
221 QStringList fieldlist = qres[0].split("\t");
222 QString field = fieldlist[0];
224 int val = field.toInt(&ok, 10);
225 if (ok) m_nullFileNameId = val;
229 /* now create the query to get the list of paths */
231 "SELECT DISTINCT Path.Path AS Path, File.PathId AS PathId"
233 " INNER JOIN Path ON (File.PathId=Path.PathId)";
234 if (m_nullFileNameId != -1)
235 cmd += " WHERE File.FilenameId=" + QString("%1").arg(m_nullFileNameId);
237 cmd += " WHERE File.FilenameId IN (SELECT FilenameId FROM Filename WHERE Name='')";
238 cmd += " AND File.Jobid IN (" + m_checkedJobs + ")"
240 if (mainWin->m_sqlDebug)
241 Pmsg1(000, "Query cmd : %s\n", cmd.toUtf8().data());
242 prBar1->setValue(ontask++);
243 prLabel1->setText("Task " + QString("%1").arg(ontask) + " of " + QString("%1").arg(taskcount));
245 prBar2->setRange(0,0);
246 prLabel2->setText("Querying for Directories");
249 m_directoryPathIdHash.clear();
250 bool querydone = false;
251 if (m_console->sql_cmd(cmd, results)) {
254 prLabel2->setText("Processing Directories");
255 prBar2->setRange(0,results.count());
258 if (mainWin->m_miscDebug)
259 Pmsg1(000, "Done with query %i results\n", results.count());
260 QStringList fieldlist;
261 foreach(QString resultline, results) {
263 prBar2->setValue(m_debugCnt);
264 fieldlist = resultline.split("\t");
267 /* Iterate through fields in the record */
268 foreach (field, fieldlist) {
269 if (fieldcnt == 0 ) {
270 parseDirectory(field);
271 } else if (fieldcnt == 1) {
273 int pathid = field.toInt(&ok, 10);
275 m_directoryPathIdHash.insert(fieldlist[0], pathid);
282 QMessageBox::warning(this, tr("Bat"),
283 tr("No jobs were selected in the job query !!!.\n"
284 "Press OK to continue?"),
287 prBar1->setVisible(false);
288 prBar2->setVisible(false);
289 prLabel1->setVisible(false);
290 prLabel2->setVisible(false);
294 * Function to set m_checkedJobs from the jobs that are checked in the table
297 void restoreTree::setJobsCheckedList()
299 m_JobsCheckedList = "";
301 /* Update the items in the version table */
302 int cnt = jobTable->rowCount();
303 for (int row=0; row<cnt; row++) {
304 QTableWidgetItem* jobItem = jobTable->item(row, 0);
305 if (jobItem->checkState() == Qt::Checked) {
307 m_JobsCheckedList += ",";
308 m_JobsCheckedList += jobItem->text();
310 jobItem->setBackground(Qt::green);
312 if (jobItem->flags())
313 jobItem->setBackground(Qt::gray);
315 jobItem->setBackground(Qt::darkYellow);
318 m_checkedJobs = m_JobsCheckedList;
322 * Function to parse a directory into all possible subdirectories, then add to
325 void restoreTree::parseDirectory(QString &dir_in)
327 /* m_debugTrap is to only print debugs for a few occurances of calling parseDirectory
328 * instead of printing out what could potentially a whole bunch */
331 /* Clean up the directory string remove some funny char after last '/' */
332 QRegExp rgx("[^/]$");
333 int lastslash = rgx.indexIn(dir_in);
335 dir_in.replace(lastslash, dir_in.length()-lastslash, "");
336 if ((mainWin->m_miscDebug) && (m_debugTrap))
337 Pmsg1(000, "parsing %s\n", dir_in.toUtf8().data());
339 /* split and add if not in yet */
340 QString direct, path;
343 QStringList pathAfter, dirAfter;
344 /* start from the end, turn /etc/somedir/subdir/ into /etc/somedir and subdir/
345 * if not added into tree, then try /etc/ and somedir/ if not added, then try
346 * / and etc/ . That should succeed, then add the ones that failed in reverse */
347 while (((index = m_slashregex.lastIndexIn(dir_in, -2)) != -1) && (!done)) {
348 direct = path = dir_in;
349 path.replace(index+1, dir_in.length()-index-1,"");
350 direct.replace(0, index+1, "");
351 if ((mainWin->m_miscDebug) && (m_debugTrap)) {
352 QString msg = QString("length = \"%1\" index = \"%2\" Adding \"%3\" \"%4\"\n")
353 .arg(dir_in.length()).arg(index).arg(path).arg(direct);
354 Pmsg0(000, msg.toUtf8().data());
356 if (addDirectory(path, direct)) done = true;
358 if ((mainWin->m_miscDebug) && (m_debugTrap))
359 Pmsg0(000, "Saving for later\n");
360 pathAfter.prepend(path);
361 dirAfter.prepend(direct);
366 for (int k=0; k<pathAfter.count(); k++) {
367 if (addDirectory(pathAfter[k], dirAfter[k]))
368 if ((mainWin->m_miscDebug) && (m_debugTrap))
369 Pmsg2(000, "Adding After %s %s\n", pathAfter[k].toUtf8().data(), dirAfter[k].toUtf8().data());
371 if ((mainWin->m_miscDebug) && (m_debugTrap))
372 Pmsg2(000, "Error Adding %s %s\n", pathAfter[k].toUtf8().data(), dirAfter[k].toUtf8().data());
377 * Function called from fill directory when a directory is found to see if this
378 * directory exists in the directory pane and then add it to the directory pane
380 bool restoreTree::addDirectory(QString &m_cwd, QString &newdirr)
382 QString newdir = newdirr;
383 QString fullPath = m_cwd + newdirr;
384 bool ok = true, added = false;
386 if ((mainWin->m_miscDebug) && (m_debugTrap)) {
387 QString msg = QString("In addDirectory cwd \"%1\" newdir \"%2\"\n")
390 Pmsg0(000, msg.toUtf8().data());
394 /* add unix '/' directory first */
395 if (m_dirPaths.empty() && (m_winRegExpPath.indexIn(fullPath, 0) == -1)) {
397 QTreeWidgetItem *item = new QTreeWidgetItem(directoryTree);
399 item->setText(0, text.toUtf8().data());
400 item->setData(0, Qt::UserRole, QVariant(text));
401 item->setData(1, Qt::UserRole, QVariant(Qt::Unchecked));
402 item->setIcon(0, QIcon(QString::fromUtf8(":images/folder.png")));
403 if ((mainWin->m_miscDebug) && (m_debugTrap)) {
404 Pmsg1(000, "Pre Inserting %s\n", text.toUtf8().data());
406 m_dirPaths.insert(text, item);
408 /* no need to check for windows drive if unix */
409 if (m_winRegExpDrive.indexIn(m_cwd, 0) == 0) {
410 if (!m_dirPaths.contains(m_cwd)) {
411 /* this is a windows drive add the base widget */
412 QTreeWidgetItem *item = new QTreeWidgetItem(directoryTree);
413 item->setText(0, m_cwd);
414 item->setData(0, Qt::UserRole, QVariant(fullPath));
415 item->setData(1, Qt::UserRole, QVariant(Qt::Unchecked));
416 item->setIcon(0, QIcon(QString::fromUtf8(":images/folder.png")));
417 if ((mainWin->m_miscDebug) && (m_debugTrap)) {
418 Pmsg0(000, "Added Base \"letter\":/\n");
420 m_dirPaths.insert(m_cwd, item);
425 /* is it already existent ?? */
426 if (!m_dirPaths.contains(fullPath)) {
427 QTreeWidgetItem *item = NULL;
428 QTreeWidgetItem *parent = m_dirPaths.value(m_cwd);
430 /* new directories to add */
431 item = new QTreeWidgetItem(parent);
432 item->setText(0, newdir.toUtf8().data());
433 item->setData(0, Qt::UserRole, QVariant(fullPath));
434 item->setCheckState(0, Qt::Unchecked);
435 /* Store the current state of the check status in column 1, which at
436 * this point has no text*/
437 item->setData(1, Qt::UserRole, QVariant(Qt::Unchecked));
440 if ((mainWin->m_miscDebug) && (m_debugTrap)) {
441 QString msg = QString("In else of if parent cwd \"%1\" newdir \"%2\"\n")
444 Pmsg0(000, msg.toUtf8().data());
447 /* insert into hash */
449 if ((mainWin->m_miscDebug) && (m_debugTrap)) {
450 Pmsg1(000, "Inserting %s\n", fullPath.toUtf8().data());
452 m_dirPaths.insert(fullPath, item);
460 * Virtual function which is called when this page is visible on the stack
462 void restoreTree::currentStackItem()
465 if (!m_console->preventInUseConnect())
473 * Populate the tree when refresh button pushed.
475 void restoreTree::refreshButtonPushed()
477 populateDirectoryTree();
481 * Set the values of non-job combo boxes to the job defaults
483 void restoreTree::jobComboChanged(int)
485 if (jobCombo->currentText() == "Any") {
486 fileSetCombo->setCurrentIndex(fileSetCombo->findText("Any", Qt::MatchExactly));
489 job_defaults job_defs;
492 job_defs.job_name = jobCombo->currentText();
493 if (m_console->get_job_defaults(job_defs)) {
494 fileSetCombo->setCurrentIndex(fileSetCombo->findText(job_defs.fileset_name, Qt::MatchExactly));
495 clientCombo->setCurrentIndex(clientCombo->findText(job_defs.client_name, Qt::MatchExactly));
500 * Function to populate the file list table
502 void restoreTree::directoryCurrentItemChanged(QTreeWidgetItem *item, QTreeWidgetItem *)
508 /* Also clear the version table here */
509 versionTable->clear();
510 versionFileLabel->setText("");
511 versionTable->setRowCount(0);
512 versionTable->setColumnCount(0);
514 QStringList headerlist = (QStringList() << "File Name" << "Filename Id");
515 fileTable->setColumnCount(headerlist.size());
516 fileTable->setHorizontalHeaderLabels(headerlist);
517 fileTable->setRowCount(0);
519 m_fileCheckStateList.clear();
520 disconnect(fileTable, SIGNAL(itemChanged(QTableWidgetItem *)),
521 this, SLOT(fileTableItemChanged(QTableWidgetItem *)));
522 QBrush blackBrush(Qt::black);
523 QString directory = item->data(0, Qt::UserRole).toString();
524 directoryLabel->setText("Present Working Directory : " + directory);
525 int pathid = m_directoryPathIdHash.value(directory, -1);
528 "SELECT DISTINCT Filename.Name AS FileName, Filename.FilenameId AS FilenameId"
530 " INNER JOIN Filename on (Filename.FilenameId=File.FilenameId)"
531 " WHERE File.PathId=" + QString("%1").arg(pathid) +
532 " AND File.Jobid IN (" + m_checkedJobs + ")"
533 " AND Filename.Name!=''"
534 " ORDER BY FileName";
536 if (mainWin->m_sqlDebug) {
537 Pmsg1(000, "Query cmd : %s\n", cmd.toUtf8().data());
540 if (m_console->sql_cmd(cmd, results)) {
542 QTableWidgetItem* tableItem;
544 QStringList fieldlist;
545 fileTable->setRowCount(results.size());
548 /* Iterate through the record returned from the query */
549 foreach (QString resultline, results) {
550 /* Iterate through fields in the record */
552 fieldlist = resultline.split("\t");
553 foreach (field, fieldlist) {
554 field = field.trimmed(); /* strip leading & trailing spaces */
555 tableItem = new QTableWidgetItem(field, 1);
556 /* Possible flags are Qt::ItemFlags flag = Qt::ItemIsSelectable | Qt::ItemIsEditablex
557 * | Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled | Qt::ItemIsUserCheckable
558 * | Qt::ItemIsEnabled | Qt::ItemIsTristate; */
559 tableItem->setForeground(blackBrush);
560 /* Just in case a column ever gets added */
562 Qt::ItemFlags flag = Qt::ItemIsUserCheckable | Qt::ItemIsEnabled | Qt::ItemIsTristate;
563 tableItem->setFlags(flag);
564 tableItem->setData(Qt::UserRole, QVariant(directory));
565 fileTable->setItem(row, column, tableItem);
566 m_fileCheckStateList.append(Qt::Unchecked);
567 tableItem->setCheckState(Qt::Unchecked);
568 } else if (column == 1) {
569 Qt::ItemFlags flag = Qt::ItemIsEnabled;
570 tableItem->setFlags(flag);
572 int filenameid = field.toInt(&ok, 10);
573 if (!ok) filenameid = -1;
574 tableItem->setData(Qt::UserRole, QVariant(filenameid));
575 fileTable->setItem(row, column, tableItem);
581 fileTable->setRowCount(row);
583 fileTable->resizeColumnsToContents();
584 fileTable->resizeRowsToContents();
585 fileTable->verticalHeader()->hide();
586 fileTable->hideColumn(1);
587 if (mainWin->m_rtDirCurICDebug) Pmsg0(000, "will update file table checks\n");
588 updateFileTableChecks();
589 } else if (mainWin->m_sqlDebug)
590 Pmsg1(000, "did not perform query, pathid=%i not found\n", pathid);
591 connect(fileTable, SIGNAL(itemChanged(QTableWidgetItem *)),
592 this, SLOT(fileTableItemChanged(QTableWidgetItem *)));
596 * Function to populate the version table
598 void restoreTree::fileCurrentItemChanged(QTableWidgetItem *currentFileTableItem, QTableWidgetItem *)
600 if (currentFileTableItem == NULL)
603 int currentRow = fileTable->row(currentFileTableItem);
604 QTableWidgetItem *fileTableItem = fileTable->item(currentRow, 0);
605 QTableWidgetItem *fileNameIdTableItem = fileTable->item(currentRow, 1);
606 int fileNameId = fileNameIdTableItem->data(Qt::UserRole).toInt();
608 m_versionCheckStateList.clear();
609 disconnect(versionTable, SIGNAL(itemChanged(QTableWidgetItem *)),
610 this, SLOT(versionTableItemChanged(QTableWidgetItem *)));
612 QString file = fileTableItem->text();
613 versionFileLabel->setText(file);
614 QString directory = fileTableItem->data(Qt::UserRole).toString();
616 QBrush blackBrush(Qt::black);
618 QStringList headerlist = (QStringList() << "Job Id" << "Type" << "End Time" << "Md5" << "FileId");
619 versionTable->clear();
620 versionTable->setColumnCount(headerlist.size());
621 versionTable->setHorizontalHeaderLabels(headerlist);
622 versionTable->setRowCount(0);
624 int pathid = m_directoryPathIdHash.value(directory, -1);
625 if ((pathid != -1) && (fileNameId != -1)) {
627 "SELECT Job.JobId AS JobId, Job.Level AS Type, Job.EndTime AS EndTime, File.Md5 AS MD5, File.FileId AS FileId"
629 " INNER JOIN Filename on (Filename.FilenameId=File.FilenameId)"
630 " INNER JOIN Path ON (Path.PathId=File.PathId)"
631 " INNER JOIN Job ON (File.JobId=Job.JobId)"
632 " WHERE Path.PathId=" + QString("%1").arg(pathid) +
633 //" AND Filename.Name='" + file + "'"
634 " AND Filename.FilenameId=" + QString("%1").arg(fileNameId) +
635 " AND Job.Jobid IN (" + m_checkedJobs + ")"
636 " ORDER BY Job.EndTime DESC";
638 if (mainWin->m_sqlDebug)
639 Pmsg1(000, "Query cmd : %s\n", cmd.toUtf8().data());
641 if (m_console->sql_cmd(cmd, results)) {
643 QTableWidgetItem* tableItem;
645 QStringList fieldlist;
646 versionTable->setRowCount(results.size());
649 /* Iterate through the record returned from the query */
650 foreach (QString resultline, results) {
651 fieldlist = resultline.split("\t");
653 /* remove directory */
654 if (fieldlist[0].trimmed() != "") {
655 /* Iterate through fields in the record */
656 foreach (field, fieldlist) {
657 field = field.trimmed(); /* strip leading & trailing spaces */
658 tableItem = new QTableWidgetItem(field, 1);
659 tableItem->setFlags(0);
660 tableItem->setForeground(blackBrush);
661 tableItem->setData(Qt::UserRole, QVariant(directory));
662 versionTable->setItem(row, column, tableItem);
665 Qt::ItemFlags flag = Qt::ItemIsUserCheckable | Qt::ItemIsEnabled | Qt::ItemIsTristate;
666 tableItem->setFlags(flag);
667 m_versionCheckStateList.append(Qt::Unchecked);
668 tableItem->setCheckState(Qt::Unchecked);
676 versionTable->resizeColumnsToContents();
677 versionTable->resizeRowsToContents();
678 versionTable->verticalHeader()->hide();
679 updateVersionTableChecks();
681 if (mainWin->m_sqlDebug)
682 Pmsg2(000, "not querying : pathid=%i fileNameId=%i\n", pathid, fileNameId);
684 connect(versionTable, SIGNAL(itemChanged(QTableWidgetItem *)),
685 this, SLOT(versionTableItemChanged(QTableWidgetItem *)));
689 * Save user settings associated with this page
691 void restoreTree::writeSettings()
693 QSettings settings(m_console->m_dir->name(), "bat");
694 settings.beginGroup(m_groupText);
695 settings.setValue(m_splitText, m_splitter->saveState());
700 * Read and restore user settings associated with this page
702 void restoreTree::readSettings()
704 m_groupText = "RestoreTreePage";
705 m_splitText = "splitterSizes_1";
706 QSettings settings(m_console->m_dir->name(), "bat");
707 settings.beginGroup(m_groupText);
708 m_splitter->restoreState(settings.value(m_splitText).toByteArray());
713 * This is a funcion to accomplish the one thing I struggled to figure out what
714 * was taking so long. It add the icons, but after the tree is made. Seemed to
715 * work fast after changing from png to png file for graphic.
717 void restoreTree::directoryItemExpanded(QTreeWidgetItem *item)
719 int childCount = item->childCount();
720 for (int i=0; i<childCount; i++) {
721 QTreeWidgetItem *child = item->child(i);
722 if (child->icon(0).isNull())
723 child->setIcon(0, QIcon(QString::fromUtf8(":images/folder.png")));
728 * I wanted a table to show what jobs meet the criterion and are being used to
729 * populate the directory tree and file and version tables.
731 void restoreTree::populateJobTable()
733 QBrush blackBrush(Qt::black);
735 if (mainWin->m_rtPopDirDebug) Pmsg0(000, "Repopulating the Job Table\n");
736 QStringList headerlist = (QStringList() << "Job Id" << "End Time" << "Level" << "Name" << "Purged" << "TU" << "TD");
737 m_toggleUpIndex = headerlist.indexOf("TU");
738 m_toggleDownIndex = headerlist.indexOf("TD");
739 int purgedIndex = headerlist.indexOf("Purged");
741 jobTable->setColumnCount(headerlist.size());
742 jobTable->setHorizontalHeaderLabels(headerlist);
744 "SELECT Job.Jobid AS Id, Job.EndTime AS EndTime, Job.Level AS Level, Job.Name AS JobName, Job.purgedfiles AS Purged"
746 /* INNER JOIN FileSet eliminates all restore jobs */
747 " INNER JOIN Client ON (Job.ClientId=Client.ClientId)"
748 " INNER JOIN FileSet ON (Job.FileSetId=FileSet.FileSetId)"
750 " Client.Name='" + clientCombo->currentText() + "'";
751 if ((jobCombo->currentIndex() >= 0) && (jobCombo->currentText() != "Any")) {
752 jobQuery += " AND Job.name = '" + jobCombo->currentText() + "'";
754 if ((fileSetCombo->currentIndex() >= 0) && (fileSetCombo->currentText() != "Any")) {
755 jobQuery += " AND FileSet.FileSet='" + fileSetCombo->currentText() + "'";
757 /* If Limit check box For limit by days is checked */
758 if (daysCheckBox->checkState() == Qt::Checked) {
759 QDateTime stamp = QDateTime::currentDateTime().addDays(-daysSpinBox->value());
760 QString since = stamp.toString(Qt::ISODate);
761 jobQuery += " AND Job.Starttime>'" + since + "'";
763 //jobQuery += " AND Job.purgedfiles=0";
764 jobQuery += " ORDER BY Job.EndTime DESC";
765 /* If Limit check box for limit records returned is checked */
766 if (limitCheckBox->checkState() == Qt::Checked) {
768 limit.setNum(limitSpinBox->value());
769 jobQuery += " LIMIT " + limit;
771 if (mainWin->m_sqlDebug)
772 Pmsg1(000, "Query cmd : %s\n", jobQuery.toUtf8().data());
775 if (m_console->sql_cmd(jobQuery, results)) {
777 QTableWidgetItem* tableItem;
779 QStringList fieldlist;
780 jobTable->setRowCount(results.size());
783 /* Iterate through the record returned from the query */
784 foreach (QString resultline, results) {
785 fieldlist = resultline.split("\t");
787 /* remove directory */
788 if (fieldlist[0].trimmed() != "") {
789 /* Iterate through fields in the record */
790 foreach (field, fieldlist) {
791 field = field.trimmed(); /* strip leading & trailing spaces */
793 tableItem = new QTableWidgetItem(field, 1);
794 tableItem->setFlags(0);
795 tableItem->setForeground(blackBrush);
796 jobTable->setItem(row, column, tableItem);
799 int purged = fieldlist[purgedIndex].toInt(&ok, 10);
800 if (!((ok) && (purged == 1))) {
801 Qt::ItemFlags flag = Qt::ItemIsUserCheckable | Qt::ItemIsEnabled | Qt::ItemIsTristate;
802 tableItem->setFlags(flag);
803 tableItem->setCheckState(Qt::Checked);
804 tableItem->setBackground(Qt::green);
806 tableItem->setFlags(0);
807 tableItem->setCheckState(Qt::Unchecked);
813 tableItem = new QTableWidgetItem(QIcon(QString::fromUtf8(":images/go-up.png")), "", 1);
814 tableItem->setFlags(0);
815 tableItem->setForeground(blackBrush);
816 jobTable->setItem(row, column, tableItem);
818 tableItem = new QTableWidgetItem(QIcon(QString::fromUtf8(":images/go-down.png")), "", 1);
819 tableItem->setFlags(0);
820 tableItem->setForeground(blackBrush);
821 jobTable->setItem(row, column, tableItem);
826 jobTable->resizeColumnsToContents();
827 jobTable->resizeRowsToContents();
828 jobTable->verticalHeader()->hide();
829 jobTable->hideColumn(purgedIndex);
832 void restoreTree::jobTableCellClicked(int row, int column)
834 if (column == m_toggleUpIndex){
836 for (cnt=0; cnt<row+1; cnt++) {
837 QTableWidgetItem *item = jobTable->item(cnt, 0);
839 Qt::CheckState state = item->checkState();
840 if (state == Qt::Checked)
841 item->setCheckState(Qt::Unchecked);
842 else if (state == Qt::Unchecked)
843 item->setCheckState(Qt::Checked);
847 if (column == m_toggleDownIndex){
848 int cnt, max = jobTable->rowCount();
849 for (cnt=row; cnt<max; cnt++) {
850 QTableWidgetItem *item = jobTable->item(cnt, 0);
852 Qt::CheckState state = item->checkState();
853 if (state == Qt::Checked)
854 item->setCheckState(Qt::Unchecked);
855 else if (state == Qt::Unchecked)
856 item->setCheckState(Qt::Checked);
863 * When a directory item is "changed" check the state of the checkable item
864 * to see if it is different than what it was which is stored in Qt::UserRole
865 * of the 2nd column, column 1, of the tree widget.
867 void restoreTree::directoryItemChanged(QTreeWidgetItem *item, int /*column*/)
869 Qt::CheckState prevState = (Qt::CheckState)item->data(1, Qt::UserRole).toInt();
870 Qt::CheckState curState = item->checkState(0);
871 QTreeWidgetItem* parent = item->parent();
872 Qt::CheckState parState;
873 if (parent) parState = parent->checkState(0);
874 else parState = (Qt::CheckState)3;
875 if (mainWin->m_rtDirICDebug) {
876 QString msg = QString("directory item OBJECT has changed prev=%1 cur=%2 par=%3 dir=%4\n")
877 .arg(prevState).arg(curState).arg(parState).arg(item->text(0));
878 Pmsg1(000, "%s", msg.toUtf8().data()); }
879 /* I only care when the check state changes */
880 if (prevState == curState) {
881 if (mainWin->m_rtDirICDebug) Pmsg0(000, "Returning Early\n");
885 if ((prevState == Qt::Unchecked) && (curState == Qt::Checked) && (parState != Qt::Unchecked)) {
886 if (mainWin->m_rtDirICDebug) Pmsg0(000, "Disconnected Setting to Qt::PartiallyChecked\n");
887 directoryTreeDisconnectedSet(item, Qt::PartiallyChecked);
888 curState = Qt::PartiallyChecked;
890 if ((prevState == Qt::PartiallyChecked) && (curState == Qt::Checked)) {
891 if (mainWin->m_rtDirICDebug) Pmsg0(000, "Disconnected Setting to Qt::Unchecked\n");
892 directoryTreeDisconnectedSet(item, Qt::Unchecked);
893 curState = Qt::Unchecked;
895 if (mainWin->m_rtDirICDebug) {
896 QString msg = QString("directory item CHECKSTATE has changed prev=%1 cur=%2 par=%3 dir=%4\n")
897 .arg(prevState).arg(curState).arg(parState).arg(item->text(0));
898 Pmsg1(000, "%s", msg.toUtf8().data()); }
900 item->setData(1, Qt::UserRole, QVariant(curState));
901 Qt::CheckState childState = curState;
902 if (childState == Qt::Checked)
903 childState = Qt::PartiallyChecked;
904 setCheckofChildren(item, childState);
906 /* Remove items from the exception lists. The multi exception list is my index
907 * of what exceptions can be removed when the directory is known*/
908 QString directory = item->data(0, Qt::UserRole).toString();
909 QStringList fullPathList = m_fileExceptionMulti.values(directory);
910 int fullPathListCount = fullPathList.count();
911 if ((mainWin->m_rtDirICDebug) && fullPathListCount) Pmsg2(000, "Will attempt to remove file exceptions for %s count %i\n", directory.toUtf8().data(), fullPathListCount);
912 foreach (QString fullPath, fullPathList) {
913 /* If there is no value in the hash for the key fullPath a value of 3 will be returned
914 * which will match no Qt::xxx values */
915 Qt::CheckState hashState = m_fileExceptionHash.value(fullPath, (Qt::CheckState)3);
916 if (mainWin->m_rtDirICDebug) Pmsg2(000, "hashState=%i childState=%i\n", hashState, childState);
917 if (hashState == Qt::Unchecked) {
918 fileExceptionRemove(fullPath, directory);
919 m_versionExceptionHash.remove(fullPath);
920 if (mainWin->m_rtDirICDebug) Pmsg0(000, "Attempted Removal A\n");
922 if (hashState == Qt::Checked) {
923 fileExceptionRemove(fullPath, directory);
924 m_versionExceptionHash.remove(fullPath);
925 if (mainWin->m_rtDirICDebug) Pmsg0(000, "Attempted Removal B\n");
929 if (item == directoryTree->currentItem()) {
930 if (mainWin->m_rtDirICDebug) Pmsg0(000, "Will attempt to update File Table Checks\n");
931 updateFileTableChecks();
932 versionTable->clear();
933 versionTable->setRowCount(0);
934 versionTable->setColumnCount(0);
936 if (mainWin->m_rtDirICDebug) Pmsg0(000, "Returning At End\n");
940 * When a directory item check state is changed, this function iterates through
941 * all subdirectories and sets all to the passed state, which is either partially
942 * checked or unchecked.
944 void restoreTree::setCheckofChildren(QTreeWidgetItem *item, Qt::CheckState state)
947 childCount = item->childCount();
948 for (int i=0; i<childCount; i++) {
949 QTreeWidgetItem *child = item->child(i);
950 child->setData(1, Qt::UserRole, QVariant(state));
951 child->setCheckState(0, state);
952 setCheckofChildren(child, state);
957 * When a File Table Item is "changed" check to see if the state of the checkable
958 * item has changed which is stored in m_fileCheckStateList
959 * If changed store in a hash m_fileExceptionHash that whether this file should be
961 * Called as a slot, connected after populated (after directory current changed called)
963 void restoreTree::fileTableItemChanged(QTableWidgetItem *item)
965 /* get the previous and current check states */
966 int row = fileTable->row(item);
967 Qt::CheckState prevState;
968 /* prevent a segfault */
969 prevState = m_fileCheckStateList[row];
970 Qt::CheckState curState = item->checkState();
972 /* deterimine the default state from the state of the directory */
973 QTreeWidgetItem *dirTreeItem = directoryTree->currentItem();
974 Qt::CheckState dirState = (Qt::CheckState)dirTreeItem->data(1, Qt::UserRole).toInt();
975 Qt::CheckState defState = Qt::PartiallyChecked;
976 if (dirState == Qt::Unchecked) defState = Qt::Unchecked;
978 /* determine if it is already in the m_fileExceptionHash */
979 QString directory = directoryTree->currentItem()->data(0, Qt::UserRole).toString();
980 QString file = item->text();
981 QString fullPath = directory + file;
982 Qt::CheckState hashState = m_fileExceptionHash.value(fullPath, (Qt::CheckState)3);
983 int verJobNum = m_versionExceptionHash.value(fullPath, 0);
985 if (mainWin->m_rtFileTabICDebug) {
986 QString msg = QString("filerow=%1 prev=%2 cur=%3 def=%4 hash=%5 dir=%6 verJobNum=%7\n")
987 .arg(row).arg(prevState).arg(curState).arg(defState).arg(hashState).arg(dirState).arg(verJobNum);
988 Pmsg1(000, "%s", msg.toUtf8().data()); }
990 /* Remove the hash if currently checked previously unchecked and directory is checked or partial */
991 if ((prevState == Qt::Checked) && (curState == Qt::Unchecked) && (dirState == Qt::Unchecked)) {
992 /* it can behave as defaulted so current of unchecked is fine */
993 if (mainWin->m_rtFileTabICDebug) Pmsg0(000, "Will fileExceptionRemove and m_versionExceptionHash.remove here\n");
994 fileExceptionRemove(fullPath, directory);
995 m_versionExceptionHash.remove(fullPath);
996 } else if ((prevState == Qt::PartiallyChecked) && (curState == Qt::Checked) && (dirState != Qt::Unchecked) && (verJobNum == 0)) {
997 if (mainWin->m_rtFileTabICDebug) Pmsg0(000, "Will fileExceptionInsert here\n");
998 fileExceptionInsert(fullPath, directory, Qt::Unchecked);
999 } else if ((prevState == Qt::Unchecked) && (curState == Qt::Checked) && (dirState != Qt::Unchecked) && (verJobNum == 0) && (defState == Qt::PartiallyChecked)) {
1000 /* filerow=2 prev=0 cur=2 def=1 hash=0 dir=2 verJobNum=0 */
1001 if (mainWin->m_rtFileTabICDebug) Pmsg0(000, "Will fileExceptionRemove here\n");
1002 fileExceptionRemove(fullPath, directory);
1003 } else if ((prevState == Qt::Checked) && (curState == Qt::Unchecked) && (defState == Qt::PartiallyChecked) && (verJobNum != 0) && (hashState == Qt::Checked)) {
1004 /* Check dir, check version, attempt uncheck in file
1005 * filerow=4 prev=2 cur=0 def=1 hash=2 dir=2 verJobNum=53 */
1006 if (mainWin->m_rtFileTabICDebug) Pmsg0(000, "Will fileExceptionRemove and m_versionExceptionHash.remove here\n");
1007 fileExceptionRemove(fullPath, directory);
1008 m_versionExceptionHash.remove(fullPath);
1009 } else if ((prevState == Qt::Unchecked) && (curState == Qt::Checked) && (dirState != Qt::Unchecked) && (verJobNum == 0)) {
1010 /* filerow=0 prev=0 cur=2 def=1 hash=0 dirState=2 verJobNum */
1011 if (mainWin->m_rtFileTabICDebug) Pmsg0(000, "Will Not remove here\n");
1012 } else if (prevState != curState) {
1013 if (mainWin->m_rtFileTabICDebug) Pmsg2(000, " THE STATE OF THE Check has changed, Setting StateList[%i] to %i\n", row, curState);
1014 /* A user did not set the check state to Partially checked, ignore if so */
1015 if (curState != Qt::PartiallyChecked) {
1016 if ((defState == Qt::Unchecked) && (prevState == Qt::PartiallyChecked) && (curState == Qt::Unchecked)) {
1017 if (mainWin->m_rtFileTabICDebug) Pmsg0(000, " got here\n");
1019 if (mainWin->m_rtFileTabICDebug) Pmsg2(000, " Inserting into m_fileExceptionHash %s, %i\n", fullPath.toUtf8().data(), curState);
1020 fileExceptionInsert(fullPath, directory, curState);
1023 if (mainWin->m_rtFileTabICDebug) Pmsg1(000, "Removing version hash for %s\n", fullPath.toUtf8().data());
1024 /* programattically been changed back to a default state of Qt::PartiallyChecked remove the version hash here */
1025 m_versionExceptionHash.remove(fullPath);
1029 updateFileTableChecks();
1030 updateVersionTableChecks();
1034 * function to insert keys and values to both m_fileExceptionHash and m_fileExceptionMulti
1036 void restoreTree::fileExceptionInsert(QString &fullPath, QString &direcotry, Qt::CheckState state)
1038 m_fileExceptionHash.insert(fullPath, state);
1039 m_fileExceptionMulti.insert(direcotry, fullPath);
1040 directoryIconStateInsert(fullPath, state);
1044 * function to remove keys from both m_fileExceptionHash and m_fileExceptionMulti
1046 void restoreTree::fileExceptionRemove(QString &fullPath, QString &directory)
1048 m_fileExceptionHash.remove(fullPath);
1049 /* pull the list of values in the multi */
1050 QStringList fullPathList = m_fileExceptionMulti.values(directory);
1051 /* get the index of the fullpath to remove */
1052 int index = fullPathList.indexOf(fullPath);
1054 /* remove the desired item in the list */
1055 fullPathList.removeAt(index);
1056 /* remove the entire list from the multi */
1057 m_fileExceptionMulti.remove(directory);
1058 /* readd the remaining */
1059 foreach (QString fp, fullPathList) {
1060 m_fileExceptionMulti.insert(directory, fp);
1063 directoryIconStateRemove();
1067 * Overloaded function to be called from the slot and from other places to set the state
1068 * of the check marks in the version table
1070 void restoreTree::versionTableItemChanged(QTableWidgetItem *item)
1072 /* get the previous and current check states */
1073 int row = versionTable->row(item);
1074 QTableWidgetItem *colZeroItem = versionTable->item(row, 0);
1075 Qt::CheckState prevState = m_versionCheckStateList[row];
1076 Qt::CheckState curState = (Qt::CheckState)colZeroItem->checkState();
1077 m_versionCheckStateList[row] = curState;
1079 /* deterimine the default state from the state of the file */
1080 QTableWidgetItem *fileTableItem = fileTable->currentItem();
1081 Qt::CheckState fileState = (Qt::CheckState)fileTableItem->checkState();
1083 /* determine the default state */
1084 Qt::CheckState defState;
1086 defState = Qt::PartiallyChecked;
1087 if (fileState == Qt::Unchecked)
1088 defState = Qt::Unchecked;
1091 defState = Qt::Unchecked;
1093 /* determine if it is already in the versionExceptionHash */
1094 QString directory = directoryTree->currentItem()->data(0, Qt::UserRole).toString();
1095 Qt::CheckState dirState = directoryTree->currentItem()->checkState(0);
1096 QString file = fileTableItem->text();
1097 QString fullPath = directory + file;
1098 int thisJobNum = colZeroItem->text().toInt();
1099 int hashJobNum = m_versionExceptionHash.value(fullPath, 0);
1101 if (mainWin->m_rtVerTabICDebug) {
1102 QString msg = QString("versrow=%1 prev=%2 cur=%3 def=%4 dir=%5 hashJobNum=%6 thisJobNum=%7 filestate=%8 fec=%9 vec=%10\n")
1103 .arg(row).arg(prevState).arg(curState).arg(defState).arg(dirState).arg(hashJobNum).arg(thisJobNum).arg(fileState)
1104 .arg(m_fileExceptionHash.count()).arg(m_versionExceptionHash.count());
1105 Pmsg1(000, "%s", msg.toUtf8().data()); }
1106 /* if changed from partially checked to checked, make it unchecked */
1107 if ((curState == Qt::Checked) && (row == 0) && (fileState == Qt::Unchecked)) {
1108 if (mainWin->m_rtVerTabICDebug) Pmsg0(000, "Setting to Qt::Checked\n");
1109 fileTableItem->setCheckState(Qt::Checked);
1110 } else if ((prevState == Qt::PartiallyChecked) && (curState == Qt::Checked) && (row == 0) && (fileState == Qt::Checked) && (dirState == Qt::Unchecked)) {
1111 //versrow=0 prev=1 cur=2 def=1 dir=0 hashJobNum=0 thisJobNum=64 filestate=2 fec=1 vec=0
1112 if (mainWin->m_rtVerTabICDebug) Pmsg1(000, "fileExceptionRemove %s, %i\n", fullPath.toUtf8().data());
1113 fileExceptionRemove(fullPath, directory);
1114 } else if ((curState == Qt::Checked) && (row == 0) && (hashJobNum != 0) && (dirState != Qt::Unchecked)) {
1115 //versrow=0 prev=0 cur=2 def=1 dir=2 hashJobNum=53 thisJobNum=64 filestate=2 fec=1 vec=1
1116 if (mainWin->m_rtVerTabICDebug) Pmsg1(000, "m_versionExceptionHash.remove %s\n", fullPath.toUtf8().data());
1117 m_versionExceptionHash.remove(fullPath);
1118 fileExceptionRemove(fullPath, directory);
1119 } else if ((curState == Qt::Checked) && (row == 0)) {
1120 if (mainWin->m_rtVerTabICDebug) Pmsg1(000, "m_versionExceptionHash.remove %s\n", fullPath.toUtf8().data());
1121 m_versionExceptionHash.remove(fullPath);
1122 } else if (prevState != curState) {
1123 if (mainWin->m_rtVerTabICDebug) Pmsg2(000, " THE STATE OF THE version Check has changed, Setting StateList[%i] to %i\n", row, curState);
1124 if ((curState == Qt::Checked) || (curState == Qt::PartiallyChecked) && (row != 0)) {
1125 if (mainWin->m_rtVerTabICDebug) Pmsg2(000, "Inserting into m_versionExceptionHash %s, %i\n", fullPath.toUtf8().data(), thisJobNum);
1126 m_versionExceptionHash.insert(fullPath, thisJobNum);
1127 if (fileState != Qt::Checked) {
1128 if (mainWin->m_rtVerTabICDebug) Pmsg2(000, "Inserting into m_fileExceptionHash %s, %i\n", fullPath.toUtf8().data(), curState);
1129 fileExceptionInsert(fullPath, directory, curState);
1132 if (mainWin->m_rtVerTabICDebug) Pmsg0(000, "got here\n");
1135 if (mainWin->m_rtVerTabICDebug) Pmsg0(000, "no conditions met\n");
1138 updateFileTableChecks();
1139 updateVersionTableChecks();
1143 * Simple function to set the check state in the file table by disconnecting the
1144 * signal/slot the setting then reconnecting the signal/slot
1146 void restoreTree::fileTableDisconnectedSet(QTableWidgetItem *item, Qt::CheckState state, bool color)
1148 disconnect(fileTable, SIGNAL(itemChanged(QTableWidgetItem *)),
1149 this, SLOT(fileTableItemChanged(QTableWidgetItem *)));
1150 item->setCheckState(state);
1151 if (color) item->setBackground(Qt::yellow);
1152 else item->setBackground(Qt::white);
1153 connect(fileTable, SIGNAL(itemChanged(QTableWidgetItem *)),
1154 this, SLOT(fileTableItemChanged(QTableWidgetItem *)));
1158 * Simple function to set the check state in the version table by disconnecting the
1159 * signal/slot the setting then reconnecting the signal/slot
1161 void restoreTree::versionTableDisconnectedSet(QTableWidgetItem *item, Qt::CheckState state)
1163 disconnect(versionTable, SIGNAL(itemChanged(QTableWidgetItem *)),
1164 this, SLOT(versionTableItemChanged(QTableWidgetItem *)));
1165 item->setCheckState(state);
1166 connect(versionTable, SIGNAL(itemChanged(QTableWidgetItem *)),
1167 this, SLOT(versionTableItemChanged(QTableWidgetItem *)));
1171 * Simple function to set the check state in the directory tree by disconnecting the
1172 * signal/slot the setting then reconnecting the signal/slot
1174 void restoreTree::directoryTreeDisconnectedSet(QTreeWidgetItem *item, Qt::CheckState state)
1176 disconnect(directoryTree, SIGNAL(itemChanged(QTreeWidgetItem *, int)),
1177 this, SLOT(directoryItemChanged(QTreeWidgetItem *, int)));
1178 item->setCheckState(0, state);
1179 connect(directoryTree, SIGNAL(itemChanged(QTreeWidgetItem *, int)),
1180 this, SLOT(directoryItemChanged(QTreeWidgetItem *, int)));
1184 * Simplify the updating of the check state in the File table by iterating through
1185 * each item in the file table to determine it's appropriate state.
1186 * !! Will probably want to concoct a way to do this without iterating for the possibility
1187 * of the very large directories.
1189 void restoreTree::updateFileTableChecks()
1191 /* deterimine the default state from the state of the directory */
1192 QTreeWidgetItem *dirTreeItem = directoryTree->currentItem();
1193 Qt::CheckState dirState = dirTreeItem->checkState(0);
1195 QString dirName = dirTreeItem->data(0, Qt::UserRole).toString();
1197 /* Update the items in the version table */
1198 int rcnt = fileTable->rowCount();
1199 for (int row=0; row<rcnt; row++) {
1200 QTableWidgetItem* item = fileTable->item(row, 0);
1202 Qt::CheckState curState = item->checkState();
1203 Qt::CheckState newState = Qt::PartiallyChecked;
1204 if (dirState == Qt::Unchecked) newState = Qt::Unchecked;
1206 /* determine if it is already in the m_fileExceptionHash */
1207 QString file = item->text();
1208 QString fullPath = dirName + file;
1209 Qt::CheckState hashState = m_fileExceptionHash.value(fullPath, (Qt::CheckState)3);
1210 int hashJobNum = m_versionExceptionHash.value(fullPath, 0);
1212 if (hashState != 3) newState = hashState;
1214 if (mainWin->m_rtUpdateFTDebug) {
1215 QString msg = QString("file row=%1 cur=%2 hash=%3 new=%4 dirState=%5\n")
1216 .arg(row).arg(curState).arg(hashState).arg(newState).arg(dirState);
1217 Pmsg1(000, "%s", msg.toUtf8().data());
1220 bool docolor = false;
1221 if (hashJobNum != 0) docolor = true;
1222 bool isyellow = item->background().color() == QColor(Qt::yellow);
1223 if ((newState != curState) || (hashState == 3) || ((isyellow && !docolor) || (!isyellow && docolor)))
1224 fileTableDisconnectedSet(item, newState, docolor);
1225 m_fileCheckStateList[row] = newState;
1230 * Simplify the updating of the check state in the Version table by iterating through
1231 * each item in the file table to determine it's appropriate state.
1233 void restoreTree::updateVersionTableChecks()
1235 /* deterimine the default state from the state of the directory */
1236 QTreeWidgetItem *dirTreeItem = directoryTree->currentItem();
1237 Qt::CheckState dirState = dirTreeItem->checkState(0);
1238 QString dirName = dirTreeItem->data(0, Qt::UserRole).toString();
1240 /* deterimine the default state from the state of the file */
1241 QTableWidgetItem *fileTableItem = fileTable->item(fileTable->currentRow(), 0);
1242 Qt::CheckState fileState = fileTableItem->checkState();
1243 QString file = fileTableItem->text();
1244 QString fullPath = dirName + file;
1245 int hashJobNum = m_versionExceptionHash.value(fullPath, 0);
1247 /* Update the items in the version table */
1248 int cnt = versionTable->rowCount();
1249 for (int row=0; row<cnt; row++) {
1250 QTableWidgetItem* item = versionTable->item(row, 0);
1252 Qt::CheckState curState = item->checkState();
1253 Qt::CheckState newState = Qt::Unchecked;
1255 if ((row == 0) && (fileState != Qt::Unchecked) && (hashJobNum == 0))
1256 newState = Qt::PartiallyChecked;
1257 /* determine if it is already in the versionExceptionHash */
1259 int thisJobNum = item->text().toInt();
1260 if (thisJobNum == hashJobNum)
1261 newState = Qt::Checked;
1263 if (mainWin->m_rtChecksDebug) {
1264 QString msg = QString("ver row=%1 cur=%2 hashJobNum=%3 new=%4 dirState=%5\n")
1265 .arg(row).arg(curState).arg(hashJobNum).arg(newState).arg(dirState);
1266 Pmsg1(000, "%s", msg.toUtf8().data());
1268 if (newState != curState)
1269 versionTableDisconnectedSet(item, newState);
1270 m_versionCheckStateList[row] = newState;
1275 * Quick subroutine to "return via subPaths" a list of subpaths when passed a fullPath
1277 void restoreTree::fullPathtoSubPaths(QStringList &subPaths, QString &fullPath_in)
1281 QString fullPath = fullPath_in;
1282 QString direct, path;
1283 while (((index = m_slashregex.lastIndexIn(fullPath, -2)) != -1) && (!done)) {
1284 direct = path = fullPath;
1285 path.replace(index+1, fullPath.length()-index-1, "");
1286 direct.replace(0, index+1, "");
1288 QString msg = QString("length = \"%1\" index = \"%2\" Considering \"%3\" \"%4\"\n")
1289 .arg(fullPath.length()).arg(index).arg(path).arg(direct);
1290 Pmsg0(000, msg.toUtf8().data());
1293 subPaths.append(fullPath);
1298 * A Function to set the icon state and insert a record into
1299 * m_directoryIconStateHash when an exception is added by the user
1301 void restoreTree::directoryIconStateInsert(QString &fullPath, Qt::CheckState excpState)
1304 fullPathtoSubPaths(paths, fullPath);
1305 /* an exception that causes the item in the file table to be "Checked" has occured */
1306 if (excpState == Qt::Checked) {
1307 bool foundAsUnChecked = false;
1308 QTreeWidgetItem *firstItem = m_dirPaths.value(paths[0]);
1310 if (firstItem->checkState(0) == Qt::Unchecked)
1311 foundAsUnChecked = true;
1313 if (foundAsUnChecked) {
1314 /* as long as directory item is Unchecked, set icon state to "green check" */
1316 QListIterator<QString> siter(paths);
1317 while (siter.hasNext() && !done) {
1318 QString path = siter.next();
1319 QTreeWidgetItem *item = m_dirPaths.value(path);
1321 if (item->checkState(0) != Qt::Unchecked)
1324 directorySetIcon(1, FolderGreenChecked, path, item);
1325 if (mainWin->m_rtIconStateDebug) Pmsg1(000, "In restoreTree::directoryIconStateInsert inserting %s\n", path.toUtf8().data());
1330 /* if it is partially checked or fully checked insert green Check until a unchecked is found in the path */
1331 if (mainWin->m_rtIconStateDebug) Pmsg1(000, "In restoreTree::directoryIconStateInsert Aqua %s\n", paths[0].toUtf8().data());
1333 QListIterator<QString> siter(paths);
1334 while (siter.hasNext() && !done) {
1335 QString path = siter.next();
1336 QTreeWidgetItem *item = m_dirPaths.value(path);
1337 if (item) { /* if the directory item is checked, set icon state to unchecked "green check" */
1338 if (item->checkState(0) == Qt::Checked)
1340 directorySetIcon(1, FolderGreenChecked, path, item);
1341 if (mainWin->m_rtIconStateDebug) Pmsg1(000, "In restoreTree::directoryIconStateInsert boogie %s\n", path.toUtf8().data());
1346 /* an exception that causes the item in the file table to be "Unchecked" has occured */
1347 if (excpState == Qt::Unchecked) {
1349 QListIterator<QString> siter(paths);
1350 while (siter.hasNext() && !done) {
1351 QString path = siter.next();
1352 QTreeWidgetItem *item = m_dirPaths.value(path);
1353 if (item) { /* if the directory item is checked, set icon state to unchecked "white check" */
1354 if (item->checkState(0) == Qt::Checked)
1356 directorySetIcon(1, FolderWhiteChecked, path, item);
1357 if (mainWin->m_rtIconStateDebug) Pmsg1(000, "In restoreTree::directoryIconStateInsert boogie %s\n", path.toUtf8().data());
1364 * A function to set the icon state back to "folder" and to remove a record from
1365 * m_directoryIconStateHash when an exception is removed by a user.
1367 void restoreTree::directoryIconStateRemove()
1369 QHash<QString, int> shouldBeIconStateHash;
1370 /* First determine all paths with icons that should be checked with m_fileExceptionHash */
1371 /* Use iterator tera to iterate through m_fileExceptionHash */
1372 QHashIterator<QString, Qt::CheckState> tera(m_fileExceptionHash);
1373 while (tera.hasNext()) {
1375 if (mainWin->m_rtIconStateDebug) Pmsg2(000, "Alpha Key %s value %i\n", tera.key().toUtf8().data(), tera.value());
1377 QString keyPath = tera.key();
1378 Qt::CheckState state = tera.value();
1381 fullPathtoSubPaths(paths, keyPath);
1382 /* if the state of the item in m_fileExceptionHash is checked
1383 * each of the subpaths should be "Checked Green" */
1384 if (state == Qt::Checked) {
1386 bool foundAsUnChecked = false;
1387 QTreeWidgetItem *firstItem = m_dirPaths.value(paths[0]);
1389 if (firstItem->checkState(0) == Qt::Unchecked)
1390 foundAsUnChecked = true;
1392 if (foundAsUnChecked) {
1393 /* The right most directory is Unchecked, iterate leftwards
1394 * as long as directory item is Unchecked, set icon state to "green check" */
1396 QListIterator<QString> siter(paths);
1397 while (siter.hasNext() && !done) {
1398 QString path = siter.next();
1399 QTreeWidgetItem *item = m_dirPaths.value(path);
1401 if (item->checkState(0) != Qt::Unchecked)
1404 shouldBeIconStateHash.insert(path, FolderGreenChecked);
1405 if (mainWin->m_rtIconStateDebug) Pmsg1(000, "In restoreTree::directoryIconStateInsert inserting %s\n", path.toUtf8().data());
1411 /* The right most directory is Unchecked, iterate leftwards
1412 * until directory item is Checked, set icon state to "green check" */
1414 QListIterator<QString> siter(paths);
1415 while (siter.hasNext() && !done) {
1416 QString path = siter.next();
1417 QTreeWidgetItem *item = m_dirPaths.value(path);
1419 if (item->checkState(0) == Qt::Checked)
1421 shouldBeIconStateHash.insert(path, FolderGreenChecked);
1426 /* if the state of the item in m_fileExceptionHash is UNChecked
1427 * each of the subpaths should be "Checked white" until the tree item
1428 * which represents that path is Qt::Checked */
1429 if (state == Qt::Unchecked) {
1431 QListIterator<QString> siter(paths);
1432 while (siter.hasNext() && !done) {
1433 QString path = siter.next();
1434 QTreeWidgetItem *item = m_dirPaths.value(path);
1436 if (item->checkState(0) == Qt::Checked)
1438 shouldBeIconStateHash.insert(path, FolderWhiteChecked);
1443 /* now iterate through m_directoryIconStateHash which are the items that are checked
1444 * and remove all of those that are not in shouldBeIconStateHash */
1445 QHashIterator<QString, int> iter(m_directoryIconStateHash);
1446 while (iter.hasNext()) {
1448 if (mainWin->m_rtIconStateDebug) Pmsg2(000, "Beta Key %s value %i\n", iter.key().toUtf8().data(), iter.value());
1450 QString keyPath = iter.key();
1451 if (shouldBeIconStateHash.value(keyPath)) {
1452 if (mainWin->m_rtIconStateDebug) Pmsg1(000, "WAS found in shouldBeStateHash %s\n", keyPath.toUtf8().data());
1453 //newval = m_directoryIconStateHash.value(path, FolderUnchecked) & (~change);
1454 int newval = shouldBeIconStateHash.value(keyPath);
1456 newval = newval & FolderBothChecked;
1457 QTreeWidgetItem *item = m_dirPaths.value(keyPath);
1459 directorySetIcon(0, newval, keyPath, item);
1461 if (mainWin->m_rtIconStateDebug) Pmsg1(000, "NOT found in shouldBeStateHash %s\n", keyPath.toUtf8().data());
1462 QTreeWidgetItem *item = m_dirPaths.value(keyPath);
1464 directorySetIcon(0, FolderBothChecked, keyPath, item);
1465 //item->setIcon(0,QIcon(QString::fromUtf8(":images/folder.png")));
1466 //m_directoryIconStateHash.remove(keyPath);
1471 void restoreTree::directorySetIcon(int operation, int change, QString &path, QTreeWidgetItem* item) {
1473 /* we are adding a check type white or green */
1474 if (operation > 0) {
1475 /* get the old val and "bitwise OR" with the change */
1476 newval = m_directoryIconStateHash.value(path, FolderUnchecked) | change;
1477 if (mainWin->m_rtIconStateDebug) Pmsg2(000, "Inserting into m_directoryIconStateHash path=%s newval=%i\n", path.toUtf8().data(), newval);
1478 m_directoryIconStateHash.insert(path, newval);
1480 /* we are removing a check type white or green */
1481 newval = m_directoryIconStateHash.value(path, FolderUnchecked) & (~change);
1483 if (mainWin->m_rtIconStateDebug) Pmsg2(000, "Removing from m_directoryIconStateHash path=%s newval=%i\n", path.toUtf8().data(), newval);
1484 m_directoryIconStateHash.remove(path);
1487 if (mainWin->m_rtIconStateDebug) Pmsg2(000, "Inserting into m_directoryIconStateHash path=%s newval=%i\n", path.toUtf8().data(), newval);
1488 m_directoryIconStateHash.insert(path, newval);
1491 if (newval == FolderUnchecked)
1492 item->setIcon(0, QIcon(QString::fromUtf8(":images/folder.png")));
1493 else if (newval == FolderGreenChecked)
1494 item->setIcon(0, QIcon(QString::fromUtf8(":images/folderchecked.png")));
1495 else if (newval == FolderWhiteChecked)
1496 item->setIcon(0, QIcon(QString::fromUtf8(":images/folderunchecked.png")));
1497 else if (newval == FolderBothChecked)
1498 item->setIcon(0, QIcon(QString::fromUtf8(":images/folderbothchecked.png")));
1504 void restoreTree::restoreButtonPushed()
1506 /* Set progress bars and repaint */
1507 prLabel1->setVisible(true);
1508 prLabel1->setText("Task 1 of 3");
1509 prLabel2->setVisible(true);
1510 prLabel2->setText("Processing Checked directories");
1511 prBar1->setVisible(true);
1512 prBar1->setRange(0, 3);
1513 prBar1->setValue(0);
1514 prBar2->setVisible(true);
1515 prBar2->setRange(0, 0);
1517 QMultiHash<int, QString> versionFilesMulti;
1519 QHash <QString, bool> fullPathDone;
1520 QHash <QString, int> fileIndexHash;
1521 if ((mainWin->m_rtRestore1Debug) || (mainWin->m_rtRestore2Debug) || (mainWin->m_rtRestore3Debug))
1522 Pmsg0(000, "In restoreTree::restoreButtonPushed\n");
1523 /* Use a tree widget item iterator to count directories for the progress bar */
1524 QTreeWidgetItemIterator diterc(directoryTree, QTreeWidgetItemIterator::Checked);
1529 } /* while (*diterc) */
1530 prBar2->setRange(0, ditcount);
1531 prBar2->setValue(0);
1533 /* Use a tree widget item iterator filtering for Checked Items */
1534 QTreeWidgetItemIterator diter(directoryTree, QTreeWidgetItemIterator::Checked);
1536 QString directory = (*diter)->data(0, Qt::UserRole).toString();
1537 int pathid = m_directoryPathIdHash.value(directory, -1);
1539 if (mainWin->m_rtRestore1Debug)
1540 Pmsg1(000, "Directory Checked=\"%s\"\n", directory.toUtf8().data());
1541 /* With a checked directory, query for the files in the directory */
1544 "SELECT Filename.Name AS Filename, t1.JobId AS JobId, File.FileIndex AS FileIndex"
1546 " ( SELECT File.FilenameId AS FilenameId, MAX(Job.JobId) AS JobId"
1548 " INNER JOIN Job ON (Job.JobId=File.JobId)"
1549 " WHERE File.PathId=" + QString("%1").arg(pathid) +
1550 " AND Job.Jobid IN (" + m_checkedJobs + ")"
1551 " AND File.FilenameId!=" + QString("%1").arg(m_nullFileNameId) +
1552 " GROUP BY File.FilenameId"
1554 " INNER JOIN Filename on (Filename.FilenameId=File.FilenameId)"
1555 " INNER JOIN Job ON (Job.JobId=File.JobId)"
1556 " WHERE File.PathId=" + QString("%1").arg(pathid) +
1557 " AND File.FilenameId=t1.FilenameId"
1558 " AND Job.Jobid=t1.JobId"
1559 " ORDER BY Filename";
1561 if (mainWin->m_sqlDebug) Pmsg1(000, "Query cmd : %s\n", cmd.toUtf8().data());
1562 QStringList results;
1563 if (m_console->sql_cmd(cmd, results)) {
1564 QStringList fieldlist;
1567 /* Iterate through the record returned from the query */
1568 foreach (QString resultline, results) {
1569 /* Iterate through fields in the record */
1571 QString fullPath = "";
1572 Qt::CheckState fileExcpState = (Qt::CheckState)4;
1573 fieldlist = resultline.split("\t");
1576 foreach (QString field, fieldlist) {
1578 fullPath = directory + field;
1581 version = field.toInt();
1584 fileIndex = field.toInt();
1588 fileExcpState = m_fileExceptionHash.value(fullPath, (Qt::CheckState)3);
1590 int excpVersion = m_versionExceptionHash.value(fullPath, 0);
1591 if (fileExcpState != Qt::Unchecked) {
1593 if (excpVersion != 0) {
1594 debugtext = QString("*E* version=%1").arg(excpVersion);
1595 version = excpVersion;
1596 fileIndex = queryFileIndex(fullPath, excpVersion);
1598 debugtext = QString("___ version=%1").arg(version);
1599 if (mainWin->m_rtRestore1Debug)
1600 Pmsg2(000, "Restoring %s File %s\n", debugtext.toUtf8().data(), fullPath.toUtf8().data());
1601 fullPathDone.insert(fullPath, 1);
1602 fileIndexHash.insert(fullPath, fileIndex);
1603 versionFilesMulti.insert(version, fullPath);
1611 prBar2->setValue(ditcount);
1613 } /* while (*diter) */
1614 prBar1->setValue(1);
1615 prLabel1->setText("Task 2 of 3");
1616 prLabel2->setText("Processing Exceptions");
1617 prBar2->setRange(0, 0);
1620 /* There may be some exceptions not accounted for yet with fullPathDone */
1621 QHashIterator<QString, Qt::CheckState> ftera(m_fileExceptionHash);
1622 while (ftera.hasNext()) {
1624 QString fullPath = ftera.key();
1625 Qt::CheckState state = ftera.value();
1627 /* now we don't want the ones already done */
1628 if (fullPathDone.value(fullPath, 0) == 0) {
1629 int version = m_versionExceptionHash.value(fullPath, 0);
1631 QString debugtext = "";
1633 fileIndex = queryFileIndex(fullPath, version);
1634 debugtext = QString("E1* version=%1 fileid=%2").arg(version).arg(fileIndex);
1636 version = mostRecentVersionfromFullPath(fullPath);
1638 fileIndex = queryFileIndex(fullPath, version);
1639 debugtext = QString("E2* version=%1 fileid=%2").arg(version).arg(fileIndex);
1641 debugtext = QString("Error det vers").arg(version);
1643 if (mainWin->m_rtRestore1Debug)
1644 Pmsg2(000, "Restoring %s file %s\n", debugtext.toUtf8().data(), fullPath.toUtf8().data());
1645 versionFilesMulti.insert(version, fullPath);
1647 fileIndexHash.insert(fullPath, fileIndex);
1648 } /* if fullPathDone.value(fullPath, 0) == 0 */
1649 } /* if state != 0 */
1650 } /* while ftera.hasNext */
1651 /* The progress bars for the next step */
1652 prBar1->setValue(2);
1653 prLabel1->setText("Task 3 of 3");
1654 prLabel2->setText("Filling Database Table");
1655 prBar2->setRange(0, vFMCounter);
1657 prBar2->setValue(vFMCounter);
1660 /* now for the final spit out of the versions and lists of files for each version */
1661 QHash<int, int> doneKeys;
1662 QHashIterator<int, QString> vFMiter(versionFilesMulti);
1663 QString tempTable = "";
1665 while (vFMiter.hasNext()) {
1667 int fversion = vFMiter.key();
1668 /* did not succeed in getting an iterator to work as expected on versionFilesMulti so use doneKeys */
1669 if (doneKeys.value(fversion, 0) == 0) {
1670 if (tempTable == "") {
1671 QSettings settings("www.bacula.org", "bat");
1672 settings.beginGroup("Restore");
1673 int counter = settings.value("Counter", 1).toInt();
1674 settings.setValue("Counter", counter+1);
1675 settings.endGroup();
1676 tempTable = "restore_" + QString("%1").arg(qrand()) + "_" + QString("%1").arg(counter);
1677 QString sqlcmd = "CREATE TEMPORARY TABLE " + tempTable + " (JobId INTEGER, FileIndex INTEGER)";
1678 if (mainWin->m_sqlDebug)
1679 Pmsg1(000, "Query cmd : %s ;\n", sqlcmd.toUtf8().data());
1680 QStringList results;
1681 if (!m_console->sql_cmd(sqlcmd, results))
1682 Pmsg1(000, "CREATE TABLE FAILED!!!! %s\n", sqlcmd.toUtf8().data());
1685 if (mainWin->m_rtRestore2Debug) Pmsg1(000, "Version->%i\n", fversion);
1686 QStringList fullPathList = versionFilesMulti.values(fversion);
1687 /* create the command to perform the restore */
1688 foreach(QString ffullPath, fullPathList) {
1689 int fileIndex = fileIndexHash.value(ffullPath);
1690 if (mainWin->m_rtRestore2Debug) Pmsg2(000, " file->%s id %i\n", ffullPath.toUtf8().data(), fileIndex);
1691 QString sqlcmd = "INSERT INTO " + tempTable + " (JobId, FileIndex) VALUES (" + QString("%1").arg(fversion) + ", " + QString("%1").arg(fileIndex) + ")";
1692 if (mainWin->m_rtRestore3Debug)
1693 Pmsg1(000, "Insert cmd : %s\n", sqlcmd.toUtf8().data());
1694 QStringList results;
1695 if (!m_console->sql_cmd(sqlcmd, results))
1696 Pmsg1(000, "INSERT INTO FAILED!!!! %s\n", sqlcmd.toUtf8().data());
1697 prBar2->setValue(++vFMCounter);
1698 } /* foreach fullPathList */
1699 doneKeys.insert(fversion,1);
1700 jobList.append(fversion);
1701 } /* if (doneKeys.value(fversion, 0) == 0) */
1702 } /* while (vFMiter.hasNext()) */
1703 if (tempTable != "") {
1704 /* a table was made, lets run the job */
1705 QString jobOption = " jobid=\"";
1707 /* create a list of jobs comma separated */
1708 foreach (int job, jobList) {
1709 if (first) first = false;
1710 else jobOption += ",";
1711 jobOption += QString("%1").arg(job);
1714 QString cmd = QString("restore");
1716 " client=\"" + m_prevClientCombo + "\"" +
1717 " file=\"?" + tempTable + "\" done";
1718 if (mainWin->m_commandDebug)
1719 Pmsg1(000, "preRestore command \'%s\'\n", cmd.toUtf8().data());
1720 consoleCommand(cmd);
1722 /* turn off the progress widgets */
1723 prBar1->setVisible(false);
1724 prBar2->setVisible(false);
1725 prLabel1->setVisible(false);
1726 prLabel2->setVisible(false);
1729 int restoreTree::mostRecentVersionfromFullPath(QString &fullPath)
1732 QString directory, fileName;
1733 int index = m_slashregex.lastIndexIn(fullPath, -2);
1735 directory = fileName = fullPath;
1736 directory.replace(index+1, fullPath.length()-index-1, "");
1737 fileName.replace(0, index+1, "");
1739 QString msg = QString("length = \"%1\" index = \"%2\" Considering \"%3\" \"%4\"\n")
1740 .arg(fullPath.length()).arg(index).arg(fileName).arg(directory);
1741 Pmsg0(000, msg.toUtf8().data());
1743 int pathid = m_directoryPathIdHash.value(directory, -1);
1745 /* so now we need the latest version from the database */
1747 "SELECT MAX(Job.JobId)"
1749 " INNER JOIN Filename on (Filename.FilenameId=File.FilenameId)"
1750 " INNER JOIN Job ON (File.JobId=Job.JobId)"
1751 " WHERE File.PathId=" + QString("%1").arg(pathid) +
1752 " AND Job.Jobid IN (" + m_checkedJobs + ")"
1753 " AND Filename.Name='" + fileName + "'"
1754 " AND File.FilenameId!=" + QString("%1").arg(m_nullFileNameId) +
1755 " GROUP BY Filename.Name";
1757 if (mainWin->m_sqlDebug) Pmsg1(000, "Query cmd : %s\n", cmd.toUtf8().data());
1758 QStringList results;
1759 if (m_console->sql_cmd(cmd, results)) {
1760 QStringList fieldlist;
1762 /* Iterate through the record returned from the query */
1763 foreach (QString resultline, results) {
1764 /* Iterate through fields in the record */
1766 fieldlist = resultline.split("\t");
1767 foreach (QString field, fieldlist) {
1769 qversion = field.toInt();
1777 } /* if (index != -1) */
1782 int restoreTree::queryFileIndex(QString &fullPath, int jobId)
1785 QString directory, fileName;
1786 int index = m_slashregex.lastIndexIn(fullPath, -2);
1788 directory = fileName = fullPath;
1789 directory.replace(index+1, fullPath.length()-index-1, "");
1790 fileName.replace(0, index+1, "");
1792 QString msg = QString("length = \"%1\" index = \"%2\" Considering \"%3\" \"%4\"\n")
1793 .arg(fullPath.length()).arg(index).arg(fileName).arg(directory);
1794 Pmsg0(000, msg.toUtf8().data());
1796 int pathid = m_directoryPathIdHash.value(directory, -1);
1798 /* so now we need the latest version from the database */
1803 " INNER JOIN Filename on (Filename.FilenameId=File.FilenameId)"
1804 " INNER JOIN Job ON (File.JobId=Job.JobId)"
1805 " WHERE File.PathId=" + QString("%1").arg(pathid) +
1806 " AND Filename.Name='" + fileName + "'"
1807 " AND Job.Jobid='" + QString("%1").arg(jobId) + "'"
1808 " GROUP BY File.FileIndex";
1810 if (mainWin->m_sqlDebug) Pmsg1(000, "Query cmd : %s\n", cmd.toUtf8().data());
1811 QStringList results;
1812 if (m_console->sql_cmd(cmd, results)) {
1813 QStringList fieldlist;
1815 /* Iterate through the record returned from the query */
1816 foreach (QString resultline, results) {
1817 /* Iterate through fields in the record */
1819 fieldlist = resultline.split("\t");
1820 foreach (QString field, fieldlist) {
1822 qfileIndex = field.toInt();
1830 } /* if (index != -1) */