2 Bacula® - The Network Backup Solution
4 Copyright (C) 2007-2007 Free Software Foundation Europe e.V.
6 The main author of Bacula is Kern Sibbald, with contributions from
7 many others, a complete list can be found in the file AUTHORS.
8 This program is Free Software; you can redistribute it and/or
9 modify it under the terms of version two of the GNU General Public
10 License as published by the Free Software Foundation and included
13 This program is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
23 Bacula® is a registered trademark of John Walker.
24 The licensor of Bacula is the Free Software Foundation Europe
25 (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich,
26 Switzerland, email:ftf@fsfeurope.org.
30 * Version $Id: restore.cpp 4945 2007-05-31 01:24:28Z bartleyd2 $
34 * Kern Sibbald, February MMVII
39 #include "restoretree.h"
42 restoreTree::restoreTree()
45 m_name = "Version Browser";
47 QTreeWidgetItem* thisitem = mainWin->getFromHash(this);
48 thisitem->setIcon(0, QIcon(QString::fromUtf8(":images/browse.png")));
55 m_winRegExpDrive.setPattern("^[a-z]:/$");
56 m_winRegExpPath.setPattern("^[a-z]:/");
57 m_slashregex.setPattern("/");
62 restoreTree::~restoreTree()
68 * Called from the constructor to set up the page widgets and connections.
70 void restoreTree::setupPage()
72 connect(refreshButton, SIGNAL(pressed()), this, SLOT(refreshButtonPushed()));
73 connect(testButton, SIGNAL(pressed()), this, SLOT(testButtonPushed()));
74 connect(jobCombo, SIGNAL(currentIndexChanged(int)), this, SLOT(jobComboChanged(int)));
75 connect(directoryTree, SIGNAL(currentItemChanged(QTreeWidgetItem *, QTreeWidgetItem *)),
76 this, SLOT(directoryCurrentItemChanged(QTreeWidgetItem *, QTreeWidgetItem *)));
77 connect(directoryTree, SIGNAL(itemExpanded(QTreeWidgetItem *)),
78 this, SLOT(directoryItemExpanded(QTreeWidgetItem *)));
79 connect(directoryTree, SIGNAL(itemChanged(QTreeWidgetItem *, int)),
80 this, SLOT(directoryItemChanged(QTreeWidgetItem *, int)));
81 connect(fileTable, SIGNAL(currentItemChanged(QTableWidgetItem *, QTableWidgetItem *)),
82 this, SLOT(fileCurrentItemChanged(QTableWidgetItem *, QTableWidgetItem *)));
84 QStringList titles = QStringList() << "Directories";
85 directoryTree->setHeaderLabels(titles);
86 clientCombo->addItems(m_console->client_list);
87 fileSetCombo->addItem("Any");
88 fileSetCombo->addItems(m_console->fileset_list);
89 jobCombo->addItems(m_console->job_list);
91 directoryTree->setContextMenuPolicy(Qt::ActionsContextMenu);
95 * When refresh button is pushed, perform a query getting the directories and
96 * use parseDirectory and addDirectory to populate the directory tree with items.
98 void restoreTree::populateDirectoryTree()
102 directoryTree->clear();
104 fileTable->setRowCount(0);
105 fileTable->setColumnCount(0);
106 versionTable->clear();
107 versionTable->setRowCount(0);
108 versionTable->setColumnCount(0);
109 m_fileExceptionHash.clear();
110 m_fileExceptionMulti.clear();
111 m_versionExceptionHash.clear();
112 m_directoryIconStateHash.clear();
115 int clientIndex = clientCombo->currentIndex();
116 int fileSetIndex = fileSetCombo->currentIndex();
117 QString jobComboText = jobCombo->itemText(jobCombo->currentIndex());
118 QString clientComboText = clientCombo->itemText(clientIndex);
119 QString fileSetComboText = fileSetCombo->itemText(fileSetIndex);
120 if ((m_prevJobCombo != jobComboText) || (m_prevClientCombo != clientComboText) || (m_prevFileSetCombo != fileSetComboText)) {
121 m_prevJobCombo = jobComboText;
122 m_prevClientCombo = clientComboText;
123 m_prevFileSetCombo = fileSetComboText;
124 if (mainWin->m_rtPopDirDebug) Pmsg0(000, "Repopulating the Job Table\n");
126 m_condition = " Job.name = '" + jobCombo->itemText(jobCombo->currentIndex()) + "'";
127 if ((clientIndex >= 0) && (clientCombo->itemText(clientIndex) != "Any")) {
128 m_condition.append(" AND Client.Name='" + clientCombo->itemText(clientIndex) + "'");
130 if ((fileSetIndex >= 0) && (fileSetCombo->itemText(fileSetIndex) != "Any")) {
131 m_condition.append(" AND FileSet.FileSet='" + fileSetCombo->itemText(fileSetIndex) + "'");
134 " LEFT OUTER JOIN Client ON (Job.ClientId=Client.ClientId)"
135 " LEFT OUTER JOIN FileSet ON (Job.FileSetId=FileSet.FileSetId)"
136 " WHERE" + m_condition +
137 " AND Job.purgedfiles=0";
140 " From Job" + m_jobQueryPart;
141 if (mainWin->m_sqlDebug) {
142 Pmsg1(000, "Query cmd : %s\n", m_jobQuery.toUtf8().data());
145 setJobsCheckedList();
147 setJobsCheckedList();
151 "SELECT DISTINCT Path.Path"
153 " LEFT OUTER JOIN File ON (File.PathId=Path.PathId)"
154 " LEFT OUTER JOIN Job ON (File.JobId=Job.JobId)"
155 " WHERE Job.Jobid IN (" + m_jobQuery + ")";
156 if (mainWin->m_sqlDebug) {
157 Pmsg1(000, "Query cmd : %s\n", cmd.toUtf8().data());
159 QStringList directories;
160 if (m_console->sql_cmd(cmd, directories)) {
161 if (mainWin->m_miscDebug) {
162 Pmsg1(000, "Done with query %i directories\n", directories.count());
164 foreach(QString directory, directories) {
166 parseDirectory(directory);
172 * Function to set m_jobQuery from the jobs that are checked in the table
175 void restoreTree::setJobsCheckedList()
177 m_JobsCheckedList = "";
179 /* Update the items in the version table */
180 int cnt = jobTable->rowCount();
181 for (int row=0; row<cnt; row++) {
182 QTableWidgetItem* jobItem = jobTable->item(row, 0);
183 if (jobItem->checkState() == Qt::Checked) {
185 m_JobsCheckedList += ",";
186 m_JobsCheckedList += jobItem->text();
188 jobItem->setBackground(Qt::green);
190 jobItem->setBackground(Qt::gray);
192 m_jobQuery = m_JobsCheckedList;
196 * Function to parse a directory into all possible subdirectories, then add to
199 void restoreTree::parseDirectory(QString &dir_in)
201 /* m_debugTrap is to only print debugs for a few occurances of calling parseDirectory
202 * instead of printing out what could potentially a whole bunch */
205 /* Clean up the directory string remove some funny char after last '/' */
206 QRegExp rgx("[^/]$");
207 int lastslash = rgx.indexIn(dir_in);
208 dir_in.replace(lastslash, dir_in.length()-lastslash, "");
209 if ((mainWin->m_miscDebug) && (m_debugTrap))
210 Pmsg1(000, "parsing %s\n", dir_in.toUtf8().data());
212 /* split and add if not in yet */
213 QString direct, path;
216 QStringList pathAfter, dirAfter;
217 /* start from the end, turn /etc/somedir/subdir/ into /etc/somedir and subdir/
218 * if not added into tree, then try /etc/ and somedir/ if not added, then try
219 * / and etc/ . That should succeed, then add the ones that failed in reverse */
220 while (((index = m_slashregex.lastIndexIn(dir_in, -2)) != -1) && (!done)) {
221 direct = path = dir_in;
222 path.replace(index+1, dir_in.length()-index-1,"");
223 direct.replace(0, index+1, "");
224 if ((mainWin->m_miscDebug) && (m_debugTrap)) {
225 QString msg = QString("length = \"%1\" index = \"%2\" Adding \"%3\" \"%4\"\n")
226 .arg(dir_in.length()).arg(index).arg(path).arg(direct);
227 Pmsg0(000, msg.toUtf8().data());
229 if (addDirectory(path, direct)) done = true;
231 if ((mainWin->m_miscDebug) && (m_debugTrap))
232 Pmsg0(000, "Saving for later\n");
233 pathAfter.prepend(path);
234 dirAfter.prepend(direct);
239 for (int k=0; k<pathAfter.count(); k++) {
240 if (addDirectory(pathAfter[k], dirAfter[k]))
241 if ((mainWin->m_miscDebug) && (m_debugTrap))
242 Pmsg2(000, "Adding After %s %s\n", pathAfter[k].toUtf8().data(), dirAfter[k].toUtf8().data());
244 if ((mainWin->m_miscDebug) && (m_debugTrap))
245 Pmsg2(000, "Error Adding %s %s\n", pathAfter[k].toUtf8().data(), dirAfter[k].toUtf8().data());
250 * Function called from fill directory when a directory is found to see if this
251 * directory exists in the directory pane and then add it to the directory pane
253 bool restoreTree::addDirectory(QString &m_cwd, QString &newdirr)
255 QString newdir = newdirr;
256 QString fullPath = m_cwd + newdirr;
257 bool ok = true, added = false;
259 if ((mainWin->m_miscDebug) && (m_debugTrap)) {
260 QString msg = QString("In addDirectory cwd \"%1\" newdir \"%2\"\n")
263 Pmsg0(000, msg.toUtf8().data());
267 /* add unix '/' directory first */
268 if (m_dirPaths.empty() && (m_winRegExpPath.indexIn(fullPath, 0) == -1)) {
270 QTreeWidgetItem *item = new QTreeWidgetItem(directoryTree);
272 item->setText(0, text.toUtf8().data());
273 item->setData(0, Qt::UserRole, QVariant(text));
274 item->setData(1, Qt::UserRole, QVariant(Qt::Unchecked));
275 item->setIcon(0, QIcon(QString::fromUtf8(":images/folder.png")));
276 if ((mainWin->m_miscDebug) && (m_debugTrap)) {
277 Pmsg1(000, "Pre Inserting %s\n", text.toUtf8().data());
279 m_dirPaths.insert(text, item);
281 /* no need to check for windows drive if unix */
282 if (m_winRegExpDrive.indexIn(m_cwd, 0) == 0) {
283 /* this is a windows drive add the base widget */
284 QTreeWidgetItem *item = new QTreeWidgetItem(directoryTree);
285 item->setText(0, m_cwd);
286 item->setData(0, Qt::UserRole, QVariant(fullPath));
287 item->setData(1, Qt::UserRole, QVariant(Qt::Unchecked));
288 item->setIcon(0, QIcon(QString::fromUtf8(":images/folder.png")));
289 if ((mainWin->m_miscDebug) && (m_debugTrap)) {
290 Pmsg0(000, "Added Base \"letter\":/\n");
292 m_dirPaths.insert(m_cwd, item);
296 /* is it already existent ?? */
297 if (!m_dirPaths.contains(fullPath)) {
298 QTreeWidgetItem *item = NULL;
299 QTreeWidgetItem *parent = m_dirPaths.value(m_cwd);
301 /* new directories to add */
302 item = new QTreeWidgetItem(parent);
303 item->setText(0, newdir.toUtf8().data());
304 item->setData(0, Qt::UserRole, QVariant(fullPath));
305 item->setCheckState(0, Qt::Unchecked);
306 /* Store the current state of the check status in column 1, which at
307 * this point has no text*/
308 item->setData(1, Qt::UserRole, QVariant(Qt::Unchecked));
311 if ((mainWin->m_miscDebug) && (m_debugTrap)) {
312 QString msg = QString("In else of if parent cwd \"%1\" newdir \"%2\"\n")
315 Pmsg0(000, msg.toUtf8().data());
318 /* insert into hash */
320 if ((mainWin->m_miscDebug) && (m_debugTrap)) {
321 Pmsg1(000, "Inserting %s\n", fullPath.toUtf8().data());
323 m_dirPaths.insert(fullPath, item);
331 * Virtual function which is called when this page is visible on the stack
333 void restoreTree::currentStackItem()
336 if (!m_console->preventInUseConnect())
344 * Populate the tree when refresh button pushed.
346 void restoreTree::refreshButtonPushed()
348 populateDirectoryTree();
352 * Set the values of non-job combo boxes to the job defaults
354 void restoreTree::jobComboChanged(int)
356 job_defaults job_defs;
359 job_defs.job_name = jobCombo->currentText();
360 if (m_console->get_job_defaults(job_defs)) {
361 fileSetCombo->setCurrentIndex(fileSetCombo->findText(job_defs.fileset_name, Qt::MatchExactly));
362 clientCombo->setCurrentIndex(clientCombo->findText(job_defs.client_name, Qt::MatchExactly));
367 * Function to populate the file list table
369 void restoreTree::directoryCurrentItemChanged(QTreeWidgetItem *item, QTreeWidgetItem *)
374 m_fileCheckStateList.clear();
375 disconnect(fileTable, SIGNAL(itemChanged(QTableWidgetItem *)),
376 this, SLOT(fileTableItemChanged(QTableWidgetItem *)));
377 QBrush blackBrush(Qt::black);
378 QString directory = item->data(0, Qt::UserRole).toString();
379 directoryLabel->setText("Present Working Directory : " + directory);
381 "SELECT DISTINCT Filename.Name"
383 " LEFT OUTER JOIN Filename on (Filename.FilenameId=File.FilenameId)"
384 " LEFT OUTER JOIN Path ON (Path.PathId=File.PathId)"
385 " LEFT OUTER JOIN Job ON (File.JobId=Job.JobId)"
386 " WHERE Path.Path='" + directory + "' AND Filename.Name!=''"
387 " AND Job.Jobid IN (" + m_jobQuery + ")";
389 QStringList headerlist = (QStringList() << "File Name");
391 /* Also clear the version table here */
392 versionTable->clear();
393 versionFileLabel->setText("");
394 versionTable->setRowCount(0);
395 versionTable->setColumnCount(0);
396 fileTable->setColumnCount(headerlist.size());
397 fileTable->setHorizontalHeaderLabels(headerlist);
399 if (mainWin->m_sqlDebug) {
400 Pmsg1(000, "Query cmd : %s\n", cmd.toUtf8().data());
403 if (m_console->sql_cmd(cmd, results)) {
405 QTableWidgetItem* tableItem;
407 QStringList fieldlist;
408 fileTable->setRowCount(results.size());
411 /* Iterate through the record returned from the query */
412 foreach (QString resultline, results) {
413 /* Iterate through fields in the record */
415 fieldlist = resultline.split("\t");
416 foreach (field, fieldlist) {
417 field = field.trimmed(); /* strip leading & trailing spaces */
418 tableItem = new QTableWidgetItem(field, 1);
419 /* Possible flags are Qt::ItemFlags flag = Qt::ItemIsSelectable | Qt::ItemIsEditablex
420 * | Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled | Qt::ItemIsUserCheckable
421 * | Qt::ItemIsEnabled | Qt::ItemIsTristate; */
422 tableItem->setForeground(blackBrush);
423 /* Just in case a column ever gets added */
425 Qt::ItemFlags flag = Qt::ItemIsUserCheckable | Qt::ItemIsEnabled | Qt::ItemIsTristate;
426 tableItem->setFlags(flag);
427 tableItem->setData(Qt::UserRole, QVariant(directory));
428 fileTable->setItem(row, column, tableItem);
429 m_fileCheckStateList.append(Qt::Unchecked);
430 tableItem->setCheckState(Qt::Unchecked);
436 fileTable->setRowCount(row);
438 fileTable->resizeColumnsToContents();
439 fileTable->resizeRowsToContents();
440 fileTable->verticalHeader()->hide();
441 connect(fileTable, SIGNAL(itemChanged(QTableWidgetItem *)),
442 this, SLOT(fileTableItemChanged(QTableWidgetItem *)));
443 if (mainWin->m_rtDirCurICDebug) Pmsg0(000, "will update file table checks\n");
444 updateFileTableChecks();
448 * Function to populate the version table
450 void restoreTree::fileCurrentItemChanged(QTableWidgetItem *fileTableItem, QTableWidgetItem *)
452 if (fileTableItem == NULL)
455 m_versionCheckStateList.clear();
456 disconnect(versionTable, SIGNAL(itemChanged(QTableWidgetItem *)),
457 this, SLOT(versionTableItemChanged(QTableWidgetItem *)));
459 QString file = fileTableItem->text();
460 versionFileLabel->setText(file);
461 QString directory = fileTableItem->data(Qt::UserRole).toString();
463 QBrush blackBrush(Qt::black);
465 "SELECT Job.JobId AS JobId, Job.Level AS Type, Job.EndTime AS EndTime, File.Md5 AS MD5, File.FileId AS FileId"
467 " LEFT OUTER JOIN Filename on (Filename.FilenameId=File.FilenameId)"
468 " LEFT OUTER JOIN Path ON (Path.PathId=File.PathId)"
469 " LEFT OUTER JOIN Job ON (File.JobId=Job.JobId)"
470 " WHERE Filename.Name='" + file + "' AND Path.Path='" + directory + "'"
471 " AND Job.Jobid IN (" + m_jobQuery + ")"
472 " ORDER BY Job.EndTime DESC";
474 QStringList headerlist = (QStringList() << "Job Id" << "Type" << "End Time" << "Md5" << "FileId");
475 versionTable->clear();
476 versionTable->setColumnCount(headerlist.size());
477 versionTable->setHorizontalHeaderLabels(headerlist);
479 if (mainWin->m_sqlDebug) {
480 Pmsg1(000, "Query cmd : %s\n", cmd.toUtf8().data());
483 if (m_console->sql_cmd(cmd, results)) {
485 QTableWidgetItem* tableItem;
487 QStringList fieldlist;
488 versionTable->setRowCount(results.size());
491 /* Iterate through the record returned from the query */
492 foreach (QString resultline, results) {
493 fieldlist = resultline.split("\t");
495 /* remove directory */
496 if (fieldlist[0].trimmed() != "") {
497 /* Iterate through fields in the record */
498 foreach (field, fieldlist) {
499 field = field.trimmed(); /* strip leading & trailing spaces */
500 tableItem = new QTableWidgetItem(field, 1);
501 tableItem->setFlags(0);
502 tableItem->setForeground(blackBrush);
503 tableItem->setData(Qt::UserRole, QVariant(directory));
504 versionTable->setItem(row, column, tableItem);
507 Qt::ItemFlags flag = Qt::ItemIsUserCheckable | Qt::ItemIsEnabled | Qt::ItemIsTristate;
508 tableItem->setFlags(flag);
509 m_versionCheckStateList.append(Qt::Unchecked);
510 tableItem->setCheckState(Qt::Unchecked);
518 versionTable->resizeColumnsToContents();
519 versionTable->resizeRowsToContents();
520 versionTable->verticalHeader()->hide();
521 connect(versionTable, SIGNAL(itemChanged(QTableWidgetItem *)),
522 this, SLOT(versionTableItemChanged(QTableWidgetItem *)));
523 updateVersionTableChecks();
527 * Save user settings associated with this page
529 void restoreTree::writeSettings()
531 QSettings settings(m_console->m_dir->name(), "bat");
532 settings.beginGroup("RestoreTree");
533 settings.setValue("splitterSizes", splitter->saveState());
538 * Read and restore user settings associated with this page
540 void restoreTree::readSettings()
542 QSettings settings(m_console->m_dir->name(), "bat");
543 settings.beginGroup("RestoreTree");
544 splitter->restoreState(settings.value("splitterSizes").toByteArray());
549 * This is a funcion to accomplish the one thing I struggled to figure out what
550 * was taking so long. It add the icons, but after the tree is made. Seemed to
551 * work fast after changing from svg to png file for graphic.
553 void restoreTree::directoryItemExpanded(QTreeWidgetItem *item)
555 int childCount = item->childCount();
556 for (int i=0; i<childCount; i++) {
557 QTreeWidgetItem *child = item->child(i);
558 if (child->icon(0).isNull())
559 child->setIcon(0, QIcon(QString::fromUtf8(":images/folder.png")));
564 * I wanted a table to show what jobs meet the criterion and are being used to
565 * populate the directory tree and file and version tables.
567 void restoreTree::populateJobTable()
569 QBrush blackBrush(Qt::black);
570 QStringList headerlist = (QStringList() << "Job Id" << "End Time" << "Type");
572 jobTable->setColumnCount(headerlist.size());
573 jobTable->setHorizontalHeaderLabels(headerlist);
575 "SELECT Job.Jobid AS Id, Job.EndTime AS EndTime, Job.Level AS Level"
576 " FROM Job" + m_jobQueryPart +
577 " ORDER BY Job.EndTime DESC";
578 if (mainWin->m_sqlDebug) {
579 Pmsg1(000, "Query cmd : %s\n", jobQuery.toUtf8().data());
583 if (m_console->sql_cmd(jobQuery, results)) {
585 QTableWidgetItem* tableItem;
587 QStringList fieldlist;
588 jobTable->setRowCount(results.size());
591 /* Iterate through the record returned from the query */
592 foreach (QString resultline, results) {
593 fieldlist = resultline.split("\t");
595 /* remove directory */
596 if (fieldlist[0].trimmed() != "") {
597 /* Iterate through fields in the record */
598 foreach (field, fieldlist) {
599 field = field.trimmed(); /* strip leading & trailing spaces */
600 tableItem = new QTableWidgetItem(field, 1);
601 tableItem->setFlags(0);
602 tableItem->setForeground(blackBrush);
603 jobTable->setItem(row, column, tableItem);
605 Qt::ItemFlags flag = Qt::ItemIsUserCheckable | Qt::ItemIsEnabled | Qt::ItemIsTristate;
606 tableItem->setFlags(flag);
607 tableItem->setCheckState(Qt::Checked);
608 tableItem->setBackground(Qt::green);
616 jobTable->resizeColumnsToContents();
617 jobTable->resizeRowsToContents();
618 jobTable->verticalHeader()->hide();
622 * When a directory item is "changed" check the state of the checkable item
623 * to see if it is different than what it was which is stored in Qt::UserRole
624 * of the 2nd column, column 1, of the tree widget.
626 void restoreTree::directoryItemChanged(QTreeWidgetItem *item, int /*column*/)
628 Qt::CheckState prevState = (Qt::CheckState)item->data(1, Qt::UserRole).toInt();
629 Qt::CheckState curState = item->checkState(0);
630 QTreeWidgetItem* parent = item->parent();
631 Qt::CheckState parState;
632 if (parent) parState = parent->checkState(0);
633 else parState = (Qt::CheckState)3;
634 if (mainWin->m_rtDirICDebug) {
635 QString msg = QString("directory item OBJECT has changed prev=%1 cur=%2 par=%3 dir=%4\n")
636 .arg(prevState).arg(curState).arg(parState).arg(item->text(0));
637 Pmsg1(000, "%s", msg.toUtf8().data()); }
638 /* I only care when the check state changes */
639 if (prevState == curState) {
640 if (mainWin->m_rtDirICDebug) Pmsg0(000, "Returning Early\n");
644 if ((prevState == Qt::Unchecked) && (curState == Qt::Checked) && (parState != Qt::Unchecked)) {
645 if (mainWin->m_rtDirICDebug) Pmsg0(000, "Disconnected Setting to Qt::PartiallyChecked\n");
646 directoryTreeDisconnectedSet(item, Qt::PartiallyChecked);
647 curState = Qt::PartiallyChecked;
649 if ((prevState == Qt::PartiallyChecked) && (curState == Qt::Checked)) {
650 if (mainWin->m_rtDirICDebug) Pmsg0(000, "Disconnected Setting to Qt::Unchecked\n");
651 directoryTreeDisconnectedSet(item, Qt::Unchecked);
652 curState = Qt::Unchecked;
654 if (mainWin->m_rtDirICDebug) {
655 QString msg = QString("directory item CHECKSTATE has changed prev=%1 cur=%2 par=%3 dir=%4\n")
656 .arg(prevState).arg(curState).arg(parState).arg(item->text(0));
657 Pmsg1(000, "%s", msg.toUtf8().data()); }
659 item->setData(1, Qt::UserRole, QVariant(curState));
660 Qt::CheckState childState = curState;
661 if (childState == Qt::Checked)
662 childState = Qt::PartiallyChecked;
663 setCheckofChildren(item, childState);
665 /* Remove items from the exception lists. The multi exception list is my index
666 * of what exceptions can be removed when the directory is known*/
667 QString directory = item->data(0, Qt::UserRole).toString();
668 QStringList fullPathList = m_fileExceptionMulti.values(directory);
669 int fullPathListCount = fullPathList.count();
670 if ((mainWin->m_rtDirICDebug) && fullPathListCount) Pmsg2(000, "Will attempt to remove file exceptions for %s count %i\n", directory.toUtf8().data(), fullPathListCount);
671 foreach (QString fullPath, fullPathList) {
672 /* If there is no value in the hash for the key fullPath a value of 3 will be returned
673 * which will match no Qt::xxx values */
674 Qt::CheckState hashState = m_fileExceptionHash.value(fullPath, (Qt::CheckState)3);
675 if (mainWin->m_rtDirICDebug) Pmsg2(000, "hashState=%i childState=%i\n", hashState, childState);
676 if (hashState == Qt::Unchecked) {
677 fileExceptionRemove(fullPath, directory);
678 m_versionExceptionHash.remove(fullPath);
679 if (mainWin->m_rtDirICDebug) Pmsg0(000, "Attempted Removal A\n");
681 if (hashState == Qt::Checked) {
682 fileExceptionRemove(fullPath, directory);
683 m_versionExceptionHash.remove(fullPath);
684 if (mainWin->m_rtDirICDebug) Pmsg0(000, "Attempted Removal B\n");
688 if (item == directoryTree->currentItem()) {
689 if (mainWin->m_rtDirICDebug) Pmsg0(000, "Will attempt to update File Table Checks\n");
690 updateFileTableChecks();
691 versionTable->clear();
692 versionTable->setRowCount(0);
693 versionTable->setColumnCount(0);
695 if (mainWin->m_rtDirICDebug) Pmsg0(000, "Returning At End\n");
699 * When a directory item check state is changed, this function iterates through
700 * all subdirectories and sets all to the passed state, which is either partially
701 * checked or unchecked.
703 void restoreTree::setCheckofChildren(QTreeWidgetItem *item, Qt::CheckState state)
706 childCount = item->childCount();
707 for (int i=0; i<childCount; i++) {
708 QTreeWidgetItem *child = item->child(i);
709 child->setData(1, Qt::UserRole, QVariant(state));
710 child->setCheckState(0, state);
711 setCheckofChildren(child, state);
716 * When a File Table Item is "changed" check to see if the state of the checkable
717 * item has changed which is stored in m_fileCheckStateList
718 * If changed store in a hash m_fileExceptionHash that whether this file should be
720 * Called as a slot, connected after populated (after directory current changed called)
722 void restoreTree::fileTableItemChanged(QTableWidgetItem *item)
724 /* get the previous and current check states */
725 int row = fileTable->row(item);
726 Qt::CheckState prevState;
727 /* prevent a segfault */
728 prevState = m_fileCheckStateList[row];
729 Qt::CheckState curState = item->checkState();
731 /* deterimine the default state from the state of the directory */
732 QTreeWidgetItem *dirTreeItem = directoryTree->currentItem();
733 Qt::CheckState dirState = (Qt::CheckState)dirTreeItem->data(1, Qt::UserRole).toInt();
734 Qt::CheckState defState = Qt::PartiallyChecked;
735 if (dirState == Qt::Unchecked) defState = Qt::Unchecked;
737 /* determine if it is already in the m_fileExceptionHash */
738 QString directory = directoryTree->currentItem()->data(0, Qt::UserRole).toString();
739 QString file = item->text();
740 QString fullPath = directory + file;
741 Qt::CheckState hashState = m_fileExceptionHash.value(fullPath, (Qt::CheckState)3);
742 int verJobNum = m_versionExceptionHash.value(fullPath, 0);
744 if (mainWin->m_rtFileTabICDebug) {
745 QString msg = QString("filerow=%1 prev=%2 cur=%3 def=%4 hash=%5 dir=%6 verJobNum=%7\n")
746 .arg(row).arg(prevState).arg(curState).arg(defState).arg(hashState).arg(dirState).arg(verJobNum);
747 Pmsg1(000, "%s", msg.toUtf8().data()); }
749 /* Remove the hash if currently checked previously unchecked and directory is checked or partial */
750 if ((prevState == Qt::Checked) && (curState == Qt::Unchecked) && (dirState == Qt::Unchecked)) {
751 /* it can behave as defaulted so current of unchecked is fine */
752 if (mainWin->m_rtFileTabICDebug) Pmsg0(000, "Will fileExceptionRemove and m_versionExceptionHash.remove here\n");
753 fileExceptionRemove(fullPath, directory);
754 m_versionExceptionHash.remove(fullPath);
755 } else if ((prevState == Qt::PartiallyChecked) && (curState == Qt::Checked) && (dirState != Qt::Unchecked) && (verJobNum == 0)) {
756 if (mainWin->m_rtFileTabICDebug) Pmsg0(000, "Will fileExceptionInsert here\n");
757 fileExceptionInsert(fullPath, directory, Qt::Unchecked);
758 } else if ((prevState == Qt::Unchecked) && (curState == Qt::Checked) && (dirState != Qt::Unchecked) && (verJobNum == 0) && (defState == Qt::PartiallyChecked)) {
759 /* filerow=2 prev=0 cur=2 def=1 hash=0 dir=2 verJobNum=0 */
760 if (mainWin->m_rtFileTabICDebug) Pmsg0(000, "Will fileExceptionRemove here\n");
761 fileExceptionRemove(fullPath, directory);
762 } else if ((prevState == Qt::Checked) && (curState == Qt::Unchecked) && (defState == Qt::PartiallyChecked) && (verJobNum != 0) && (hashState == Qt::Checked)) {
763 /* Check dir, check version, attempt uncheck in file
764 * filerow=4 prev=2 cur=0 def=1 hash=2 dir=2 verJobNum=53 */
765 if (mainWin->m_rtFileTabICDebug) Pmsg0(000, "Will fileExceptionRemove and m_versionExceptionHash.remove here\n");
766 fileExceptionRemove(fullPath, directory);
767 m_versionExceptionHash.remove(fullPath);
768 } else if ((prevState == Qt::Unchecked) && (curState == Qt::Checked) && (dirState != Qt::Unchecked) && (verJobNum == 0)) {
769 /* filerow=0 prev=0 cur=2 def=1 hash=0 dirState=2 verJobNum */
770 if (mainWin->m_rtFileTabICDebug) Pmsg0(000, "Will Not remove here\n");
771 } else if (prevState != curState) {
772 if (mainWin->m_rtFileTabICDebug) Pmsg2(000, " THE STATE OF THE Check has changed, Setting StateList[%i] to %i\n", row, curState);
773 /* A user did not set the check state to Partially checked, ignore if so */
774 if (curState != Qt::PartiallyChecked) {
775 if ((defState == Qt::Unchecked) && (prevState == Qt::PartiallyChecked) && (curState == Qt::Unchecked)) {
776 if (mainWin->m_rtFileTabICDebug) Pmsg0(000, " got here\n");
778 if (mainWin->m_rtFileTabICDebug) Pmsg2(000, " Inserting into m_fileExceptionHash %s, %i\n", fullPath.toUtf8().data(), curState);
779 fileExceptionInsert(fullPath, directory, curState);
782 if (mainWin->m_rtFileTabICDebug) Pmsg1(000, "Removing version hash for %s\n", fullPath.toUtf8().data());
783 /* programattically been changed back to a default state of Qt::PartiallyChecked remove the version hash here */
784 m_versionExceptionHash.remove(fullPath);
788 updateFileTableChecks();
789 updateVersionTableChecks();
793 * function to insert keys and values to both m_fileExceptionHash and m_fileExceptionMulti
795 void restoreTree::fileExceptionInsert(QString &fullPath, QString &direcotry, Qt::CheckState state)
797 m_fileExceptionHash.insert(fullPath, state);
798 m_fileExceptionMulti.insert(direcotry, fullPath);
799 directoryIconStateInsert(fullPath, state);
803 * function to remove keys from both m_fileExceptionHash and m_fileExceptionMulti
805 void restoreTree::fileExceptionRemove(QString &fullPath, QString &directory)
807 m_fileExceptionHash.remove(fullPath);
808 /* pull the list of values in the multi */
809 QStringList fullPathList = m_fileExceptionMulti.values(directory);
810 /* get the index of the fullpath to remove */
811 int index = fullPathList.indexOf(fullPath);
813 /* remove the desired item in the list */
814 fullPathList.removeAt(index);
815 /* remove the entire list from the multi */
816 m_fileExceptionMulti.remove(directory);
817 /* readd the remaining */
818 foreach (QString fp, fullPathList) {
819 m_fileExceptionMulti.insert(directory, fp);
822 directoryIconStateRemove();
826 * Overloaded function to be called from the slot and from other places to set the state
827 * of the check marks in the version table
829 void restoreTree::versionTableItemChanged(QTableWidgetItem *item)
831 /* get the previous and current check states */
832 int row = versionTable->row(item);
833 QTableWidgetItem *colZeroItem = versionTable->item(row, 0);
834 Qt::CheckState prevState = m_versionCheckStateList[row];
835 Qt::CheckState curState = (Qt::CheckState)colZeroItem->checkState();
836 m_versionCheckStateList[row] = curState;
838 /* deterimine the default state from the state of the file */
839 QTableWidgetItem *fileTableItem = fileTable->currentItem();
840 Qt::CheckState fileState = (Qt::CheckState)fileTableItem->checkState();
842 /* determine the default state */
843 Qt::CheckState defState;
845 defState = Qt::PartiallyChecked;
846 if (fileState == Qt::Unchecked)
847 defState = Qt::Unchecked;
850 defState = Qt::Unchecked;
852 /* determine if it is already in the versionExceptionHash */
853 QString directory = directoryTree->currentItem()->data(0, Qt::UserRole).toString();
854 Qt::CheckState dirState = directoryTree->currentItem()->checkState(0);
855 QString file = fileTableItem->text();
856 QString fullPath = directory + file;
857 int thisJobNum = colZeroItem->text().toInt();
858 int hashJobNum = m_versionExceptionHash.value(fullPath, 0);
860 if (mainWin->m_rtVerTabICDebug) {
861 QString msg = QString("versrow=%1 prev=%2 cur=%3 def=%4 dir=%5 hashJobNum=%6 thisJobNum=%7 filestate=%8 fec=%9 vec=%10\n")
862 .arg(row).arg(prevState).arg(curState).arg(defState).arg(dirState).arg(hashJobNum).arg(thisJobNum).arg(fileState)
863 .arg(m_fileExceptionHash.count()).arg(m_versionExceptionHash.count());
864 Pmsg1(000, "%s", msg.toUtf8().data()); }
865 /* if changed from partially checked to checked, make it unchecked */
866 if ((curState == Qt::Checked) && (row == 0) && (fileState == Qt::Unchecked)) {
867 if (mainWin->m_rtVerTabICDebug) Pmsg0(000, "Setting to Qt::Checked\n");
868 fileTableItem->setCheckState(Qt::Checked);
869 } else if ((prevState == Qt::PartiallyChecked) && (curState == Qt::Checked) && (row == 0) && (fileState == Qt::Checked) && (dirState == Qt::Unchecked)) {
870 //versrow=0 prev=1 cur=2 def=1 dir=0 hashJobNum=0 thisJobNum=64 filestate=2 fec=1 vec=0
871 if (mainWin->m_rtVerTabICDebug) Pmsg1(000, "fileExceptionRemove %s, %i\n", fullPath.toUtf8().data());
872 fileExceptionRemove(fullPath, directory);
873 } else if ((curState == Qt::Checked) && (row == 0) && (hashJobNum != 0) && (dirState != Qt::Unchecked)) {
874 //versrow=0 prev=0 cur=2 def=1 dir=2 hashJobNum=53 thisJobNum=64 filestate=2 fec=1 vec=1
875 if (mainWin->m_rtVerTabICDebug) Pmsg1(000, "m_versionExceptionHash.remove %s\n", fullPath.toUtf8().data());
876 m_versionExceptionHash.remove(fullPath);
877 fileExceptionRemove(fullPath, directory);
878 } else if ((curState == Qt::Checked) && (row == 0)) {
879 if (mainWin->m_rtVerTabICDebug) Pmsg1(000, "m_versionExceptionHash.remove %s\n", fullPath.toUtf8().data());
880 m_versionExceptionHash.remove(fullPath);
881 } else if (prevState != curState) {
882 if (mainWin->m_rtVerTabICDebug) Pmsg2(000, " THE STATE OF THE version Check has changed, Setting StateList[%i] to %i\n", row, curState);
883 if ((curState == Qt::Checked) || (curState == Qt::PartiallyChecked) && (row != 0)) {
884 if (mainWin->m_rtVerTabICDebug) Pmsg2(000, "Inserting into m_versionExceptionHash %s, %i\n", fullPath.toUtf8().data(), thisJobNum);
885 m_versionExceptionHash.insert(fullPath, thisJobNum);
886 if (fileState != Qt::Checked) {
887 if (mainWin->m_rtVerTabICDebug) Pmsg2(000, "Inserting into m_fileExceptionHash %s, %i\n", fullPath.toUtf8().data(), curState);
888 fileExceptionInsert(fullPath, directory, curState);
891 if (mainWin->m_rtVerTabICDebug) Pmsg0(000, "got here\n");
894 if (mainWin->m_rtVerTabICDebug) Pmsg0(000, "no conditions met\n");
897 updateFileTableChecks();
898 updateVersionTableChecks();
902 * Simple function to set the check state in the file table by disconnecting the
903 * signal/slot the setting then reconnecting the signal/slot
905 void restoreTree::fileTableDisconnectedSet(QTableWidgetItem *item, Qt::CheckState state, bool color)
907 disconnect(fileTable, SIGNAL(itemChanged(QTableWidgetItem *)),
908 this, SLOT(fileTableItemChanged(QTableWidgetItem *)));
909 item->setCheckState(state);
910 if (color) item->setBackground(Qt::yellow);
911 else item->setBackground(Qt::white);
912 connect(fileTable, SIGNAL(itemChanged(QTableWidgetItem *)),
913 this, SLOT(fileTableItemChanged(QTableWidgetItem *)));
917 * Simple function to set the check state in the version table by disconnecting the
918 * signal/slot the setting then reconnecting the signal/slot
920 void restoreTree::versionTableDisconnectedSet(QTableWidgetItem *item, Qt::CheckState state)
922 disconnect(versionTable, SIGNAL(itemChanged(QTableWidgetItem *)),
923 this, SLOT(versionTableItemChanged(QTableWidgetItem *)));
924 item->setCheckState(state);
925 connect(versionTable, SIGNAL(itemChanged(QTableWidgetItem *)),
926 this, SLOT(versionTableItemChanged(QTableWidgetItem *)));
930 * Simple function to set the check state in the directory tree by disconnecting the
931 * signal/slot the setting then reconnecting the signal/slot
933 void restoreTree::directoryTreeDisconnectedSet(QTreeWidgetItem *item, Qt::CheckState state)
935 disconnect(directoryTree, SIGNAL(itemChanged(QTreeWidgetItem *, int)),
936 this, SLOT(directoryItemChanged(QTreeWidgetItem *, int)));
937 item->setCheckState(0, state);
938 connect(directoryTree, SIGNAL(itemChanged(QTreeWidgetItem *, int)),
939 this, SLOT(directoryItemChanged(QTreeWidgetItem *, int)));
943 * Simplify the updating of the check state in the File table by iterating through
944 * each item in the file table to determine it's appropriate state.
945 * !! Will probably want to concoct a way to do this without iterating for the possibility
946 * of the very large directories.
948 void restoreTree::updateFileTableChecks()
950 /* deterimine the default state from the state of the directory */
951 QTreeWidgetItem *dirTreeItem = directoryTree->currentItem();
952 Qt::CheckState dirState = dirTreeItem->checkState(0);
954 QString dirName = dirTreeItem->data(0, Qt::UserRole).toString();
956 /* Update the items in the version table */
957 int rcnt = fileTable->rowCount();
958 for (int row=0; row<rcnt; row++) {
959 QTableWidgetItem* item = fileTable->item(row, 0);
961 Qt::CheckState curState = item->checkState();
962 Qt::CheckState newState = Qt::PartiallyChecked;
963 if (dirState == Qt::Unchecked) newState = Qt::Unchecked;
965 /* determine if it is already in the m_fileExceptionHash */
966 QString file = item->text();
967 QString fullPath = dirName + file;
968 Qt::CheckState hashState = m_fileExceptionHash.value(fullPath, (Qt::CheckState)3);
969 int hashJobNum = m_versionExceptionHash.value(fullPath, 0);
971 if (hashState != 3) newState = hashState;
973 if (mainWin->m_rtUpdateFTDebug) {
974 QString msg = QString("file row=%1 cur=%2 hash=%3 new=%4 dirState=%5\n")
975 .arg(row).arg(curState).arg(hashState).arg(newState).arg(dirState);
976 Pmsg1(000, "%s", msg.toUtf8().data());
979 bool docolor = false;
980 if (hashJobNum != 0) docolor = true;
981 bool isyellow = item->background().color() == QColor(Qt::yellow);
982 if ((newState != curState) || (hashState == 3) || ((isyellow && !docolor) || (!isyellow && docolor)))
983 fileTableDisconnectedSet(item, newState, docolor);
984 m_fileCheckStateList[row] = newState;
989 * Simplify the updating of the check state in the Version table by iterating through
990 * each item in the file table to determine it's appropriate state.
992 void restoreTree::updateVersionTableChecks()
994 /* deterimine the default state from the state of the directory */
995 QTreeWidgetItem *dirTreeItem = directoryTree->currentItem();
996 Qt::CheckState dirState = dirTreeItem->checkState(0);
997 QString dirName = dirTreeItem->data(0, Qt::UserRole).toString();
999 /* deterimine the default state from the state of the file */
1000 QTableWidgetItem *fileTableItem = fileTable->item(fileTable->currentRow(), 0);
1001 Qt::CheckState fileState = fileTableItem->checkState();
1002 QString file = fileTableItem->text();
1003 QString fullPath = dirName + file;
1004 int hashJobNum = m_versionExceptionHash.value(fullPath, 0);
1006 /* Update the items in the version table */
1007 int cnt = versionTable->rowCount();
1008 for (int row=0; row<cnt; row++) {
1009 QTableWidgetItem* item = versionTable->item(row, 0);
1011 Qt::CheckState curState = item->checkState();
1012 Qt::CheckState newState = Qt::Unchecked;
1014 if ((row == 0) && (fileState != Qt::Unchecked) && (hashJobNum == 0))
1015 newState = Qt::PartiallyChecked;
1016 /* determine if it is already in the versionExceptionHash */
1018 int thisJobNum = item->text().toInt();
1019 if (thisJobNum == hashJobNum)
1020 newState = Qt::Checked;
1022 if (mainWin->m_rtChecksDebug) {
1023 QString msg = QString("ver row=%1 cur=%2 hashJobNum=%3 new=%4 dirState=%5\n")
1024 .arg(row).arg(curState).arg(hashJobNum).arg(newState).arg(dirState);
1025 Pmsg1(000, "%s", msg.toUtf8().data());
1027 if (newState != curState)
1028 versionTableDisconnectedSet(item, newState);
1029 m_versionCheckStateList[row] = newState;
1034 * Quick subroutine to "return via subPaths" a list of subpaths when passed a fullPath
1036 void restoreTree::fullPathtoSubPaths(QStringList &subPaths, QString &fullPath_in)
1040 QString fullPath = fullPath_in;
1041 QString direct, path;
1042 while (((index = m_slashregex.lastIndexIn(fullPath, -2)) != -1) && (!done)) {
1043 direct = path = fullPath;
1044 path.replace(index+1, fullPath.length()-index-1, "");
1045 direct.replace(0, index+1, "");
1047 QString msg = QString("length = \"%1\" index = \"%2\" Considering \"%3\" \"%4\"\n")
1048 .arg(fullPath.length()).arg(index).arg(path).arg(direct);
1049 Pmsg0(000, msg.toUtf8().data());
1052 subPaths.append(fullPath);
1057 * A Function to set the icon state and insert a record into
1058 * m_directoryIconStateHash when an exception is added by the user
1060 void restoreTree::directoryIconStateInsert(QString &fullPath, Qt::CheckState excpState)
1063 fullPathtoSubPaths(paths, fullPath);
1064 /* an exception that causes the item in the file table to be "Checked" has occured */
1065 if (excpState == Qt::Checked) {
1066 bool foundAsUnChecked = false;
1067 QTreeWidgetItem *firstItem = m_dirPaths.value(paths[0]);
1069 if (firstItem->checkState(0) == Qt::Unchecked)
1070 foundAsUnChecked = true;
1072 if (foundAsUnChecked) {
1073 /* as long as directory item is Unchecked, set icon state to "green check" */
1075 QListIterator<QString> siter(paths);
1076 while (siter.hasNext() && !done) {
1077 QString path = siter.next();
1078 QTreeWidgetItem *item = m_dirPaths.value(path);
1080 if (item->checkState(0) != Qt::Unchecked)
1083 directorySetIcon(1, FolderGreenChecked, path, item);
1084 if (mainWin->m_rtIconStateDebug) Pmsg1(000, "In restoreTree::directoryIconStateInsert inserting %s\n", path.toUtf8().data());
1089 /* if it is partially checked or fully checked insert green Check until a unchecked is found in the path */
1090 if (mainWin->m_rtIconStateDebug) Pmsg1(000, "In restoreTree::directoryIconStateInsert Aqua %s\n", paths[0].toUtf8().data());
1092 QListIterator<QString> siter(paths);
1093 while (siter.hasNext() && !done) {
1094 QString path = siter.next();
1095 QTreeWidgetItem *item = m_dirPaths.value(path);
1096 if (item) { /* if the directory item is checked, set icon state to unchecked "green check" */
1097 if (item->checkState(0) == Qt::Checked)
1099 directorySetIcon(1, FolderGreenChecked, path, item);
1100 if (mainWin->m_rtIconStateDebug) Pmsg1(000, "In restoreTree::directoryIconStateInsert boogie %s\n", path.toUtf8().data());
1105 /* an exception that causes the item in the file table to be "Unchecked" has occured */
1106 if (excpState == Qt::Unchecked) {
1108 QListIterator<QString> siter(paths);
1109 while (siter.hasNext() && !done) {
1110 QString path = siter.next();
1111 QTreeWidgetItem *item = m_dirPaths.value(path);
1112 if (item) { /* if the directory item is checked, set icon state to unchecked "white check" */
1113 if (item->checkState(0) == Qt::Checked)
1115 directorySetIcon(1, FolderWhiteChecked, path, item);
1116 if (mainWin->m_rtIconStateDebug) Pmsg1(000, "In restoreTree::directoryIconStateInsert boogie %s\n", path.toUtf8().data());
1123 * A function to set the icon state back to "folder" and to remove a record from
1124 * m_directoryIconStateHash when an exception is removed by a user.
1126 void restoreTree::directoryIconStateRemove()
1128 QHash<QString, int> shouldBeIconStateHash;
1129 /* First determine all paths with icons that should be checked with m_fileExceptionHash */
1130 /* Use iterator tera to iterate through m_fileExceptionHash */
1131 QHashIterator<QString, Qt::CheckState> tera(m_fileExceptionHash);
1132 while (tera.hasNext()) {
1134 if (mainWin->m_rtIconStateDebug) Pmsg2(000, "Alpha Key %s value %i\n", tera.key().toUtf8().data(), tera.value());
1136 QString keyPath = tera.key();
1137 Qt::CheckState state = tera.value();
1140 fullPathtoSubPaths(paths, keyPath);
1141 /* if the state of the item in m_fileExceptionHash is checked
1142 * each of the subpaths should be "Checked Green" */
1143 if (state == Qt::Checked) {
1145 bool foundAsUnChecked = false;
1146 QTreeWidgetItem *firstItem = m_dirPaths.value(paths[0]);
1148 if (firstItem->checkState(0) == Qt::Unchecked)
1149 foundAsUnChecked = true;
1151 if (foundAsUnChecked) {
1152 /* The right most directory is Unchecked, iterate leftwards
1153 * as long as directory item is Unchecked, set icon state to "green check" */
1155 QListIterator<QString> siter(paths);
1156 while (siter.hasNext() && !done) {
1157 QString path = siter.next();
1158 QTreeWidgetItem *item = m_dirPaths.value(path);
1160 if (item->checkState(0) != Qt::Unchecked)
1163 shouldBeIconStateHash.insert(path, FolderGreenChecked);
1164 if (mainWin->m_rtIconStateDebug) Pmsg1(000, "In restoreTree::directoryIconStateInsert inserting %s\n", path.toUtf8().data());
1170 /* The right most directory is Unchecked, iterate leftwards
1171 * until directory item is Checked, set icon state to "green check" */
1173 QListIterator<QString> siter(paths);
1174 while (siter.hasNext() && !done) {
1175 QString path = siter.next();
1176 QTreeWidgetItem *item = m_dirPaths.value(path);
1178 if (item->checkState(0) == Qt::Checked)
1180 shouldBeIconStateHash.insert(path, FolderGreenChecked);
1185 /* if the state of the item in m_fileExceptionHash is UNChecked
1186 * each of the subpaths should be "Checked white" until the tree item
1187 * which represents that path is Qt::Checked */
1188 if (state == Qt::Unchecked) {
1190 QListIterator<QString> siter(paths);
1191 while (siter.hasNext() && !done) {
1192 QString path = siter.next();
1193 QTreeWidgetItem *item = m_dirPaths.value(path);
1195 if (item->checkState(0) == Qt::Checked)
1197 shouldBeIconStateHash.insert(path, FolderWhiteChecked);
1202 /* now iterate through m_directoryIconStateHash which are the items that are checked
1203 * and remove all of those that are not in shouldBeIconStateHash */
1204 QHashIterator<QString, int> iter(m_directoryIconStateHash);
1205 while (iter.hasNext()) {
1207 if (mainWin->m_rtIconStateDebug) Pmsg2(000, "Beta Key %s value %i\n", iter.key().toUtf8().data(), iter.value());
1209 QString keyPath = iter.key();
1210 if (shouldBeIconStateHash.value(keyPath)) {
1211 if (mainWin->m_rtIconStateDebug) Pmsg1(000, "WAS found in shouldBeStateHash %s\n", keyPath.toUtf8().data());
1212 //newval = m_directoryIconStateHash.value(path, FolderUnchecked) & (~change);
1213 int newval = shouldBeIconStateHash.value(keyPath);
1215 newval = newval & FolderBothChecked;
1216 QTreeWidgetItem *item = m_dirPaths.value(keyPath);
1218 directorySetIcon(0, newval, keyPath, item);
1220 if (mainWin->m_rtIconStateDebug) Pmsg1(000, "NOT found in shouldBeStateHash %s\n", keyPath.toUtf8().data());
1221 QTreeWidgetItem *item = m_dirPaths.value(keyPath);
1223 directorySetIcon(0, FolderBothChecked, keyPath, item);
1224 //item->setIcon(0,QIcon(QString::fromUtf8(":images/folder.png")));
1225 //m_directoryIconStateHash.remove(keyPath);
1230 void restoreTree::directorySetIcon(int operation, int change, QString &path, QTreeWidgetItem* item) {
1232 /* we are adding a check type white or green */
1233 if (operation > 0) {
1234 /* get the old val and "bitwise OR" with the change */
1235 newval = m_directoryIconStateHash.value(path, FolderUnchecked) | change;
1236 if (mainWin->m_rtIconStateDebug) Pmsg2(000, "Inserting into m_directoryIconStateHash path=%s newval=%i\n", path.toUtf8().data(), newval);
1237 m_directoryIconStateHash.insert(path, newval);
1239 /* we are removing a check type white or green */
1240 newval = m_directoryIconStateHash.value(path, FolderUnchecked) & (~change);
1242 if (mainWin->m_rtIconStateDebug) Pmsg2(000, "Removing from m_directoryIconStateHash path=%s newval=%i\n", path.toUtf8().data(), newval);
1243 m_directoryIconStateHash.remove(path);
1246 if (mainWin->m_rtIconStateDebug) Pmsg2(000, "Inserting into m_directoryIconStateHash path=%s newval=%i\n", path.toUtf8().data(), newval);
1247 m_directoryIconStateHash.insert(path, newval);
1250 if (newval == FolderUnchecked)
1251 item->setIcon(0, QIcon(QString::fromUtf8(":images/folder.png")));
1252 else if (newval == FolderGreenChecked)
1253 item->setIcon(0, QIcon(QString::fromUtf8(":images/folderchecked.png")));
1254 else if (newval == FolderWhiteChecked)
1255 item->setIcon(0, QIcon(QString::fromUtf8(":images/folderunchecked.png")));
1256 else if (newval == FolderBothChecked)
1257 item->setIcon(0, QIcon(QString::fromUtf8(":images/folderbothchecked.png")));
1263 void restoreTree::testButtonPushed()
1265 QMultiHash<int, QString> versionFilesMulti;
1266 QHash <QString, bool> fullPathDone;
1267 QHash <QString, int> fileIdHash;
1268 if ((mainWin->m_rtRestore1Debug) || (mainWin->m_rtRestore2Debug) || (mainWin->m_rtRestore3Debug))
1269 Pmsg0(000, "In restoreTree::testButtonPushed\n");
1270 /* Use a tree widget item iterator filtering for Checked Items */
1271 QTreeWidgetItemIterator diter(directoryTree, QTreeWidgetItemIterator::Checked);
1273 QString directory = (*diter)->data(0, Qt::UserRole).toString();
1274 if (mainWin->m_rtRestore1Debug)
1275 Pmsg1(000, "Directory Checked=\"%s\"\n", directory.toUtf8().data());
1276 /* With a checked directory, query for the files in the directory */
1279 "SELECT t1.Filename AS Filename, t1.JobId AS JobId, File.Fileid AS Fileid"
1281 " ( SELECT Filename.Name AS Filename, MAX(Job.JobId) AS JobId"
1283 " LEFT OUTER JOIN Filename on (Filename.FilenameId=File.FilenameId)"
1284 " LEFT OUTER JOIN Path ON (Path.PathId=File.PathId)"
1285 " LEFT OUTER JOIN Job ON (Job.JobId=File.JobId)"
1286 " WHERE Path.Path='" + directory + "' AND Filename.Name!=''"
1287 " AND Job.Jobid IN (" + m_jobQuery + ")"
1288 " GROUP BY Filename.Name"
1290 " LEFT OUTER JOIN Filename on (Filename.FilenameId=File.FilenameId)"
1291 " LEFT OUTER JOIN Path ON (Path.PathId=File.PathId)"
1292 " LEFT OUTER JOIN Job ON (Job.JobId=File.JobId)"
1294 " Path.Path='/etc/bacula/'"
1295 " AND Filename.Name=t1.Filename"
1296 " AND Job.Jobid=t1.JobId"
1297 " ORDER BY Filename";
1299 if (mainWin->m_sqlDebug) Pmsg1(000, "Query cmd : %s\n", cmd.toUtf8().data());
1300 QStringList results;
1301 if (m_console->sql_cmd(cmd, results)) {
1303 QStringList fieldlist;
1306 /* Iterate through the record returned from the query */
1307 foreach (QString resultline, results) {
1308 /* Iterate through fields in the record */
1310 QString fullPath = "";
1311 Qt::CheckState fileExcpState = (Qt::CheckState)4;
1312 fieldlist = resultline.split("\t");
1315 foreach (QString field, fieldlist) {
1317 fullPath = directory + field;
1320 version = field.toInt();
1323 fileId = field.toInt();
1327 fileExcpState = m_fileExceptionHash.value(fullPath, (Qt::CheckState)3);
1329 int excpVersion = m_versionExceptionHash.value(fullPath, 0);
1330 if (fileExcpState != Qt::Unchecked) {
1332 if (excpVersion != 0) {
1333 debugtext = QString("*E* version=%1").arg(excpVersion);
1334 version = excpVersion;
1335 fileId = queryFileId(fullPath, excpVersion);
1337 debugtext = QString("___ version=%1").arg(version);
1338 if (mainWin->m_rtRestore1Debug)
1339 Pmsg2(000, "Restoring %s File %s\n", debugtext.toUtf8().data(), fullPath.toUtf8().data());
1340 fullPathDone.insert(fullPath, 1);
1341 fileIdHash.insert(fullPath, fileId);
1342 versionFilesMulti.insert(version, fullPath);
1348 } /* while (*diter) */
1350 /* There may be some exceptions not accounted for yet with fullPathDone */
1351 QHashIterator<QString, Qt::CheckState> ftera(m_fileExceptionHash);
1352 while (ftera.hasNext()) {
1354 QString fullPath = ftera.key();
1355 Qt::CheckState state = ftera.value();
1357 /* now we don't want the ones already done */
1358 if (fullPathDone.value(fullPath, 0) == 0) {
1359 int version = m_versionExceptionHash.value(fullPath, 0);
1361 QString debugtext = "";
1363 fileId = queryFileId(fullPath, version);
1364 debugtext = QString("E1* version=%1 fileid=%2").arg(version).arg(fileId);
1366 version = mostRecentVersionfromFullPath(fullPath);
1368 fileId = queryFileId(fullPath, version);
1369 debugtext = QString("E2* version=%1 fileid=%2").arg(version).arg(fileId);
1371 debugtext = QString("Error det vers").arg(version);
1373 if (mainWin->m_rtRestore1Debug)
1374 Pmsg2(000, "Restoring %s file %s\n", debugtext.toUtf8().data(), fullPath.toUtf8().data());
1375 versionFilesMulti.insert(version, fullPath);
1376 fileIdHash.insert(fullPath, fileId);
1377 } /* if fullPathDone.value(fullPath, 0) == 0 */
1378 } /* if state != 0 */
1379 } /* while ftera.hasNext */
1381 /* now for the final spit out of the versions and lists of files for each version */
1382 QHash<int, int> doneKeys;
1383 QHashIterator<int, QString> miter(versionFilesMulti);
1384 while (miter.hasNext()) {
1386 int fversion = miter.key();
1387 /* did not succeed in getting an iterator to work as expected on versionFilesMulti so use doneKeys */
1388 if (doneKeys.value(fversion, 0) == 0) {
1389 QString tempTable = "restoretest" + QString("%1").arg(fversion);
1390 //if (mainWin->m_sqlDebug)
1391 QString sqlcmd = "CREATE TEMPORARY TABLE " + tempTable + " (JobId INTEGER, FileIndex INTEGER)";
1392 QStringList results;
1393 Pmsg1(000, "Query cmd : %s\n", sqlcmd.toUtf8().data());
1394 /*if (m_console->sql_cmd(sqlcmd, results)) {
1395 QStringList fieldlist;
1397 foreach (QString resultline, results) {
1399 fieldlist = resultline.split("\t");
1400 foreach (QString field, fieldlist) {
1402 Pmsg1(000, "Returned from create table command %s\n", field.toUtf8().data());
1410 if (mainWin->m_rtRestore2Debug) Pmsg1(000, "Version->%i\n", fversion);
1411 QStringList fullPathList = versionFilesMulti.values(fversion);
1412 /* create the command to perform the restore */
1413 foreach(QString ffullPath, fullPathList) {
1414 int fileId = fileIdHash.value(ffullPath);
1415 if (mainWin->m_rtRestore2Debug) Pmsg2(000, " file->%s id %i\n", ffullPath.toUtf8().data(), fileId);
1416 //cmd += " file=\"" + ffullPath + "\"";
1417 sqlcmd = "INSERT INTO " + tempTable + " (JobId, FileIndex) VALUES (" + QString("%1").arg(fversion) + "," + QString("%1").arg(fileId) + ")";
1419 Pmsg1(000, "Query cmd : %s\n", sqlcmd.toUtf8().data());
1420 /*if (m_console->sql_cmd(sqlcmd, results)) {
1421 QStringList fieldlist;
1423 foreach (QString resultline, results) {
1425 fieldlist = resultline.split("\t");
1426 foreach (QString field, fieldlist) {
1428 Pmsg1(000, "Returned from create table command %s\n", field.toUtf8().data());
1436 QString cmd = QString("restore");
1437 cmd += " client=\"" + m_prevClientCombo + "\""
1438 " jobid=\"" + QString("%1").arg(fversion) + "\""
1439 " file=\"?" + tempTable + "\" yes";
1440 if (mainWin->m_commandDebug)
1441 Pmsg1(000, "preRestore command \'%s\'\n", cmd.toUtf8().data());
1442 //consoleCommand(cmd);
1443 mainWin->resetFocus();
1444 doneKeys.insert(fversion,1);
1449 int restoreTree::mostRecentVersionfromFullPath(QString &fullPath)
1452 QString directory, fileName;
1453 int index = m_slashregex.lastIndexIn(fullPath, -2);
1455 directory = fileName = fullPath;
1456 directory.replace(index+1, fullPath.length()-index-1, "");
1457 fileName.replace(0, index+1, "");
1459 QString msg = QString("length = \"%1\" index = \"%2\" Considering \"%3\" \"%4\"\n")
1460 .arg(fullPath.length()).arg(index).arg(fileName).arg(directory);
1461 Pmsg0(000, msg.toUtf8().data());
1463 /* so now we need the latest version from the database */
1465 "SELECT MAX(Job.JobId)"
1467 " LEFT OUTER JOIN Filename on (Filename.FilenameId=File.FilenameId)"
1468 " LEFT OUTER JOIN Path ON (Path.PathId=File.PathId)"
1469 " LEFT OUTER JOIN Job ON (File.JobId=Job.JobId)"
1470 " WHERE Path.Path='" + directory + "' AND Filename.Name!=''"
1471 " AND Job.Jobid IN (" + m_jobQuery + ")"
1472 " AND Filename.Name='" + fileName + "'"
1473 " GROUP BY Filename.Name";
1475 if (mainWin->m_sqlDebug) Pmsg1(000, "Query cmd : %s\n", cmd.toUtf8().data());
1476 QStringList results;
1477 if (m_console->sql_cmd(cmd, results)) {
1478 QStringList fieldlist;
1480 /* Iterate through the record returned from the query */
1481 foreach (QString resultline, results) {
1482 /* Iterate through fields in the record */
1484 fieldlist = resultline.split("\t");
1485 foreach (QString field, fieldlist) {
1487 qversion = field.toInt();
1494 } /* if (index != -1) */
1499 int restoreTree::queryFileId(QString &fullPath, int jobId)
1502 QString directory, fileName;
1503 int index = m_slashregex.lastIndexIn(fullPath, -2);
1505 directory = fileName = fullPath;
1506 directory.replace(index+1, fullPath.length()-index-1, "");
1507 fileName.replace(0, index+1, "");
1509 QString msg = QString("length = \"%1\" index = \"%2\" Considering \"%3\" \"%4\"\n")
1510 .arg(fullPath.length()).arg(index).arg(fileName).arg(directory);
1511 Pmsg0(000, msg.toUtf8().data());
1513 /* so now we need the latest version from the database */
1518 " LEFT OUTER JOIN Filename on (Filename.FilenameId=File.FilenameId)"
1519 " LEFT OUTER JOIN Path ON (Path.PathId=File.PathId)"
1520 " LEFT OUTER JOIN Job ON (File.JobId=Job.JobId)"
1522 " Path.Path='" + directory + "'"
1523 " AND Filename.Name='" + fileName + "'"
1524 " AND Job.Jobid='" + QString("%1").arg(jobId) + "'"
1525 " GROUP BY File.Fileid";
1527 if (mainWin->m_sqlDebug) Pmsg1(000, "Query cmd : %s\n", cmd.toUtf8().data());
1528 QStringList results;
1529 if (m_console->sql_cmd(cmd, results)) {
1530 QStringList fieldlist;
1532 /* Iterate through the record returned from the query */
1533 foreach (QString resultline, results) {
1534 /* Iterate through fields in the record */
1536 fieldlist = resultline.split("\t");
1537 foreach (QString field, fieldlist) {
1539 qfileId = field.toInt();
1546 } /* if (index != -1) */