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);
1206 Qt::CheckState curState = item->checkState();
1207 Qt::CheckState newState = Qt::PartiallyChecked;
1208 if (dirState == Qt::Unchecked) newState = Qt::Unchecked;
1210 /* determine if it is already in the m_fileExceptionHash */
1211 QString file = item->text();
1212 QString fullPath = dirName + file;
1213 Qt::CheckState hashState = m_fileExceptionHash.value(fullPath, (Qt::CheckState)3);
1214 int hashJobNum = m_versionExceptionHash.value(fullPath, 0);
1216 if (hashState != 3) newState = hashState;
1218 if (mainWin->m_rtUpdateFTDebug) {
1219 QString msg = QString("file row=%1 cur=%2 hash=%3 new=%4 dirState=%5\n")
1220 .arg(row).arg(curState).arg(hashState).arg(newState).arg(dirState);
1221 Pmsg1(000, "%s", msg.toUtf8().data());
1224 bool docolor = false;
1225 if (hashJobNum != 0) docolor = true;
1226 bool isyellow = item->background().color() == QColor(Qt::yellow);
1227 if ((newState != curState) || (hashState == 3) || ((isyellow && !docolor) || (!isyellow && docolor)))
1228 fileTableDisconnectedSet(item, newState, docolor);
1229 m_fileCheckStateList[row] = newState;
1234 * Simplify the updating of the check state in the Version table by iterating through
1235 * each item in the file table to determine it's appropriate state.
1237 void restoreTree::updateVersionTableChecks()
1239 /* deterimine the default state from the state of the directory */
1240 QTreeWidgetItem *dirTreeItem = directoryTree->currentItem();
1241 Qt::CheckState dirState = dirTreeItem->checkState(0);
1242 QString dirName = dirTreeItem->data(0, Qt::UserRole).toString();
1244 /* deterimine the default state from the state of the file */
1245 QTableWidgetItem *fileTableItem = fileTable->item(fileTable->currentRow(), 0);
1246 Qt::CheckState fileState = fileTableItem->checkState();
1247 QString file = fileTableItem->text();
1248 QString fullPath = dirName + file;
1249 int hashJobNum = m_versionExceptionHash.value(fullPath, 0);
1251 /* Update the items in the version table */
1252 int cnt = versionTable->rowCount();
1253 for (int row=0; row<cnt; row++) {
1254 QTableWidgetItem* item = versionTable->item(row, 0);
1256 Qt::CheckState curState = item->checkState();
1257 Qt::CheckState newState = Qt::Unchecked;
1259 if ((row == 0) && (fileState != Qt::Unchecked) && (hashJobNum == 0))
1260 newState = Qt::PartiallyChecked;
1261 /* determine if it is already in the versionExceptionHash */
1263 int thisJobNum = item->text().toInt();
1264 if (thisJobNum == hashJobNum)
1265 newState = Qt::Checked;
1267 if (mainWin->m_rtChecksDebug) {
1268 QString msg = QString("ver row=%1 cur=%2 hashJobNum=%3 new=%4 dirState=%5\n")
1269 .arg(row).arg(curState).arg(hashJobNum).arg(newState).arg(dirState);
1270 Pmsg1(000, "%s", msg.toUtf8().data());
1272 if (newState != curState)
1273 versionTableDisconnectedSet(item, newState);
1274 m_versionCheckStateList[row] = newState;
1279 * Quick subroutine to "return via subPaths" a list of subpaths when passed a fullPath
1281 void restoreTree::fullPathtoSubPaths(QStringList &subPaths, QString &fullPath_in)
1285 QString fullPath = fullPath_in;
1286 QString direct, path;
1287 while (((index = fullPath.lastIndexOf("/", -2)) != -1) && (!done)) {
1288 direct = path = fullPath;
1289 path.replace(index+1, fullPath.length()-index-1, "");
1290 direct.replace(0, index+1, "");
1292 QString msg = QString("length = \"%1\" index = \"%2\" Considering \"%3\" \"%4\"\n")
1293 .arg(fullPath.length()).arg(index).arg(path).arg(direct);
1294 Pmsg0(000, msg.toUtf8().data());
1297 subPaths.append(fullPath);
1302 * A Function to set the icon state and insert a record into
1303 * m_directoryIconStateHash when an exception is added by the user
1305 void restoreTree::directoryIconStateInsert(QString &fullPath, Qt::CheckState excpState)
1308 fullPathtoSubPaths(paths, fullPath);
1309 /* an exception that causes the item in the file table to be "Checked" has occured */
1310 if (excpState == Qt::Checked) {
1311 bool foundAsUnChecked = false;
1312 QTreeWidgetItem *firstItem = m_dirPaths.value(paths[0]);
1314 if (firstItem->checkState(0) == Qt::Unchecked)
1315 foundAsUnChecked = true;
1317 if (foundAsUnChecked) {
1318 /* as long as directory item is Unchecked, set icon state to "green check" */
1320 QListIterator<QString> siter(paths);
1321 while (siter.hasNext() && !done) {
1322 QString path = siter.next();
1323 QTreeWidgetItem *item = m_dirPaths.value(path);
1325 if (item->checkState(0) != Qt::Unchecked)
1328 directorySetIcon(1, FolderGreenChecked, path, item);
1329 if (mainWin->m_rtIconStateDebug) Pmsg1(000, "In restoreTree::directoryIconStateInsert inserting %s\n", path.toUtf8().data());
1334 /* if it is partially checked or fully checked insert green Check until a unchecked is found in the path */
1335 if (mainWin->m_rtIconStateDebug) Pmsg1(000, "In restoreTree::directoryIconStateInsert Aqua %s\n", paths[0].toUtf8().data());
1337 QListIterator<QString> siter(paths);
1338 while (siter.hasNext() && !done) {
1339 QString path = siter.next();
1340 QTreeWidgetItem *item = m_dirPaths.value(path);
1341 if (item) { /* if the directory item is checked, set icon state to unchecked "green check" */
1342 if (item->checkState(0) == Qt::Checked)
1344 directorySetIcon(1, FolderGreenChecked, path, item);
1345 if (mainWin->m_rtIconStateDebug) Pmsg1(000, "In restoreTree::directoryIconStateInsert boogie %s\n", path.toUtf8().data());
1350 /* an exception that causes the item in the file table to be "Unchecked" has occured */
1351 if (excpState == Qt::Unchecked) {
1353 QListIterator<QString> siter(paths);
1354 while (siter.hasNext() && !done) {
1355 QString path = siter.next();
1356 QTreeWidgetItem *item = m_dirPaths.value(path);
1357 if (item) { /* if the directory item is checked, set icon state to unchecked "white check" */
1358 if (item->checkState(0) == Qt::Checked)
1360 directorySetIcon(1, FolderWhiteChecked, path, item);
1361 if (mainWin->m_rtIconStateDebug) Pmsg1(000, "In restoreTree::directoryIconStateInsert boogie %s\n", path.toUtf8().data());
1368 * A function to set the icon state back to "folder" and to remove a record from
1369 * m_directoryIconStateHash when an exception is removed by a user.
1371 void restoreTree::directoryIconStateRemove()
1373 QHash<QString, int> shouldBeIconStateHash;
1374 /* First determine all paths with icons that should be checked with m_fileExceptionHash */
1375 /* Use iterator tera to iterate through m_fileExceptionHash */
1376 QHashIterator<QString, Qt::CheckState> tera(m_fileExceptionHash);
1377 while (tera.hasNext()) {
1379 if (mainWin->m_rtIconStateDebug) Pmsg2(000, "Alpha Key %s value %i\n", tera.key().toUtf8().data(), tera.value());
1381 QString keyPath = tera.key();
1382 Qt::CheckState state = tera.value();
1385 fullPathtoSubPaths(paths, keyPath);
1386 /* if the state of the item in m_fileExceptionHash is checked
1387 * each of the subpaths should be "Checked Green" */
1388 if (state == Qt::Checked) {
1390 bool foundAsUnChecked = false;
1391 QTreeWidgetItem *firstItem = m_dirPaths.value(paths[0]);
1393 if (firstItem->checkState(0) == Qt::Unchecked)
1394 foundAsUnChecked = true;
1396 if (foundAsUnChecked) {
1397 /* The right most directory is Unchecked, iterate leftwards
1398 * as long as directory item is Unchecked, set icon state to "green check" */
1400 QListIterator<QString> siter(paths);
1401 while (siter.hasNext() && !done) {
1402 QString path = siter.next();
1403 QTreeWidgetItem *item = m_dirPaths.value(path);
1405 if (item->checkState(0) != Qt::Unchecked)
1408 shouldBeIconStateHash.insert(path, FolderGreenChecked);
1409 if (mainWin->m_rtIconStateDebug) Pmsg1(000, "In restoreTree::directoryIconStateInsert inserting %s\n", path.toUtf8().data());
1415 /* The right most directory is Unchecked, iterate leftwards
1416 * until directory item is Checked, set icon state to "green check" */
1418 QListIterator<QString> siter(paths);
1419 while (siter.hasNext() && !done) {
1420 QString path = siter.next();
1421 QTreeWidgetItem *item = m_dirPaths.value(path);
1423 if (item->checkState(0) == Qt::Checked)
1425 shouldBeIconStateHash.insert(path, FolderGreenChecked);
1430 /* if the state of the item in m_fileExceptionHash is UNChecked
1431 * each of the subpaths should be "Checked white" until the tree item
1432 * which represents that path is Qt::Checked */
1433 if (state == Qt::Unchecked) {
1435 QListIterator<QString> siter(paths);
1436 while (siter.hasNext() && !done) {
1437 QString path = siter.next();
1438 QTreeWidgetItem *item = m_dirPaths.value(path);
1440 if (item->checkState(0) == Qt::Checked)
1442 shouldBeIconStateHash.insert(path, FolderWhiteChecked);
1447 /* now iterate through m_directoryIconStateHash which are the items that are checked
1448 * and remove all of those that are not in shouldBeIconStateHash */
1449 QHashIterator<QString, int> iter(m_directoryIconStateHash);
1450 while (iter.hasNext()) {
1452 if (mainWin->m_rtIconStateDebug) Pmsg2(000, "Beta Key %s value %i\n", iter.key().toUtf8().data(), iter.value());
1454 QString keyPath = iter.key();
1455 if (shouldBeIconStateHash.value(keyPath)) {
1456 if (mainWin->m_rtIconStateDebug) Pmsg1(000, "WAS found in shouldBeStateHash %s\n", keyPath.toUtf8().data());
1457 //newval = m_directoryIconStateHash.value(path, FolderUnchecked) & (~change);
1458 int newval = shouldBeIconStateHash.value(keyPath);
1460 newval = newval & FolderBothChecked;
1461 QTreeWidgetItem *item = m_dirPaths.value(keyPath);
1463 directorySetIcon(0, newval, keyPath, item);
1465 if (mainWin->m_rtIconStateDebug) Pmsg1(000, "NOT found in shouldBeStateHash %s\n", keyPath.toUtf8().data());
1466 QTreeWidgetItem *item = m_dirPaths.value(keyPath);
1468 directorySetIcon(0, FolderBothChecked, keyPath, item);
1469 //item->setIcon(0,QIcon(QString::fromUtf8(":images/folder.png")));
1470 //m_directoryIconStateHash.remove(keyPath);
1475 void restoreTree::directorySetIcon(int operation, int change, QString &path, QTreeWidgetItem* item) {
1477 /* we are adding a check type white or green */
1478 if (operation > 0) {
1479 /* get the old val and "bitwise OR" with the change */
1480 newval = m_directoryIconStateHash.value(path, FolderUnchecked) | change;
1481 if (mainWin->m_rtIconStateDebug) Pmsg2(000, "Inserting into m_directoryIconStateHash path=%s newval=%i\n", path.toUtf8().data(), newval);
1482 m_directoryIconStateHash.insert(path, newval);
1484 /* we are removing a check type white or green */
1485 newval = m_directoryIconStateHash.value(path, FolderUnchecked) & (~change);
1487 if (mainWin->m_rtIconStateDebug) Pmsg2(000, "Removing from m_directoryIconStateHash path=%s newval=%i\n", path.toUtf8().data(), newval);
1488 m_directoryIconStateHash.remove(path);
1491 if (mainWin->m_rtIconStateDebug) Pmsg2(000, "Inserting into m_directoryIconStateHash path=%s newval=%i\n", path.toUtf8().data(), newval);
1492 m_directoryIconStateHash.insert(path, newval);
1495 if (newval == FolderUnchecked)
1496 item->setIcon(0, QIcon(QString::fromUtf8(":images/folder.png")));
1497 else if (newval == FolderGreenChecked)
1498 item->setIcon(0, QIcon(QString::fromUtf8(":images/folderchecked.png")));
1499 else if (newval == FolderWhiteChecked)
1500 item->setIcon(0, QIcon(QString::fromUtf8(":images/folderunchecked.png")));
1501 else if (newval == FolderBothChecked)
1502 item->setIcon(0, QIcon(QString::fromUtf8(":images/folderbothchecked.png")));
1508 void restoreTree::restoreButtonPushed()
1510 /* Set progress bars and repaint */
1511 prLabel1->setVisible(true);
1512 prLabel1->setText(tr("Task 1 of 3"));
1513 prLabel2->setVisible(true);
1514 prLabel2->setText(tr("Processing Checked directories"));
1515 prBar1->setVisible(true);
1516 prBar1->setRange(0, 3);
1517 prBar1->setValue(0);
1518 prBar2->setVisible(true);
1519 prBar2->setRange(0, 0);
1521 QMultiHash<int, QString> versionFilesMulti;
1523 QHash <QString, bool> fullPathDone;
1524 QHash <QString, int> fileIndexHash;
1525 if ((mainWin->m_rtRestore1Debug) || (mainWin->m_rtRestore2Debug) || (mainWin->m_rtRestore3Debug))
1526 Pmsg0(000, "In restoreTree::restoreButtonPushed\n");
1527 /* Use a tree widget item iterator to count directories for the progress bar */
1528 QTreeWidgetItemIterator diterc(directoryTree, QTreeWidgetItemIterator::Checked);
1533 } /* while (*diterc) */
1534 prBar2->setRange(0, ditcount);
1535 prBar2->setValue(0);
1537 /* Use a tree widget item iterator filtering for Checked Items */
1538 QTreeWidgetItemIterator diter(directoryTree, QTreeWidgetItemIterator::Checked);
1540 QString directory = (*diter)->data(0, Qt::UserRole).toString();
1541 int pathid = m_directoryPathIdHash.value(directory, -1);
1543 if (mainWin->m_rtRestore1Debug)
1544 Pmsg1(000, "Directory Checked=\"%s\"\n", directory.toUtf8().data());
1545 /* With a checked directory, query for the files in the directory */
1548 "SELECT Filename.Name AS Filename, t1.JobId AS JobId, File.FileIndex AS FileIndex"
1550 " ( SELECT File.FilenameId AS FilenameId, MAX(Job.JobId) AS JobId"
1552 " INNER JOIN Job ON (Job.JobId=File.JobId)"
1553 " WHERE File.PathId=" + QString("%1").arg(pathid) +
1554 " AND Job.Jobid IN (" + m_checkedJobs + ")"
1555 " AND File.FilenameId!=" + QString("%1").arg(m_nullFileNameId) +
1556 " GROUP BY File.FilenameId"
1558 " INNER JOIN Filename on (Filename.FilenameId=File.FilenameId)"
1559 " INNER JOIN Job ON (Job.JobId=File.JobId)"
1560 " WHERE File.PathId=" + QString("%1").arg(pathid) +
1561 " AND File.FilenameId=t1.FilenameId"
1562 " AND Job.Jobid=t1.JobId"
1563 " ORDER BY Filename";
1565 if (mainWin->m_sqlDebug) Pmsg1(000, "Query cmd : %s\n", cmd.toUtf8().data());
1566 QStringList results;
1567 if (m_console->sql_cmd(cmd, results)) {
1568 QStringList fieldlist;
1571 /* Iterate through the record returned from the query */
1572 foreach (QString resultline, results) {
1573 /* Iterate through fields in the record */
1575 QString fullPath = "";
1576 Qt::CheckState fileExcpState = (Qt::CheckState)4;
1577 fieldlist = resultline.split("\t");
1580 foreach (QString field, fieldlist) {
1582 fullPath = directory + field;
1585 version = field.toInt();
1588 fileIndex = field.toInt();
1592 fileExcpState = m_fileExceptionHash.value(fullPath, (Qt::CheckState)3);
1594 int excpVersion = m_versionExceptionHash.value(fullPath, 0);
1595 if (fileExcpState != Qt::Unchecked) {
1597 if (excpVersion != 0) {
1598 debugtext = QString("*E* version=%1").arg(excpVersion);
1599 version = excpVersion;
1600 fileIndex = queryFileIndex(fullPath, excpVersion);
1602 debugtext = QString("___ version=%1").arg(version);
1603 if (mainWin->m_rtRestore1Debug)
1604 Pmsg2(000, "Restoring %s File %s\n", debugtext.toUtf8().data(), fullPath.toUtf8().data());
1605 fullPathDone.insert(fullPath, 1);
1606 fileIndexHash.insert(fullPath, fileIndex);
1607 versionFilesMulti.insert(version, fullPath);
1615 prBar2->setValue(ditcount);
1617 } /* while (*diter) */
1618 prBar1->setValue(1);
1619 prLabel1->setText( tr("Task 2 of 3"));
1620 prLabel2->setText(tr("Processing Exceptions"));
1621 prBar2->setRange(0, 0);
1624 /* There may be some exceptions not accounted for yet with fullPathDone */
1625 QHashIterator<QString, Qt::CheckState> ftera(m_fileExceptionHash);
1626 while (ftera.hasNext()) {
1628 QString fullPath = ftera.key();
1629 Qt::CheckState state = ftera.value();
1631 /* now we don't want the ones already done */
1632 if (fullPathDone.value(fullPath, 0) == 0) {
1633 int version = m_versionExceptionHash.value(fullPath, 0);
1635 QString debugtext = "";
1637 fileIndex = queryFileIndex(fullPath, version);
1638 debugtext = QString("E1* version=%1 fileid=%2").arg(version).arg(fileIndex);
1640 version = mostRecentVersionfromFullPath(fullPath);
1642 fileIndex = queryFileIndex(fullPath, version);
1643 debugtext = QString("E2* version=%1 fileid=%2").arg(version).arg(fileIndex);
1645 debugtext = QString("Error det vers").arg(version);
1647 if (mainWin->m_rtRestore1Debug)
1648 Pmsg2(000, "Restoring %s file %s\n", debugtext.toUtf8().data(), fullPath.toUtf8().data());
1649 versionFilesMulti.insert(version, fullPath);
1651 fileIndexHash.insert(fullPath, fileIndex);
1652 } /* if fullPathDone.value(fullPath, 0) == 0 */
1653 } /* if state != 0 */
1654 } /* while ftera.hasNext */
1655 /* The progress bars for the next step */
1656 prBar1->setValue(2);
1657 prLabel1->setText(tr("Task 3 of 3"));
1658 prLabel2->setText(tr("Filling Database Table"));
1659 prBar2->setRange(0, vFMCounter);
1661 prBar2->setValue(vFMCounter);
1664 /* now for the final spit out of the versions and lists of files for each version */
1665 QHash<int, int> doneKeys;
1666 QHashIterator<int, QString> vFMiter(versionFilesMulti);
1667 QString tempTable = "";
1669 while (vFMiter.hasNext()) {
1671 int fversion = vFMiter.key();
1672 /* did not succeed in getting an iterator to work as expected on versionFilesMulti so use doneKeys */
1673 if (doneKeys.value(fversion, 0) == 0) {
1674 if (tempTable == "") {
1675 QSettings settings("www.bacula.org", "bat");
1676 settings.beginGroup("Restore");
1677 int counter = settings.value("Counter", 1).toInt();
1678 settings.setValue("Counter", counter+1);
1679 settings.endGroup();
1680 tempTable = "restore_" + QString("%1").arg(qrand()) + "_" + QString("%1").arg(counter);
1681 QString sqlcmd = "CREATE TEMPORARY TABLE " + tempTable + " (JobId INTEGER, FileIndex INTEGER)";
1682 if (mainWin->m_sqlDebug)
1683 Pmsg1(000, "Query cmd : %s ;\n", sqlcmd.toUtf8().data());
1684 QStringList results;
1685 if (!m_console->sql_cmd(sqlcmd, results))
1686 Pmsg1(000, "CREATE TABLE FAILED!!!! %s\n", sqlcmd.toUtf8().data());
1689 if (mainWin->m_rtRestore2Debug) Pmsg1(000, "Version->%i\n", fversion);
1690 QStringList fullPathList = versionFilesMulti.values(fversion);
1691 /* create the command to perform the restore */
1692 foreach(QString ffullPath, fullPathList) {
1693 int fileIndex = fileIndexHash.value(ffullPath);
1694 if (mainWin->m_rtRestore2Debug) Pmsg2(000, " file->%s id %i\n", ffullPath.toUtf8().data(), fileIndex);
1695 QString sqlcmd = "INSERT INTO " + tempTable + " (JobId, FileIndex) VALUES (" + QString("%1").arg(fversion) + ", " + QString("%1").arg(fileIndex) + ")";
1696 if (mainWin->m_rtRestore3Debug)
1697 Pmsg1(000, "Insert cmd : %s\n", sqlcmd.toUtf8().data());
1698 QStringList results;
1699 if (!m_console->sql_cmd(sqlcmd, results))
1700 Pmsg1(000, "INSERT INTO FAILED!!!! %s\n", sqlcmd.toUtf8().data());
1701 prBar2->setValue(++vFMCounter);
1702 } /* foreach fullPathList */
1703 doneKeys.insert(fversion,1);
1704 jobList.append(fversion);
1705 } /* if (doneKeys.value(fversion, 0) == 0) */
1706 } /* while (vFMiter.hasNext()) */
1707 if (tempTable != "") {
1708 /* a table was made, lets run the job */
1709 QString jobOption = " jobid=\"";
1711 /* create a list of jobs comma separated */
1712 foreach (int job, jobList) {
1713 if (first) first = false;
1714 else jobOption += ",";
1715 jobOption += QString("%1").arg(job);
1718 QString cmd = QString("restore");
1720 " client=\"" + m_prevClientCombo + "\"" +
1721 " file=\"?" + tempTable + "\" done";
1722 if (mainWin->m_commandDebug)
1723 Pmsg1(000, "preRestore command \'%s\'\n", cmd.toUtf8().data());
1724 consoleCommand(cmd);
1726 /* turn off the progress widgets */
1727 prBar1->setVisible(false);
1728 prBar2->setVisible(false);
1729 prLabel1->setVisible(false);
1730 prLabel2->setVisible(false);
1733 int restoreTree::mostRecentVersionfromFullPath(QString &fullPath)
1736 QString directory, fileName;
1737 int index = fullPath.lastIndexOf("/", -2);
1739 directory = fileName = fullPath;
1740 directory.replace(index+1, fullPath.length()-index-1, "");
1741 fileName.replace(0, index+1, "");
1743 QString msg = QString("length = \"%1\" index = \"%2\" Considering \"%3\" \"%4\"\n")
1744 .arg(fullPath.length()).arg(index).arg(fileName).arg(directory);
1745 Pmsg0(000, msg.toUtf8().data());
1747 int pathid = m_directoryPathIdHash.value(directory, -1);
1749 /* so now we need the latest version from the database */
1751 "SELECT MAX(Job.JobId)"
1753 " INNER JOIN Filename on (Filename.FilenameId=File.FilenameId)"
1754 " INNER JOIN Job ON (File.JobId=Job.JobId)"
1755 " WHERE File.PathId=" + QString("%1").arg(pathid) +
1756 " AND Job.Jobid IN (" + m_checkedJobs + ")"
1757 " AND Filename.Name='" + fileName + "'"
1758 " AND File.FilenameId!=" + QString("%1").arg(m_nullFileNameId) +
1759 " GROUP BY Filename.Name";
1761 if (mainWin->m_sqlDebug) Pmsg1(000, "Query cmd : %s\n", cmd.toUtf8().data());
1762 QStringList results;
1763 if (m_console->sql_cmd(cmd, results)) {
1764 QStringList fieldlist;
1766 /* Iterate through the record returned from the query */
1767 foreach (QString resultline, results) {
1768 /* Iterate through fields in the record */
1770 fieldlist = resultline.split("\t");
1771 foreach (QString field, fieldlist) {
1773 qversion = field.toInt();
1781 } /* if (index != -1) */
1786 int restoreTree::queryFileIndex(QString &fullPath, int jobId)
1789 QString directory, fileName;
1790 int index = fullPath.lastIndexOf("/", -2);
1792 directory = fileName = fullPath;
1793 directory.replace(index+1, fullPath.length()-index-1, "");
1794 fileName.replace(0, index+1, "");
1796 QString msg = QString("length = \"%1\" index = \"%2\" Considering \"%3\" \"%4\"\n")
1797 .arg(fullPath.length()).arg(index).arg(fileName).arg(directory);
1798 Pmsg0(000, msg.toUtf8().data());
1800 int pathid = m_directoryPathIdHash.value(directory, -1);
1802 /* so now we need the latest version from the database */
1807 " INNER JOIN Filename on (Filename.FilenameId=File.FilenameId)"
1808 " INNER JOIN Job ON (File.JobId=Job.JobId)"
1809 " WHERE File.PathId=" + QString("%1").arg(pathid) +
1810 " AND Filename.Name='" + fileName + "'"
1811 " AND Job.Jobid='" + QString("%1").arg(jobId) + "'"
1812 " GROUP BY File.FileIndex";
1814 if (mainWin->m_sqlDebug) Pmsg1(000, "Query cmd : %s\n", cmd.toUtf8().data());
1815 QStringList results;
1816 if (m_console->sql_cmd(cmd, results)) {
1817 QStringList fieldlist;
1819 /* Iterate through the record returned from the query */
1820 foreach (QString resultline, results) {
1821 /* Iterate through fields in the record */
1823 fieldlist = resultline.split("\t");
1824 foreach (QString field, fieldlist) {
1826 qfileIndex = field.toInt();
1834 } /* if (index != -1) */