2 Bacula® - The Network Backup Solution
4 Copyright (C) 2007-2009 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 Kern Sibbald.
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);
69 splitter->setCollapsible(0, false);
71 gridLayout->addWidget(m_splitter, 0, 0, 1, 1);
73 /* progress widgets */
74 prBar1->setVisible(false);
75 prBar2->setVisible(false);
76 prLabel1->setVisible(false);
77 prLabel2->setVisible(false);
79 /* Set Defaults for check and spin for limits */
80 limitCheckBox->setCheckState(mainWin->m_recordLimitCheck ? Qt::Checked : Qt::Unchecked);
81 limitSpinBox->setValue(mainWin->m_recordLimitVal);
82 daysCheckBox->setCheckState(mainWin->m_daysLimitCheck ? Qt::Checked : Qt::Unchecked);
83 daysSpinBox->setValue(mainWin->m_daysLimitVal);
85 m_nullFileNameId = -1;
88 restoreTree::~restoreTree()
94 * Called from the constructor to set up the page widgets and connections.
96 void restoreTree::setupPage()
98 connect(refreshButton, SIGNAL(pressed()), this, SLOT(refreshButtonPushed()));
99 connect(restoreButton, SIGNAL(pressed()), this, SLOT(restoreButtonPushed()));
100 connect(jobCombo, SIGNAL(currentIndexChanged(int)), this, SLOT(jobComboChanged(int)));
101 connect(jobCombo, SIGNAL(currentIndexChanged(int)), this, SLOT(updateRefresh()));
102 connect(clientCombo, SIGNAL(currentIndexChanged(int)), this, SLOT(updateRefresh()));
103 connect(fileSetCombo, SIGNAL(currentIndexChanged(int)), this, SLOT(updateRefresh()));
104 connect(limitCheckBox, SIGNAL(stateChanged(int)), this, SLOT(updateRefresh()));
105 connect(daysCheckBox, SIGNAL(stateChanged(int)), this, SLOT(updateRefresh()));
106 connect(daysSpinBox, SIGNAL(valueChanged(int)), this, SLOT(updateRefresh()));
107 connect(limitSpinBox, SIGNAL(valueChanged(int)), this, SLOT(updateRefresh()));
108 connect(directoryTree, SIGNAL(currentItemChanged(QTreeWidgetItem *, QTreeWidgetItem *)),
109 this, SLOT(directoryCurrentItemChanged(QTreeWidgetItem *, QTreeWidgetItem *)));
110 connect(directoryTree, SIGNAL(itemExpanded(QTreeWidgetItem *)),
111 this, SLOT(directoryItemExpanded(QTreeWidgetItem *)));
112 connect(directoryTree, SIGNAL(itemChanged(QTreeWidgetItem *, int)),
113 this, SLOT(directoryItemChanged(QTreeWidgetItem *, int)));
114 connect(fileTable, SIGNAL(currentItemChanged(QTableWidgetItem *, QTableWidgetItem *)),
115 this, SLOT(fileCurrentItemChanged(QTableWidgetItem *, QTableWidgetItem *)));
116 connect(jobTable, SIGNAL(cellClicked(int, int)),
117 this, SLOT(jobTableCellClicked(int, int)));
119 QStringList titles = QStringList() << tr("Directories");
120 directoryTree->setHeaderLabels(titles);
121 clientCombo->addItems(m_console->client_list);
122 fileSetCombo->addItem(tr("Any"));
123 fileSetCombo->addItems(m_console->fileset_list);
124 jobCombo->addItem(tr("Any"));
125 jobCombo->addItems(m_console->job_list);
127 directoryTree->setContextMenuPolicy(Qt::ActionsContextMenu);
130 void restoreTree::updateRefresh()
132 if (mainWin->m_rtPopDirDebug) Pmsg2(000, "testing prev=\"%s\" current=\"%s\"\n", m_prevJobCombo.toUtf8().data(), jobCombo->currentText().toUtf8().data());
133 m_dropdownChanged = (m_prevJobCombo != jobCombo->currentText())
134 || (m_prevClientCombo != clientCombo->currentText())
135 || (m_prevFileSetCombo != fileSetCombo->currentText()
136 || (m_prevLimitSpinBox != limitSpinBox->value())
137 || (m_prevDaysSpinBox != daysSpinBox->value())
138 || (m_prevLimitCheckState != limitCheckBox->checkState())
139 || (m_prevDaysCheckState != daysCheckBox->checkState())
141 if (m_dropdownChanged) {
142 if (mainWin->m_rtPopDirDebug) Pmsg0(000, "In restoreTree::updateRefresh Is CHANGED\n");
143 refreshLabel->setText(tr("Refresh From Re-Select"));
145 if (mainWin->m_rtPopDirDebug) Pmsg0(000, "In restoreTree::updateRefresh Is not Changed\n");
146 refreshLabel->setText(tr("Refresh From JobChecks"));
151 * When refresh button is pushed, perform a query getting the directories and
152 * use parseDirectory and addDirectory to populate the directory tree with items.
154 void restoreTree::populateDirectoryTree()
158 directoryTree->clear();
160 fileTable->setRowCount(0);
161 fileTable->setColumnCount(0);
162 versionTable->clear();
163 versionTable->setRowCount(0);
164 versionTable->setColumnCount(0);
165 m_fileExceptionHash.clear();
166 m_fileExceptionMulti.clear();
167 m_versionExceptionHash.clear();
168 m_directoryIconStateHash.clear();
171 int taskcount = 3, ontask = 1;
172 if (m_dropdownChanged) taskcount += 1;
174 /* Set progress bars and repaint */
175 prBar1->setVisible(true);
176 prBar1->setRange(0,taskcount);
178 prLabel1->setText(tr("Task %1 of %2").arg(ontask).arg(taskcount));
179 prLabel1->setVisible(true);
180 prBar2->setVisible(true);
181 prBar2->setRange(0,0);
182 prLabel2->setText(tr("Querying Database"));
183 prLabel2->setVisible(true);
186 if (m_dropdownChanged) {
187 m_prevJobCombo = jobCombo->currentText();
188 m_prevClientCombo = clientCombo->currentText();
189 m_prevFileSetCombo = fileSetCombo->currentText();
190 m_prevLimitSpinBox = limitSpinBox->value();
191 m_prevDaysSpinBox = daysSpinBox->value();
192 m_prevLimitCheckState = limitCheckBox->checkState();
193 m_prevDaysCheckState = daysCheckBox->checkState();
195 prBar1->setValue(ontask++);
196 prLabel1->setText(tr("Task %1 of %2").arg(ontask).arg(taskcount));
198 prBar2->setRange(0,0);
199 prLabel2->setText(tr("Querying Jobs"));
203 setJobsCheckedList();
204 if (mainWin->m_rtPopDirDebug) Pmsg0(000, "Repopulating from checks in Job Table\n");
206 if (m_checkedJobs != "") {
207 /* First get the filenameid of where the nae is null. These will be the directories
208 * This could be done in a subquery but postgres's query analyzer won't do the right
209 * thing like I want */
210 if (m_nullFileNameId == -1) {
211 QString cmd = "SELECT FilenameId FROM Filename WHERE name=''";
212 if (mainWin->m_sqlDebug)
213 Pmsg1(000, "Query cmd : %s\n", cmd.toUtf8().data());
215 if (m_console->sql_cmd(cmd, qres)) {
217 QStringList fieldlist = qres[0].split("\t");
218 QString field = fieldlist[0];
220 int val = field.toInt(&ok, 10);
221 if (ok) m_nullFileNameId = val;
225 /* now create the query to get the list of paths */
227 "SELECT DISTINCT Path.Path AS Path, File.PathId AS PathId"
229 " INNER JOIN Path ON (File.PathId=Path.PathId)";
230 if (m_nullFileNameId != -1)
231 cmd += " WHERE File.FilenameId=" + QString("%1").arg(m_nullFileNameId);
233 cmd += " WHERE File.FilenameId IN (SELECT FilenameId FROM Filename WHERE Name='')";
234 cmd += " AND File.Jobid IN (" + m_checkedJobs + ")"
236 if (mainWin->m_sqlDebug)
237 Pmsg1(000, "Query cmd : %s\n", cmd.toUtf8().data());
238 prBar1->setValue(ontask++);
239 prLabel1->setText(tr("Task %1 of %2").arg(ontask).arg(taskcount));
241 prBar2->setRange(0,0);
242 prLabel2->setText(tr("Querying for Directories"));
245 m_directoryPathIdHash.clear();
246 bool querydone = false;
247 if (m_console->sql_cmd(cmd, results)) {
250 prLabel2->setText(tr("Processing Directories"));
251 prBar2->setRange(0,results.count());
254 if (mainWin->m_miscDebug)
255 Pmsg1(000, "Done with query %i results\n", results.count());
256 QStringList fieldlist;
257 foreach(QString resultline, results) {
258 /* Update progress bar periodically */
259 if ((++m_debugCnt && 0x3FF) == 0) {
260 prBar2->setValue(m_debugCnt);
262 fieldlist = resultline.split("\t");
265 /* Iterate through fields in the record */
266 foreach (field, fieldlist) {
267 if (fieldcnt == 0 ) {
268 parseDirectory(field);
269 } else if (fieldcnt == 1) {
271 int pathid = field.toInt(&ok, 10);
273 m_directoryPathIdHash.insert(fieldlist[0], pathid);
280 QMessageBox::warning(this, "Bat",
281 tr("No jobs were selected in the job query !!!.\n"
282 "Press OK to continue"),
285 prBar1->setVisible(false);
286 prBar2->setVisible(false);
287 prLabel1->setVisible(false);
288 prLabel2->setVisible(false);
292 * Function to set m_checkedJobs from the jobs that are checked in the table
295 void restoreTree::setJobsCheckedList()
297 m_JobsCheckedList = "";
299 /* Update the items in the version table */
300 int cnt = jobTable->rowCount();
301 for (int row=0; row<cnt; row++) {
302 QTableWidgetItem* jobItem = jobTable->item(row, 0);
303 if (jobItem->checkState() == Qt::Checked) {
305 m_JobsCheckedList += ",";
306 m_JobsCheckedList += jobItem->text();
308 jobItem->setBackground(Qt::green);
310 if (jobItem->flags())
311 jobItem->setBackground(Qt::gray);
313 jobItem->setBackground(Qt::darkYellow);
316 m_checkedJobs = m_JobsCheckedList;
320 * Function to parse a directory into all possible subdirectories, then add to
323 void restoreTree::parseDirectory(QString &dir_in)
325 /* m_debugTrap is to only print debugs for a few occurennces of calling parseDirectory
326 * instead of printing out what could potentially a whole bunch */
329 /* Truncate everything after the last / */
330 if (dir_in.right(1) != "/") {
331 dir_in.truncate(dir_in.lastIndexOf("/") + 1);
333 if ((mainWin->m_miscDebug) && (m_debugTrap))
334 Pmsg1(000, "parsing %s\n", dir_in.toUtf8().data());
336 /* split and add if not in yet */
337 QString direct, path;
340 QStringList pathAfter, dirAfter;
341 /* start from the end, turn /etc/somedir/subdir/ into /etc/somedir and subdir/
342 * if not added into tree, then try /etc/ and somedir/ if not added, then try
343 * / and etc/ . That should succeed, then add the ones that failed in reverse */
344 while (((index = dir_in.lastIndexOf("/", -2)) != -1) && (!done)) {
345 direct = path = dir_in;
346 path.replace(index+1, dir_in.length()-index-1,"");
347 direct.replace(0, index+1, "");
348 if ((mainWin->m_miscDebug) && (m_debugTrap)) {
349 QString msg = QString("length = \"%1\" index = \"%2\" Adding \"%3\" \"%4\"\n")
350 .arg(dir_in.length()).arg(index).arg(path).arg(direct);
351 Pmsg0(000, msg.toUtf8().data());
353 if (addDirectory(path, direct)) done = true;
355 if ((mainWin->m_miscDebug) && (m_debugTrap))
356 Pmsg0(000, "Saving for later\n");
357 pathAfter.prepend(path);
358 dirAfter.prepend(direct);
363 for (int k=0; k<pathAfter.count(); k++) {
364 if (addDirectory(pathAfter[k], dirAfter[k])) {
365 if ((mainWin->m_miscDebug) && (m_debugTrap))
366 Pmsg2(000, "Adding After %s %s\n", pathAfter[k].toUtf8().data(), dirAfter[k].toUtf8().data());
368 if ((mainWin->m_miscDebug) && (m_debugTrap))
369 Pmsg2(000, "Error Adding %s %s\n", pathAfter[k].toUtf8().data(), dirAfter[k].toUtf8().data());
376 * Function called from fill directory when a directory is found to see if this
377 * directory exists in the directory pane and then add it to the directory pane
379 bool restoreTree::addDirectory(QString &m_cwd, QString &newdirr)
381 QString newdir = newdirr;
382 QString fullPath = m_cwd + newdirr;
383 bool ok = true, added = false;
385 if ((mainWin->m_miscDebug) && (m_debugTrap)) {
386 QString msg = QString("In addDirectory cwd \"%1\" newdir \"%2\"\n")
389 Pmsg0(000, msg.toUtf8().data());
393 /* add unix '/' directory first */
394 if (m_dirPaths.empty() && !isWin32Path(fullPath)) {
396 QTreeWidgetItem *item = new QTreeWidgetItem(directoryTree);
398 item->setText(0, text.toUtf8().data());
399 item->setData(0, Qt::UserRole, QVariant(text));
400 item->setData(1, Qt::UserRole, QVariant(Qt::Unchecked));
401 item->setIcon(0, QIcon(QString::fromUtf8(":images/folder.png")));
402 if ((mainWin->m_miscDebug) && (m_debugTrap)) {
403 Pmsg1(000, "Pre Inserting %s\n", text.toUtf8().data());
405 m_dirPaths.insert(text, item);
407 /* no need to check for windows drive if unix */
408 if (isWin32Path(m_cwd)) {
409 if (!m_dirPaths.contains(m_cwd)) {
410 /* this is a windows drive add the base widget */
411 QTreeWidgetItem *item = new QTreeWidgetItem(directoryTree);
412 item->setText(0, m_cwd);
413 item->setData(0, Qt::UserRole, QVariant(fullPath));
414 item->setData(1, Qt::UserRole, QVariant(Qt::Unchecked));
415 item->setIcon(0, QIcon(QString::fromUtf8(":images/folder.png")));
416 if ((mainWin->m_miscDebug) && (m_debugTrap)) {
417 Pmsg0(000, "Added Base \"letter\":/\n");
419 m_dirPaths.insert(m_cwd, item);
424 /* is it already existent ?? */
425 if (!m_dirPaths.contains(fullPath)) {
426 QTreeWidgetItem *item = NULL;
427 QTreeWidgetItem *parent = m_dirPaths.value(m_cwd);
429 /* new directories to add */
430 item = new QTreeWidgetItem(parent);
431 item->setText(0, newdir.toUtf8().data());
432 item->setData(0, Qt::UserRole, QVariant(fullPath));
433 item->setCheckState(0, Qt::Unchecked);
434 /* Store the current state of the check status in column 1, which at
435 * this point has no text*/
436 item->setData(1, Qt::UserRole, QVariant(Qt::Unchecked));
439 if ((mainWin->m_miscDebug) && (m_debugTrap)) {
440 QString msg = QString("In else of if parent cwd \"%1\" newdir \"%2\"\n")
443 Pmsg0(000, msg.toUtf8().data());
446 /* insert into hash */
448 if ((mainWin->m_miscDebug) && (m_debugTrap)) {
449 Pmsg1(000, "Inserting %s\n", fullPath.toUtf8().data());
451 m_dirPaths.insert(fullPath, item);
459 * Virtual function which is called when this page is visible on the stack
461 void restoreTree::currentStackItem()
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: %1").arg(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_splitText1, m_splitter->saveState());
694 settings.setValue(m_splitText2, splitter->saveState());
699 * Read and restore user settings associated with this page
701 void restoreTree::readSettings()
703 m_groupText = tr("RestoreTreePage");
704 m_splitText1 = "splitterSizes1_2";
705 m_splitText2 = "splitterSizes2_2";
706 QSettings settings(m_console->m_dir->name(), "bat");
707 settings.beginGroup(m_groupText);
708 m_splitter->restoreState(settings.value(m_splitText1).toByteArray());
709 splitter->restoreState(settings.value(m_splitText2).toByteArray());
714 * This is a funcion to accomplish the one thing I struggled to figure out what
715 * was taking so long. It add the icons, but after the tree is made. Seemed to
716 * work fast after changing from png to png file for graphic.
718 void restoreTree::directoryItemExpanded(QTreeWidgetItem *item)
720 int childCount = item->childCount();
721 for (int i=0; i<childCount; i++) {
722 QTreeWidgetItem *child = item->child(i);
723 if (child->icon(0).isNull())
724 child->setIcon(0, QIcon(QString::fromUtf8(":images/folder.png")));
729 * Show what jobs meet the criteria and are being used to
730 * populate the directory tree and file and version tables.
732 void restoreTree::populateJobTable()
734 QBrush blackBrush(Qt::black);
736 if (mainWin->m_rtPopDirDebug) Pmsg0(000, "Repopulating the Job Table\n");
737 QStringList headerlist = (QStringList()
738 << tr("Job Id") << tr("End Time") << tr("Level")
739 << tr("Name") << tr("Purged") << tr("TU") << tr("TD"));
740 m_toggleUpIndex = headerlist.indexOf(tr("TU"));
741 m_toggleDownIndex = headerlist.indexOf(tr("TD"));
742 int purgedIndex = headerlist.indexOf(tr("Purged"));
744 jobTable->setColumnCount(headerlist.size());
745 jobTable->setHorizontalHeaderLabels(headerlist);
747 "SELECT Job.Jobid AS Id,Job.EndTime AS EndTime,Job.Level AS Level,"
748 "Job.Name AS JobName,Job.purgedfiles AS Purged"
750 /* INNER JOIN FileSet eliminates all restore jobs */
751 " INNER JOIN Client ON (Job.ClientId=Client.ClientId)"
752 " INNER JOIN FileSet ON (Job.FileSetId=FileSet.FileSetId)"
754 " Client.Name='" + clientCombo->currentText() + "'";
755 if ((jobCombo->currentIndex() >= 0) && (jobCombo->currentText() != tr("Any"))) {
756 jobQuery += " AND Job.name = '" + jobCombo->currentText() + "'";
758 if ((fileSetCombo->currentIndex() >= 0) && (fileSetCombo->currentText() != tr("Any"))) {
759 jobQuery += " AND FileSet.FileSet='" + fileSetCombo->currentText() + "'";
761 /* If Limit check box For limit by days is checked */
762 if (daysCheckBox->checkState() == Qt::Checked) {
763 QDateTime stamp = QDateTime::currentDateTime().addDays(-daysSpinBox->value());
764 QString since = stamp.toString(Qt::ISODate);
765 jobQuery += " AND Job.Starttime>'" + since + "'";
767 //jobQuery += " AND Job.purgedfiles=0";
768 jobQuery += " ORDER BY Job.EndTime DESC";
769 /* If Limit check box for limit records returned is checked */
770 if (limitCheckBox->checkState() == Qt::Checked) {
772 limit.setNum(limitSpinBox->value());
773 jobQuery += " LIMIT " + limit;
775 if (mainWin->m_sqlDebug)
776 Pmsg1(000, "Query cmd : %s\n", jobQuery.toUtf8().data());
779 if (m_console->sql_cmd(jobQuery, results)) {
781 QTableWidgetItem* tableItem;
783 QStringList fieldlist;
784 jobTable->setRowCount(results.size());
787 /* Iterate through the record returned from the query */
788 foreach (QString resultline, results) {
789 fieldlist = resultline.split("\t");
791 /* remove directory */
792 if (fieldlist[0].trimmed() != "") {
793 /* Iterate through fields in the record */
794 foreach (field, fieldlist) {
795 field = field.trimmed(); /* strip leading & trailing spaces */
797 tableItem = new QTableWidgetItem(field, 1);
798 tableItem->setFlags(0);
799 tableItem->setForeground(blackBrush);
800 jobTable->setItem(row, column, tableItem);
803 int purged = fieldlist[purgedIndex].toInt(&ok, 10);
804 if (!((ok) && (purged == 1))) {
805 Qt::ItemFlags flag = Qt::ItemIsUserCheckable | Qt::ItemIsEnabled | Qt::ItemIsTristate;
806 tableItem->setFlags(flag);
807 tableItem->setCheckState(Qt::Checked);
808 tableItem->setBackground(Qt::green);
810 tableItem->setFlags(0);
811 tableItem->setCheckState(Qt::Unchecked);
817 tableItem = new QTableWidgetItem(QIcon(QString::fromUtf8(":images/go-up.png")), "", 1);
818 tableItem->setFlags(0);
819 tableItem->setForeground(blackBrush);
820 jobTable->setItem(row, column, tableItem);
822 tableItem = new QTableWidgetItem(QIcon(QString::fromUtf8(":images/go-down.png")), "", 1);
823 tableItem->setFlags(0);
824 tableItem->setForeground(blackBrush);
825 jobTable->setItem(row, column, tableItem);
830 jobTable->resizeColumnsToContents();
831 jobTable->resizeRowsToContents();
832 jobTable->verticalHeader()->hide();
833 jobTable->hideColumn(purgedIndex);
836 void restoreTree::jobTableCellClicked(int row, int column)
838 if (column == m_toggleUpIndex){
840 for (cnt=0; cnt<row+1; cnt++) {
841 QTableWidgetItem *item = jobTable->item(cnt, 0);
843 Qt::CheckState state = item->checkState();
844 if (state == Qt::Checked)
845 item->setCheckState(Qt::Unchecked);
846 else if (state == Qt::Unchecked)
847 item->setCheckState(Qt::Checked);
851 if (column == m_toggleDownIndex){
852 int cnt, max = jobTable->rowCount();
853 for (cnt=row; cnt<max; cnt++) {
854 QTableWidgetItem *item = jobTable->item(cnt, 0);
856 Qt::CheckState state = item->checkState();
857 if (state == Qt::Checked)
858 item->setCheckState(Qt::Unchecked);
859 else if (state == Qt::Unchecked)
860 item->setCheckState(Qt::Checked);
867 * When a directory item is "changed" check the state of the checkable item
868 * to see if it is different than what it was which is stored in Qt::UserRole
869 * of the 2nd column, column 1, of the tree widget.
871 void restoreTree::directoryItemChanged(QTreeWidgetItem *item, int /*column*/)
873 Qt::CheckState prevState = (Qt::CheckState)item->data(1, Qt::UserRole).toInt();
874 Qt::CheckState curState = item->checkState(0);
875 QTreeWidgetItem* parent = item->parent();
876 Qt::CheckState parState;
877 if (parent) parState = parent->checkState(0);
878 else parState = (Qt::CheckState)3;
879 if (mainWin->m_rtDirICDebug) {
880 QString msg = QString("directory item OBJECT has changed prev=%1 cur=%2 par=%3 dir=%4\n")
881 .arg(prevState).arg(curState).arg(parState).arg(item->text(0));
882 Pmsg1(000, "%s", msg.toUtf8().data()); }
883 /* I only care when the check state changes */
884 if (prevState == curState) {
885 if (mainWin->m_rtDirICDebug) Pmsg0(000, "Returning Early\n");
889 if ((prevState == Qt::Unchecked) && (curState == Qt::Checked) && (parState != Qt::Unchecked)) {
890 if (mainWin->m_rtDirICDebug) Pmsg0(000, "Disconnected Setting to Qt::PartiallyChecked\n");
891 directoryTreeDisconnectedSet(item, Qt::PartiallyChecked);
892 curState = Qt::PartiallyChecked;
894 if ((prevState == Qt::PartiallyChecked) && (curState == Qt::Checked)) {
895 if (mainWin->m_rtDirICDebug) Pmsg0(000, "Disconnected Setting to Qt::Unchecked\n");
896 directoryTreeDisconnectedSet(item, Qt::Unchecked);
897 curState = Qt::Unchecked;
899 if (mainWin->m_rtDirICDebug) {
900 QString msg = QString("directory item CHECKSTATE has changed prev=%1 cur=%2 par=%3 dir=%4\n")
901 .arg(prevState).arg(curState).arg(parState).arg(item->text(0));
902 Pmsg1(000, "%s", msg.toUtf8().data()); }
904 item->setData(1, Qt::UserRole, QVariant(curState));
905 Qt::CheckState childState = curState;
906 if (childState == Qt::Checked)
907 childState = Qt::PartiallyChecked;
908 setCheckofChildren(item, childState);
910 /* Remove items from the exception lists. The multi exception list is my index
911 * of what exceptions can be removed when the directory is known*/
912 QString directory = item->data(0, Qt::UserRole).toString();
913 QStringList fullPathList = m_fileExceptionMulti.values(directory);
914 int fullPathListCount = fullPathList.count();
915 if ((mainWin->m_rtDirICDebug) && fullPathListCount) Pmsg2(000, "Will attempt to remove file exceptions for %s count %i\n", directory.toUtf8().data(), fullPathListCount);
916 foreach (QString fullPath, fullPathList) {
917 /* If there is no value in the hash for the key fullPath a value of 3 will be returned
918 * which will match no Qt::xxx values */
919 Qt::CheckState hashState = m_fileExceptionHash.value(fullPath, (Qt::CheckState)3);
920 if (mainWin->m_rtDirICDebug) Pmsg2(000, "hashState=%i childState=%i\n", hashState, childState);
921 if (hashState == Qt::Unchecked) {
922 fileExceptionRemove(fullPath, directory);
923 m_versionExceptionHash.remove(fullPath);
924 if (mainWin->m_rtDirICDebug) Pmsg0(000, "Attempted Removal A\n");
926 if (hashState == Qt::Checked) {
927 fileExceptionRemove(fullPath, directory);
928 m_versionExceptionHash.remove(fullPath);
929 if (mainWin->m_rtDirICDebug) Pmsg0(000, "Attempted Removal B\n");
933 if (item == directoryTree->currentItem()) {
934 if (mainWin->m_rtDirICDebug) Pmsg0(000, "Will attempt to update File Table Checks\n");
935 updateFileTableChecks();
936 versionTable->clear();
937 versionTable->setRowCount(0);
938 versionTable->setColumnCount(0);
940 if (mainWin->m_rtDirICDebug) Pmsg0(000, "Returning At End\n");
944 * When a directory item check state is changed, this function iterates through
945 * all subdirectories and sets all to the passed state, which is either partially
946 * checked or unchecked.
948 void restoreTree::setCheckofChildren(QTreeWidgetItem *item, Qt::CheckState state)
951 childCount = item->childCount();
952 for (int i=0; i<childCount; i++) {
953 QTreeWidgetItem *child = item->child(i);
954 child->setData(1, Qt::UserRole, QVariant(state));
955 child->setCheckState(0, state);
956 setCheckofChildren(child, state);
961 * When a File Table Item is "changed" check to see if the state of the checkable
962 * item has changed which is stored in m_fileCheckStateList
963 * If changed store in a hash m_fileExceptionHash that whether this file should be
965 * Called as a slot, connected after populated (after directory current changed called)
967 void restoreTree::fileTableItemChanged(QTableWidgetItem *item)
969 /* get the previous and current check states */
970 int row = fileTable->row(item);
971 Qt::CheckState prevState;
972 /* prevent a segfault */
973 prevState = m_fileCheckStateList[row];
974 Qt::CheckState curState = item->checkState();
976 /* deterimine the default state from the state of the directory */
977 QTreeWidgetItem *dirTreeItem = directoryTree->currentItem();
978 Qt::CheckState dirState = (Qt::CheckState)dirTreeItem->data(1, Qt::UserRole).toInt();
979 Qt::CheckState defState = Qt::PartiallyChecked;
980 if (dirState == Qt::Unchecked) defState = Qt::Unchecked;
982 /* determine if it is already in the m_fileExceptionHash */
983 QString directory = directoryTree->currentItem()->data(0, Qt::UserRole).toString();
984 QString file = item->text();
985 QString fullPath = directory + file;
986 Qt::CheckState hashState = m_fileExceptionHash.value(fullPath, (Qt::CheckState)3);
987 int verJobNum = m_versionExceptionHash.value(fullPath, 0);
989 if (mainWin->m_rtFileTabICDebug) {
990 QString msg = QString("filerow=%1 prev=%2 cur=%3 def=%4 hash=%5 dir=%6 verJobNum=%7\n")
991 .arg(row).arg(prevState).arg(curState).arg(defState).arg(hashState).arg(dirState).arg(verJobNum);
992 Pmsg1(000, "%s", msg.toUtf8().data()); }
994 /* Remove the hash if currently checked previously unchecked and directory is checked or partial */
995 if ((prevState == Qt::Checked) && (curState == Qt::Unchecked) && (dirState == Qt::Unchecked)) {
996 /* it can behave as defaulted so current of unchecked is fine */
997 if (mainWin->m_rtFileTabICDebug) Pmsg0(000, "Will fileExceptionRemove and m_versionExceptionHash.remove here\n");
998 fileExceptionRemove(fullPath, directory);
999 m_versionExceptionHash.remove(fullPath);
1000 } else if ((prevState == Qt::PartiallyChecked) && (curState == Qt::Checked) && (dirState != Qt::Unchecked) && (verJobNum == 0)) {
1001 if (mainWin->m_rtFileTabICDebug) Pmsg0(000, "Will fileExceptionInsert here\n");
1002 fileExceptionInsert(fullPath, directory, Qt::Unchecked);
1003 } else if ((prevState == Qt::Unchecked) && (curState == Qt::Checked) && (dirState != Qt::Unchecked) && (verJobNum == 0) && (defState == Qt::PartiallyChecked)) {
1004 /* filerow=2 prev=0 cur=2 def=1 hash=0 dir=2 verJobNum=0 */
1005 if (mainWin->m_rtFileTabICDebug) Pmsg0(000, "Will fileExceptionRemove here\n");
1006 fileExceptionRemove(fullPath, directory);
1007 } else if ((prevState == Qt::Checked) && (curState == Qt::Unchecked) && (defState == Qt::PartiallyChecked) && (verJobNum != 0) && (hashState == Qt::Checked)) {
1008 /* Check dir, check version, attempt uncheck in file
1009 * filerow=4 prev=2 cur=0 def=1 hash=2 dir=2 verJobNum=53 */
1010 if (mainWin->m_rtFileTabICDebug) Pmsg0(000, "Will fileExceptionRemove and m_versionExceptionHash.remove here\n");
1011 fileExceptionRemove(fullPath, directory);
1012 m_versionExceptionHash.remove(fullPath);
1013 } else if ((prevState == Qt::Unchecked) && (curState == Qt::Checked) && (dirState != Qt::Unchecked) && (verJobNum == 0)) {
1014 /* filerow=0 prev=0 cur=2 def=1 hash=0 dirState=2 verJobNum */
1015 if (mainWin->m_rtFileTabICDebug) Pmsg0(000, "Will Not remove here\n");
1016 } else if (prevState != curState) {
1017 if (mainWin->m_rtFileTabICDebug) Pmsg2(000, " THE STATE OF THE Check has changed, Setting StateList[%i] to %i\n", row, curState);
1018 /* A user did not set the check state to Partially checked, ignore if so */
1019 if (curState != Qt::PartiallyChecked) {
1020 if ((defState == Qt::Unchecked) && (prevState == Qt::PartiallyChecked) && (curState == Qt::Unchecked)) {
1021 if (mainWin->m_rtFileTabICDebug) Pmsg0(000, " got here\n");
1023 if (mainWin->m_rtFileTabICDebug) Pmsg2(000, " Inserting into m_fileExceptionHash %s, %i\n", fullPath.toUtf8().data(), curState);
1024 fileExceptionInsert(fullPath, directory, curState);
1027 if (mainWin->m_rtFileTabICDebug) Pmsg1(000, "Removing version hash for %s\n", fullPath.toUtf8().data());
1028 /* programattically been changed back to a default state of Qt::PartiallyChecked remove the version hash here */
1029 m_versionExceptionHash.remove(fullPath);
1033 updateFileTableChecks();
1034 updateVersionTableChecks();
1038 * function to insert keys and values to both m_fileExceptionHash and m_fileExceptionMulti
1040 void restoreTree::fileExceptionInsert(QString &fullPath, QString &direcotry, Qt::CheckState state)
1042 m_fileExceptionHash.insert(fullPath, state);
1043 m_fileExceptionMulti.insert(direcotry, fullPath);
1044 directoryIconStateInsert(fullPath, state);
1048 * function to remove keys from both m_fileExceptionHash and m_fileExceptionMulti
1050 void restoreTree::fileExceptionRemove(QString &fullPath, QString &directory)
1052 m_fileExceptionHash.remove(fullPath);
1053 /* pull the list of values in the multi */
1054 QStringList fullPathList = m_fileExceptionMulti.values(directory);
1055 /* get the index of the fullpath to remove */
1056 int index = fullPathList.indexOf(fullPath);
1058 /* remove the desired item in the list */
1059 fullPathList.removeAt(index);
1060 /* remove the entire list from the multi */
1061 m_fileExceptionMulti.remove(directory);
1062 /* readd the remaining */
1063 foreach (QString fp, fullPathList) {
1064 m_fileExceptionMulti.insert(directory, fp);
1067 directoryIconStateRemove();
1071 * Overloaded function to be called from the slot and from other places to set the state
1072 * of the check marks in the version table
1074 void restoreTree::versionTableItemChanged(QTableWidgetItem *item)
1076 /* get the previous and current check states */
1077 int row = versionTable->row(item);
1078 QTableWidgetItem *colZeroItem = versionTable->item(row, 0);
1079 Qt::CheckState prevState = m_versionCheckStateList[row];
1080 Qt::CheckState curState = (Qt::CheckState)colZeroItem->checkState();
1081 m_versionCheckStateList[row] = curState;
1083 /* deterimine the default state from the state of the file */
1084 QTableWidgetItem *fileTableItem = fileTable->currentItem();
1085 Qt::CheckState fileState = (Qt::CheckState)fileTableItem->checkState();
1087 /* determine the default state */
1088 Qt::CheckState defState;
1090 defState = Qt::PartiallyChecked;
1091 if (fileState == Qt::Unchecked)
1092 defState = Qt::Unchecked;
1095 defState = Qt::Unchecked;
1097 /* determine if it is already in the versionExceptionHash */
1098 QString directory = directoryTree->currentItem()->data(0, Qt::UserRole).toString();
1099 Qt::CheckState dirState = directoryTree->currentItem()->checkState(0);
1100 QString file = fileTableItem->text();
1101 QString fullPath = directory + file;
1102 int thisJobNum = colZeroItem->text().toInt();
1103 int hashJobNum = m_versionExceptionHash.value(fullPath, 0);
1105 if (mainWin->m_rtVerTabICDebug) {
1106 QString msg = QString("versrow=%1 prev=%2 cur=%3 def=%4 dir=%5 hashJobNum=%6 thisJobNum=%7 filestate=%8 fec=%9 vec=%10\n")
1107 .arg(row).arg(prevState).arg(curState).arg(defState).arg(dirState).arg(hashJobNum).arg(thisJobNum).arg(fileState)
1108 .arg(m_fileExceptionHash.count()).arg(m_versionExceptionHash.count());
1109 Pmsg1(000, "%s", msg.toUtf8().data()); }
1110 /* if changed from partially checked to checked, make it unchecked */
1111 if ((curState == Qt::Checked) && (row == 0) && (fileState == Qt::Unchecked)) {
1112 if (mainWin->m_rtVerTabICDebug) Pmsg0(000, "Setting to Qt::Checked\n");
1113 fileTableItem->setCheckState(Qt::Checked);
1114 } else if ((prevState == Qt::PartiallyChecked) && (curState == Qt::Checked) && (row == 0) && (fileState == Qt::Checked) && (dirState == Qt::Unchecked)) {
1115 //versrow=0 prev=1 cur=2 def=1 dir=0 hashJobNum=0 thisJobNum=64 filestate=2 fec=1 vec=0
1116 if (mainWin->m_rtVerTabICDebug) Pmsg1(000, "fileExceptionRemove %s, %i\n", fullPath.toUtf8().data());
1117 fileExceptionRemove(fullPath, directory);
1118 } else if ((curState == Qt::Checked) && (row == 0) && (hashJobNum != 0) && (dirState != Qt::Unchecked)) {
1119 //versrow=0 prev=0 cur=2 def=1 dir=2 hashJobNum=53 thisJobNum=64 filestate=2 fec=1 vec=1
1120 if (mainWin->m_rtVerTabICDebug) Pmsg1(000, "m_versionExceptionHash.remove %s\n", fullPath.toUtf8().data());
1121 m_versionExceptionHash.remove(fullPath);
1122 fileExceptionRemove(fullPath, directory);
1123 } else if ((curState == Qt::Checked) && (row == 0)) {
1124 if (mainWin->m_rtVerTabICDebug) Pmsg1(000, "m_versionExceptionHash.remove %s\n", fullPath.toUtf8().data());
1125 m_versionExceptionHash.remove(fullPath);
1126 } else if (prevState != curState) {
1127 if (mainWin->m_rtVerTabICDebug) Pmsg2(000, " THE STATE OF THE version Check has changed, Setting StateList[%i] to %i\n", row, curState);
1128 if ((curState == Qt::Checked) || (curState == Qt::PartiallyChecked && row != 0)) {
1129 if (mainWin->m_rtVerTabICDebug) Pmsg2(000, "Inserting into m_versionExceptionHash %s, %i\n", fullPath.toUtf8().data(), thisJobNum);
1130 m_versionExceptionHash.insert(fullPath, thisJobNum);
1131 if (fileState != Qt::Checked) {
1132 if (mainWin->m_rtVerTabICDebug) Pmsg2(000, "Inserting into m_fileExceptionHash %s, %i\n", fullPath.toUtf8().data(), curState);
1133 fileExceptionInsert(fullPath, directory, curState);
1136 if (mainWin->m_rtVerTabICDebug) Pmsg0(000, "got here\n");
1139 if (mainWin->m_rtVerTabICDebug) Pmsg0(000, "no conditions met\n");
1142 updateFileTableChecks();
1143 updateVersionTableChecks();
1147 * Simple function to set the check state in the file table by disconnecting the
1148 * signal/slot the setting then reconnecting the signal/slot
1150 void restoreTree::fileTableDisconnectedSet(QTableWidgetItem *item, Qt::CheckState state, bool color)
1152 disconnect(fileTable, SIGNAL(itemChanged(QTableWidgetItem *)),
1153 this, SLOT(fileTableItemChanged(QTableWidgetItem *)));
1154 item->setCheckState(state);
1155 if (color) item->setBackground(Qt::yellow);
1156 else item->setBackground(Qt::white);
1157 connect(fileTable, SIGNAL(itemChanged(QTableWidgetItem *)),
1158 this, SLOT(fileTableItemChanged(QTableWidgetItem *)));
1162 * Simple function to set the check state in the version table by disconnecting the
1163 * signal/slot the setting then reconnecting the signal/slot
1165 void restoreTree::versionTableDisconnectedSet(QTableWidgetItem *item, Qt::CheckState state)
1167 disconnect(versionTable, SIGNAL(itemChanged(QTableWidgetItem *)),
1168 this, SLOT(versionTableItemChanged(QTableWidgetItem *)));
1169 item->setCheckState(state);
1170 connect(versionTable, SIGNAL(itemChanged(QTableWidgetItem *)),
1171 this, SLOT(versionTableItemChanged(QTableWidgetItem *)));
1175 * Simple function to set the check state in the directory tree by disconnecting the
1176 * signal/slot the setting then reconnecting the signal/slot
1178 void restoreTree::directoryTreeDisconnectedSet(QTreeWidgetItem *item, Qt::CheckState state)
1180 disconnect(directoryTree, SIGNAL(itemChanged(QTreeWidgetItem *, int)),
1181 this, SLOT(directoryItemChanged(QTreeWidgetItem *, int)));
1182 item->setCheckState(0, state);
1183 connect(directoryTree, SIGNAL(itemChanged(QTreeWidgetItem *, int)),
1184 this, SLOT(directoryItemChanged(QTreeWidgetItem *, int)));
1188 * Simplify the updating of the check state in the File table by iterating through
1189 * each item in the file table to determine it's appropriate state.
1190 * !! Will probably want to concoct a way to do this without iterating for the possibility
1191 * of the very large directories.
1193 void restoreTree::updateFileTableChecks()
1195 /* deterimine the default state from the state of the directory */
1196 QTreeWidgetItem *dirTreeItem = directoryTree->currentItem();
1197 Qt::CheckState dirState = dirTreeItem->checkState(0);
1199 QString dirName = dirTreeItem->data(0, Qt::UserRole).toString();
1201 /* Update the items in the version table */
1202 int rcnt = fileTable->rowCount();
1203 for (int row=0; row<rcnt; row++) {
1204 QTableWidgetItem* item = fileTable->item(row, 0);
1205 if (!item) { return; }
1207 Qt::CheckState curState = item->checkState();
1208 Qt::CheckState newState = Qt::PartiallyChecked;
1209 if (dirState == Qt::Unchecked) newState = Qt::Unchecked;
1211 /* determine if it is already in the m_fileExceptionHash */
1212 QString file = item->text();
1213 QString fullPath = dirName + file;
1214 Qt::CheckState hashState = m_fileExceptionHash.value(fullPath, (Qt::CheckState)3);
1215 int hashJobNum = m_versionExceptionHash.value(fullPath, 0);
1217 if (hashState != 3) newState = hashState;
1219 if (mainWin->m_rtUpdateFTDebug) {
1220 QString msg = QString("file row=%1 cur=%2 hash=%3 new=%4 dirState=%5\n")
1221 .arg(row).arg(curState).arg(hashState).arg(newState).arg(dirState);
1222 Pmsg1(000, "%s", msg.toUtf8().data());
1225 bool docolor = false;
1226 if (hashJobNum != 0) docolor = true;
1227 bool isyellow = item->background().color() == QColor(Qt::yellow);
1228 if ((newState != curState) || (hashState == 3) || ((isyellow && !docolor) || (!isyellow && docolor)))
1229 fileTableDisconnectedSet(item, newState, docolor);
1230 m_fileCheckStateList[row] = newState;
1235 * Simplify the updating of the check state in the Version table by iterating through
1236 * each item in the file table to determine it's appropriate state.
1238 void restoreTree::updateVersionTableChecks()
1240 /* deterimine the default state from the state of the directory */
1241 QTreeWidgetItem *dirTreeItem = directoryTree->currentItem();
1242 Qt::CheckState dirState = dirTreeItem->checkState(0);
1243 QString dirName = dirTreeItem->data(0, Qt::UserRole).toString();
1245 /* deterimine the default state from the state of the file */
1246 QTableWidgetItem *fileTableItem = fileTable->item(fileTable->currentRow(), 0);
1247 if (!fileTableItem) { return; }
1248 Qt::CheckState fileState = fileTableItem->checkState();
1249 QString file = fileTableItem->text();
1250 QString fullPath = dirName + file;
1251 int hashJobNum = m_versionExceptionHash.value(fullPath, 0);
1253 /* Update the items in the version table */
1254 int cnt = versionTable->rowCount();
1255 for (int row=0; row<cnt; row++) {
1256 QTableWidgetItem* item = versionTable->item(row, 0);
1257 if (!item) { break; }
1259 Qt::CheckState curState = item->checkState();
1260 Qt::CheckState newState = Qt::Unchecked;
1262 if ((row == 0) && (fileState != Qt::Unchecked) && (hashJobNum == 0))
1263 newState = Qt::PartiallyChecked;
1264 /* determine if it is already in the versionExceptionHash */
1266 int thisJobNum = item->text().toInt();
1267 if (thisJobNum == hashJobNum)
1268 newState = Qt::Checked;
1270 if (mainWin->m_rtChecksDebug) {
1271 QString msg = QString("ver row=%1 cur=%2 hashJobNum=%3 new=%4 dirState=%5\n")
1272 .arg(row).arg(curState).arg(hashJobNum).arg(newState).arg(dirState);
1273 Pmsg1(000, "%s", msg.toUtf8().data());
1275 if (newState != curState)
1276 versionTableDisconnectedSet(item, newState);
1277 m_versionCheckStateList[row] = newState;
1282 * Quick subroutine to "return via subPaths" a list of subpaths when passed a fullPath
1284 void restoreTree::fullPathtoSubPaths(QStringList &subPaths, QString &fullPath_in)
1288 QString fullPath = fullPath_in;
1289 QString direct, path;
1290 while (((index = fullPath.lastIndexOf("/", -2)) != -1) && (!done)) {
1291 direct = path = fullPath;
1292 path.replace(index+1, fullPath.length()-index-1, "");
1293 direct.replace(0, index+1, "");
1295 QString msg = QString("length = \"%1\" index = \"%2\" Considering \"%3\" \"%4\"\n")
1296 .arg(fullPath.length()).arg(index).arg(path).arg(direct);
1297 Pmsg0(000, msg.toUtf8().data());
1300 subPaths.append(fullPath);
1305 * A Function to set the icon state and insert a record into
1306 * m_directoryIconStateHash when an exception is added by the user
1308 void restoreTree::directoryIconStateInsert(QString &fullPath, Qt::CheckState excpState)
1311 fullPathtoSubPaths(paths, fullPath);
1312 /* an exception that causes the item in the file table to be "Checked" has occured */
1313 if (excpState == Qt::Checked) {
1314 bool foundAsUnChecked = false;
1315 QTreeWidgetItem *firstItem = m_dirPaths.value(paths[0]);
1317 if (firstItem->checkState(0) == Qt::Unchecked)
1318 foundAsUnChecked = true;
1320 if (foundAsUnChecked) {
1321 /* as long as directory item is Unchecked, set icon state to "green check" */
1323 QListIterator<QString> siter(paths);
1324 while (siter.hasNext() && !done) {
1325 QString path = siter.next();
1326 QTreeWidgetItem *item = m_dirPaths.value(path);
1328 if (item->checkState(0) != Qt::Unchecked)
1331 directorySetIcon(1, FolderGreenChecked, path, item);
1332 if (mainWin->m_rtIconStateDebug) Pmsg1(000, "In restoreTree::directoryIconStateInsert inserting %s\n", path.toUtf8().data());
1337 /* if it is partially checked or fully checked insert green Check until a unchecked is found in the path */
1338 if (mainWin->m_rtIconStateDebug) Pmsg1(000, "In restoreTree::directoryIconStateInsert Aqua %s\n", paths[0].toUtf8().data());
1340 QListIterator<QString> siter(paths);
1341 while (siter.hasNext() && !done) {
1342 QString path = siter.next();
1343 QTreeWidgetItem *item = m_dirPaths.value(path);
1344 if (item) { /* if the directory item is checked, set icon state to unchecked "green check" */
1345 if (item->checkState(0) == Qt::Checked)
1347 directorySetIcon(1, FolderGreenChecked, path, item);
1348 if (mainWin->m_rtIconStateDebug) Pmsg1(000, "In restoreTree::directoryIconStateInsert boogie %s\n", path.toUtf8().data());
1353 /* an exception that causes the item in the file table to be "Unchecked" has occured */
1354 if (excpState == Qt::Unchecked) {
1356 QListIterator<QString> siter(paths);
1357 while (siter.hasNext() && !done) {
1358 QString path = siter.next();
1359 QTreeWidgetItem *item = m_dirPaths.value(path);
1360 if (item) { /* if the directory item is checked, set icon state to unchecked "white check" */
1361 if (item->checkState(0) == Qt::Checked)
1363 directorySetIcon(1, FolderWhiteChecked, path, item);
1364 if (mainWin->m_rtIconStateDebug) Pmsg1(000, "In restoreTree::directoryIconStateInsert boogie %s\n", path.toUtf8().data());
1371 * A function to set the icon state back to "folder" and to remove a record from
1372 * m_directoryIconStateHash when an exception is removed by a user.
1374 void restoreTree::directoryIconStateRemove()
1376 QHash<QString, int> shouldBeIconStateHash;
1377 /* First determine all paths with icons that should be checked with m_fileExceptionHash */
1378 /* Use iterator tera to iterate through m_fileExceptionHash */
1379 QHashIterator<QString, Qt::CheckState> tera(m_fileExceptionHash);
1380 while (tera.hasNext()) {
1382 if (mainWin->m_rtIconStateDebug) Pmsg2(000, "Alpha Key %s value %i\n", tera.key().toUtf8().data(), tera.value());
1384 QString keyPath = tera.key();
1385 Qt::CheckState state = tera.value();
1388 fullPathtoSubPaths(paths, keyPath);
1389 /* if the state of the item in m_fileExceptionHash is checked
1390 * each of the subpaths should be "Checked Green" */
1391 if (state == Qt::Checked) {
1393 bool foundAsUnChecked = false;
1394 QTreeWidgetItem *firstItem = m_dirPaths.value(paths[0]);
1396 if (firstItem->checkState(0) == Qt::Unchecked)
1397 foundAsUnChecked = true;
1399 if (foundAsUnChecked) {
1400 /* The right most directory is Unchecked, iterate leftwards
1401 * as long as directory item is Unchecked, set icon state to "green check" */
1403 QListIterator<QString> siter(paths);
1404 while (siter.hasNext() && !done) {
1405 QString path = siter.next();
1406 QTreeWidgetItem *item = m_dirPaths.value(path);
1408 if (item->checkState(0) != Qt::Unchecked)
1411 shouldBeIconStateHash.insert(path, FolderGreenChecked);
1412 if (mainWin->m_rtIconStateDebug) Pmsg1(000, "In restoreTree::directoryIconStateInsert inserting %s\n", path.toUtf8().data());
1418 /* The right most directory is Unchecked, iterate leftwards
1419 * until directory item is Checked, set icon state to "green check" */
1421 QListIterator<QString> siter(paths);
1422 while (siter.hasNext() && !done) {
1423 QString path = siter.next();
1424 QTreeWidgetItem *item = m_dirPaths.value(path);
1426 if (item->checkState(0) == Qt::Checked)
1428 shouldBeIconStateHash.insert(path, FolderGreenChecked);
1433 /* if the state of the item in m_fileExceptionHash is UNChecked
1434 * each of the subpaths should be "Checked white" until the tree item
1435 * which represents that path is Qt::Checked */
1436 if (state == Qt::Unchecked) {
1438 QListIterator<QString> siter(paths);
1439 while (siter.hasNext() && !done) {
1440 QString path = siter.next();
1441 QTreeWidgetItem *item = m_dirPaths.value(path);
1443 if (item->checkState(0) == Qt::Checked)
1445 shouldBeIconStateHash.insert(path, FolderWhiteChecked);
1450 /* now iterate through m_directoryIconStateHash which are the items that are checked
1451 * and remove all of those that are not in shouldBeIconStateHash */
1452 QHashIterator<QString, int> iter(m_directoryIconStateHash);
1453 while (iter.hasNext()) {
1455 if (mainWin->m_rtIconStateDebug) Pmsg2(000, "Beta Key %s value %i\n", iter.key().toUtf8().data(), iter.value());
1457 QString keyPath = iter.key();
1458 if (shouldBeIconStateHash.value(keyPath)) {
1459 if (mainWin->m_rtIconStateDebug) Pmsg1(000, "WAS found in shouldBeStateHash %s\n", keyPath.toUtf8().data());
1460 //newval = m_directoryIconStateHash.value(path, FolderUnchecked) & (~change);
1461 int newval = shouldBeIconStateHash.value(keyPath);
1463 newval = newval & FolderBothChecked;
1464 QTreeWidgetItem *item = m_dirPaths.value(keyPath);
1466 directorySetIcon(0, newval, keyPath, item);
1468 if (mainWin->m_rtIconStateDebug) Pmsg1(000, "NOT found in shouldBeStateHash %s\n", keyPath.toUtf8().data());
1469 QTreeWidgetItem *item = m_dirPaths.value(keyPath);
1471 directorySetIcon(0, FolderBothChecked, keyPath, item);
1472 //item->setIcon(0,QIcon(QString::fromUtf8(":images/folder.png")));
1473 //m_directoryIconStateHash.remove(keyPath);
1478 void restoreTree::directorySetIcon(int operation, int change, QString &path, QTreeWidgetItem* item) {
1480 /* we are adding a check type white or green */
1481 if (operation > 0) {
1482 /* get the old val and "bitwise OR" with the change */
1483 newval = m_directoryIconStateHash.value(path, FolderUnchecked) | change;
1484 if (mainWin->m_rtIconStateDebug) Pmsg2(000, "Inserting into m_directoryIconStateHash path=%s newval=%i\n", path.toUtf8().data(), newval);
1485 m_directoryIconStateHash.insert(path, newval);
1487 /* we are removing a check type white or green */
1488 newval = m_directoryIconStateHash.value(path, FolderUnchecked) & (~change);
1490 if (mainWin->m_rtIconStateDebug) Pmsg2(000, "Removing from m_directoryIconStateHash path=%s newval=%i\n", path.toUtf8().data(), newval);
1491 m_directoryIconStateHash.remove(path);
1494 if (mainWin->m_rtIconStateDebug) Pmsg2(000, "Inserting into m_directoryIconStateHash path=%s newval=%i\n", path.toUtf8().data(), newval);
1495 m_directoryIconStateHash.insert(path, newval);
1498 if (newval == FolderUnchecked)
1499 item->setIcon(0, QIcon(QString::fromUtf8(":images/folder.png")));
1500 else if (newval == FolderGreenChecked)
1501 item->setIcon(0, QIcon(QString::fromUtf8(":images/folderchecked.png")));
1502 else if (newval == FolderWhiteChecked)
1503 item->setIcon(0, QIcon(QString::fromUtf8(":images/folderunchecked.png")));
1504 else if (newval == FolderBothChecked)
1505 item->setIcon(0, QIcon(QString::fromUtf8(":images/folderbothchecked.png")));
1511 void restoreTree::restoreButtonPushed()
1513 /* Set progress bars and repaint */
1514 prLabel1->setVisible(true);
1515 prLabel1->setText(tr("Task 1 of 3"));
1516 prLabel2->setVisible(true);
1517 prLabel2->setText(tr("Processing Checked directories"));
1518 prBar1->setVisible(true);
1519 prBar1->setRange(0, 3);
1520 prBar1->setValue(0);
1521 prBar2->setVisible(true);
1522 prBar2->setRange(0, 0);
1524 QMultiHash<int, QString> versionFilesMulti;
1526 QHash <QString, bool> fullPathDone;
1527 QHash <QString, int> fileIndexHash;
1528 if ((mainWin->m_rtRestore1Debug) || (mainWin->m_rtRestore2Debug) || (mainWin->m_rtRestore3Debug))
1529 Pmsg0(000, "In restoreTree::restoreButtonPushed\n");
1530 /* Use a tree widget item iterator to count directories for the progress bar */
1531 QTreeWidgetItemIterator diterc(directoryTree, QTreeWidgetItemIterator::Checked);
1536 } /* while (*diterc) */
1537 prBar2->setRange(0, ditcount);
1538 prBar2->setValue(0);
1540 /* Use a tree widget item iterator filtering for Checked Items */
1541 QTreeWidgetItemIterator diter(directoryTree, QTreeWidgetItemIterator::Checked);
1543 QString directory = (*diter)->data(0, Qt::UserRole).toString();
1544 int pathid = m_directoryPathIdHash.value(directory, -1);
1546 if (mainWin->m_rtRestore1Debug)
1547 Pmsg1(000, "Directory Checked=\"%s\"\n", directory.toUtf8().data());
1548 /* With a checked directory, query for the files in the directory */
1551 "SELECT Filename.Name AS Filename, t1.JobId AS JobId, File.FileIndex AS FileIndex"
1553 " ( SELECT File.FilenameId AS FilenameId, MAX(Job.JobId) AS JobId"
1555 " INNER JOIN Job ON (Job.JobId=File.JobId)"
1556 " WHERE File.PathId=" + QString("%1").arg(pathid) +
1557 " AND Job.Jobid IN (" + m_checkedJobs + ")"
1558 " AND File.FilenameId!=" + QString("%1").arg(m_nullFileNameId) +
1559 " GROUP BY File.FilenameId"
1561 " INNER JOIN Filename on (Filename.FilenameId=File.FilenameId)"
1562 " INNER JOIN Job ON (Job.JobId=File.JobId)"
1563 " WHERE File.PathId=" + QString("%1").arg(pathid) +
1564 " AND File.FilenameId=t1.FilenameId"
1565 " AND Job.Jobid=t1.JobId"
1566 " ORDER BY Filename";
1568 if (mainWin->m_sqlDebug) Pmsg1(000, "Query cmd : %s\n", cmd.toUtf8().data());
1569 QStringList results;
1570 if (m_console->sql_cmd(cmd, results)) {
1571 QStringList fieldlist;
1574 /* Iterate through the record returned from the query */
1575 foreach (QString resultline, results) {
1576 /* Iterate through fields in the record */
1578 QString fullPath = "";
1579 Qt::CheckState fileExcpState = (Qt::CheckState)4;
1580 fieldlist = resultline.split("\t");
1583 foreach (QString field, fieldlist) {
1585 fullPath = directory + field;
1588 version = field.toInt();
1591 fileIndex = field.toInt();
1595 fileExcpState = m_fileExceptionHash.value(fullPath, (Qt::CheckState)3);
1597 int excpVersion = m_versionExceptionHash.value(fullPath, 0);
1598 if (fileExcpState != Qt::Unchecked) {
1600 if (excpVersion != 0) {
1601 debugtext = QString("*E* version=%1").arg(excpVersion);
1602 version = excpVersion;
1603 fileIndex = queryFileIndex(fullPath, excpVersion);
1605 debugtext = QString("___ version=%1").arg(version);
1606 if (mainWin->m_rtRestore1Debug)
1607 Pmsg2(000, "Restoring %s File %s\n", debugtext.toUtf8().data(), fullPath.toUtf8().data());
1608 fullPathDone.insert(fullPath, 1);
1609 fileIndexHash.insert(fullPath, fileIndex);
1610 versionFilesMulti.insert(version, fullPath);
1618 prBar2->setValue(ditcount);
1620 } /* while (*diter) */
1621 prBar1->setValue(1);
1622 prLabel1->setText( tr("Task 2 of 3"));
1623 prLabel2->setText(tr("Processing Exceptions"));
1624 prBar2->setRange(0, 0);
1627 /* There may be some exceptions not accounted for yet with fullPathDone */
1628 QHashIterator<QString, Qt::CheckState> ftera(m_fileExceptionHash);
1629 while (ftera.hasNext()) {
1631 QString fullPath = ftera.key();
1632 Qt::CheckState state = ftera.value();
1634 /* now we don't want the ones already done */
1635 if (fullPathDone.value(fullPath, 0) == 0) {
1636 int version = m_versionExceptionHash.value(fullPath, 0);
1638 QString debugtext = "";
1640 fileIndex = queryFileIndex(fullPath, version);
1641 debugtext = QString("E1* version=%1 fileid=%2").arg(version).arg(fileIndex);
1643 version = mostRecentVersionfromFullPath(fullPath);
1645 fileIndex = queryFileIndex(fullPath, version);
1646 debugtext = QString("E2* version=%1 fileid=%2").arg(version).arg(fileIndex);
1648 debugtext = QString("Error det vers").arg(version);
1650 if (mainWin->m_rtRestore1Debug)
1651 Pmsg2(000, "Restoring %s file %s\n", debugtext.toUtf8().data(), fullPath.toUtf8().data());
1652 versionFilesMulti.insert(version, fullPath);
1654 fileIndexHash.insert(fullPath, fileIndex);
1655 } /* if fullPathDone.value(fullPath, 0) == 0 */
1656 } /* if state != 0 */
1657 } /* while ftera.hasNext */
1658 /* The progress bars for the next step */
1659 prBar1->setValue(2);
1660 prLabel1->setText(tr("Task 3 of 3"));
1661 prLabel2->setText(tr("Filling Database Table"));
1662 prBar2->setRange(0, vFMCounter);
1664 prBar2->setValue(vFMCounter);
1667 /* now for the final spit out of the versions and lists of files for each version */
1668 QHash<int, int> doneKeys;
1669 QHashIterator<int, QString> vFMiter(versionFilesMulti);
1670 QString tempTable = "";
1672 while (vFMiter.hasNext()) {
1674 int fversion = vFMiter.key();
1675 /* did not succeed in getting an iterator to work as expected on versionFilesMulti so use doneKeys */
1676 if (doneKeys.value(fversion, 0) == 0) {
1677 if (tempTable == "") {
1678 QSettings settings("www.bacula.org", "bat");
1679 settings.beginGroup("Restore");
1680 int counter = settings.value("Counter", 1).toInt();
1681 settings.setValue("Counter", counter+1);
1682 settings.endGroup();
1683 tempTable = "restore_" + QString("%1").arg(qrand()) + "_" + QString("%1").arg(counter);
1684 QString sqlcmd = "CREATE TEMPORARY TABLE " + tempTable + " (JobId INTEGER, FileIndex INTEGER)";
1685 if (mainWin->m_sqlDebug)
1686 Pmsg1(000, "Query cmd : %s ;\n", sqlcmd.toUtf8().data());
1687 QStringList results;
1688 if (!m_console->sql_cmd(sqlcmd, results))
1689 Pmsg1(000, "CREATE TABLE FAILED!!!! %s\n", sqlcmd.toUtf8().data());
1692 if (mainWin->m_rtRestore2Debug) Pmsg1(000, "Version->%i\n", fversion);
1693 QStringList fullPathList = versionFilesMulti.values(fversion);
1694 /* create the command to perform the restore */
1695 foreach(QString ffullPath, fullPathList) {
1696 int fileIndex = fileIndexHash.value(ffullPath);
1697 if (mainWin->m_rtRestore2Debug) Pmsg2(000, " file->%s id %i\n", ffullPath.toUtf8().data(), fileIndex);
1698 QString sqlcmd = "INSERT INTO " + tempTable + " (JobId, FileIndex) VALUES (" + QString("%1").arg(fversion) + ", " + QString("%1").arg(fileIndex) + ")";
1699 if (mainWin->m_rtRestore3Debug)
1700 Pmsg1(000, "Insert cmd : %s\n", sqlcmd.toUtf8().data());
1701 QStringList results;
1702 if (!m_console->sql_cmd(sqlcmd, results))
1703 Pmsg1(000, "INSERT INTO FAILED!!!! %s\n", sqlcmd.toUtf8().data());
1704 prBar2->setValue(++vFMCounter);
1705 } /* foreach fullPathList */
1706 doneKeys.insert(fversion,1);
1707 jobList.append(fversion);
1708 } /* if (doneKeys.value(fversion, 0) == 0) */
1709 } /* while (vFMiter.hasNext()) */
1710 if (tempTable != "") {
1711 /* a table was made, lets run the job */
1712 QString jobOption = " jobid=\"";
1714 /* create a list of jobs comma separated */
1715 foreach (int job, jobList) {
1716 if (first) first = false;
1717 else jobOption += ",";
1718 jobOption += QString("%1").arg(job);
1721 QString cmd = QString("restore");
1723 " client=\"" + m_prevClientCombo + "\"" +
1724 " file=\"?" + tempTable + "\" done";
1725 if (mainWin->m_commandDebug)
1726 Pmsg1(000, "preRestore command \'%s\'\n", cmd.toUtf8().data());
1727 consoleCommand(cmd);
1729 /* turn off the progress widgets */
1730 prBar1->setVisible(false);
1731 prBar2->setVisible(false);
1732 prLabel1->setVisible(false);
1733 prLabel2->setVisible(false);
1736 int restoreTree::mostRecentVersionfromFullPath(QString &fullPath)
1739 QString directory, fileName;
1740 int index = fullPath.lastIndexOf("/", -2);
1742 directory = fileName = fullPath;
1743 directory.replace(index+1, fullPath.length()-index-1, "");
1744 fileName.replace(0, index+1, "");
1746 QString msg = QString("length = \"%1\" index = \"%2\" Considering \"%3\" \"%4\"\n")
1747 .arg(fullPath.length()).arg(index).arg(fileName).arg(directory);
1748 Pmsg0(000, msg.toUtf8().data());
1750 int pathid = m_directoryPathIdHash.value(directory, -1);
1752 /* so now we need the latest version from the database */
1754 "SELECT MAX(Job.JobId)"
1756 " INNER JOIN Filename on (Filename.FilenameId=File.FilenameId)"
1757 " INNER JOIN Job ON (File.JobId=Job.JobId)"
1758 " WHERE File.PathId=" + QString("%1").arg(pathid) +
1759 " AND Job.Jobid IN (" + m_checkedJobs + ")"
1760 " AND Filename.Name='" + fileName + "'"
1761 " AND File.FilenameId!=" + QString("%1").arg(m_nullFileNameId) +
1762 " GROUP BY Filename.Name";
1764 if (mainWin->m_sqlDebug) Pmsg1(000, "Query cmd : %s\n", cmd.toUtf8().data());
1765 QStringList results;
1766 if (m_console->sql_cmd(cmd, results)) {
1767 QStringList fieldlist;
1769 /* Iterate through the record returned from the query */
1770 foreach (QString resultline, results) {
1771 /* Iterate through fields in the record */
1773 fieldlist = resultline.split("\t");
1774 foreach (QString field, fieldlist) {
1776 qversion = field.toInt();
1784 } /* if (index != -1) */
1789 int restoreTree::queryFileIndex(QString &fullPath, int jobId)
1792 QString directory, fileName;
1793 int index = fullPath.lastIndexOf("/", -2);
1795 directory = fileName = fullPath;
1796 directory.replace(index+1, fullPath.length()-index-1, "");
1797 fileName.replace(0, index+1, "");
1799 QString msg = QString("length = \"%1\" index = \"%2\" Considering \"%3\" \"%4\"\n")
1800 .arg(fullPath.length()).arg(index).arg(fileName).arg(directory);
1801 Pmsg0(000, msg.toUtf8().data());
1803 int pathid = m_directoryPathIdHash.value(directory, -1);
1805 /* so now we need the latest version from the database */
1810 " INNER JOIN Filename on (Filename.FilenameId=File.FilenameId)"
1811 " INNER JOIN Job ON (File.JobId=Job.JobId)"
1812 " WHERE File.PathId=" + QString("%1").arg(pathid) +
1813 " AND Filename.Name='" + fileName + "'"
1814 " AND Job.Jobid='" + QString("%1").arg(jobId) + "'"
1815 " GROUP BY File.FileIndex";
1817 if (mainWin->m_sqlDebug) Pmsg1(000, "Query cmd : %s\n", cmd.toUtf8().data());
1818 QStringList results;
1819 if (m_console->sql_cmd(cmd, results)) {
1820 QStringList fieldlist;
1822 /* Iterate through the record returned from the query */
1823 foreach (QString resultline, results) {
1824 /* Iterate through fields in the record */
1826 fieldlist = resultline.split("\t");
1827 foreach (QString field, fieldlist) {
1829 qfileIndex = field.toInt();
1837 } /* if (index != -1) */