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 three of the GNU Affero 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 Affero 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")));
55 QGridLayout *gridLayout = new QGridLayout(this);
56 gridLayout->setSpacing(6);
57 gridLayout->setMargin(9);
58 gridLayout->setObjectName(QString::fromUtf8("gridLayout"));
60 m_splitter = new QSplitter(Qt::Vertical, this);
61 QScrollArea *area = new QScrollArea();
62 area->setObjectName(QString::fromUtf8("area"));
63 area->setWidget(widget);
64 area->setWidgetResizable(true);
65 m_splitter->addWidget(area);
66 m_splitter->addWidget(splitter);
67 splitter->setChildrenCollapsible(false);
69 gridLayout->addWidget(m_splitter, 0, 0, 1, 1);
71 /* progress widgets */
72 prBar1->setVisible(false);
73 prBar2->setVisible(false);
74 prLabel1->setVisible(false);
75 prLabel2->setVisible(false);
77 /* Set Defaults for check and spin for limits */
78 limitCheckBox->setCheckState(mainWin->m_recordLimitCheck ? Qt::Checked : Qt::Unchecked);
79 limitSpinBox->setValue(mainWin->m_recordLimitVal);
80 daysCheckBox->setCheckState(mainWin->m_daysLimitCheck ? Qt::Checked : Qt::Unchecked);
81 daysSpinBox->setValue(mainWin->m_daysLimitVal);
83 m_nullFileNameId = -1;
86 restoreTree::~restoreTree()
92 * Called from the constructor to set up the page widgets and connections.
94 void restoreTree::setupPage()
96 connect(refreshButton, SIGNAL(pressed()), this, SLOT(refreshButtonPushed()));
97 connect(restoreButton, SIGNAL(pressed()), this, SLOT(restoreButtonPushed()));
98 connect(jobCombo, SIGNAL(currentIndexChanged(int)), this, SLOT(jobComboChanged(int)));
99 connect(jobCombo, SIGNAL(currentIndexChanged(int)), this, SLOT(updateRefresh()));
100 connect(clientCombo, SIGNAL(currentIndexChanged(int)), this, SLOT(updateRefresh()));
101 connect(fileSetCombo, SIGNAL(currentIndexChanged(int)), this, SLOT(updateRefresh()));
102 connect(limitCheckBox, SIGNAL(stateChanged(int)), this, SLOT(updateRefresh()));
103 connect(daysCheckBox, SIGNAL(stateChanged(int)), this, SLOT(updateRefresh()));
104 connect(daysSpinBox, SIGNAL(valueChanged(int)), this, SLOT(updateRefresh()));
105 connect(limitSpinBox, SIGNAL(valueChanged(int)), this, SLOT(updateRefresh()));
106 connect(directoryTree, SIGNAL(currentItemChanged(QTreeWidgetItem *, QTreeWidgetItem *)),
107 this, SLOT(directoryCurrentItemChanged(QTreeWidgetItem *, QTreeWidgetItem *)));
108 connect(directoryTree, SIGNAL(itemExpanded(QTreeWidgetItem *)),
109 this, SLOT(directoryItemExpanded(QTreeWidgetItem *)));
110 connect(directoryTree, SIGNAL(itemChanged(QTreeWidgetItem *, int)),
111 this, SLOT(directoryItemChanged(QTreeWidgetItem *, int)));
112 connect(fileTable, SIGNAL(currentItemChanged(QTableWidgetItem *, QTableWidgetItem *)),
113 this, SLOT(fileCurrentItemChanged(QTableWidgetItem *, QTableWidgetItem *)));
114 connect(jobTable, SIGNAL(cellClicked(int, int)),
115 this, SLOT(jobTableCellClicked(int, int)));
117 QStringList titles = QStringList() << tr("Directories");
118 directoryTree->setHeaderLabels(titles);
119 clientCombo->addItems(m_console->client_list);
120 fileSetCombo->addItem(tr("Any"));
121 fileSetCombo->addItems(m_console->fileset_list);
122 jobCombo->addItem(tr("Any"));
123 jobCombo->addItems(m_console->job_list);
125 directoryTree->setContextMenuPolicy(Qt::ActionsContextMenu);
128 void restoreTree::updateRefresh()
130 if (mainWin->m_rtPopDirDebug) Pmsg2(000, "testing prev=\"%s\" current=\"%s\"\n", m_prevJobCombo.toUtf8().data(), jobCombo->currentText().toUtf8().data());
131 m_dropdownChanged = (m_prevJobCombo != jobCombo->currentText())
132 || (m_prevClientCombo != clientCombo->currentText())
133 || (m_prevFileSetCombo != fileSetCombo->currentText()
134 || (m_prevLimitSpinBox != limitSpinBox->value())
135 || (m_prevDaysSpinBox != daysSpinBox->value())
136 || (m_prevLimitCheckState != limitCheckBox->checkState())
137 || (m_prevDaysCheckState != daysCheckBox->checkState())
139 if (m_dropdownChanged) {
140 if (mainWin->m_rtPopDirDebug) Pmsg0(000, "In restoreTree::updateRefresh Is CHANGED\n");
141 refreshLabel->setText(tr("Refresh From Re-Select"));
143 if (mainWin->m_rtPopDirDebug) Pmsg0(000, "In restoreTree::updateRefresh Is not Changed\n");
144 refreshLabel->setText(tr("Refresh From JobChecks"));
149 * When refresh button is pushed, perform a query getting the directories and
150 * use parseDirectory and addDirectory to populate the directory tree with items.
152 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");
358 pathAfter.prepend(path);
359 dirAfter.prepend(direct);
364 for (int k=0; k<pathAfter.count(); k++) {
365 if (addDirectory(pathAfter[k], dirAfter[k])) {
366 if ((mainWin->m_miscDebug) && (m_debugTrap))
367 Pmsg2(000, "Adding After %s %s\n", pathAfter[k].toUtf8().data(), dirAfter[k].toUtf8().data());
369 if ((mainWin->m_miscDebug) && (m_debugTrap))
370 Pmsg2(000, "Error Adding %s %s\n", pathAfter[k].toUtf8().data(), dirAfter[k].toUtf8().data());
377 * Function called from fill directory when a directory is found to see if this
378 * directory exists in the directory pane and then add it to the directory pane
380 bool restoreTree::addDirectory(QString &m_cwd, QString &newdirr)
382 QString newdir = newdirr;
383 QString fullPath = m_cwd + newdirr;
384 bool ok = true, added = false;
386 if ((mainWin->m_miscDebug) && (m_debugTrap)) {
387 QString msg = QString("In addDirectory cwd \"%1\" newdir \"%2\"\n")
390 Pmsg0(000, msg.toUtf8().data());
394 /* add unix '/' directory first */
395 if (m_dirPaths.empty() && !isWin32Path(fullPath)) {
397 QTreeWidgetItem *item = new QTreeWidgetItem(directoryTree);
399 item->setText(0, text.toUtf8().data());
400 item->setData(0, Qt::UserRole, QVariant(text));
401 item->setData(1, Qt::UserRole, QVariant(Qt::Unchecked));
402 item->setIcon(0, QIcon(QString::fromUtf8(":images/folder.png")));
403 if ((mainWin->m_miscDebug) && (m_debugTrap)) {
404 Pmsg1(000, "Pre Inserting %s\n", text.toUtf8().data());
406 m_dirPaths.insert(text, item);
408 /* no need to check for windows drive if unix */
409 if (isWin32Path(m_cwd)) {
410 if (!m_dirPaths.contains(m_cwd)) {
411 if (m_cwd.count('/') > 1) { return false; }
412 /* this is a windows drive add the base widget */
413 QTreeWidgetItem *item = new QTreeWidgetItem(directoryTree);
414 item->setText(0, m_cwd);
415 item->setData(0, Qt::UserRole, QVariant(fullPath));
416 item->setData(1, Qt::UserRole, QVariant(Qt::Unchecked));
417 item->setIcon(0, QIcon(QString::fromUtf8(":images/folder.png")));
418 if ((mainWin->m_miscDebug) && (m_debugTrap)) {
419 Pmsg0(000, "Added Base \"letter\":/\n");
421 m_dirPaths.insert(m_cwd, item);
426 /* is it already existent ?? */
427 if (!m_dirPaths.contains(fullPath)) {
428 QTreeWidgetItem *item = NULL;
429 QTreeWidgetItem *parent = m_dirPaths.value(m_cwd);
431 /* new directories to add */
432 item = new QTreeWidgetItem(parent);
433 item->setText(0, newdir.toUtf8().data());
434 item->setData(0, Qt::UserRole, QVariant(fullPath));
435 item->setCheckState(0, Qt::Unchecked);
436 /* Store the current state of the check status in column 1, which at
437 * this point has no text*/
438 item->setData(1, Qt::UserRole, QVariant(Qt::Unchecked));
441 if ((mainWin->m_miscDebug) && (m_debugTrap)) {
442 QString msg = QString("In else of if parent cwd \"%1\" newdir \"%2\"\n")
445 Pmsg0(000, msg.toUtf8().data());
448 /* insert into hash */
450 if ((mainWin->m_miscDebug) && (m_debugTrap)) {
451 Pmsg1(000, "Inserting %s\n", fullPath.toUtf8().data());
453 m_dirPaths.insert(fullPath, item);
461 * Virtual function which is called when this page is visible on the stack
463 void restoreTree::currentStackItem()
472 * Populate the tree when refresh button pushed.
474 void restoreTree::refreshButtonPushed()
476 populateDirectoryTree();
480 * Set the values of non-job combo boxes to the job defaults
482 void restoreTree::jobComboChanged(int)
484 if (jobCombo->currentText() == tr("Any")) {
485 fileSetCombo->setCurrentIndex(fileSetCombo->findText(tr("Any"), Qt::MatchExactly));
488 job_defaults job_defs;
491 job_defs.job_name = jobCombo->currentText();
492 if (m_console->get_job_defaults(job_defs)) {
493 fileSetCombo->setCurrentIndex(fileSetCombo->findText(job_defs.fileset_name, Qt::MatchExactly));
494 clientCombo->setCurrentIndex(clientCombo->findText(job_defs.client_name, Qt::MatchExactly));
499 * Function to populate the file list table
501 void restoreTree::directoryCurrentItemChanged(QTreeWidgetItem *item, QTreeWidgetItem *)
507 /* Also clear the version table here */
508 versionTable->clear();
509 versionFileLabel->setText("");
510 versionTable->setRowCount(0);
511 versionTable->setColumnCount(0);
513 QStringList headerlist = (QStringList() << tr("File Name") << tr("Filename Id"));
514 fileTable->setColumnCount(headerlist.size());
515 fileTable->setHorizontalHeaderLabels(headerlist);
516 fileTable->setRowCount(0);
518 m_fileCheckStateList.clear();
519 disconnect(fileTable, SIGNAL(itemChanged(QTableWidgetItem *)),
520 this, SLOT(fileTableItemChanged(QTableWidgetItem *)));
521 QBrush blackBrush(Qt::black);
522 QString directory = item->data(0, Qt::UserRole).toString();
523 directoryLabel->setText(tr("Present Working Directory: %1").arg(directory));
524 int pathid = m_directoryPathIdHash.value(directory, -1);
527 "SELECT DISTINCT Filename.Name AS FileName, Filename.FilenameId AS FilenameId"
529 " INNER JOIN Filename on (Filename.FilenameId=File.FilenameId)"
530 " WHERE File.PathId=" + QString("%1").arg(pathid) +
531 " AND File.Jobid IN (" + m_checkedJobs + ")"
532 " AND Filename.Name!=''"
533 " ORDER BY FileName";
535 if (mainWin->m_sqlDebug) {
536 Pmsg1(000, "Query cmd : %s\n", cmd.toUtf8().data());
539 if (m_console->sql_cmd(cmd, results)) {
541 QTableWidgetItem* tableItem;
543 QStringList fieldlist;
544 fileTable->setRowCount(results.size());
547 /* Iterate through the record returned from the query */
548 foreach (QString resultline, results) {
549 /* Iterate through fields in the record */
551 fieldlist = resultline.split("\t");
552 foreach (field, fieldlist) {
553 field = field.trimmed(); /* strip leading & trailing spaces */
554 tableItem = new QTableWidgetItem(field, 1);
555 /* Possible flags are Qt::ItemFlags flag = Qt::ItemIsSelectable | Qt::ItemIsEditablex
556 * | Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled | Qt::ItemIsUserCheckable
557 * | Qt::ItemIsEnabled | Qt::ItemIsTristate; */
558 tableItem->setForeground(blackBrush);
559 /* Just in case a column ever gets added */
561 Qt::ItemFlags flag = Qt::ItemIsUserCheckable | Qt::ItemIsEnabled | Qt::ItemIsTristate;
562 tableItem->setFlags(flag);
563 tableItem->setData(Qt::UserRole, QVariant(directory));
564 fileTable->setItem(row, column, tableItem);
565 m_fileCheckStateList.append(Qt::Unchecked);
566 tableItem->setCheckState(Qt::Unchecked);
567 } else if (column == 1) {
568 Qt::ItemFlags flag = Qt::ItemIsEnabled;
569 tableItem->setFlags(flag);
571 int filenameid = field.toInt(&ok, 10);
572 if (!ok) filenameid = -1;
573 tableItem->setData(Qt::UserRole, QVariant(filenameid));
574 fileTable->setItem(row, column, tableItem);
580 fileTable->setRowCount(row);
582 fileTable->resizeColumnsToContents();
583 fileTable->resizeRowsToContents();
584 fileTable->verticalHeader()->hide();
585 fileTable->hideColumn(1);
586 if (mainWin->m_rtDirCurICDebug) Pmsg0(000, "will update file table checks\n");
587 updateFileTableChecks();
588 } else if (mainWin->m_sqlDebug)
589 Pmsg1(000, "did not perform query, pathid=%i not found\n", pathid);
590 connect(fileTable, SIGNAL(itemChanged(QTableWidgetItem *)),
591 this, SLOT(fileTableItemChanged(QTableWidgetItem *)));
595 * Function to populate the version table
597 void restoreTree::fileCurrentItemChanged(QTableWidgetItem *currentFileTableItem, QTableWidgetItem *)
599 if (currentFileTableItem == NULL)
602 int currentRow = fileTable->row(currentFileTableItem);
603 QTableWidgetItem *fileTableItem = fileTable->item(currentRow, 0);
604 QTableWidgetItem *fileNameIdTableItem = fileTable->item(currentRow, 1);
605 int fileNameId = fileNameIdTableItem->data(Qt::UserRole).toInt();
607 m_versionCheckStateList.clear();
608 disconnect(versionTable, SIGNAL(itemChanged(QTableWidgetItem *)),
609 this, SLOT(versionTableItemChanged(QTableWidgetItem *)));
611 QString file = fileTableItem->text();
612 versionFileLabel->setText(file);
613 QString directory = fileTableItem->data(Qt::UserRole).toString();
615 QBrush blackBrush(Qt::black);
617 QStringList headerlist = (QStringList()
618 << tr("Job Id") << tr("Type") << tr("End Time") << tr("Hash") << tr("FileId") << tr("Job Type") << tr("First Volume"));
619 versionTable->clear();
620 versionTable->setColumnCount(headerlist.size());
621 versionTable->setHorizontalHeaderLabels(headerlist);
622 versionTable->setRowCount(0);
624 int pathid = m_directoryPathIdHash.value(directory, -1);
625 if ((pathid != -1) && (fileNameId != -1)) {
627 "SELECT Job.JobId AS JobId, Job.Level AS Type,"
628 " Job.EndTime AS EndTime, File.MD5 AS MD5,"
629 " File.FileId AS FileId, Job.Type AS JobType,"
630 " (SELECT Media.VolumeName FROM JobMedia JOIN Media ON JobMedia.MediaId=Media.MediaId WHERE JobMedia.JobId=Job.JobId ORDER BY JobMediaId LIMIT 1) AS FirstVolume"
632 " INNER JOIN Filename on (Filename.FilenameId=File.FilenameId)"
633 " INNER JOIN Path ON (Path.PathId=File.PathId)"
634 " INNER JOIN Job ON (File.JobId=Job.JobId)"
635 " WHERE Path.PathId=" + QString("%1").arg(pathid) +
636 //" AND Filename.Name='" + file + "'"
637 " AND Filename.FilenameId=" + QString("%1").arg(fileNameId) +
638 " AND Job.Jobid IN (" + m_checkedJobs + ")"
639 " ORDER BY Job.EndTime DESC";
641 if (mainWin->m_sqlDebug)
642 Pmsg1(000, "Query cmd : %s\n", cmd.toUtf8().data());
644 if (m_console->sql_cmd(cmd, results)) {
646 QTableWidgetItem* tableItem;
648 QStringList fieldlist;
649 versionTable->setRowCount(results.size());
652 /* Iterate through the record returned from the query */
653 foreach (QString resultline, results) {
654 fieldlist = resultline.split("\t");
656 /* remove directory */
657 if (fieldlist[0].trimmed() != "") {
658 /* Iterate through fields in the record */
659 foreach (field, fieldlist) {
660 field = field.trimmed(); /* strip leading & trailing spaces */
662 QByteArray jtype(field.trimmed().toAscii());
664 field = job_type_to_str(jtype[0]);
667 tableItem = new QTableWidgetItem(field, 1);
668 tableItem->setFlags(0);
669 tableItem->setForeground(blackBrush);
670 tableItem->setData(Qt::UserRole, QVariant(directory));
671 versionTable->setItem(row, column, tableItem);
674 Qt::ItemFlags flag = Qt::ItemIsUserCheckable | Qt::ItemIsEnabled | Qt::ItemIsTristate;
675 tableItem->setFlags(flag);
676 m_versionCheckStateList.append(Qt::Unchecked);
677 tableItem->setCheckState(Qt::Unchecked);
685 versionTable->resizeColumnsToContents();
686 versionTable->resizeRowsToContents();
687 versionTable->verticalHeader()->hide();
688 updateVersionTableChecks();
690 if (mainWin->m_sqlDebug)
691 Pmsg2(000, "not querying : pathid=%i fileNameId=%i\n", pathid, fileNameId);
693 connect(versionTable, SIGNAL(itemChanged(QTableWidgetItem *)),
694 this, SLOT(versionTableItemChanged(QTableWidgetItem *)));
698 * Save user settings associated with this page
700 void restoreTree::writeSettings()
702 QSettings settings(m_console->m_dir->name(), "bat");
703 settings.beginGroup(m_groupText);
704 settings.setValue(m_splitText1, m_splitter->saveState());
705 settings.setValue(m_splitText2, splitter->saveState());
710 * Read and restore user settings associated with this page
712 void restoreTree::readSettings()
714 m_groupText = tr("RestoreTreePage");
715 m_splitText1 = "splitterSizes1_3";
716 m_splitText2 = "splitterSizes2_3";
717 QSettings settings(m_console->m_dir->name(), "bat");
718 settings.beginGroup(m_groupText);
719 if (settings.contains(m_splitText1)) { m_splitter->restoreState(settings.value(m_splitText1).toByteArray()); }
720 if (settings.contains(m_splitText2)) { splitter->restoreState(settings.value(m_splitText2).toByteArray()); }
725 * This is a funcion to accomplish the one thing I struggled to figure out what
726 * was taking so long. It add the icons, but after the tree is made. Seemed to
727 * work fast after changing from png to png file for graphic.
729 void restoreTree::directoryItemExpanded(QTreeWidgetItem *item)
731 int childCount = item->childCount();
732 for (int i=0; i<childCount; i++) {
733 QTreeWidgetItem *child = item->child(i);
734 if (child->icon(0).isNull())
735 child->setIcon(0, QIcon(QString::fromUtf8(":images/folder.png")));
740 * Show what jobs meet the criteria and are being used to
741 * populate the directory tree and file and version tables.
743 void restoreTree::populateJobTable()
745 QBrush blackBrush(Qt::black);
747 if (mainWin->m_rtPopDirDebug) Pmsg0(000, "Repopulating the Job Table\n");
748 QStringList headerlist = (QStringList()
749 << tr("Job Id") << tr("End Time") << tr("Level") << tr("Type")
750 << tr("Name") << tr("Purged") << tr("TU") << tr("TD"));
751 m_toggleUpIndex = headerlist.indexOf(tr("TU"));
752 m_toggleDownIndex = headerlist.indexOf(tr("TD"));
753 int purgedIndex = headerlist.indexOf(tr("Purged"));
754 int typeIndex = headerlist.indexOf(tr("Type"));
756 jobTable->setColumnCount(headerlist.size());
757 jobTable->setHorizontalHeaderLabels(headerlist);
759 "SELECT Job.Jobid AS Id, Job.EndTime AS EndTime,"
760 " Job.Level AS Level, Job.Type AS Type,"
761 " Job.Name AS JobName, Job.purgedfiles AS Purged"
763 /* INNER JOIN FileSet eliminates all restore jobs */
764 " INNER JOIN Client ON (Job.ClientId=Client.ClientId)"
765 " INNER JOIN FileSet ON (Job.FileSetId=FileSet.FileSetId)"
767 " Client.Name='" + clientCombo->currentText() + "'";
768 if ((jobCombo->currentIndex() >= 0) && (jobCombo->currentText() != tr("Any"))) {
769 jobQuery += " AND Job.name = '" + jobCombo->currentText() + "'";
771 if ((fileSetCombo->currentIndex() >= 0) && (fileSetCombo->currentText() != tr("Any"))) {
772 jobQuery += " AND FileSet.FileSet='" + fileSetCombo->currentText() + "'";
774 /* If Limit check box For limit by days is checked */
775 if (daysCheckBox->checkState() == Qt::Checked) {
776 QDateTime stamp = QDateTime::currentDateTime().addDays(-daysSpinBox->value());
777 QString since = stamp.toString(Qt::ISODate);
778 jobQuery += " AND Job.Starttime>'" + since + "'";
780 //jobQuery += " AND Job.purgedfiles=0";
781 jobQuery += " ORDER BY Job.EndTime DESC";
782 /* If Limit check box for limit records returned is checked */
783 if (limitCheckBox->checkState() == Qt::Checked) {
785 limit.setNum(limitSpinBox->value());
786 jobQuery += " LIMIT " + limit;
788 if (mainWin->m_sqlDebug)
789 Pmsg1(000, "Query cmd : %s\n", jobQuery.toUtf8().data());
792 if (m_console->sql_cmd(jobQuery, results)) {
794 QTableWidgetItem* tableItem;
796 QStringList fieldlist;
797 jobTable->setRowCount(results.size());
800 /* Iterate through the record returned from the query */
801 foreach (QString resultline, results) {
802 fieldlist = resultline.split("\t");
804 /* remove directory */
805 if (fieldlist[0].trimmed() != "") {
806 /* Iterate through fields in the record */
807 foreach (field, fieldlist) {
808 field = field.trimmed(); /* strip leading & trailing spaces */
810 if (column == typeIndex) {
811 QByteArray jtype(field.trimmed().toAscii());
813 field = job_type_to_str(jtype[0]);
816 tableItem = new QTableWidgetItem(field, 1);
817 tableItem->setFlags(0);
818 tableItem->setForeground(blackBrush);
819 jobTable->setItem(row, column, tableItem);
822 int purged = fieldlist[purgedIndex].toInt(&ok, 10);
823 if (!((ok) && (purged == 1))) {
824 Qt::ItemFlags flag = Qt::ItemIsUserCheckable | Qt::ItemIsEnabled | Qt::ItemIsTristate;
825 tableItem->setFlags(flag);
826 tableItem->setCheckState(Qt::Checked);
827 tableItem->setBackground(Qt::green);
829 tableItem->setFlags(0);
830 tableItem->setCheckState(Qt::Unchecked);
836 tableItem = new QTableWidgetItem(QIcon(QString::fromUtf8(":images/go-up.png")), "", 1);
837 tableItem->setFlags(0);
838 tableItem->setForeground(blackBrush);
839 jobTable->setItem(row, column, tableItem);
841 tableItem = new QTableWidgetItem(QIcon(QString::fromUtf8(":images/go-down.png")), "", 1);
842 tableItem->setFlags(0);
843 tableItem->setForeground(blackBrush);
844 jobTable->setItem(row, column, tableItem);
849 jobTable->resizeColumnsToContents();
850 jobTable->resizeRowsToContents();
851 jobTable->verticalHeader()->hide();
852 jobTable->hideColumn(purgedIndex);
855 void restoreTree::jobTableCellClicked(int row, int column)
857 if (column == m_toggleUpIndex){
859 for (cnt=0; cnt<row+1; cnt++) {
860 QTableWidgetItem *item = jobTable->item(cnt, 0);
862 Qt::CheckState state = item->checkState();
863 if (state == Qt::Checked)
864 item->setCheckState(Qt::Unchecked);
865 else if (state == Qt::Unchecked)
866 item->setCheckState(Qt::Checked);
870 if (column == m_toggleDownIndex){
871 int cnt, max = jobTable->rowCount();
872 for (cnt=row; cnt<max; cnt++) {
873 QTableWidgetItem *item = jobTable->item(cnt, 0);
875 Qt::CheckState state = item->checkState();
876 if (state == Qt::Checked)
877 item->setCheckState(Qt::Unchecked);
878 else if (state == Qt::Unchecked)
879 item->setCheckState(Qt::Checked);
886 * When a directory item is "changed" check the state of the checkable item
887 * to see if it is different than what it was which is stored in Qt::UserRole
888 * of the 2nd column, column 1, of the tree widget.
890 void restoreTree::directoryItemChanged(QTreeWidgetItem *item, int /*column*/)
892 Qt::CheckState prevState = (Qt::CheckState)item->data(1, Qt::UserRole).toInt();
893 Qt::CheckState curState = item->checkState(0);
894 QTreeWidgetItem* parent = item->parent();
895 Qt::CheckState parState;
896 if (parent) parState = parent->checkState(0);
897 else parState = (Qt::CheckState)3;
898 if (mainWin->m_rtDirICDebug) {
899 QString msg = QString("directory item OBJECT has changed prev=%1 cur=%2 par=%3 dir=%4\n")
900 .arg(prevState).arg(curState).arg(parState).arg(item->text(0));
901 Pmsg1(000, "%s", msg.toUtf8().data()); }
902 /* I only care when the check state changes */
903 if (prevState == curState) {
904 if (mainWin->m_rtDirICDebug) Pmsg0(000, "Returning Early\n");
908 if ((prevState == Qt::Unchecked) && (curState == Qt::Checked) && (parState != Qt::Unchecked)) {
909 if (mainWin->m_rtDirICDebug) Pmsg0(000, "Disconnected Setting to Qt::PartiallyChecked\n");
910 directoryTreeDisconnectedSet(item, Qt::PartiallyChecked);
911 curState = Qt::PartiallyChecked;
913 if ((prevState == Qt::PartiallyChecked) && (curState == Qt::Checked)) {
914 if (mainWin->m_rtDirICDebug) Pmsg0(000, "Disconnected Setting to Qt::Unchecked\n");
915 directoryTreeDisconnectedSet(item, Qt::Unchecked);
916 curState = Qt::Unchecked;
918 if (mainWin->m_rtDirICDebug) {
919 QString msg = QString("directory item CHECKSTATE has changed prev=%1 cur=%2 par=%3 dir=%4\n")
920 .arg(prevState).arg(curState).arg(parState).arg(item->text(0));
921 Pmsg1(000, "%s", msg.toUtf8().data()); }
923 item->setData(1, Qt::UserRole, QVariant(curState));
924 Qt::CheckState childState = curState;
925 if (childState == Qt::Checked)
926 childState = Qt::PartiallyChecked;
927 setCheckofChildren(item, childState);
929 /* Remove items from the exception lists. The multi exception list is my index
930 * of what exceptions can be removed when the directory is known*/
931 QString directory = item->data(0, Qt::UserRole).toString();
932 QStringList fullPathList = m_fileExceptionMulti.values(directory);
933 int fullPathListCount = fullPathList.count();
934 if ((mainWin->m_rtDirICDebug) && fullPathListCount) Pmsg2(000, "Will attempt to remove file exceptions for %s count %i\n", directory.toUtf8().data(), fullPathListCount);
935 foreach (QString fullPath, fullPathList) {
936 /* If there is no value in the hash for the key fullPath a value of 3 will be returned
937 * which will match no Qt::xxx values */
938 Qt::CheckState hashState = m_fileExceptionHash.value(fullPath, (Qt::CheckState)3);
939 if (mainWin->m_rtDirICDebug) Pmsg2(000, "hashState=%i childState=%i\n", hashState, childState);
940 if (hashState == Qt::Unchecked) {
941 fileExceptionRemove(fullPath, directory);
942 m_versionExceptionHash.remove(fullPath);
943 if (mainWin->m_rtDirICDebug) Pmsg0(000, "Attempted Removal A\n");
945 if (hashState == Qt::Checked) {
946 fileExceptionRemove(fullPath, directory);
947 m_versionExceptionHash.remove(fullPath);
948 if (mainWin->m_rtDirICDebug) Pmsg0(000, "Attempted Removal B\n");
952 if (item == directoryTree->currentItem()) {
953 if (mainWin->m_rtDirICDebug) Pmsg0(000, "Will attempt to update File Table Checks\n");
954 updateFileTableChecks();
955 versionTable->clear();
956 versionTable->setRowCount(0);
957 versionTable->setColumnCount(0);
959 if (mainWin->m_rtDirICDebug) Pmsg0(000, "Returning At End\n");
963 * When a directory item check state is changed, this function iterates through
964 * all subdirectories and sets all to the passed state, which is either partially
965 * checked or unchecked.
967 void restoreTree::setCheckofChildren(QTreeWidgetItem *item, Qt::CheckState state)
970 childCount = item->childCount();
971 for (int i=0; i<childCount; i++) {
972 QTreeWidgetItem *child = item->child(i);
973 child->setData(1, Qt::UserRole, QVariant(state));
974 child->setCheckState(0, state);
975 setCheckofChildren(child, state);
980 * When a File Table Item is "changed" check to see if the state of the checkable
981 * item has changed which is stored in m_fileCheckStateList
982 * If changed store in a hash m_fileExceptionHash that whether this file should be
984 * Called as a slot, connected after populated (after directory current changed called)
986 void restoreTree::fileTableItemChanged(QTableWidgetItem *item)
988 /* get the previous and current check states */
989 int row = fileTable->row(item);
990 Qt::CheckState prevState;
991 /* prevent a segfault */
992 prevState = m_fileCheckStateList[row];
993 Qt::CheckState curState = item->checkState();
995 /* deterimine the default state from the state of the directory */
996 QTreeWidgetItem *dirTreeItem = directoryTree->currentItem();
997 Qt::CheckState dirState = (Qt::CheckState)dirTreeItem->data(1, Qt::UserRole).toInt();
998 Qt::CheckState defState = Qt::PartiallyChecked;
999 if (dirState == Qt::Unchecked) defState = Qt::Unchecked;
1001 /* determine if it is already in the m_fileExceptionHash */
1002 QString directory = directoryTree->currentItem()->data(0, Qt::UserRole).toString();
1003 QString file = item->text();
1004 QString fullPath = directory + file;
1005 Qt::CheckState hashState = m_fileExceptionHash.value(fullPath, (Qt::CheckState)3);
1006 int verJobNum = m_versionExceptionHash.value(fullPath, 0);
1008 if (mainWin->m_rtFileTabICDebug) {
1009 QString msg = QString("filerow=%1 prev=%2 cur=%3 def=%4 hash=%5 dir=%6 verJobNum=%7\n")
1010 .arg(row).arg(prevState).arg(curState).arg(defState).arg(hashState).arg(dirState).arg(verJobNum);
1011 Pmsg1(000, "%s", msg.toUtf8().data()); }
1013 /* Remove the hash if currently checked previously unchecked and directory is checked or partial */
1014 if ((prevState == Qt::Checked) && (curState == Qt::Unchecked) && (dirState == Qt::Unchecked)) {
1015 /* it can behave as defaulted so current of unchecked is fine */
1016 if (mainWin->m_rtFileTabICDebug) Pmsg0(000, "Will fileExceptionRemove and m_versionExceptionHash.remove here\n");
1017 fileExceptionRemove(fullPath, directory);
1018 m_versionExceptionHash.remove(fullPath);
1019 } else if ((prevState == Qt::PartiallyChecked) && (curState == Qt::Checked) && (dirState != Qt::Unchecked) && (verJobNum == 0)) {
1020 if (mainWin->m_rtFileTabICDebug) Pmsg0(000, "Will fileExceptionInsert here\n");
1021 fileExceptionInsert(fullPath, directory, Qt::Unchecked);
1022 } else if ((prevState == Qt::Unchecked) && (curState == Qt::Checked) && (dirState != Qt::Unchecked) && (verJobNum == 0) && (defState == Qt::PartiallyChecked)) {
1023 /* filerow=2 prev=0 cur=2 def=1 hash=0 dir=2 verJobNum=0 */
1024 if (mainWin->m_rtFileTabICDebug) Pmsg0(000, "Will fileExceptionRemove here\n");
1025 fileExceptionRemove(fullPath, directory);
1026 } else if ((prevState == Qt::Checked) && (curState == Qt::Unchecked) && (defState == Qt::PartiallyChecked) && (verJobNum != 0) && (hashState == Qt::Checked)) {
1027 /* Check dir, check version, attempt uncheck in file
1028 * filerow=4 prev=2 cur=0 def=1 hash=2 dir=2 verJobNum=53 */
1029 if (mainWin->m_rtFileTabICDebug) Pmsg0(000, "Will fileExceptionRemove and m_versionExceptionHash.remove here\n");
1030 fileExceptionRemove(fullPath, directory);
1031 m_versionExceptionHash.remove(fullPath);
1032 } else if ((prevState == Qt::Unchecked) && (curState == Qt::Checked) && (dirState != Qt::Unchecked) && (verJobNum == 0)) {
1033 /* filerow=0 prev=0 cur=2 def=1 hash=0 dirState=2 verJobNum */
1034 if (mainWin->m_rtFileTabICDebug) Pmsg0(000, "Will Not remove here\n");
1035 } else if (prevState != curState) {
1036 if (mainWin->m_rtFileTabICDebug) Pmsg2(000, " THE STATE OF THE Check has changed, Setting StateList[%i] to %i\n", row, curState);
1037 /* A user did not set the check state to Partially checked, ignore if so */
1038 if (curState != Qt::PartiallyChecked) {
1039 if ((defState == Qt::Unchecked) && (prevState == Qt::PartiallyChecked) && (curState == Qt::Unchecked)) {
1040 if (mainWin->m_rtFileTabICDebug) Pmsg0(000, " got here\n");
1042 if (mainWin->m_rtFileTabICDebug) Pmsg2(000, " Inserting into m_fileExceptionHash %s, %i\n", fullPath.toUtf8().data(), curState);
1043 fileExceptionInsert(fullPath, directory, curState);
1046 if (mainWin->m_rtFileTabICDebug) Pmsg1(000, "Removing version hash for %s\n", fullPath.toUtf8().data());
1047 /* programattically been changed back to a default state of Qt::PartiallyChecked remove the version hash here */
1048 m_versionExceptionHash.remove(fullPath);
1052 updateFileTableChecks();
1053 updateVersionTableChecks();
1057 * function to insert keys and values to both m_fileExceptionHash and m_fileExceptionMulti
1059 void restoreTree::fileExceptionInsert(QString &fullPath, QString &direcotry, Qt::CheckState state)
1061 m_fileExceptionHash.insert(fullPath, state);
1062 m_fileExceptionMulti.insert(direcotry, fullPath);
1063 directoryIconStateInsert(fullPath, state);
1067 * function to remove keys from both m_fileExceptionHash and m_fileExceptionMulti
1069 void restoreTree::fileExceptionRemove(QString &fullPath, QString &directory)
1071 m_fileExceptionHash.remove(fullPath);
1072 /* pull the list of values in the multi */
1073 QStringList fullPathList = m_fileExceptionMulti.values(directory);
1074 /* get the index of the fullpath to remove */
1075 int index = fullPathList.indexOf(fullPath);
1077 /* remove the desired item in the list */
1078 fullPathList.removeAt(index);
1079 /* remove the entire list from the multi */
1080 m_fileExceptionMulti.remove(directory);
1081 /* readd the remaining */
1082 foreach (QString fp, fullPathList) {
1083 m_fileExceptionMulti.insert(directory, fp);
1086 directoryIconStateRemove();
1090 * Overloaded function to be called from the slot and from other places to set the state
1091 * of the check marks in the version table
1093 void restoreTree::versionTableItemChanged(QTableWidgetItem *item)
1095 /* get the previous and current check states */
1096 int row = versionTable->row(item);
1097 QTableWidgetItem *colZeroItem = versionTable->item(row, 0);
1098 Qt::CheckState prevState = m_versionCheckStateList[row];
1099 Qt::CheckState curState = (Qt::CheckState)colZeroItem->checkState();
1100 m_versionCheckStateList[row] = curState;
1102 /* deterimine the default state from the state of the file */
1103 QTableWidgetItem *fileTableItem = fileTable->currentItem();
1104 Qt::CheckState fileState = (Qt::CheckState)fileTableItem->checkState();
1106 /* determine the default state */
1107 Qt::CheckState defState;
1109 defState = Qt::PartiallyChecked;
1110 if (fileState == Qt::Unchecked)
1111 defState = Qt::Unchecked;
1114 defState = Qt::Unchecked;
1116 /* determine if it is already in the versionExceptionHash */
1117 QString directory = directoryTree->currentItem()->data(0, Qt::UserRole).toString();
1118 Qt::CheckState dirState = directoryTree->currentItem()->checkState(0);
1119 QString file = fileTableItem->text();
1120 QString fullPath = directory + file;
1121 int thisJobNum = colZeroItem->text().toInt();
1122 int hashJobNum = m_versionExceptionHash.value(fullPath, 0);
1124 if (mainWin->m_rtVerTabICDebug) {
1125 QString msg = QString("versrow=%1 prev=%2 cur=%3 def=%4 dir=%5 hashJobNum=%6 thisJobNum=%7 filestate=%8 fec=%9 vec=%10\n")
1126 .arg(row).arg(prevState).arg(curState).arg(defState).arg(dirState).arg(hashJobNum).arg(thisJobNum).arg(fileState)
1127 .arg(m_fileExceptionHash.count()).arg(m_versionExceptionHash.count());
1128 Pmsg1(000, "%s", msg.toUtf8().data()); }
1129 /* if changed from partially checked to checked, make it unchecked */
1130 if ((curState == Qt::Checked) && (row == 0) && (fileState == Qt::Unchecked)) {
1131 if (mainWin->m_rtVerTabICDebug) Pmsg0(000, "Setting to Qt::Checked\n");
1132 fileTableItem->setCheckState(Qt::Checked);
1133 } else if ((prevState == Qt::PartiallyChecked) && (curState == Qt::Checked) && (row == 0) && (fileState == Qt::Checked) && (dirState == Qt::Unchecked)) {
1134 //versrow=0 prev=1 cur=2 def=1 dir=0 hashJobNum=0 thisJobNum=64 filestate=2 fec=1 vec=0
1135 if (mainWin->m_rtVerTabICDebug) Pmsg1(000, "fileExceptionRemove %s, %i\n", fullPath.toUtf8().data());
1136 fileExceptionRemove(fullPath, directory);
1137 } else if ((curState == Qt::Checked) && (row == 0) && (hashJobNum != 0) && (dirState != Qt::Unchecked)) {
1138 //versrow=0 prev=0 cur=2 def=1 dir=2 hashJobNum=53 thisJobNum=64 filestate=2 fec=1 vec=1
1139 if (mainWin->m_rtVerTabICDebug) Pmsg1(000, "m_versionExceptionHash.remove %s\n", fullPath.toUtf8().data());
1140 m_versionExceptionHash.remove(fullPath);
1141 fileExceptionRemove(fullPath, directory);
1142 } else if ((curState == Qt::Checked) && (row == 0)) {
1143 if (mainWin->m_rtVerTabICDebug) Pmsg1(000, "m_versionExceptionHash.remove %s\n", fullPath.toUtf8().data());
1144 m_versionExceptionHash.remove(fullPath);
1145 } else if (prevState != curState) {
1146 if (mainWin->m_rtVerTabICDebug) Pmsg2(000, " THE STATE OF THE version Check has changed, Setting StateList[%i] to %i\n", row, curState);
1147 if ((curState == Qt::Checked) || (curState == Qt::PartiallyChecked && row != 0)) {
1148 if (mainWin->m_rtVerTabICDebug) Pmsg2(000, "Inserting into m_versionExceptionHash %s, %i\n", fullPath.toUtf8().data(), thisJobNum);
1149 m_versionExceptionHash.insert(fullPath, thisJobNum);
1150 if (fileState != Qt::Checked) {
1151 if (mainWin->m_rtVerTabICDebug) Pmsg2(000, "Inserting into m_fileExceptionHash %s, %i\n", fullPath.toUtf8().data(), curState);
1152 fileExceptionInsert(fullPath, directory, curState);
1155 if (mainWin->m_rtVerTabICDebug) Pmsg0(000, "got here\n");
1158 if (mainWin->m_rtVerTabICDebug) Pmsg0(000, "no conditions met\n");
1161 updateFileTableChecks();
1162 updateVersionTableChecks();
1166 * Simple function to set the check state in the file table by disconnecting the
1167 * signal/slot the setting then reconnecting the signal/slot
1169 void restoreTree::fileTableDisconnectedSet(QTableWidgetItem *item, Qt::CheckState state, bool color)
1171 disconnect(fileTable, SIGNAL(itemChanged(QTableWidgetItem *)),
1172 this, SLOT(fileTableItemChanged(QTableWidgetItem *)));
1173 item->setCheckState(state);
1174 if (color) item->setBackground(Qt::yellow);
1175 else item->setBackground(Qt::white);
1176 connect(fileTable, SIGNAL(itemChanged(QTableWidgetItem *)),
1177 this, SLOT(fileTableItemChanged(QTableWidgetItem *)));
1181 * Simple function to set the check state in the version table by disconnecting the
1182 * signal/slot the setting then reconnecting the signal/slot
1184 void restoreTree::versionTableDisconnectedSet(QTableWidgetItem *item, Qt::CheckState state)
1186 disconnect(versionTable, SIGNAL(itemChanged(QTableWidgetItem *)),
1187 this, SLOT(versionTableItemChanged(QTableWidgetItem *)));
1188 item->setCheckState(state);
1189 connect(versionTable, SIGNAL(itemChanged(QTableWidgetItem *)),
1190 this, SLOT(versionTableItemChanged(QTableWidgetItem *)));
1194 * Simple function to set the check state in the directory tree by disconnecting the
1195 * signal/slot the setting then reconnecting the signal/slot
1197 void restoreTree::directoryTreeDisconnectedSet(QTreeWidgetItem *item, Qt::CheckState state)
1199 disconnect(directoryTree, SIGNAL(itemChanged(QTreeWidgetItem *, int)),
1200 this, SLOT(directoryItemChanged(QTreeWidgetItem *, int)));
1201 item->setCheckState(0, state);
1202 connect(directoryTree, SIGNAL(itemChanged(QTreeWidgetItem *, int)),
1203 this, SLOT(directoryItemChanged(QTreeWidgetItem *, int)));
1207 * Simplify the updating of the check state in the File table by iterating through
1208 * each item in the file table to determine it's appropriate state.
1209 * !! Will probably want to concoct a way to do this without iterating for the possibility
1210 * of the very large directories.
1212 void restoreTree::updateFileTableChecks()
1214 /* deterimine the default state from the state of the directory */
1215 QTreeWidgetItem *dirTreeItem = directoryTree->currentItem();
1216 Qt::CheckState dirState = dirTreeItem->checkState(0);
1218 QString dirName = dirTreeItem->data(0, Qt::UserRole).toString();
1220 /* Update the items in the version table */
1221 int rcnt = fileTable->rowCount();
1222 for (int row=0; row<rcnt; row++) {
1223 QTableWidgetItem* item = fileTable->item(row, 0);
1224 if (!item) { return; }
1226 Qt::CheckState curState = item->checkState();
1227 Qt::CheckState newState = Qt::PartiallyChecked;
1228 if (dirState == Qt::Unchecked) newState = Qt::Unchecked;
1230 /* determine if it is already in the m_fileExceptionHash */
1231 QString file = item->text();
1232 QString fullPath = dirName + file;
1233 Qt::CheckState hashState = m_fileExceptionHash.value(fullPath, (Qt::CheckState)3);
1234 int hashJobNum = m_versionExceptionHash.value(fullPath, 0);
1236 if (hashState != 3) newState = hashState;
1238 if (mainWin->m_rtUpdateFTDebug) {
1239 QString msg = QString("file row=%1 cur=%2 hash=%3 new=%4 dirState=%5\n")
1240 .arg(row).arg(curState).arg(hashState).arg(newState).arg(dirState);
1241 Pmsg1(000, "%s", msg.toUtf8().data());
1244 bool docolor = false;
1245 if (hashJobNum != 0) docolor = true;
1246 bool isyellow = item->background().color() == QColor(Qt::yellow);
1247 if ((newState != curState) || (hashState == 3) || ((isyellow && !docolor) || (!isyellow && docolor)))
1248 fileTableDisconnectedSet(item, newState, docolor);
1249 m_fileCheckStateList[row] = newState;
1254 * Simplify the updating of the check state in the Version table by iterating through
1255 * each item in the file table to determine it's appropriate state.
1257 void restoreTree::updateVersionTableChecks()
1259 /* deterimine the default state from the state of the directory */
1260 QTreeWidgetItem *dirTreeItem = directoryTree->currentItem();
1261 Qt::CheckState dirState = dirTreeItem->checkState(0);
1262 QString dirName = dirTreeItem->data(0, Qt::UserRole).toString();
1264 /* deterimine the default state from the state of the file */
1265 QTableWidgetItem *fileTableItem = fileTable->item(fileTable->currentRow(), 0);
1266 if (!fileTableItem) { return; }
1267 Qt::CheckState fileState = fileTableItem->checkState();
1268 QString file = fileTableItem->text();
1269 QString fullPath = dirName + file;
1270 int hashJobNum = m_versionExceptionHash.value(fullPath, 0);
1272 /* Update the items in the version table */
1273 int cnt = versionTable->rowCount();
1274 for (int row=0; row<cnt; row++) {
1275 QTableWidgetItem* item = versionTable->item(row, 0);
1276 if (!item) { break; }
1278 Qt::CheckState curState = item->checkState();
1279 Qt::CheckState newState = Qt::Unchecked;
1281 if ((row == 0) && (fileState != Qt::Unchecked) && (hashJobNum == 0))
1282 newState = Qt::PartiallyChecked;
1283 /* determine if it is already in the versionExceptionHash */
1285 int thisJobNum = item->text().toInt();
1286 if (thisJobNum == hashJobNum)
1287 newState = Qt::Checked;
1289 if (mainWin->m_rtChecksDebug) {
1290 QString msg = QString("ver row=%1 cur=%2 hashJobNum=%3 new=%4 dirState=%5\n")
1291 .arg(row).arg(curState).arg(hashJobNum).arg(newState).arg(dirState);
1292 Pmsg1(000, "%s", msg.toUtf8().data());
1294 if (newState != curState)
1295 versionTableDisconnectedSet(item, newState);
1296 m_versionCheckStateList[row] = newState;
1301 * Quick subroutine to "return via subPaths" a list of subpaths when passed a fullPath
1303 void restoreTree::fullPathtoSubPaths(QStringList &subPaths, QString &fullPath_in)
1307 QString fullPath = fullPath_in;
1308 QString direct, path;
1309 while (((index = fullPath.lastIndexOf("/", -2)) != -1) && (!done)) {
1310 direct = path = fullPath;
1311 path.replace(index+1, fullPath.length()-index-1, "");
1312 direct.replace(0, index+1, "");
1314 QString msg = QString("length = \"%1\" index = \"%2\" Considering \"%3\" \"%4\"\n")
1315 .arg(fullPath.length()).arg(index).arg(path).arg(direct);
1316 Pmsg0(000, msg.toUtf8().data());
1319 subPaths.append(fullPath);
1324 * A Function to set the icon state and insert a record into
1325 * m_directoryIconStateHash when an exception is added by the user
1327 void restoreTree::directoryIconStateInsert(QString &fullPath, Qt::CheckState excpState)
1330 fullPathtoSubPaths(paths, fullPath);
1331 /* an exception that causes the item in the file table to be "Checked" has occured */
1332 if (excpState == Qt::Checked) {
1333 bool foundAsUnChecked = false;
1334 QTreeWidgetItem *firstItem = m_dirPaths.value(paths[0]);
1336 if (firstItem->checkState(0) == Qt::Unchecked)
1337 foundAsUnChecked = true;
1339 if (foundAsUnChecked) {
1340 /* as long as directory item is Unchecked, set icon state to "green check" */
1342 QListIterator<QString> siter(paths);
1343 while (siter.hasNext() && !done) {
1344 QString path = siter.next();
1345 QTreeWidgetItem *item = m_dirPaths.value(path);
1347 if (item->checkState(0) != Qt::Unchecked)
1350 directorySetIcon(1, FolderGreenChecked, path, item);
1351 if (mainWin->m_rtIconStateDebug) Pmsg1(000, "In restoreTree::directoryIconStateInsert inserting %s\n", path.toUtf8().data());
1356 /* if it is partially checked or fully checked insert green Check until a unchecked is found in the path */
1357 if (mainWin->m_rtIconStateDebug) Pmsg1(000, "In restoreTree::directoryIconStateInsert Aqua %s\n", paths[0].toUtf8().data());
1359 QListIterator<QString> siter(paths);
1360 while (siter.hasNext() && !done) {
1361 QString path = siter.next();
1362 QTreeWidgetItem *item = m_dirPaths.value(path);
1363 if (item) { /* if the directory item is checked, set icon state to unchecked "green check" */
1364 if (item->checkState(0) == Qt::Checked)
1366 directorySetIcon(1, FolderGreenChecked, path, item);
1367 if (mainWin->m_rtIconStateDebug) Pmsg1(000, "In restoreTree::directoryIconStateInsert boogie %s\n", path.toUtf8().data());
1372 /* an exception that causes the item in the file table to be "Unchecked" has occured */
1373 if (excpState == Qt::Unchecked) {
1375 QListIterator<QString> siter(paths);
1376 while (siter.hasNext() && !done) {
1377 QString path = siter.next();
1378 QTreeWidgetItem *item = m_dirPaths.value(path);
1379 if (item) { /* if the directory item is checked, set icon state to unchecked "white check" */
1380 if (item->checkState(0) == Qt::Checked)
1382 directorySetIcon(1, FolderWhiteChecked, path, item);
1383 if (mainWin->m_rtIconStateDebug) Pmsg1(000, "In restoreTree::directoryIconStateInsert boogie %s\n", path.toUtf8().data());
1390 * A function to set the icon state back to "folder" and to remove a record from
1391 * m_directoryIconStateHash when an exception is removed by a user.
1393 void restoreTree::directoryIconStateRemove()
1395 QHash<QString, int> shouldBeIconStateHash;
1396 /* First determine all paths with icons that should be checked with m_fileExceptionHash */
1397 /* Use iterator tera to iterate through m_fileExceptionHash */
1398 QHashIterator<QString, Qt::CheckState> tera(m_fileExceptionHash);
1399 while (tera.hasNext()) {
1401 if (mainWin->m_rtIconStateDebug) Pmsg2(000, "Alpha Key %s value %i\n", tera.key().toUtf8().data(), tera.value());
1403 QString keyPath = tera.key();
1404 Qt::CheckState state = tera.value();
1407 fullPathtoSubPaths(paths, keyPath);
1408 /* if the state of the item in m_fileExceptionHash is checked
1409 * each of the subpaths should be "Checked Green" */
1410 if (state == Qt::Checked) {
1412 bool foundAsUnChecked = false;
1413 QTreeWidgetItem *firstItem = m_dirPaths.value(paths[0]);
1415 if (firstItem->checkState(0) == Qt::Unchecked)
1416 foundAsUnChecked = true;
1418 if (foundAsUnChecked) {
1419 /* The right most directory is Unchecked, iterate leftwards
1420 * as long as directory item is Unchecked, set icon state to "green check" */
1422 QListIterator<QString> siter(paths);
1423 while (siter.hasNext() && !done) {
1424 QString path = siter.next();
1425 QTreeWidgetItem *item = m_dirPaths.value(path);
1427 if (item->checkState(0) != Qt::Unchecked)
1430 shouldBeIconStateHash.insert(path, FolderGreenChecked);
1431 if (mainWin->m_rtIconStateDebug) Pmsg1(000, "In restoreTree::directoryIconStateInsert inserting %s\n", path.toUtf8().data());
1437 /* The right most directory is Unchecked, iterate leftwards
1438 * until directory item is Checked, set icon state to "green check" */
1440 QListIterator<QString> siter(paths);
1441 while (siter.hasNext() && !done) {
1442 QString path = siter.next();
1443 QTreeWidgetItem *item = m_dirPaths.value(path);
1445 if (item->checkState(0) == Qt::Checked)
1447 shouldBeIconStateHash.insert(path, FolderGreenChecked);
1452 /* if the state of the item in m_fileExceptionHash is UNChecked
1453 * each of the subpaths should be "Checked white" until the tree item
1454 * which represents that path is Qt::Checked */
1455 if (state == Qt::Unchecked) {
1457 QListIterator<QString> siter(paths);
1458 while (siter.hasNext() && !done) {
1459 QString path = siter.next();
1460 QTreeWidgetItem *item = m_dirPaths.value(path);
1462 if (item->checkState(0) == Qt::Checked)
1464 shouldBeIconStateHash.insert(path, FolderWhiteChecked);
1469 /* now iterate through m_directoryIconStateHash which are the items that are checked
1470 * and remove all of those that are not in shouldBeIconStateHash */
1471 QHashIterator<QString, int> iter(m_directoryIconStateHash);
1472 while (iter.hasNext()) {
1474 if (mainWin->m_rtIconStateDebug) Pmsg2(000, "Beta Key %s value %i\n", iter.key().toUtf8().data(), iter.value());
1476 QString keyPath = iter.key();
1477 if (shouldBeIconStateHash.value(keyPath)) {
1478 if (mainWin->m_rtIconStateDebug) Pmsg1(000, "WAS found in shouldBeStateHash %s\n", keyPath.toUtf8().data());
1479 //newval = m_directoryIconStateHash.value(path, FolderUnchecked) & (~change);
1480 int newval = shouldBeIconStateHash.value(keyPath);
1482 newval = newval & FolderBothChecked;
1483 QTreeWidgetItem *item = m_dirPaths.value(keyPath);
1485 directorySetIcon(0, newval, keyPath, item);
1487 if (mainWin->m_rtIconStateDebug) Pmsg1(000, "NOT found in shouldBeStateHash %s\n", keyPath.toUtf8().data());
1488 QTreeWidgetItem *item = m_dirPaths.value(keyPath);
1490 directorySetIcon(0, FolderBothChecked, keyPath, item);
1491 //item->setIcon(0,QIcon(QString::fromUtf8(":images/folder.png")));
1492 //m_directoryIconStateHash.remove(keyPath);
1497 void restoreTree::directorySetIcon(int operation, int change, QString &path, QTreeWidgetItem* item) {
1499 /* we are adding a check type white or green */
1500 if (operation > 0) {
1501 /* get the old val and "bitwise OR" with the change */
1502 newval = m_directoryIconStateHash.value(path, FolderUnchecked) | change;
1503 if (mainWin->m_rtIconStateDebug) Pmsg2(000, "Inserting into m_directoryIconStateHash path=%s newval=%i\n", path.toUtf8().data(), newval);
1504 m_directoryIconStateHash.insert(path, newval);
1506 /* we are removing a check type white or green */
1507 newval = m_directoryIconStateHash.value(path, FolderUnchecked) & (~change);
1509 if (mainWin->m_rtIconStateDebug) Pmsg2(000, "Removing from m_directoryIconStateHash path=%s newval=%i\n", path.toUtf8().data(), newval);
1510 m_directoryIconStateHash.remove(path);
1513 if (mainWin->m_rtIconStateDebug) Pmsg2(000, "Inserting into m_directoryIconStateHash path=%s newval=%i\n", path.toUtf8().data(), newval);
1514 m_directoryIconStateHash.insert(path, newval);
1517 if (newval == FolderUnchecked)
1518 item->setIcon(0, QIcon(QString::fromUtf8(":images/folder.png")));
1519 else if (newval == FolderGreenChecked)
1520 item->setIcon(0, QIcon(QString::fromUtf8(":images/folderchecked.png")));
1521 else if (newval == FolderWhiteChecked)
1522 item->setIcon(0, QIcon(QString::fromUtf8(":images/folderunchecked.png")));
1523 else if (newval == FolderBothChecked)
1524 item->setIcon(0, QIcon(QString::fromUtf8(":images/folderbothchecked.png")));
1530 void restoreTree::restoreButtonPushed()
1532 /* Set progress bars and repaint */
1533 prLabel1->setVisible(true);
1534 prLabel1->setText(tr("Task 1 of 3"));
1535 prLabel2->setVisible(true);
1536 prLabel2->setText(tr("Processing Checked directories"));
1537 prBar1->setVisible(true);
1538 prBar1->setRange(0, 3);
1539 prBar1->setValue(0);
1540 prBar2->setVisible(true);
1541 prBar2->setRange(0, 0);
1543 QMultiHash<int, QString> versionFilesMulti;
1545 QHash <QString, bool> fullPathDone;
1546 QHash <QString, int> fileIndexHash;
1547 if ((mainWin->m_rtRestore1Debug) || (mainWin->m_rtRestore2Debug) || (mainWin->m_rtRestore3Debug))
1548 Pmsg0(000, "In restoreTree::restoreButtonPushed\n");
1549 /* Use a tree widget item iterator to count directories for the progress bar */
1550 QTreeWidgetItemIterator diterc(directoryTree, QTreeWidgetItemIterator::Checked);
1555 } /* while (*diterc) */
1556 prBar2->setRange(0, ditcount);
1557 prBar2->setValue(0);
1559 /* Use a tree widget item iterator filtering for Checked Items */
1560 QTreeWidgetItemIterator diter(directoryTree, QTreeWidgetItemIterator::Checked);
1562 QString directory = (*diter)->data(0, Qt::UserRole).toString();
1563 int pathid = m_directoryPathIdHash.value(directory, -1);
1565 if (mainWin->m_rtRestore1Debug)
1566 Pmsg1(000, "Directory Checked=\"%s\"\n", directory.toUtf8().data());
1567 /* With a checked directory, query for the files in the directory */
1570 "SELECT Filename.Name AS Filename, t1.JobId AS JobId, File.FileIndex AS FileIndex"
1572 " ( SELECT File.FilenameId AS FilenameId, MAX(Job.JobId) AS JobId"
1574 " INNER JOIN Job ON (Job.JobId=File.JobId)"
1575 " WHERE File.PathId=" + QString("%1").arg(pathid) +
1576 " AND Job.Jobid IN (" + m_checkedJobs + ")"
1577 " GROUP BY File.FilenameId"
1579 " INNER JOIN Filename on (Filename.FilenameId=File.FilenameId)"
1580 " INNER JOIN Job ON (Job.JobId=File.JobId)"
1581 " WHERE File.PathId=" + QString("%1").arg(pathid) +
1582 " AND File.FilenameId=t1.FilenameId"
1583 " AND Job.Jobid=t1.JobId"
1584 " ORDER BY Filename";
1586 if (mainWin->m_sqlDebug) Pmsg1(000, "Query cmd : %s\n", cmd.toUtf8().data());
1587 QStringList results;
1588 if (m_console->sql_cmd(cmd, results)) {
1589 QStringList fieldlist;
1592 /* Iterate through the record returned from the query */
1593 foreach (QString resultline, results) {
1594 /* Iterate through fields in the record */
1596 QString fullPath = "";
1597 Qt::CheckState fileExcpState = (Qt::CheckState)4;
1598 fieldlist = resultline.split("\t");
1601 foreach (QString field, fieldlist) {
1603 fullPath = directory + field;
1606 version = field.toInt();
1609 fileIndex = field.toInt();
1613 fileExcpState = m_fileExceptionHash.value(fullPath, (Qt::CheckState)3);
1615 int excpVersion = m_versionExceptionHash.value(fullPath, 0);
1616 if (fileExcpState != Qt::Unchecked) {
1618 if (excpVersion != 0) {
1619 debugtext = QString("*E* version=%1").arg(excpVersion);
1620 version = excpVersion;
1621 fileIndex = queryFileIndex(fullPath, excpVersion);
1623 debugtext = QString("___ version=%1").arg(version);
1624 if (mainWin->m_rtRestore1Debug)
1625 Pmsg2(000, "Restoring %s File %s\n", debugtext.toUtf8().data(), fullPath.toUtf8().data());
1626 fullPathDone.insert(fullPath, 1);
1627 fileIndexHash.insert(fullPath, fileIndex);
1628 versionFilesMulti.insert(version, fullPath);
1636 prBar2->setValue(ditcount);
1638 } /* while (*diter) */
1639 prBar1->setValue(1);
1640 prLabel1->setText( tr("Task 2 of 3"));
1641 prLabel2->setText(tr("Processing Exceptions"));
1642 prBar2->setRange(0, 0);
1645 /* There may be some exceptions not accounted for yet with fullPathDone */
1646 QHashIterator<QString, Qt::CheckState> ftera(m_fileExceptionHash);
1647 while (ftera.hasNext()) {
1649 QString fullPath = ftera.key();
1650 Qt::CheckState state = ftera.value();
1652 /* now we don't want the ones already done */
1653 if (fullPathDone.value(fullPath, 0) == 0) {
1654 int version = m_versionExceptionHash.value(fullPath, 0);
1656 QString debugtext = "";
1658 fileIndex = queryFileIndex(fullPath, version);
1659 debugtext = QString("E1* version=%1 fileid=%2").arg(version).arg(fileIndex);
1661 version = mostRecentVersionfromFullPath(fullPath);
1663 fileIndex = queryFileIndex(fullPath, version);
1664 debugtext = QString("E2* version=%1 fileid=%2").arg(version).arg(fileIndex);
1666 debugtext = QString("Error det vers").arg(version);
1668 if (mainWin->m_rtRestore1Debug)
1669 Pmsg2(000, "Restoring %s file %s\n", debugtext.toUtf8().data(), fullPath.toUtf8().data());
1670 versionFilesMulti.insert(version, fullPath);
1672 fileIndexHash.insert(fullPath, fileIndex);
1673 } /* if fullPathDone.value(fullPath, 0) == 0 */
1674 } /* if state != 0 */
1675 } /* while ftera.hasNext */
1676 /* The progress bars for the next step */
1677 prBar1->setValue(2);
1678 prLabel1->setText(tr("Task 3 of 3"));
1679 prLabel2->setText(tr("Filling Database Table"));
1680 prBar2->setRange(0, vFMCounter);
1682 prBar2->setValue(vFMCounter);
1685 /* now for the final spit out of the versions and lists of files for each version */
1686 QHash<int, int> doneKeys;
1687 QHashIterator<int, QString> vFMiter(versionFilesMulti);
1688 QString tempTable = "";
1690 while (vFMiter.hasNext()) {
1692 int fversion = vFMiter.key();
1693 /* did not succeed in getting an iterator to work as expected on versionFilesMulti so use doneKeys */
1694 if (doneKeys.value(fversion, 0) == 0) {
1695 if (tempTable == "") {
1696 QSettings settings("www.bacula.org", "bat");
1697 settings.beginGroup("Restore");
1698 int counter = settings.value("Counter", 1).toInt();
1699 settings.setValue("Counter", counter+1);
1700 settings.endGroup();
1701 tempTable = "restore_" + QString("%1").arg(qrand()) + "_" + QString("%1").arg(counter);
1702 QString sqlcmd = "CREATE TEMPORARY TABLE " + tempTable + " (JobId INTEGER, FileIndex INTEGER)";
1703 if (mainWin->m_sqlDebug)
1704 Pmsg1(000, "Query cmd : %s ;\n", sqlcmd.toUtf8().data());
1705 QStringList results;
1706 if (!m_console->sql_cmd(sqlcmd, results))
1707 Pmsg1(000, "CREATE TABLE FAILED!!!! %s\n", sqlcmd.toUtf8().data());
1710 if (mainWin->m_rtRestore2Debug) Pmsg1(000, "Version->%i\n", fversion);
1711 QStringList fullPathList = versionFilesMulti.values(fversion);
1712 /* create the command to perform the restore */
1713 foreach(QString ffullPath, fullPathList) {
1714 int fileIndex = fileIndexHash.value(ffullPath);
1715 if (mainWin->m_rtRestore2Debug) Pmsg2(000, " file->%s id %i\n", ffullPath.toUtf8().data(), fileIndex);
1716 QString sqlcmd = "INSERT INTO " + tempTable + " (JobId, FileIndex) VALUES (" + QString("%1").arg(fversion) + ", " + QString("%1").arg(fileIndex) + ")";
1717 if (mainWin->m_rtRestore3Debug)
1718 Pmsg1(000, "Insert cmd : %s\n", sqlcmd.toUtf8().data());
1719 QStringList results;
1720 if (!m_console->sql_cmd(sqlcmd, results))
1721 Pmsg1(000, "INSERT INTO FAILED!!!! %s\n", sqlcmd.toUtf8().data());
1722 prBar2->setValue(++vFMCounter);
1723 } /* foreach fullPathList */
1724 doneKeys.insert(fversion,1);
1725 jobList.append(fversion);
1726 } /* if (doneKeys.value(fversion, 0) == 0) */
1727 } /* while (vFMiter.hasNext()) */
1728 if (tempTable != "") {
1729 /* a table was made, lets run the job */
1730 QString jobOption = " jobid=\"";
1732 /* create a list of jobs comma separated */
1733 foreach (int job, jobList) {
1734 if (first) first = false;
1735 else jobOption += ",";
1736 jobOption += QString("%1").arg(job);
1739 QString cmd = QString("restore");
1741 " client=\"" + m_prevClientCombo + "\"" +
1742 " file=\"?" + tempTable + "\" done";
1743 if (mainWin->m_commandDebug)
1744 Pmsg1(000, "preRestore command \'%s\'\n", cmd.toUtf8().data());
1745 consoleCommand(cmd);
1747 /* turn off the progress widgets */
1748 prBar1->setVisible(false);
1749 prBar2->setVisible(false);
1750 prLabel1->setVisible(false);
1751 prLabel2->setVisible(false);
1754 int restoreTree::mostRecentVersionfromFullPath(QString &fullPath)
1757 QString directory, fileName;
1758 int index = fullPath.lastIndexOf("/", -2);
1760 directory = fileName = fullPath;
1761 directory.replace(index+1, fullPath.length()-index-1, "");
1762 fileName.replace(0, index+1, "");
1764 QString msg = QString("length = \"%1\" index = \"%2\" Considering \"%3\" \"%4\"\n")
1765 .arg(fullPath.length()).arg(index).arg(fileName).arg(directory);
1766 Pmsg0(000, msg.toUtf8().data());
1768 int pathid = m_directoryPathIdHash.value(directory, -1);
1770 /* so now we need the latest version from the database */
1772 "SELECT MAX(Job.JobId)"
1774 " INNER JOIN Filename on (Filename.FilenameId=File.FilenameId)"
1775 " INNER JOIN Job ON (File.JobId=Job.JobId)"
1776 " WHERE File.PathId=" + QString("%1").arg(pathid) +
1777 " AND Job.Jobid IN (" + m_checkedJobs + ")"
1778 " AND Filename.Name='" + fileName + "'"
1779 " AND File.FilenameId!=" + QString("%1").arg(m_nullFileNameId) +
1780 " GROUP BY Filename.Name";
1782 if (mainWin->m_sqlDebug) Pmsg1(000, "Query cmd : %s\n", cmd.toUtf8().data());
1783 QStringList results;
1784 if (m_console->sql_cmd(cmd, results)) {
1785 QStringList fieldlist;
1787 /* Iterate through the record returned from the query */
1788 foreach (QString resultline, results) {
1789 /* Iterate through fields in the record */
1791 fieldlist = resultline.split("\t");
1792 foreach (QString field, fieldlist) {
1794 qversion = field.toInt();
1802 } /* if (index != -1) */
1807 int restoreTree::queryFileIndex(QString &fullPath, int jobId)
1810 QString directory, fileName;
1811 int index = fullPath.lastIndexOf("/", -2);
1813 directory = fileName = fullPath;
1814 directory.replace(index+1, fullPath.length()-index-1, "");
1815 fileName.replace(0, index+1, "");
1817 QString msg = QString("length = \"%1\" index = \"%2\" Considering \"%3\" \"%4\"\n")
1818 .arg(fullPath.length()).arg(index).arg(fileName).arg(directory);
1819 Pmsg0(000, msg.toUtf8().data());
1821 int pathid = m_directoryPathIdHash.value(directory, -1);
1823 /* so now we need the latest version from the database */
1828 " INNER JOIN Filename on (Filename.FilenameId=File.FilenameId)"
1829 " INNER JOIN Job ON (File.JobId=Job.JobId)"
1830 " WHERE File.PathId=" + QString("%1").arg(pathid) +
1831 " AND Filename.Name='" + fileName + "'"
1832 " AND Job.Jobid='" + QString("%1").arg(jobId) + "'"
1833 " GROUP BY File.FileIndex";
1835 if (mainWin->m_sqlDebug) Pmsg1(000, "Query cmd : %s\n", cmd.toUtf8().data());
1836 QStringList results;
1837 if (m_console->sql_cmd(cmd, results)) {
1838 QStringList fieldlist;
1840 /* Iterate through the record returned from the query */
1841 foreach (QString resultline, results) {
1842 /* Iterate through fields in the record */
1844 fieldlist = resultline.split("\t");
1845 foreach (QString field, fieldlist) {
1847 qfileIndex = field.toInt();
1855 } /* if (index != -1) */
1860 void restoreTree::PgSeltreeWidgetClicked()
1862 if (!isOnceDocked()) {