From c17609599bdad4b11413c7c4be0dff7838ea4c5c Mon Sep 17 00:00:00 2001 From: Dirk H Bartley Date: Wed, 25 Jul 2007 02:32:37 +0000 Subject: [PATCH] The result of the following merge: This merges the work in the branch into the head. This does not quite work yet, working with kern on getting changes in the server! svn merge -r5136:5238 https://bacula.svn.sourceforge.net/svnroot/bacula/branches/working/qt-console . git-svn-id: https://bacula.svn.sourceforge.net/svnroot/bacula/trunk@5239 91ce42f0-d328-0410-95d8-f526ca767f89 --- .../qt-console/images/folderbothchecked.png | Bin 0 -> 758 bytes .../qt-console/images/folderbothchecked.svg | 438 +++++++ .../src/qt-console/images/folderchecked.png | Bin 0 -> 709 bytes .../src/qt-console/images/folderchecked.svg | 430 +++++++ .../src/qt-console/images/folderunchecked.png | Bin 0 -> 692 bytes .../src/qt-console/images/folderunchecked.svg | 430 +++++++ bacula/src/qt-console/main.qrc | 3 + bacula/src/qt-console/mainwin.cpp | 55 +- bacula/src/qt-console/mainwin.h | 12 + bacula/src/qt-console/prefs.ui | 548 +++++---- bacula/src/qt-console/restore/restoretree.cpp | 1029 +++++++++++++++-- bacula/src/qt-console/restore/restoretree.h | 41 +- bacula/src/qt-console/restore/restoretree.ui | 177 +-- 13 files changed, 2817 insertions(+), 346 deletions(-) create mode 100644 bacula/src/qt-console/images/folderbothchecked.png create mode 100644 bacula/src/qt-console/images/folderbothchecked.svg create mode 100644 bacula/src/qt-console/images/folderchecked.png create mode 100644 bacula/src/qt-console/images/folderchecked.svg create mode 100644 bacula/src/qt-console/images/folderunchecked.png create mode 100644 bacula/src/qt-console/images/folderunchecked.svg diff --git a/bacula/src/qt-console/images/folderbothchecked.png b/bacula/src/qt-console/images/folderbothchecked.png new file mode 100644 index 0000000000000000000000000000000000000000..fdb993ba607246c274245dcd72093546d0ce1bea GIT binary patch literal 758 zcmVL z)4OXFQ547V@7$Tpy4hr-CZI+WR4{4^AB_YNgJBWzkxm7%5gY#oA%)FWYG-T&D+>`M zm0$!#K~%)I>vK11+?B+{n8{|cGjm@S;(%2^PkT8Z?m3*FW3A6E3q5F#gjOD5WsQ5Cp;G*x1-cA%tHn7N`DdI^ziHt;_A%xoHm| zj$;``5pf(Nr9^9u5MssP;9#XxD!m>a9-ehw*8#X#yL=s|^#seaN7E6)FflFDob)w!Ffv!9OMJ@obU zQJT=$^?T843&^ekZg?MwMBH&?)tQ4Q&)>e90$~`MNDDG8d92^cj!m8X4C=i9A;Hgs zpQkP)&*yK^p6O;oeotG=lBPHX^7;JIp00MJHncb)+c&S}MP-W7nM;)C9{}(wxJhh6 zHZ>36AP5_3HU(<6+P4G!+vx4kZ0^hnGI1Hi`S0RW;zktC*?0$S^ML3@los}aWuPe0d5lqFG? zoLEC|?hrZAPPe~{SXyT4iEYICQ#wKrnM`D}y!`HQVdODWjSOJY%iEGYLDpG`R6Y{J z)WrANyU}yN;om^HTEF7XKg?;Zybso5ti>9Gu@?Sh&4IVhH57jJTjlBfpz + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + Folder Icon + + + + Jakub Steiner + + + + http://jimmac.musichall.cz + + + folder + directory + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/bacula/src/qt-console/images/folderchecked.png b/bacula/src/qt-console/images/folderchecked.png new file mode 100644 index 0000000000000000000000000000000000000000..97cbf19b36a796547a9ea7211c7917780d8fa4e0 GIT binary patch literal 709 zcmV;$0y_PPP)L zlg&$1VHC!H@4Yk5 zf4#l$>gpQa2q3Jr3=R%XxvslIDTPuBV+@|>eVdq=*xS?7<87!Qj$;``5pf(Nr9^9u z*1EA!C_L%!?_Uu@;JU6b)`;HO+b_%RRK30F-ADnx@0%b9h@uE7B}yr@))-?tDwPV3 z<6s=aL-Uj}pU;3ewN62jBuRNGN8|1`BB`*f8EXLz41T}G$7-29g~O(^x##}nzM)rl zubw!c0SLoTMY>3?u1Mg^KlU7%A7HFHghPg-4VPTy)NHHEXJY^dKuVcpvN?hz;PsDt zc(RfX`)ZNV#m4{~D0Q$s-wGD|P%Wi^APA)Ex{{Zx + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + Folder Icon + + + + Jakub Steiner + + + + http://jimmac.musichall.cz + + + folder + directory + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/bacula/src/qt-console/images/folderunchecked.png b/bacula/src/qt-console/images/folderunchecked.png new file mode 100644 index 0000000000000000000000000000000000000000..13a8de2f44e110ce7d3e42f5ed985b2ce5a9a212 GIT binary patch literal 692 zcmV;l0!#ggP)L zlf6sTQ5?oU=XdV!UPZCAOekD3D$pf-nJO!ZhC-L3KcT(dRa|Na9BXT-1Sf|AGel4% z3qnlr9SgmR-K*Z;%Xw|ku8D(C&-!pa-{(B%e1-R(|4{~@udnYuZ~?$t`^TH+9=!dU{@z0i{yOMNveOBxtQM#$c_*IoFlX=Lv!UDJ7kqowT;L zJ{TJt>pqe|DWw()IT|i@kZ6PFuviaRXSv;Sh8yk8j7-kBiLJA*-aH=}efjjx;|xF? z$0o5g@l$vXH1YgS6vaN00Ds3T4llsM>Z<+7};Z!xtTlW0da4A?0p zg})PMFG6;8$fwy~bhS0{SW36cfH;nga)L-%77GFI zMrWw6J4N@cYXE$mTVXbTSZtyUO1ZT%z*?I|Mi489ww{Sq&xgr54m^gZH&8AhHJ(&^ zws)0}Q@d1t#$w`fiLXSat~_P%bAgKNJc+W*ZwJ7kx4EAG@%{ZX;L$!{er@-)+?%Mf z)@1M==RMvzzKwcWTU{A$7UBc}fe;w7Yd;sJ$BPS-B{ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + Folder Icon + + + + Jakub Steiner + + + + http://jimmac.musichall.cz + + + folder + directory + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/bacula/src/qt-console/main.qrc b/bacula/src/qt-console/main.qrc index 500943e3f8..2681725652 100644 --- a/bacula/src/qt-console/main.qrc +++ b/bacula/src/qt-console/main.qrc @@ -18,6 +18,9 @@ images/estimate-job.svg images/folder.png images/folder.svg + images/folderchecked.png + images/folderunchecked.png + images/folderbothchecked.png images/graph1.png images/help-browser.svg images/home.png diff --git a/bacula/src/qt-console/mainwin.cpp b/bacula/src/qt-console/mainwin.cpp index 64f38b5317..566c702653 100644 --- a/bacula/src/qt-console/mainwin.cpp +++ b/bacula/src/qt-console/mainwin.cpp @@ -615,7 +615,18 @@ void MainWin::setPreferences() prefs.checkMessages->setCheckState(m_checkMessages ? Qt::Checked : Qt::Unchecked); prefs.checkMessagesSpin->setValue(m_checkMessagesInterval); prefs.executeLongCheckBox->setCheckState(m_longList ? Qt::Checked : Qt::Unchecked); - + prefs.rtPopDirCheckBox->setCheckState(m_rtPopDirDebug ? Qt::Checked : Qt::Unchecked); + prefs.rtDirCurICCheckBox->setCheckState(m_rtDirCurICDebug ? Qt::Checked : Qt::Unchecked); + prefs.rtDirICCheckBox->setCheckState(m_rtDirICDebug ? Qt::Checked : Qt::Unchecked); + prefs.rtFileTabICCheckBox->setCheckState(m_rtFileTabICDebug ? Qt::Checked : Qt::Unchecked); + prefs.rtVerTabICCheckBox->setCheckState(m_rtVerTabICDebug ? Qt::Checked : Qt::Unchecked); + prefs.rtUpdateFTCheckBox->setCheckState(m_rtUpdateFTDebug ? Qt::Checked : Qt::Unchecked); + prefs.rtUpdateVTCheckBox->setCheckState(m_rtUpdateVTDebug ? Qt::Checked : Qt::Unchecked); + prefs.rtChecksCheckBox->setCheckState(m_rtChecksDebug ? Qt::Checked : Qt::Unchecked); + prefs.rtIconStateCheckBox->setCheckState(m_rtIconStateDebug ? Qt::Checked : Qt::Unchecked); + prefs.rtRestore1CheckBox->setCheckState(m_rtRestore1Debug ? Qt::Checked : Qt::Unchecked); + prefs.rtRestore2CheckBox->setCheckState(m_rtRestore2Debug ? Qt::Checked : Qt::Unchecked); + prefs.rtRestore3CheckBox->setCheckState(m_rtRestore3Debug ? Qt::Checked : Qt::Unchecked); prefs.exec(); } @@ -640,6 +651,20 @@ void prefsDialog::accept() mainWin->m_checkMessages = this->checkMessages->checkState() == Qt::Checked; mainWin->m_checkMessagesInterval = this->checkMessagesSpin->value(); mainWin->m_longList = this->executeLongCheckBox->checkState() == Qt::Checked; + + mainWin->m_rtPopDirDebug = this->rtPopDirCheckBox->checkState() == Qt::Checked; + mainWin->m_rtDirCurICDebug = this->rtDirCurICCheckBox->checkState() == Qt::Checked; + mainWin->m_rtDirICDebug = this->rtDirICCheckBox->checkState() == Qt::Checked; + mainWin->m_rtFileTabICDebug = this->rtFileTabICCheckBox->checkState() == Qt::Checked; + mainWin->m_rtVerTabICDebug = this->rtVerTabICCheckBox->checkState() == Qt::Checked; + mainWin->m_rtUpdateFTDebug = this->rtUpdateFTCheckBox->checkState() == Qt::Checked; + mainWin->m_rtUpdateVTDebug = this->rtUpdateVTCheckBox->checkState() == Qt::Checked; + mainWin->m_rtChecksDebug = this->rtChecksCheckBox->checkState() == Qt::Checked; + mainWin->m_rtIconStateDebug = this->rtIconStateCheckBox->checkState() == Qt::Checked; + mainWin->m_rtRestore1Debug = this->rtRestore1CheckBox->checkState() == Qt::Checked; + mainWin->m_rtRestore2Debug = this->rtRestore2CheckBox->checkState() == Qt::Checked; + mainWin->m_rtRestore3Debug = this->rtRestore3CheckBox->checkState() == Qt::Checked; + QSettings settings("www.bacula.org", "bat"); settings.beginGroup("Debug"); settings.setValue("commDebug", mainWin->m_commDebug); @@ -661,6 +686,20 @@ void prefsDialog::accept() settings.beginGroup("Misc"); settings.setValue("longList", mainWin->m_longList); settings.endGroup(); + settings.beginGroup("RestoreTree"); + settings.setValue("rtPopDirDebug", mainWin->m_rtPopDirDebug); + settings.setValue("rtDirCurICDebug", mainWin->m_rtDirCurICDebug); + settings.setValue("rtDirCurICRetDebug", mainWin->m_rtDirICDebug); + settings.setValue("rtFileTabICDebug", mainWin->m_rtFileTabICDebug); + settings.setValue("rtVerTabICDebug", mainWin->m_rtVerTabICDebug); + settings.setValue("rtUpdateFTDebug", mainWin->m_rtUpdateFTDebug); + settings.setValue("rtUpdateVTDebug", mainWin->m_rtUpdateVTDebug); + settings.setValue("rtChecksDebug", mainWin->m_rtChecksDebug); + settings.setValue("rtIconStateDebug", mainWin->m_rtIconStateDebug); + settings.setValue("rtRestore1Debug", mainWin->m_rtRestore1Debug); + settings.setValue("rtRestore2Debug", mainWin->m_rtRestore2Debug); + settings.setValue("rtRestore3Debug", mainWin->m_rtRestore3Debug); + settings.endGroup(); foreach(Console *console, mainWin->m_consoleHash) { console->startTimer(); } @@ -696,4 +735,18 @@ void MainWin::readPreferences() settings.beginGroup("Misc"); m_longList = settings.value("longList", false).toBool(); settings.endGroup(); + settings.beginGroup("RestoreTree"); + m_rtPopDirDebug = settings.value("rtPopDirDebug", false).toBool(); + m_rtDirCurICDebug = settings.value("rtDirCurICDebug", false).toBool(); + m_rtDirICDebug = settings.value("rtDirCurICRetDebug", false).toBool(); + m_rtFileTabICDebug = settings.value("rtFileTabICDebug", false).toBool(); + m_rtVerTabICDebug = settings.value("rtVerTabICDebug", false).toBool(); + m_rtUpdateFTDebug = settings.value("rtUpdateFTDebug", false).toBool(); + m_rtUpdateVTDebug = settings.value("rtUpdateVTDebug", false).toBool(); + m_rtChecksDebug = settings.value("rtChecksDebug", false).toBool(); + m_rtIconStateDebug = settings.value("rtIconStateDebug", false).toBool(); + m_rtRestore1Debug = settings.value("rtRestore1Debug", false).toBool(); + m_rtRestore2Debug = settings.value("rtRestore2Debug", false).toBool(); + m_rtRestore3Debug = settings.value("rtRestore3Debug", false).toBool(); + settings.endGroup(); } diff --git a/bacula/src/qt-console/mainwin.h b/bacula/src/qt-console/mainwin.h index ddeb55497d..1db143c3a1 100644 --- a/bacula/src/qt-console/mainwin.h +++ b/bacula/src/qt-console/mainwin.h @@ -84,6 +84,18 @@ public: bool m_checkMessages; int m_checkMessagesInterval; bool m_longList; + bool m_rtPopDirDebug; + bool m_rtDirCurICDebug; + bool m_rtDirICDebug; + bool m_rtFileTabICDebug; + bool m_rtVerTabICDebug; + bool m_rtUpdateFTDebug; + bool m_rtUpdateVTDebug; + bool m_rtChecksDebug; + bool m_rtIconStateDebug; + bool m_rtRestore1Debug; + bool m_rtRestore2Debug; + bool m_rtRestore3Debug; public slots: void input_line(); diff --git a/bacula/src/qt-console/prefs.ui b/bacula/src/qt-console/prefs.ui index b14febd5e8..9454dd7f7c 100644 --- a/bacula/src/qt-console/prefs.ui +++ b/bacula/src/qt-console/prefs.ui @@ -5,8 +5,8 @@ 0 0 - 415 - 396 + 361 + 452 @@ -39,140 +39,144 @@ Messages - - - - 10 - 30 - 291 - 181 - - - - - 5 - 0 - 0 - 0 - - - - Messages Options - - - - 9 - - - 6 - - - - - Message check interval in seconds - - - - - - - Check Messages - - - - - - - 3600 - - - - - - - - - Joblist - - - - - 9 - 62 - 301 - 146 - + + + 9 - - - 5 - 0 - 0 - 0 - - - - Jolist Limit Options + + 6 - - - 9 - - - 6 - - + + + + + 5 + 0 + 0 + 0 + + + + Messages Options + - 0 + 9 6 - + - Days Limit + Message check interval in seconds - - - - 10000 - - - 1 - - - 7 + + + + Check Messages - + - 10000 - - - 1 - - - 25 + 3600 + + + + + + + + Joblist + + + + 9 + + + 6 + + + + + + 5 + 0 + 0 + 0 + + + + Jolist Limit Options + + + + 9 + + + 6 + - - - Record Limit + + + 0 - + + 6 + + + + + Days Limit + + + + + + + 10000 + + + 1 + + + 7 + + + + + + + 10000 + + + 1 + + + 25 + + + + + + + Record Limit + + + + - - - + + + @@ -181,111 +185,255 @@ - 30 - 50 - 201 - 81 + 70 + 120 + 190 + 55 Context Sensitive List Commands - - - - 10 - 20 - 161 - 19 - + + + 9 - - Execute Long List + + 6 - + + + + Execute Long List + + + + Debug - - - - 20 - 40 - 271 - 181 - + + + 9 - - - 5 - 0 - 0 - 0 - + + 6 - - Debugging Options + + + + + 5 + 0 + 0 + 0 + + + + Debugging Options + + + + 9 + + + 6 + + + + + 0 + + + 6 + + + + + Debug comm + + + + + + + Display all messages in console + + + + + + + Debug Commands + + + + + + + Debug Sql queries + + + + + + + Debug Miscelaneous Items + + + + + + + + + + + + + RestoreTree + + + + 9 - - - - 10 - 21 - 241 - 131 - - - - - 0 + + 6 + + + + + + 5 + 0 + 0 + 0 + - - 6 + + Debugging Options - - - - Debug comm - - - - - - - Display all messages in console - - - - - - - Debug Commands - - - - - - - Debug Sql queries - - - - - - - Debug Miscelaneous Items - - - - - - + + + 9 + + + 6 + + + + + 0 + + + 6 + + + + + Restore Debug 2 + + + + + + + Directory Item Changed + + + + + + + Restore Debug 1 + + + + + + + Directory Current Item Changed Debug + + + + + + + Update File Table Debug + + + + + + + Version Table Item Changed Debug + + + + + + + File Table Item Changed Debug + + + + + + + Icon State Debug + + + + + + + Update Checks Debug + + + + + + + Restore Debug 3 + + + + + + + Update Version Table Debug + + + + + + + Populate Directory Debug + + + + + + + + + + + + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::NoButton|QDialogButtonBox::Ok + + + @@ -337,16 +485,6 @@ - - - - Qt::Horizontal - - - QDialogButtonBox::Cancel|QDialogButtonBox::NoButton|QDialogButtonBox::Ok - - - diff --git a/bacula/src/qt-console/restore/restoretree.cpp b/bacula/src/qt-console/restore/restoretree.cpp index a987ac7923..f7025649c7 100644 --- a/bacula/src/qt-console/restore/restoretree.cpp +++ b/bacula/src/qt-console/restore/restoretree.cpp @@ -45,7 +45,7 @@ restoreTree::restoreTree() m_name = "Version Browser"; pgInitialize(); QTreeWidgetItem* thisitem = mainWin->getFromHash(this); - thisitem->setIcon(0,QIcon(QString::fromUtf8(":images/browse.png"))); + thisitem->setIcon(0, QIcon(QString::fromUtf8(":images/browse.png"))); m_closeable = true; m_populated = false; @@ -70,21 +70,25 @@ restoreTree::~restoreTree() void restoreTree::setupPage() { connect(refreshButton, SIGNAL(pressed()), this, SLOT(refreshButtonPushed())); + connect(testButton, SIGNAL(pressed()), this, SLOT(testButtonPushed())); connect(jobCombo, SIGNAL(currentIndexChanged(int)), this, SLOT(jobComboChanged(int))); connect(directoryTree, SIGNAL(currentItemChanged(QTreeWidgetItem *, QTreeWidgetItem *)), - this, SLOT(directoryItemChanged(QTreeWidgetItem *, QTreeWidgetItem *))); - connect(fileTable, SIGNAL(currentItemChanged(QTableWidgetItem *, QTableWidgetItem *)), - this, SLOT(fileItemChanged(QTableWidgetItem *, QTableWidgetItem *))); + this, SLOT(directoryCurrentItemChanged(QTreeWidgetItem *, QTreeWidgetItem *))); connect(directoryTree, SIGNAL(itemExpanded(QTreeWidgetItem *)), this, SLOT(directoryItemExpanded(QTreeWidgetItem *))); + connect(directoryTree, SIGNAL(itemChanged(QTreeWidgetItem *, int)), + this, SLOT(directoryItemChanged(QTreeWidgetItem *, int))); + connect(fileTable, SIGNAL(currentItemChanged(QTableWidgetItem *, QTableWidgetItem *)), + this, SLOT(fileCurrentItemChanged(QTableWidgetItem *, QTableWidgetItem *))); - QStringList titles; - titles << "Directories"; + QStringList titles = QStringList() << "Directories"; directoryTree->setHeaderLabels(titles); clientCombo->addItems(m_console->client_list); fileSetCombo->addItem("Any"); fileSetCombo->addItems(m_console->fileset_list); jobCombo->addItems(m_console->job_list); + + directoryTree->setContextMenuPolicy(Qt::ActionsContextMenu); } /* @@ -102,31 +106,60 @@ void restoreTree::populateDirectoryTree() versionTable->clear(); versionTable->setRowCount(0); versionTable->setColumnCount(0); - jobTable->clear(); - jobTable->setRowCount(0); - jobTable->setColumnCount(0); + m_fileExceptionHash.clear(); + m_fileExceptionMulti.clear(); + m_versionExceptionHash.clear(); + m_directoryIconStateHash.clear(); - m_condition = " Job.name = '" + jobCombo->itemText(jobCombo->currentIndex()) + "'"; + int clientIndex = clientCombo->currentIndex(); - if ((clientIndex >= 0) && (clientCombo->itemText(clientIndex) != "Any")) { - m_condition.append(" AND Client.Name='" + clientCombo->itemText(clientIndex) + "'"); - } int fileSetIndex = fileSetCombo->currentIndex(); - if ((fileSetIndex >= 0) && (fileSetCombo->itemText(fileSetIndex) != "Any")) { - m_condition.append(" AND FileSet.FileSet='" + fileSetCombo->itemText(fileSetIndex) + "'"); - } - m_jobQueryPart = - " LEFT OUTER JOIN Client ON (Job.ClientId=Client.ClientId)" - " LEFT OUTER JOIN FileSet ON (Job.FileSetId=FileSet.FileSetId)" - " WHERE" + m_condition + - " AND Job.purgedfiles=0"; - m_jobQuery = - "SELECT Job.Jobid" - " From Job" + m_jobQueryPart; - if (mainWin->m_sqlDebug) { - Pmsg1(000, "Query cmd : %s\n",m_jobQuery.toUtf8().data()); + QString jobComboText = jobCombo->itemText(jobCombo->currentIndex()); + QString clientComboText = clientCombo->itemText(clientIndex); + QString fileSetComboText = fileSetCombo->itemText(fileSetIndex); + if ((m_prevJobCombo != jobComboText) || (m_prevClientCombo != clientComboText) || (m_prevFileSetCombo != fileSetComboText)) { + m_prevJobCombo = jobComboText; + m_prevClientCombo = clientComboText; + m_prevFileSetCombo = fileSetComboText; + if (mainWin->m_rtPopDirDebug) Pmsg0(000, "Repopulating the Job Table\n"); + + m_condition = " Job.name = '" + jobCombo->itemText(jobCombo->currentIndex()) + "'"; + if ((clientIndex >= 0) && (clientCombo->itemText(clientIndex) != "Any")) { + m_condition.append(" AND Client.Name='" + clientCombo->itemText(clientIndex) + "'"); + } + if ((fileSetIndex >= 0) && (fileSetCombo->itemText(fileSetIndex) != "Any")) { + m_condition.append(" AND FileSet.FileSet='" + fileSetCombo->itemText(fileSetIndex) + "'"); + } + m_jobQueryPart = + " LEFT OUTER JOIN Client ON (Job.ClientId=Client.ClientId)" + " LEFT OUTER JOIN FileSet ON (Job.FileSetId=FileSet.FileSetId)" + " WHERE" + m_condition + + " AND Job.purgedfiles=0"; + m_jobQuery = + "SELECT Job.Jobid" + " From Job" + m_jobQueryPart; + if (mainWin->m_sqlDebug) { + Pmsg1(000, "Query cmd : %s\n", m_jobQuery.toUtf8().data()); + } + populateJobTable(); + } else { + m_JobsCheckedList = ""; + bool first = true; + /* Update the items in the version table */ + int cnt = jobTable->rowCount(); + for (int row=0; rowitem(row, 0); + if (jobItem->checkState() == Qt::Checked) { + if (!first) + m_JobsCheckedList += ","; + m_JobsCheckedList += jobItem->text(); + first = false; + jobItem->setBackground(Qt::green); + } else + jobItem->setBackground(Qt::gray); + } + m_jobQuery = m_JobsCheckedList; } - populateJobTable(); QString cmd = "SELECT DISTINCT Path.Path" @@ -135,7 +168,7 @@ void restoreTree::populateDirectoryTree() " LEFT OUTER JOIN Job ON (File.JobId=Job.JobId)" " WHERE Job.Jobid IN (" + m_jobQuery + ")"; if (mainWin->m_sqlDebug) { - Pmsg1(000, "Query cmd : %s\n",cmd.toUtf8().data()); + Pmsg1(000, "Query cmd : %s\n", cmd.toUtf8().data()); } QStringList directories; if (m_console->sql_cmd(cmd, directories)) { @@ -155,6 +188,8 @@ void restoreTree::populateDirectoryTree() */ void restoreTree::parseDirectory(QString &dir_in) { + /* m_debugTrap is to only print debugs for a few occurances of calling parseDirectory + * instead of printing out what could potentially a whole bunch */ if (m_debugCnt > 2) m_debugTrap = false; /* Clean up the directory string remove some funny char after last '/' */ @@ -174,14 +209,11 @@ void restoreTree::parseDirectory(QString &dir_in) * / and etc/ . That should succeed, then add the ones that failed in reverse */ while (((index = m_slashregex.lastIndexIn(dir_in, -2)) != -1) && (!done)) { direct = path = dir_in; - path.replace(index+1,dir_in.length()-index-1,""); - direct.replace(0,index+1,""); + path.replace(index+1, dir_in.length()-index-1,""); + direct.replace(0, index+1, ""); if ((mainWin->m_miscDebug) && (m_debugTrap)) { QString msg = QString("length = \"%1\" index = \"%2\" Adding \"%3\" \"%4\"\n") - .arg(dir_in.length()) - .arg(index) - .arg(path) - .arg(direct); + .arg(dir_in.length()).arg(index).arg(path).arg(direct); Pmsg0(000, msg.toUtf8().data()); } if (addDirectory(path, direct)) done = true; @@ -193,6 +225,7 @@ void restoreTree::parseDirectory(QString &dir_in) } dir_in = path; } + for (int k=0; km_miscDebug) && (m_debugTrap)) @@ -210,7 +243,7 @@ void restoreTree::parseDirectory(QString &dir_in) bool restoreTree::addDirectory(QString &m_cwd, QString &newdirr) { QString newdir = newdirr; - QString fullpath = m_cwd + newdirr; + QString fullPath = m_cwd + newdirr; bool ok = true, added = false; if ((mainWin->m_miscDebug) && (m_debugTrap)) { @@ -222,15 +255,16 @@ bool restoreTree::addDirectory(QString &m_cwd, QString &newdirr) if (!m_slashTrap) { /* add unix '/' directory first */ - if (m_dirPaths.empty() && (m_winRegExpPath.indexIn(fullpath,0) == -1)) { + if (m_dirPaths.empty() && (m_winRegExpPath.indexIn(fullPath, 0) == -1)) { m_slashTrap = true; QTreeWidgetItem *item = new QTreeWidgetItem(directoryTree); - item->setIcon(0, QIcon(QString::fromUtf8(":images/folder.png"))); QString text("/"); item->setText(0, text.toUtf8().data()); item->setData(0, Qt::UserRole, QVariant(text)); + item->setData(1, Qt::UserRole, QVariant(Qt::Unchecked)); + item->setIcon(0, QIcon(QString::fromUtf8(":images/folder.png"))); if ((mainWin->m_miscDebug) && (m_debugTrap)) { - Pmsg1(000, "Pre Inserting %s\n",text.toUtf8().data()); + Pmsg1(000, "Pre Inserting %s\n", text.toUtf8().data()); } m_dirPaths.insert(text, item); } @@ -238,9 +272,10 @@ bool restoreTree::addDirectory(QString &m_cwd, QString &newdirr) if (m_winRegExpDrive.indexIn(m_cwd, 0) == 0) { /* this is a windows drive add the base widget */ QTreeWidgetItem *item = new QTreeWidgetItem(directoryTree); - item->setIcon(0, QIcon(QString::fromUtf8(":images/folder.png"))); item->setText(0, m_cwd); - item->setData(0, Qt::UserRole, QVariant(fullpath)); + item->setData(0, Qt::UserRole, QVariant(fullPath)); + item->setData(1, Qt::UserRole, QVariant(Qt::Unchecked)); + item->setIcon(0, QIcon(QString::fromUtf8(":images/folder.png"))); if ((mainWin->m_miscDebug) && (m_debugTrap)) { Pmsg0(000, "Added Base \"letter\":/\n"); } @@ -249,14 +284,18 @@ bool restoreTree::addDirectory(QString &m_cwd, QString &newdirr) } /* is it already existent ?? */ - if (!m_dirPaths.contains(fullpath)) { + if (!m_dirPaths.contains(fullPath)) { QTreeWidgetItem *item = NULL; QTreeWidgetItem *parent = m_dirPaths.value(m_cwd); if (parent) { /* new directories to add */ item = new QTreeWidgetItem(parent); item->setText(0, newdir.toUtf8().data()); - item->setData(0, Qt::UserRole, QVariant(fullpath)); + item->setData(0, Qt::UserRole, QVariant(fullPath)); + item->setCheckState(0, Qt::Unchecked); + /* Store the current state of the check status in column 1, which at + * this point has no text*/ + item->setData(1, Qt::UserRole, QVariant(Qt::Unchecked)); } else { ok = false; if ((mainWin->m_miscDebug) && (m_debugTrap)) { @@ -269,9 +308,9 @@ bool restoreTree::addDirectory(QString &m_cwd, QString &newdirr) /* insert into hash */ if (ok) { if ((mainWin->m_miscDebug) && (m_debugTrap)) { - Pmsg1(000, "Inserting %s\n",fullpath.toUtf8().data()); + Pmsg1(000, "Inserting %s\n", fullPath.toUtf8().data()); } - m_dirPaths.insert(fullpath, item); + m_dirPaths.insert(fullPath, item); added = true; } } @@ -317,12 +356,16 @@ void restoreTree::jobComboChanged(int) /* * Function to populate the file list table */ -void restoreTree::directoryItemChanged(QTreeWidgetItem *item, QTreeWidgetItem *) +void restoreTree::directoryCurrentItemChanged(QTreeWidgetItem *item, QTreeWidgetItem *) { if (item == NULL) return; + + m_fileCheckStateList.clear(); + disconnect(fileTable, SIGNAL(itemChanged(QTableWidgetItem *)), + this, SLOT(fileTableItemChanged(QTableWidgetItem *))); QBrush blackBrush(Qt::black); - QString directory = item->data(0,Qt::UserRole).toString(); + QString directory = item->data(0, Qt::UserRole).toString(); directoryLabel->setText("Present Working Directory : " + directory); QString cmd = "SELECT DISTINCT Filename.Name" @@ -333,18 +376,18 @@ void restoreTree::directoryItemChanged(QTreeWidgetItem *item, QTreeWidgetItem *) " WHERE Path.Path='" + directory + "' AND Filename.Name!=''" " AND Job.Jobid IN (" + m_jobQuery + ")"; - QStringList headerlist = (QStringList() << "File Name"); fileTable->clear(); /* Also clear the version table here */ versionTable->clear(); + versionFileLabel->setText(""); versionTable->setRowCount(0); versionTable->setColumnCount(0); fileTable->setColumnCount(headerlist.size()); fileTable->setHorizontalHeaderLabels(headerlist); if (mainWin->m_sqlDebug) { - Pmsg1(000, "Query cmd : %s\n",cmd.toUtf8().data()); + Pmsg1(000, "Query cmd : %s\n", cmd.toUtf8().data()); } QStringList results; if (m_console->sql_cmd(cmd, results)) { @@ -362,11 +405,20 @@ void restoreTree::directoryItemChanged(QTreeWidgetItem *item, QTreeWidgetItem *) fieldlist = resultline.split("\t"); foreach (field, fieldlist) { field = field.trimmed(); /* strip leading & trailing spaces */ - tableItem = new QTableWidgetItem(field,1); - tableItem->setFlags(0); + tableItem = new QTableWidgetItem(field, 1); + /* Possible flags are Qt::ItemFlags flag = Qt::ItemIsSelectable | Qt::ItemIsEditablex + * | Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled | Qt::ItemIsUserCheckable + * | Qt::ItemIsEnabled | Qt::ItemIsTristate; */ tableItem->setForeground(blackBrush); - tableItem->setData(Qt::UserRole,QVariant(directory)); - fileTable->setItem(row, column, tableItem); + /* Just in case a column ever gets added */ + if (column == 0) { + Qt::ItemFlags flag = Qt::ItemIsUserCheckable | Qt::ItemIsEnabled | Qt::ItemIsTristate; + tableItem->setFlags(flag); + tableItem->setData(Qt::UserRole, QVariant(directory)); + fileTable->setItem(row, column, tableItem); + m_fileCheckStateList.append(Qt::Unchecked); + tableItem->setCheckState(Qt::Unchecked); + } column++; } row++; @@ -376,35 +428,46 @@ void restoreTree::directoryItemChanged(QTreeWidgetItem *item, QTreeWidgetItem *) fileTable->resizeColumnsToContents(); fileTable->resizeRowsToContents(); fileTable->verticalHeader()->hide(); + connect(fileTable, SIGNAL(itemChanged(QTableWidgetItem *)), + this, SLOT(fileTableItemChanged(QTableWidgetItem *))); + if (mainWin->m_rtDirCurICDebug) Pmsg0(000, "will update file table checks\n"); + updateFileTableChecks(); } /* * Function to populate the version table */ -void restoreTree::fileItemChanged(QTableWidgetItem *fileTableItem, QTableWidgetItem *) +void restoreTree::fileCurrentItemChanged(QTableWidgetItem *fileTableItem, QTableWidgetItem *) { if (fileTableItem == NULL) return; + + m_versionCheckStateList.clear(); + disconnect(versionTable, SIGNAL(itemChanged(QTableWidgetItem *)), + this, SLOT(versionTableItemChanged(QTableWidgetItem *))); + QString file = fileTableItem->text(); + versionFileLabel->setText(file); QString directory = fileTableItem->data(Qt::UserRole).toString(); QBrush blackBrush(Qt::black); QString cmd = - "SELECT File.FileId, Job.JobId, Job.EndTime, File.Md5 " + "SELECT Job.JobId AS JobId, Job.Level AS Type, Job.EndTime AS EndTime, File.Md5 AS MD5" " FROM File" " LEFT OUTER JOIN Filename on (Filename.FilenameId=File.FilenameId)" " LEFT OUTER JOIN Path ON (Path.PathId=File.PathId)" " LEFT OUTER JOIN Job ON (File.JobId=Job.JobId)" " WHERE Filename.Name='" + file + "' AND Path.Path='" + directory + "'" - " AND Job.Jobid IN (" + m_jobQuery + ")"; + " AND Job.Jobid IN (" + m_jobQuery + ")" + " ORDER BY Job.EndTime DESC"; - QStringList headerlist = (QStringList() << "File Id" << "Job Id" << "End Time" << "Md5"); + QStringList headerlist = (QStringList() << "Job Id" << "Type" << "End Time" << "Md5"); versionTable->clear(); versionTable->setColumnCount(headerlist.size()); versionTable->setHorizontalHeaderLabels(headerlist); if (mainWin->m_sqlDebug) { - Pmsg1(000, "Query cmd : %s\n",cmd.toUtf8().data()); + Pmsg1(000, "Query cmd : %s\n", cmd.toUtf8().data()); } QStringList results; if (m_console->sql_cmd(cmd, results)) { @@ -424,11 +487,18 @@ void restoreTree::fileItemChanged(QTableWidgetItem *fileTableItem, QTableWidgetI /* Iterate through fields in the record */ foreach (field, fieldlist) { field = field.trimmed(); /* strip leading & trailing spaces */ - tableItem = new QTableWidgetItem(field,1); + tableItem = new QTableWidgetItem(field, 1); tableItem->setFlags(0); tableItem->setForeground(blackBrush); - tableItem->setData(Qt::UserRole,QVariant(directory)); + tableItem->setData(Qt::UserRole, QVariant(directory)); versionTable->setItem(row, column, tableItem); + + if (column == 0) { + Qt::ItemFlags flag = Qt::ItemIsUserCheckable | Qt::ItemIsEnabled | Qt::ItemIsTristate; + tableItem->setFlags(flag); + m_versionCheckStateList.append(Qt::Unchecked); + tableItem->setCheckState(Qt::Unchecked); + } column++; } row++; @@ -438,6 +508,9 @@ void restoreTree::fileItemChanged(QTableWidgetItem *fileTableItem, QTableWidgetI versionTable->resizeColumnsToContents(); versionTable->resizeRowsToContents(); versionTable->verticalHeader()->hide(); + connect(versionTable, SIGNAL(itemChanged(QTableWidgetItem *)), + this, SLOT(versionTableItemChanged(QTableWidgetItem *))); + updateVersionTableChecks(); } /* @@ -464,17 +537,23 @@ void restoreTree::readSettings() /* * This is a funcion to accomplish the one thing I struggled to figure out what - * was taking so long. It add the icons, but after the tree is made. + * was taking so long. It add the icons, but after the tree is made. Seemed to + * work fast after changing from svg to png file for graphic. */ void restoreTree::directoryItemExpanded(QTreeWidgetItem *item) { int childCount = item->childCount(); for (int i=0; ichild(i); - child->setIcon(0,QIcon(QString::fromUtf8(":images/folder.png"))); + if (child->icon(0).isNull()) + child->setIcon(0, QIcon(QString::fromUtf8(":images/folder.png"))); } } +/* + * I wanted a table to show what jobs meet the criterion and are being used to + * populate the directory tree and file and version tables. + */ void restoreTree::populateJobTable() { QBrush blackBrush(Qt::black); @@ -483,11 +562,11 @@ void restoreTree::populateJobTable() jobTable->setColumnCount(headerlist.size()); jobTable->setHorizontalHeaderLabels(headerlist); QString jobQuery = - "SELECT Job.Jobid AS Id, Job.Endtime AS EndTime, Job.Level AS Level" + "SELECT Job.Jobid AS Id, Job.EndTime AS EndTime, Job.Level AS Level" " FROM Job" + m_jobQueryPart + - " ORDER BY Job.Endtime DESC"; + " ORDER BY Job.EndTime DESC"; if (mainWin->m_sqlDebug) { - Pmsg1(000, "Query cmd : %s\n",jobQuery.toUtf8().data()); + Pmsg1(000, "Query cmd : %s\n", jobQuery.toUtf8().data()); } QStringList results; @@ -508,10 +587,16 @@ void restoreTree::populateJobTable() /* Iterate through fields in the record */ foreach (field, fieldlist) { field = field.trimmed(); /* strip leading & trailing spaces */ - tableItem = new QTableWidgetItem(field,1); + tableItem = new QTableWidgetItem(field, 1); tableItem->setFlags(0); tableItem->setForeground(blackBrush); jobTable->setItem(row, column, tableItem); + if (column == 0) { + Qt::ItemFlags flag = Qt::ItemIsUserCheckable | Qt::ItemIsEnabled | Qt::ItemIsTristate; + tableItem->setFlags(flag); + tableItem->setCheckState(Qt::Checked); + tableItem->setBackground(Qt::green); + } column++; } row++; @@ -522,3 +607,817 @@ void restoreTree::populateJobTable() jobTable->resizeRowsToContents(); jobTable->verticalHeader()->hide(); } + +/* + * When a directory item is "changed" check the state of the checkable item + * to see if it is different than what it was which is stored in Qt::UserRole + * of the 2nd column, column 1, of the tree widget. + */ +void restoreTree::directoryItemChanged(QTreeWidgetItem *item, int /*column*/) +{ + Qt::CheckState prevState = (Qt::CheckState)item->data(1, Qt::UserRole).toInt(); + Qt::CheckState curState = item->checkState(0); + QTreeWidgetItem* parent = item->parent(); + Qt::CheckState parState; + if (parent) parState = parent->checkState(0); + else parState = (Qt::CheckState)3; + if (mainWin->m_rtDirICDebug) { + QString msg = QString("directory item OBJECT has changed prev=%1 cur=%2 par=%3 dir=%4\n") + .arg(prevState).arg(curState).arg(parState).arg(item->text(0)); + Pmsg1(000, "%s", msg.toUtf8().data()); } + /* I only care when the check state changes */ + if (prevState == curState) { + if (mainWin->m_rtDirICDebug) Pmsg0(000, "Returning Early\n"); + return; + } + + if ((prevState == Qt::Unchecked) && (curState == Qt::Checked) && (parState != Qt::Unchecked)) { + if (mainWin->m_rtDirICDebug) Pmsg0(000, "Disconnected Setting to Qt::PartiallyChecked\n"); + directoryTreeDisconnectedSet(item, Qt::PartiallyChecked); + curState = Qt::PartiallyChecked; + } + if ((prevState == Qt::PartiallyChecked) && (curState == Qt::Checked)) { + if (mainWin->m_rtDirICDebug) Pmsg0(000, "Disconnected Setting to Qt::Unchecked\n"); + directoryTreeDisconnectedSet(item, Qt::Unchecked); + curState = Qt::Unchecked; + } + if (mainWin->m_rtDirICDebug) { + QString msg = QString("directory item CHECKSTATE has changed prev=%1 cur=%2 par=%3 dir=%4\n") + .arg(prevState).arg(curState).arg(parState).arg(item->text(0)); + Pmsg1(000, "%s", msg.toUtf8().data()); } + + item->setData(1, Qt::UserRole, QVariant(curState)); + Qt::CheckState childState = curState; + if (childState == Qt::Checked) + childState = Qt::PartiallyChecked; + setCheckofChildren(item, childState); + + /* Remove items from the exception lists. The multi exception list is my index + * of what exceptions can be removed when the directory is known*/ + QString directory = item->data(0, Qt::UserRole).toString(); + QStringList fullPathList = m_fileExceptionMulti.values(directory); + int fullPathListCount = fullPathList.count(); + if ((mainWin->m_rtDirICDebug) && fullPathListCount) Pmsg2(000, "Will attempt to remove file exceptions for %s count %i\n", directory.toUtf8().data(), fullPathListCount); + foreach (QString fullPath, fullPathList) { + /* If there is no value in the hash for the key fullPath a value of 3 will be returned + * which will match no Qt::xxx values */ + Qt::CheckState hashState = m_fileExceptionHash.value(fullPath, (Qt::CheckState)3); + if (mainWin->m_rtDirICDebug) Pmsg2(000, "hashState=%i childState=%i\n", hashState, childState); + if (hashState == Qt::Unchecked) { + fileExceptionRemove(fullPath, directory); + m_versionExceptionHash.remove(fullPath); + if (mainWin->m_rtDirICDebug) Pmsg0(000, "Attempted Removal A\n"); + } + if (hashState == Qt::Checked) { + fileExceptionRemove(fullPath, directory); + m_versionExceptionHash.remove(fullPath); + if (mainWin->m_rtDirICDebug) Pmsg0(000, "Attempted Removal B\n"); + } + } + + if (item == directoryTree->currentItem()) { + if (mainWin->m_rtDirICDebug) Pmsg0(000, "Will attempt to update File Table Checks\n"); + updateFileTableChecks(); + versionTable->clear(); + versionTable->setRowCount(0); + versionTable->setColumnCount(0); + } + if (mainWin->m_rtDirICDebug) Pmsg0(000, "Returning At End\n"); +} + +/* + * When a directory item check state is changed, this function iterates through + * all subdirectories and sets all to the passed state, which is either partially + * checked or unchecked. + */ +void restoreTree::setCheckofChildren(QTreeWidgetItem *item, Qt::CheckState state) +{ + int childCount; + childCount = item->childCount(); + for (int i=0; ichild(i); + child->setData(1, Qt::UserRole, QVariant(state)); + child->setCheckState(0, state); + setCheckofChildren(child, state); + } +} + +/* + * When a File Table Item is "changed" check to see if the state of the checkable + * item has changed which is stored in m_fileCheckStateList + * If changed store in a hash m_fileExceptionHash that whether this file should be + * restored or not. + * Called as a slot, connected after populated (after directory current changed called) + */ +void restoreTree::fileTableItemChanged(QTableWidgetItem *item) +{ + /* get the previous and current check states */ + int row = fileTable->row(item); + Qt::CheckState prevState; + /* prevent a segfault */ + prevState = m_fileCheckStateList[row]; + Qt::CheckState curState = item->checkState(); + + /* deterimine the default state from the state of the directory */ + QTreeWidgetItem *dirTreeItem = directoryTree->currentItem(); + Qt::CheckState dirState = (Qt::CheckState)dirTreeItem->data(1, Qt::UserRole).toInt(); + Qt::CheckState defState = Qt::PartiallyChecked; + if (dirState == Qt::Unchecked) defState = Qt::Unchecked; + + /* determine if it is already in the m_fileExceptionHash */ + QString directory = directoryTree->currentItem()->data(0, Qt::UserRole).toString(); + QString file = item->text(); + QString fullPath = directory + file; + Qt::CheckState hashState = m_fileExceptionHash.value(fullPath, (Qt::CheckState)3); + int verJobNum = m_versionExceptionHash.value(fullPath, 0); + + if (mainWin->m_rtFileTabICDebug) { + QString msg = QString("filerow=%1 prev=%2 cur=%3 def=%4 hash=%5 dir=%6 verJobNum=%7\n") + .arg(row).arg(prevState).arg(curState).arg(defState).arg(hashState).arg(dirState).arg(verJobNum); + Pmsg1(000, "%s", msg.toUtf8().data()); } + + /* Remove the hash if currently checked previously unchecked and directory is checked or partial */ + if ((prevState == Qt::Checked) && (curState == Qt::Unchecked) && (dirState == Qt::Unchecked)) { + /* it can behave as defaulted so current of unchecked is fine */ + if (mainWin->m_rtFileTabICDebug) Pmsg0(000, "Will fileExceptionRemove and m_versionExceptionHash.remove here\n"); + fileExceptionRemove(fullPath, directory); + m_versionExceptionHash.remove(fullPath); + } else if ((prevState == Qt::PartiallyChecked) && (curState == Qt::Checked) && (dirState != Qt::Unchecked) && (verJobNum == 0)) { + if (mainWin->m_rtFileTabICDebug) Pmsg0(000, "Will fileExceptionInsert here\n"); + fileExceptionInsert(fullPath, directory, Qt::Unchecked); + } else if ((prevState == Qt::Unchecked) && (curState == Qt::Checked) && (dirState != Qt::Unchecked) && (verJobNum == 0) && (defState == Qt::PartiallyChecked)) { + /* filerow=2 prev=0 cur=2 def=1 hash=0 dir=2 verJobNum=0 */ + if (mainWin->m_rtFileTabICDebug) Pmsg0(000, "Will fileExceptionRemove here\n"); + fileExceptionRemove(fullPath, directory); + } else if ((prevState == Qt::Checked) && (curState == Qt::Unchecked) && (defState == Qt::PartiallyChecked) && (verJobNum != 0) && (hashState == Qt::Checked)) { + /* Check dir, check version, attempt uncheck in file + * filerow=4 prev=2 cur=0 def=1 hash=2 dir=2 verJobNum=53 */ + if (mainWin->m_rtFileTabICDebug) Pmsg0(000, "Will fileExceptionRemove and m_versionExceptionHash.remove here\n"); + fileExceptionRemove(fullPath, directory); + m_versionExceptionHash.remove(fullPath); + } else if ((prevState == Qt::Unchecked) && (curState == Qt::Checked) && (dirState != Qt::Unchecked) && (verJobNum == 0)) { + /* filerow=0 prev=0 cur=2 def=1 hash=0 dirState=2 verJobNum */ + if (mainWin->m_rtFileTabICDebug) Pmsg0(000, "Will Not remove here\n"); + } else if (prevState != curState) { + if (mainWin->m_rtFileTabICDebug) Pmsg2(000, " THE STATE OF THE Check has changed, Setting StateList[%i] to %i\n", row, curState); + /* A user did not set the check state to Partially checked, ignore if so */ + if (curState != Qt::PartiallyChecked) { + if ((defState == Qt::Unchecked) && (prevState == Qt::PartiallyChecked) && (curState == Qt::Unchecked)) { + if (mainWin->m_rtFileTabICDebug) Pmsg0(000, " got here\n"); + } else { + if (mainWin->m_rtFileTabICDebug) Pmsg2(000, " Inserting into m_fileExceptionHash %s, %i\n", fullPath.toUtf8().data(), curState); + fileExceptionInsert(fullPath, directory, curState); + } + } else { + if (mainWin->m_rtFileTabICDebug) Pmsg1(000, "Removing version hash for %s\n", fullPath.toUtf8().data()); + /* programattically been changed back to a default state of Qt::PartiallyChecked remove the version hash here */ + m_versionExceptionHash.remove(fullPath); + } + } + + updateFileTableChecks(); + updateVersionTableChecks(); +} + +/* + * function to insert keys and values to both m_fileExceptionHash and m_fileExceptionMulti + */ +void restoreTree::fileExceptionInsert(QString &fullPath, QString &direcotry, Qt::CheckState state) +{ + m_fileExceptionHash.insert(fullPath, state); + m_fileExceptionMulti.insert(direcotry, fullPath); + directoryIconStateInsert(fullPath, state); +} + +/* + * function to remove keys from both m_fileExceptionHash and m_fileExceptionMulti + */ +void restoreTree::fileExceptionRemove(QString &fullPath, QString &directory) +{ + m_fileExceptionHash.remove(fullPath); + /* pull the list of values in the multi */ + QStringList fullPathList = m_fileExceptionMulti.values(directory); + /* get the index of the fullpath to remove */ + int index = fullPathList.indexOf(fullPath); + if (index != -1) { + /* remove the desired item in the list */ + fullPathList.removeAt(index); + /* remove the entire list from the multi */ + m_fileExceptionMulti.remove(directory); + /* readd the remaining */ + foreach (QString fp, fullPathList) { + m_fileExceptionMulti.insert(directory, fp); + } + } + directoryIconStateRemove(); +} + +/* + * Overloaded function to be called from the slot and from other places to set the state + * of the check marks in the version table + */ +void restoreTree::versionTableItemChanged(QTableWidgetItem *item) +{ + /* get the previous and current check states */ + int row = versionTable->row(item); + QTableWidgetItem *colZeroItem = versionTable->item(row, 0); + Qt::CheckState prevState = m_versionCheckStateList[row]; + Qt::CheckState curState = (Qt::CheckState)colZeroItem->checkState(); + m_versionCheckStateList[row] = curState; + + /* deterimine the default state from the state of the file */ + QTableWidgetItem *fileTableItem = fileTable->currentItem(); + Qt::CheckState fileState = (Qt::CheckState)fileTableItem->checkState(); + + /* determine the default state */ + Qt::CheckState defState; + if (row == 0) { + defState = Qt::PartiallyChecked; + if (fileState == Qt::Unchecked) + defState = Qt::Unchecked; + } + else + defState = Qt::Unchecked; + + /* determine if it is already in the versionExceptionHash */ + QString directory = directoryTree->currentItem()->data(0, Qt::UserRole).toString(); + Qt::CheckState dirState = directoryTree->currentItem()->checkState(0); + QString file = fileTableItem->text(); + QString fullPath = directory + file; + int thisJobNum = colZeroItem->text().toInt(); + int hashJobNum = m_versionExceptionHash.value(fullPath, 0); + + if (mainWin->m_rtVerTabICDebug) { + QString msg = QString("versrow=%1 prev=%2 cur=%3 def=%4 dir=%5 hashJobNum=%6 thisJobNum=%7 filestate=%8 fec=%9 vec=%10\n") + .arg(row).arg(prevState).arg(curState).arg(defState).arg(dirState).arg(hashJobNum).arg(thisJobNum).arg(fileState) + .arg(m_fileExceptionHash.count()).arg(m_versionExceptionHash.count()); + Pmsg1(000, "%s", msg.toUtf8().data()); } + /* if changed from partially checked to checked, make it unchecked */ + if ((curState == Qt::Checked) && (row == 0) && (fileState == Qt::Unchecked)) { + if (mainWin->m_rtVerTabICDebug) Pmsg0(000, "Setting to Qt::Checked\n"); + fileTableItem->setCheckState(Qt::Checked); + } else if ((prevState == Qt::PartiallyChecked) && (curState == Qt::Checked) && (row == 0) && (fileState == Qt::Checked) && (dirState == Qt::Unchecked)) { + //versrow=0 prev=1 cur=2 def=1 dir=0 hashJobNum=0 thisJobNum=64 filestate=2 fec=1 vec=0 + if (mainWin->m_rtVerTabICDebug) Pmsg1(000, "fileExceptionRemove %s, %i\n", fullPath.toUtf8().data()); + fileExceptionRemove(fullPath, directory); + } else if ((curState == Qt::Checked) && (row == 0) && (hashJobNum != 0) && (dirState != Qt::Unchecked)) { + //versrow=0 prev=0 cur=2 def=1 dir=2 hashJobNum=53 thisJobNum=64 filestate=2 fec=1 vec=1 + if (mainWin->m_rtVerTabICDebug) Pmsg1(000, "m_versionExceptionHash.remove %s\n", fullPath.toUtf8().data()); + m_versionExceptionHash.remove(fullPath); + fileExceptionRemove(fullPath, directory); + } else if ((curState == Qt::Checked) && (row == 0)) { + if (mainWin->m_rtVerTabICDebug) Pmsg1(000, "m_versionExceptionHash.remove %s\n", fullPath.toUtf8().data()); + m_versionExceptionHash.remove(fullPath); + } else if (prevState != curState) { + if (mainWin->m_rtVerTabICDebug) Pmsg2(000, " THE STATE OF THE version Check has changed, Setting StateList[%i] to %i\n", row, curState); + if ((curState == Qt::Checked) || (curState == Qt::PartiallyChecked) && (row != 0)) { + if (mainWin->m_rtVerTabICDebug) Pmsg2(000, "Inserting into m_versionExceptionHash %s, %i\n", fullPath.toUtf8().data(), thisJobNum); + m_versionExceptionHash.insert(fullPath, thisJobNum); + if (fileState != Qt::Checked) { + if (mainWin->m_rtVerTabICDebug) Pmsg2(000, "Inserting into m_fileExceptionHash %s, %i\n", fullPath.toUtf8().data(), curState); + fileExceptionInsert(fullPath, directory, curState); + } + } else { + if (mainWin->m_rtVerTabICDebug) Pmsg0(000, "got here\n"); + } + } else { + if (mainWin->m_rtVerTabICDebug) Pmsg0(000, "no conditions met\n"); + } + + updateFileTableChecks(); + updateVersionTableChecks(); +} + +/* + * Simple function to set the check state in the file table by disconnecting the + * signal/slot the setting then reconnecting the signal/slot + */ +void restoreTree::fileTableDisconnectedSet(QTableWidgetItem *item, Qt::CheckState state, bool color) +{ + disconnect(fileTable, SIGNAL(itemChanged(QTableWidgetItem *)), + this, SLOT(fileTableItemChanged(QTableWidgetItem *))); + item->setCheckState(state); + if (color) item->setBackground(Qt::yellow); + else item->setBackground(Qt::white); + connect(fileTable, SIGNAL(itemChanged(QTableWidgetItem *)), + this, SLOT(fileTableItemChanged(QTableWidgetItem *))); +} + +/* + * Simple function to set the check state in the version table by disconnecting the + * signal/slot the setting then reconnecting the signal/slot + */ +void restoreTree::versionTableDisconnectedSet(QTableWidgetItem *item, Qt::CheckState state) +{ + disconnect(versionTable, SIGNAL(itemChanged(QTableWidgetItem *)), + this, SLOT(versionTableItemChanged(QTableWidgetItem *))); + item->setCheckState(state); + connect(versionTable, SIGNAL(itemChanged(QTableWidgetItem *)), + this, SLOT(versionTableItemChanged(QTableWidgetItem *))); +} + +/* + * Simple function to set the check state in the directory tree by disconnecting the + * signal/slot the setting then reconnecting the signal/slot + */ +void restoreTree::directoryTreeDisconnectedSet(QTreeWidgetItem *item, Qt::CheckState state) +{ + disconnect(directoryTree, SIGNAL(itemChanged(QTreeWidgetItem *, int)), + this, SLOT(directoryItemChanged(QTreeWidgetItem *, int))); + item->setCheckState(0, state); + connect(directoryTree, SIGNAL(itemChanged(QTreeWidgetItem *, int)), + this, SLOT(directoryItemChanged(QTreeWidgetItem *, int))); +} + +/* + * Simplify the updating of the check state in the File table by iterating through + * each item in the file table to determine it's appropriate state. + * !! Will probably want to concoct a way to do this without iterating for the possibility + * of the very large directories. + */ +void restoreTree::updateFileTableChecks() +{ + /* deterimine the default state from the state of the directory */ + QTreeWidgetItem *dirTreeItem = directoryTree->currentItem(); + Qt::CheckState dirState = dirTreeItem->checkState(0); + + QString dirName = dirTreeItem->data(0, Qt::UserRole).toString(); + + /* Update the items in the version table */ + int rcnt = fileTable->rowCount(); + for (int row=0; rowitem(row, 0); + + Qt::CheckState curState = item->checkState(); + Qt::CheckState newState = Qt::PartiallyChecked; + if (dirState == Qt::Unchecked) newState = Qt::Unchecked; + + /* determine if it is already in the m_fileExceptionHash */ + QString file = item->text(); + QString fullPath = dirName + file; + Qt::CheckState hashState = m_fileExceptionHash.value(fullPath, (Qt::CheckState)3); + int hashJobNum = m_versionExceptionHash.value(fullPath, 0); + + if (hashState != 3) newState = hashState; + + if (mainWin->m_rtUpdateFTDebug) { + QString msg = QString("file row=%1 cur=%2 hash=%3 new=%4 dirState=%5\n") + .arg(row).arg(curState).arg(hashState).arg(newState).arg(dirState); + Pmsg1(000, "%s", msg.toUtf8().data()); + } + + bool docolor = false; + if (hashJobNum != 0) docolor = true; + bool isyellow = item->background().color() == QColor(Qt::yellow); + if ((newState != curState) || (hashState == 3) || ((isyellow && !docolor) || (!isyellow && docolor))) + fileTableDisconnectedSet(item, newState, docolor); + m_fileCheckStateList[row] = newState; + } +} + +/* + * Simplify the updating of the check state in the Version table by iterating through + * each item in the file table to determine it's appropriate state. + */ +void restoreTree::updateVersionTableChecks() +{ + /* deterimine the default state from the state of the directory */ + QTreeWidgetItem *dirTreeItem = directoryTree->currentItem(); + Qt::CheckState dirState = dirTreeItem->checkState(0); + QString dirName = dirTreeItem->data(0, Qt::UserRole).toString(); + + /* deterimine the default state from the state of the file */ + QTableWidgetItem *fileTableItem = fileTable->item(fileTable->currentRow(), 0); + Qt::CheckState fileState = fileTableItem->checkState(); + QString file = fileTableItem->text(); + QString fullPath = dirName + file; + int hashJobNum = m_versionExceptionHash.value(fullPath, 0); + + /* Update the items in the version table */ + int cnt = versionTable->rowCount(); + for (int row=0; rowitem(row, 0); + + Qt::CheckState curState = item->checkState(); + Qt::CheckState newState = Qt::Unchecked; + + if ((row == 0) && (fileState != Qt::Unchecked) && (hashJobNum == 0)) + newState = Qt::PartiallyChecked; + /* determine if it is already in the versionExceptionHash */ + if (hashJobNum) { + int thisJobNum = item->text().toInt(); + if (thisJobNum == hashJobNum) + newState = Qt::Checked; + } + if (mainWin->m_rtChecksDebug) { + QString msg = QString("ver row=%1 cur=%2 hashJobNum=%3 new=%4 dirState=%5\n") + .arg(row).arg(curState).arg(hashJobNum).arg(newState).arg(dirState); + Pmsg1(000, "%s", msg.toUtf8().data()); + } + if (newState != curState) + versionTableDisconnectedSet(item, newState); + m_versionCheckStateList[row] = newState; + } +} + +/* + * Quick subroutine to "return via subPaths" a list of subpaths when passed a fullPath + */ +void restoreTree::fullPathtoSubPaths(QStringList &subPaths, QString &fullPath_in) +{ + int index; + bool done = false; + QString fullPath = fullPath_in; + QString direct, path; + while (((index = m_slashregex.lastIndexIn(fullPath, -2)) != -1) && (!done)) { + direct = path = fullPath; + path.replace(index+1, fullPath.length()-index-1, ""); + direct.replace(0, index+1, ""); + if (false) { + QString msg = QString("length = \"%1\" index = \"%2\" Considering \"%3\" \"%4\"\n") + .arg(fullPath.length()).arg(index).arg(path).arg(direct); + Pmsg0(000, msg.toUtf8().data()); + } + fullPath = path; + subPaths.append(fullPath); + } +} + +/* + * A Function to set the icon state and insert a record into + * m_directoryIconStateHash when an exception is added by the user + */ +void restoreTree::directoryIconStateInsert(QString &fullPath, Qt::CheckState excpState) +{ + QStringList paths; + fullPathtoSubPaths(paths, fullPath); + /* an exception that causes the item in the file table to be "Checked" has occured */ + if (excpState == Qt::Checked) { + bool foundAsUnChecked = false; + QTreeWidgetItem *firstItem = m_dirPaths.value(paths[0]); + if (firstItem) { + if (firstItem->checkState(0) == Qt::Unchecked) + foundAsUnChecked = true; + } + if (foundAsUnChecked) { + /* as long as directory item is Unchecked, set icon state to "green check" */ + bool done = false; + QListIterator siter(paths); + while (siter.hasNext() && !done) { + QString path = siter.next(); + QTreeWidgetItem *item = m_dirPaths.value(path); + if (item) { + if (item->checkState(0) != Qt::Unchecked) + done = true; + else { + directorySetIcon(1, FolderGreenChecked, path, item); + if (mainWin->m_rtIconStateDebug) Pmsg1(000, "In restoreTree::directoryIconStateInsert inserting %s\n", path.toUtf8().data()); + } + } + } + } else { + /* if it is partially checked or fully checked insert green Check until a unchecked is found in the path */ + if (mainWin->m_rtIconStateDebug) Pmsg1(000, "In restoreTree::directoryIconStateInsert Aqua %s\n", paths[0].toUtf8().data()); + bool done = false; + QListIterator siter(paths); + while (siter.hasNext() && !done) { + QString path = siter.next(); + QTreeWidgetItem *item = m_dirPaths.value(path); + if (item) { /* if the directory item is checked, set icon state to unchecked "green check" */ + if (item->checkState(0) == Qt::Checked) + done = true; + directorySetIcon(1, FolderGreenChecked, path, item); + if (mainWin->m_rtIconStateDebug) Pmsg1(000, "In restoreTree::directoryIconStateInsert boogie %s\n", path.toUtf8().data()); + } + } + } + } + /* an exception that causes the item in the file table to be "Unchecked" has occured */ + if (excpState == Qt::Unchecked) { + bool done = false; + QListIterator siter(paths); + while (siter.hasNext() && !done) { + QString path = siter.next(); + QTreeWidgetItem *item = m_dirPaths.value(path); + if (item) { /* if the directory item is checked, set icon state to unchecked "white check" */ + if (item->checkState(0) == Qt::Checked) + done = true; + directorySetIcon(1, FolderWhiteChecked, path, item); + if (mainWin->m_rtIconStateDebug) Pmsg1(000, "In restoreTree::directoryIconStateInsert boogie %s\n", path.toUtf8().data()); + } + } + } +} + +/* + * A function to set the icon state back to "folder" and to remove a record from + * m_directoryIconStateHash when an exception is removed by a user. + */ +void restoreTree::directoryIconStateRemove() +{ + QHash shouldBeIconStateHash; + /* First determine all paths with icons that should be checked with m_fileExceptionHash */ + /* Use iterator tera to iterate through m_fileExceptionHash */ + QHashIterator tera(m_fileExceptionHash); + while (tera.hasNext()) { + tera.next(); + if (mainWin->m_rtIconStateDebug) Pmsg2(000, "Alpha Key %s value %i\n", tera.key().toUtf8().data(), tera.value()); + + QString keyPath = tera.key(); + Qt::CheckState state = tera.value(); + + QStringList paths; + fullPathtoSubPaths(paths, keyPath); + /* if the state of the item in m_fileExceptionHash is checked + * each of the subpaths should be "Checked Green" */ + if (state == Qt::Checked) { + + bool foundAsUnChecked = false; + QTreeWidgetItem *firstItem = m_dirPaths.value(paths[0]); + if (firstItem) { + if (firstItem->checkState(0) == Qt::Unchecked) + foundAsUnChecked = true; + } + if (foundAsUnChecked) { + /* The right most directory is Unchecked, iterate leftwards + * as long as directory item is Unchecked, set icon state to "green check" */ + bool done = false; + QListIterator siter(paths); + while (siter.hasNext() && !done) { + QString path = siter.next(); + QTreeWidgetItem *item = m_dirPaths.value(path); + if (item) { + if (item->checkState(0) != Qt::Unchecked) + done = true; + else { + shouldBeIconStateHash.insert(path, FolderGreenChecked); + if (mainWin->m_rtIconStateDebug) Pmsg1(000, "In restoreTree::directoryIconStateInsert inserting %s\n", path.toUtf8().data()); + } + } + } + } + else { + /* The right most directory is Unchecked, iterate leftwards + * until directory item is Checked, set icon state to "green check" */ + bool done = false; + QListIterator siter(paths); + while (siter.hasNext() && !done) { + QString path = siter.next(); + QTreeWidgetItem *item = m_dirPaths.value(path); + if (item) { + if (item->checkState(0) == Qt::Checked) + done = true; + shouldBeIconStateHash.insert(path, FolderGreenChecked); + } + } + } + } + /* if the state of the item in m_fileExceptionHash is UNChecked + * each of the subpaths should be "Checked white" until the tree item + * which represents that path is Qt::Checked */ + if (state == Qt::Unchecked) { + bool done = false; + QListIterator siter(paths); + while (siter.hasNext() && !done) { + QString path = siter.next(); + QTreeWidgetItem *item = m_dirPaths.value(path); + if (item) { + if (item->checkState(0) == Qt::Checked) + done = true; + shouldBeIconStateHash.insert(path, FolderWhiteChecked); + } + } + } + } + /* now iterate through m_directoryIconStateHash which are the items that are checked + * and remove all of those that are not in shouldBeIconStateHash */ + QHashIterator iter(m_directoryIconStateHash); + while (iter.hasNext()) { + iter.next(); + if (mainWin->m_rtIconStateDebug) Pmsg2(000, "Beta Key %s value %i\n", iter.key().toUtf8().data(), iter.value()); + + QString keyPath = iter.key(); + if (shouldBeIconStateHash.value(keyPath)) { + if (mainWin->m_rtIconStateDebug) Pmsg1(000, "WAS found in shouldBeStateHash %s\n", keyPath.toUtf8().data()); + //newval = m_directoryIconStateHash.value(path, FolderUnchecked) & (~change); + int newval = shouldBeIconStateHash.value(keyPath); + newval = ~newval; + newval = newval & FolderBothChecked; + QTreeWidgetItem *item = m_dirPaths.value(keyPath); + if (item) + directorySetIcon(0, newval, keyPath, item); + } else { + if (mainWin->m_rtIconStateDebug) Pmsg1(000, "NOT found in shouldBeStateHash %s\n", keyPath.toUtf8().data()); + QTreeWidgetItem *item = m_dirPaths.value(keyPath); + if (item) + directorySetIcon(0, FolderBothChecked, keyPath, item); + //item->setIcon(0,QIcon(QString::fromUtf8(":images/folder.png"))); + //m_directoryIconStateHash.remove(keyPath); + } + } +} + +void restoreTree::directorySetIcon(int operation, int change, QString &path, QTreeWidgetItem* item) { + int newval; + /* we are adding a check type white or green */ + if (operation > 0) { + /* get the old val and "bitwise OR" with the change */ + newval = m_directoryIconStateHash.value(path, FolderUnchecked) | change; + if (mainWin->m_rtIconStateDebug) Pmsg2(000, "Inserting into m_directoryIconStateHash path=%s newval=%i\n", path.toUtf8().data(), newval); + m_directoryIconStateHash.insert(path, newval); + } else { + /* we are removing a check type white or green */ + newval = m_directoryIconStateHash.value(path, FolderUnchecked) & (~change); + if (newval == 0) { + if (mainWin->m_rtIconStateDebug) Pmsg2(000, "Removing from m_directoryIconStateHash path=%s newval=%i\n", path.toUtf8().data(), newval); + m_directoryIconStateHash.remove(path); + } + else { + if (mainWin->m_rtIconStateDebug) Pmsg2(000, "Inserting into m_directoryIconStateHash path=%s newval=%i\n", path.toUtf8().data(), newval); + m_directoryIconStateHash.insert(path, newval); + } + } + if (newval == FolderUnchecked) + item->setIcon(0, QIcon(QString::fromUtf8(":images/folder.png"))); + else if (newval == FolderGreenChecked) + item->setIcon(0, QIcon(QString::fromUtf8(":images/folderchecked.png"))); + else if (newval == FolderWhiteChecked) + item->setIcon(0, QIcon(QString::fromUtf8(":images/folderunchecked.png"))); + else if (newval == FolderBothChecked) + item->setIcon(0, QIcon(QString::fromUtf8(":images/folderbothchecked.png"))); +} + +/* + * Test Button + */ +void restoreTree::testButtonPushed() +{ + QMultiHash versionFilesMulti; + QHash fullPathDone; + if ((mainWin->m_rtRestore1Debug) || (mainWin->m_rtRestore2Debug) || (mainWin->m_rtRestore3Debug)) + Pmsg0(000, "In restoreTree::testButtonPushed\n"); + /* Use a tree widget item iterator filtering for Checked Items */ + QTreeWidgetItemIterator diter(directoryTree, QTreeWidgetItemIterator::Checked); + while (*diter) { + QString directory = (*diter)->data(0, Qt::UserRole).toString(); + if (mainWin->m_rtRestore1Debug) + Pmsg1(000, "Directory Checked=\"%s\"\n", directory.toUtf8().data()); + /* With a checked directory, query for the files in the directory */ + QString cmd = + "SELECT DISTINCT Filename.Name, MAX(Job.JobId)" + " FROM File " + " LEFT OUTER JOIN Filename on (Filename.FilenameId=File.FilenameId)" + " LEFT OUTER JOIN Path ON (Path.PathId=File.PathId)" + " LEFT OUTER JOIN Job ON (File.JobId=Job.JobId)" + " WHERE Path.Path='" + directory + "' AND Filename.Name!=''" + " AND Job.Jobid IN (" + m_jobQuery + ")" + " GROUP BY Filename.Name"; + + if (mainWin->m_sqlDebug) Pmsg1(000, "Query cmd : %s\n", cmd.toUtf8().data()); + QStringList results; + if (m_console->sql_cmd(cmd, results)) { + + QStringList fieldlist; + + int row = 0; + /* Iterate through the record returned from the query */ + foreach (QString resultline, results) { + /* Iterate through fields in the record */ + int column = 0; + QString fullPath = ""; + Qt::CheckState fileExcpState = (Qt::CheckState)4; + fieldlist = resultline.split("\t"); + int version = 0; + foreach (QString field, fieldlist) { + if (column == 0) { + fullPath = directory + field; + } + if (column == 1) { + version = field.toInt(); + } + column++; + } + fileExcpState = m_fileExceptionHash.value(fullPath, (Qt::CheckState)3); + + int excpVersion = m_versionExceptionHash.value(fullPath, 0); + if (fileExcpState != Qt::Unchecked) { + QString debugtext; + if (excpVersion != 0) { + debugtext = QString("*E* version=%1").arg(excpVersion); + version = excpVersion; + } else + debugtext = QString("___ version=%1").arg(version); + if (mainWin->m_rtRestore1Debug) + Pmsg2(000, "Restoring %s File %s\n", debugtext.toUtf8().data(), fullPath.toUtf8().data()); + fullPathDone.insert(fullPath, 1); + versionFilesMulti.insert(version, fullPath); + } + row++; + } + } + ++diter; + } /* while (*diter) */ + + /* There may be some exceptions not accounted for yet with fullPathDone */ + QHashIterator ftera(m_fileExceptionHash); + while (ftera.hasNext()) { + ftera.next(); + QString fullPath = ftera.key(); + Qt::CheckState state = ftera.value(); + if (state != 0) { + /* now we don't want the ones already done */ + if (fullPathDone.value(fullPath, 0) == 0) { + int version = m_versionExceptionHash.value(fullPath, 0); + QString debugtext = ""; + if (version != 0) + debugtext = QString("E1* version=%1").arg(version); + else { + version = mostRecentVersionfromFullPath(fullPath); + if (version) + debugtext = QString("E2* version=%1").arg(version); + else + debugtext = QString("Error det vers").arg(version); + } + if (mainWin->m_rtRestore1Debug) + Pmsg2(000, "Restoring %s file %s\n", debugtext.toUtf8().data(), fullPath.toUtf8().data()); + versionFilesMulti.insert(version, fullPath); + } /* if fullPathDone.value(fullPath, 0) == 0 */ + } /* if state != 0 */ + } /* while ftera.hasNext */ + + /* now for the final spit out of the versions and lists of files for each version */ + QHash doneKeys; + QHashIterator miter(versionFilesMulti); + while (miter.hasNext()) { + miter.next(); + int fversion = miter.key(); + /* did not succeed in getting an iterator to work as expected on versionFilesMulti so use doneKeys */ + if (doneKeys.value(fversion, 0) == 0) { + if (mainWin->m_rtRestore2Debug) Pmsg1(000, "Version->%i\n", fversion); + QStringList fullPathList = versionFilesMulti.values(fversion); + /* create the command to perform the restore */ + QString cmd = QString("restore"); + cmd += " client=\"" + m_prevClientCombo + "\"" + " jobid=\"" + QString("%1").arg(fversion) + "\" yes"; + foreach(QString ffullPath, fullPathList) { + if (mainWin->m_rtRestore2Debug) Pmsg1(000, " file->%s\n", ffullPath.toUtf8().data()); + cmd += " file=\"" + ffullPath + "\""; + } + cmd += " yes"; + if (mainWin->m_commandDebug) + Pmsg1(000, "preRestore command \'%s\'\n", cmd.toUtf8().data()); + consoleCommand(cmd); + mainWin->resetFocus(); + doneKeys.insert(fversion,1); + } + } +} + +int restoreTree::mostRecentVersionfromFullPath(QString &fullPath) +{ + int qversion = 0; + QString directory, fileName; + int index = m_slashregex.lastIndexIn(fullPath, -2); + if (index != -1) { + directory = fileName = fullPath; + directory.replace(index+1, fullPath.length()-index-1, ""); + fileName.replace(0, index+1, ""); + if (false) { + QString msg = QString("length = \"%1\" index = \"%2\" Considering \"%3\" \"%4\"\n") + .arg(fullPath.length()).arg(index).arg(fileName).arg(directory); + Pmsg0(000, msg.toUtf8().data()); + } + /* so now we need the latest version from the database */ + QString cmd = + "SELECT MAX(Job.JobId)" + " FROM File " + " LEFT OUTER JOIN Filename on (Filename.FilenameId=File.FilenameId)" + " LEFT OUTER JOIN Path ON (Path.PathId=File.PathId)" + " LEFT OUTER JOIN Job ON (File.JobId=Job.JobId)" + " WHERE Path.Path='" + directory + "' AND Filename.Name!=''" + " AND Job.Jobid IN (" + m_jobQuery + ")" + " AND Filename.Name='" + fileName + "'" + " GROUP BY Filename.Name"; + + if (mainWin->m_sqlDebug) Pmsg1(000, "Query cmd : %s\n", cmd.toUtf8().data()); + QStringList results; + if (m_console->sql_cmd(cmd, results)) { + QStringList fieldlist; + int row = 0; + /* Iterate through the record returned from the query */ + foreach (QString resultline, results) { + /* Iterate through fields in the record */ + int column = 0; + fieldlist = resultline.split("\t"); + foreach (QString field, fieldlist) { + if (column == 0) { + qversion = field.toInt(); + } + column++; + } + row++; + } + } + } /* if (index != -1) */ + return qversion; +} diff --git a/bacula/src/qt-console/restore/restoretree.h b/bacula/src/qt-console/restore/restoretree.h index 8666ce6910..9d486536f5 100644 --- a/bacula/src/qt-console/restore/restoretree.h +++ b/bacula/src/qt-console/restore/restoretree.h @@ -38,6 +38,7 @@ #include "pages.h" #include "ui_restoretree.h" + /* * A restore tree to view files in the catalog */ @@ -49,13 +50,25 @@ public: restoreTree(); ~restoreTree(); virtual void currentStackItem(); + enum folderCheckState + { + FolderUnchecked = 0, + FolderGreenChecked = 1, + FolderWhiteChecked = 2, + FolderBothChecked = 3 + }; private slots: void refreshButtonPushed(); + void testButtonPushed(); void jobComboChanged(int); - void directoryItemChanged(QTreeWidgetItem *, QTreeWidgetItem *); - void fileItemChanged(QTableWidgetItem *,QTableWidgetItem *); + void directoryCurrentItemChanged(QTreeWidgetItem *, QTreeWidgetItem *); + void fileCurrentItemChanged(QTableWidgetItem *,QTableWidgetItem *); void directoryItemExpanded(QTreeWidgetItem *); + void setCheckofChildren(QTreeWidgetItem *item, Qt::CheckState); + void directoryItemChanged(QTreeWidgetItem *, int); + void fileTableItemChanged(QTableWidgetItem *); + void versionTableItemChanged(QTableWidgetItem *); private: void populateDirectoryTree(); @@ -65,18 +78,40 @@ private: void setupPage(); void writeSettings(); void readSettings(); + void fileExceptionInsert(QString &, QString &, Qt::CheckState); + void fileExceptionRemove(QString &, QString &); + void directoryTreeDisconnectedSet(QTreeWidgetItem *, Qt::CheckState); + void fileTableDisconnectedSet(QTableWidgetItem *, Qt::CheckState, bool color); + void versionTableDisconnectedSet(QTableWidgetItem *, Qt::CheckState); + void updateFileTableChecks(); + void updateVersionTableChecks(); + void directoryIconStateInsert(QString &, Qt::CheckState); + void directoryIconStateRemove(); + void directorySetIcon(int operation, int change, QString &, QTreeWidgetItem* item); + void fullPathtoSubPaths(QStringList &, QString &); + int mostRecentVersionfromFullPath(QString &); + bool m_populated; QRegExp m_winRegExpDrive; QRegExp m_winRegExpPath; QRegExp m_slashregex; bool m_slashTrap; - //QString m_jobCondition; QHash m_dirPaths; QString m_condition; QString m_jobQuery; QString m_jobQueryPart; + QString m_prevJobCombo; + QString m_prevClientCombo; + QString m_prevFileSetCombo; + QString m_JobsCheckedList; int m_debugCnt; bool m_debugTrap; + QList m_fileCheckStateList; + QList m_versionCheckStateList; + QHash m_fileExceptionHash; + QMultiHash m_fileExceptionMulti; + QHash m_versionExceptionHash; + QHash m_directoryIconStateHash; }; #endif /* _RESTORETREE_H_ */ diff --git a/bacula/src/qt-console/restore/restoretree.ui b/bacula/src/qt-console/restore/restoretree.ui index e6a08ff115..70c85eb35f 100644 --- a/bacula/src/qt-console/restore/restoretree.ui +++ b/bacula/src/qt-console/restore/restoretree.ui @@ -5,8 +5,8 @@ 0 0 - 400 - 319 + 449 + 313 @@ -19,12 +19,86 @@ 6 + + + + 0 + + + 6 + + + + + + 5 + 0 + 0 + 0 + + + + Directory + + + + + + + 0 + + + 6 + + + + + Refresh + + + :/images/view-refresh.svg + + + + + + + + + + + + + + + + Qt::Horizontal + + + + 21 + 26 + + + + + + + + Test + + + + + + + Qt::Horizontal - + 0 @@ -48,7 +122,7 @@ - + 0 @@ -80,90 +154,49 @@ 6 - - - - + - Versions + FileName Qt::AlignCenter - - - - - - - - 0 - - - 6 - - - - - - 5 - 0 - 0 - 0 - - - - Directory - - - - - - - 0 - - - 6 - - - + + - Refresh + Versions of File - - :/images/view-refresh.svg + + Qt::AlignCenter - - - - - - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - + + - - + + + + + + + + Select Directory + + + + + + + + UnselectDirectory + + -- 2.39.5