diff --git a/CHANGELOG.md b/CHANGELOG.md index d7b2f8f6..53874acf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,8 +5,12 @@ This project adheres to [Semantic Versioning](http://semver.org/). ## [1.0.1 / 5.55.1] - 2021-12-03 +### Added +- added checkboxed to most major box options lists + ### Changed - rolled back changed to "OpenClsid=..." handling +- made all major lists in the box options editable ### Fixed - issue with read only paths introduced in 1.0.0 diff --git a/SandboxiePlus/SandMan/Windows/OptionsAccess.cpp b/SandboxiePlus/SandMan/Windows/OptionsAccess.cpp index 69999eb5..414c5b31 100644 --- a/SandboxiePlus/SandMan/Windows/OptionsAccess.cpp +++ b/SandboxiePlus/SandMan/Windows/OptionsAccess.cpp @@ -34,6 +34,7 @@ void COptionsWindow::CreateAccess() //connect(ui.treeAccess, SIGNAL(itemClicked(QTreeWidgetItem*, int)), this, SLOT(OnAccessItemClicked(QTreeWidgetItem*, int))); connect(ui.treeAccess, SIGNAL(itemDoubleClicked(QTreeWidgetItem*, int)), this, SLOT(OnAccessItemDoubleClicked(QTreeWidgetItem*, int))); connect(ui.treeAccess, SIGNAL(itemSelectionChanged()), this, SLOT(OnAccessSelectionChanged())); + connect(ui.treeAccess, SIGNAL(itemChanged(QTreeWidgetItem *, int)), this, SLOT(OnAccessChanged(QTreeWidgetItem *, int))); } void COptionsWindow::OnAccessChanged() @@ -143,6 +144,9 @@ void COptionsWindow::LoadAccessList() { foreach(const QString& Value, m_pBox->GetTextList(AccessTypeToName((EAccessEntry)i), m_Template)) ParseAndAddAccessEntry((EAccessEntry)i, Value); + + foreach(const QString& Value, m_pBox->GetTextList(AccessTypeToName((EAccessEntry)i) + "Disabled", m_Template)) + ParseAndAddAccessEntry((EAccessEntry)i, Value, true); } LoadAccessListTmpl(); @@ -161,7 +165,7 @@ void COptionsWindow::LoadAccessListTmpl(bool bUpdate) for (int i = 0; i < eMaxAccessType; i++) { foreach(const QString& Value, m_pBox->GetTextListTmpl(AccessTypeToName((EAccessEntry)i), Template)) - ParseAndAddAccessEntry((EAccessEntry)i, Value, Template); + ParseAndAddAccessEntry((EAccessEntry)i, Value, false, Template); } } } @@ -180,7 +184,7 @@ void COptionsWindow::LoadAccessListTmpl(bool bUpdate) } } -void COptionsWindow::ParseAndAddAccessEntry(EAccessEntry EntryType, const QString& Value, const QString& Template) +void COptionsWindow::ParseAndAddAccessEntry(EAccessEntry EntryType, const QString& Value, bool disabled, const QString& Template) { EAccessType Type; EAccessMode Mode; @@ -222,11 +226,11 @@ void COptionsWindow::ParseAndAddAccessEntry(EAccessEntry EntryType, const QStrin QStringList Values = Value.split(","); if (Values.count() >= 2) - AddAccessEntry(Type, Mode, Values[0], Values[1], Template); + AddAccessEntry(Type, Mode, Values[0], Values[1], disabled, Template); else if (Values[0].left(2) == "$:") // special cases - AddAccessEntry(Type, Mode, Values[0].mid(2), "$", Template); + AddAccessEntry(Type, Mode, Values[0].mid(2), "$", disabled, Template); else // all programs - AddAccessEntry(Type, Mode, "", Values[0], Template); + AddAccessEntry(Type, Mode, "", Values[0], disabled, Template); } QString COptionsWindow::GetAccessModeStr(EAccessMode Mode) @@ -281,7 +285,7 @@ void COptionsWindow::OnBrowseFolder() OnOptChanged(); } -void COptionsWindow::AddAccessEntry(EAccessType Type, EAccessMode Mode, QString Program, const QString& Path, const QString& Template) +void COptionsWindow::AddAccessEntry(EAccessType Type, EAccessMode Mode, QString Program, const QString& Path, bool disabled, const QString& Template) { QTreeWidgetItem* pItem = new QTreeWidgetItem(); @@ -307,6 +311,8 @@ void COptionsWindow::AddAccessEntry(EAccessType Type, EAccessMode Mode, QString pItem->setText(3, Path); pItem->setData(3, Qt::UserRole, Path); + if(Template.isEmpty()) + pItem->setCheckState(0, disabled ? Qt::Unchecked : Qt::Checked); ui.treeAccess->addTopLevelItem(pItem); } @@ -483,7 +489,7 @@ void COptionsWindow::OnAccessItemDoubleClicked(QTreeWidgetItem* pItem, int Colum foreach(const QString Group, GetCurrentGroups()){ QString GroupName = Group.mid(1, Group.length() - 2); - pCombo->addItem(tr("Group: %1").arg(Group), GroupName); + pCombo->addItem(tr("Group: %1").arg(GroupName), Group); } foreach(const QString & Name, m_Programs) @@ -509,6 +515,15 @@ void COptionsWindow::OnAccessItemDoubleClicked(QTreeWidgetItem* pItem, int Colum ui.treeAccess->setItemWidget(pItem, 3, pPath); } +void COptionsWindow::OnAccessChanged(QTreeWidgetItem* pItem, int Column) +{ + if (Column != 0) + return; + + m_AccessChanged = true; + OnOptChanged(); +} + void COptionsWindow::DeleteAccessEntry(QTreeWidgetItem* pItem) { if (!pItem) @@ -539,10 +554,10 @@ void COptionsWindow::SaveAccessList() CloseAccessEdit(true); - QStringList Keys = QStringList() + /*QStringList Keys = QStringList() << "NormalFilePath" << "OpenFilePath" << "OpenPipePath" << "ClosedFilePath" << "ReadFilePath" << "WriteFilePath" << "NormalKeyPath" << "OpenKeyPath" << "OpenConfPath" << "ClosedKeyPath" << "ReadKeyPath" << "WriteKeyPath" - << "NormalIpcPath"<< "OpenIpcPath" << "ClosedIpcPath" << "OpenWinClass" << "OpenClsid" << "ClosedClsid" << "ClosedRT"; + << "NormalIpcPath"<< "OpenIpcPath" << "ClosedIpcPath" << "OpenWinClass" << "OpenClsid" << "ClosedClsid" << "ClosedRT";*/ QMap> AccessMap; for (int i = 0; i < ui.treeAccess->topLevelItemCount(); i++) @@ -558,11 +573,17 @@ void COptionsWindow::SaveAccessList() Value = "$:" + Program; else if (!Program.isEmpty()) Value.prepend(Program + ","); - AccessMap[MakeAccessStr((EAccessType)Type, (EAccessMode)Mode)].append(Value); + + QString AccessStr = MakeAccessStr((EAccessType)Type, (EAccessMode)Mode); + if (pItem->checkState(0) == Qt::Unchecked) + AccessStr += "Disabled"; + AccessMap[AccessStr].append(Value); } - foreach(const QString& Key, Keys) + foreach(const QString & Key, AccessMap.uniqueKeys()) { WriteTextList(Key, AccessMap[Key]); + WriteTextList(Key + "Disabled", AccessMap[Key + "Disabled"]); + } m_AccessChanged = false; } diff --git a/SandboxiePlus/SandMan/Windows/OptionsForce.cpp b/SandboxiePlus/SandMan/Windows/OptionsForce.cpp index cbfc2bfd..f7514e23 100644 --- a/SandboxiePlus/SandMan/Windows/OptionsForce.cpp +++ b/SandboxiePlus/SandMan/Windows/OptionsForce.cpp @@ -14,10 +14,16 @@ void COptionsWindow::LoadForced() ui.treeForced->clear(); foreach(const QString& Value, m_pBox->GetTextList("ForceProcess", m_Template)) - AddForcedEntry(Value, 1); + AddForcedEntry(Value, (int)eProcess); + + foreach(const QString& Value, m_pBox->GetTextList("ForceProcessDisabled", m_Template)) + AddForcedEntry(Value, (int)eProcess, true); foreach(const QString& Value, m_pBox->GetTextList("ForceFolder", m_Template)) - AddForcedEntry(Value, 2); + AddForcedEntry(Value, (int)ePath); + + foreach(const QString& Value, m_pBox->GetTextList("ForceFolderDisabled", m_Template)) + AddForcedEntry(Value, (int)ePath, true); LoadForcedTmpl(); @@ -31,10 +37,10 @@ void COptionsWindow::LoadForcedTmpl(bool bUpdate) foreach(const QString& Template, m_pBox->GetTemplates()) { foreach(const QString& Value, m_pBox->GetTextListTmpl("ForceProcess", Template)) - AddForcedEntry(Value, 1, Template); + AddForcedEntry(Value, (int)eProcess, false, Template); foreach(const QString& Value, m_pBox->GetTextListTmpl("ForceFolder", Template)) - AddForcedEntry(Value, 2, Template); + AddForcedEntry(Value, (int)ePath, false, Template); } } else if (bUpdate) @@ -43,7 +49,7 @@ void COptionsWindow::LoadForcedTmpl(bool bUpdate) { QTreeWidgetItem* pItem = ui.treeForced->topLevelItem(i); int Type = pItem->data(0, Qt::UserRole).toInt(); - if (Type == -1) { + if (Type == -(int)eProcess) { delete pItem; continue; // entry from template } @@ -52,34 +58,49 @@ void COptionsWindow::LoadForcedTmpl(bool bUpdate) } } -void COptionsWindow::AddForcedEntry(const QString& Name, int type, const QString& Template) +void COptionsWindow::AddForcedEntry(const QString& Name, int type, bool disabled, const QString& Template) { QTreeWidgetItem* pItem = new QTreeWidgetItem(); - pItem->setText(0, (type == 1 ? tr("Process") : tr("Folder")) + (Template.isEmpty() ? "" : (" (" + Template + ")"))); - pItem->setData(0, Qt::UserRole, Template.isEmpty() ? type : -1); - SetProgramItem(Name, pItem, 1); + pItem->setCheckState(0, disabled ? Qt::Unchecked : Qt::Checked); + pItem->setText(0, (type == (int)eProcess ? tr("Process") : tr("Folder")) + (Template.isEmpty() ? "" : (" (" + Template + ")"))); + pItem->setData(0, Qt::UserRole, Template.isEmpty() ? type : (int)eTemplate); + SetProgramItem(Name, pItem, (int)eProcess); + pItem->setFlags(pItem->flags() | Qt::ItemIsEditable); ui.treeForced->addTopLevelItem(pItem); } void COptionsWindow::SaveForced() { QStringList ForceProcess; + QStringList ForceProcessDisabled; QStringList ForceFolder; + QStringList ForceFolderDisabled; + for (int i = 0; i < ui.treeForced->topLevelItemCount(); i++) { QTreeWidgetItem* pItem = ui.treeForced->topLevelItem(i); int Type = pItem->data(0, Qt::UserRole).toInt(); - if (Type == -1) + if (Type == (int)eTemplate) continue; // entry from template - switch (Type) - { - case 1: ForceProcess.append(pItem->data(1, Qt::UserRole).toString()); break; - case 2: ForceFolder.append(pItem->data(1, Qt::UserRole).toString()); break; + + if (pItem->checkState(0) == Qt::Checked) { + switch (Type) { + case eProcess: ForceProcess.append(pItem->data(1, Qt::UserRole).toString()); break; + case ePath: ForceFolder.append(pItem->data(1, Qt::UserRole).toString()); break; + } + } + else { + switch (Type) { + case eProcess: ForceProcessDisabled.append(pItem->data(1, Qt::UserRole).toString()); break; + case ePath: ForceFolderDisabled.append(pItem->data(1, Qt::UserRole).toString()); break; + } } } WriteTextList("ForceProcess", ForceProcess); + WriteTextList("ForceProcessDisabled", ForceProcessDisabled); WriteTextList("ForceFolder", ForceFolder); + WriteTextList("ForceFolderDisabled", ForceFolderDisabled); m_ForcedChanged = false; } @@ -89,7 +110,7 @@ void COptionsWindow::OnForceProg() QString Value = SelectProgram(); if (Value.isEmpty()) return; - AddForcedEntry(Value, 1); + AddForcedEntry(Value, (int)eProcess); m_ForcedChanged = true; OnOptChanged(); } @@ -99,7 +120,7 @@ void COptionsWindow::OnForceDir() QString Value = QFileDialog::getExistingDirectory(this, tr("Select Directory")).replace("/", "\\"); if (Value.isEmpty()) return; - AddForcedEntry(Value, 2); + AddForcedEntry(Value, (int)ePath); m_ForcedChanged = true; OnOptChanged(); } @@ -110,3 +131,11 @@ void COptionsWindow::OnDelForce() m_ForcedChanged = true; OnOptChanged(); } + +void COptionsWindow::OnForcedChanged(QTreeWidgetItem* pItem, int Index) +{ + //QString Test = pItem->data(1, Qt::UserRole).toString(); + //qDebug() << Test; + m_ForcedChanged = true; + OnOptChanged(); +} \ No newline at end of file diff --git a/SandboxiePlus/SandMan/Windows/OptionsGrouping.cpp b/SandboxiePlus/SandMan/Windows/OptionsGrouping.cpp index c6abb63c..247564b5 100644 --- a/SandboxiePlus/SandMan/Windows/OptionsGrouping.cpp +++ b/SandboxiePlus/SandMan/Windows/OptionsGrouping.cpp @@ -30,8 +30,10 @@ void COptionsWindow::LoadGroups() continue; QTreeWidgetItem* pSubItem = new QTreeWidgetItem(); SetProgramItem(Entries[i], pSubItem, 0); + pSubItem->setFlags(pSubItem->flags() | Qt::ItemIsEditable); pItem->addChild(pSubItem); } + pItem->setFlags(pItem->flags() | Qt::ItemIsEditable); ui.treeGroups->addTopLevelItem(pItem); } @@ -149,52 +151,26 @@ void COptionsWindow::OnAddGroup() QTreeWidgetItem* pItem = new QTreeWidgetItem(); pItem->setText(0, Value); pItem->setData(0, Qt::UserRole, "<" + Value + ">"); + pItem->setFlags(pItem->flags() | Qt::ItemIsEditable); ui.treeGroups->addTopLevelItem(pItem); m_GroupsChanged = true; OnOptChanged(); } -void COptionsWindow::AddProgToGroup(QTreeWidget* pTree, const QString& Groupe) +void COptionsWindow::AddProgToGroup(QTreeWidget* pTree, const QString& Groupe, bool disabled) { QString Value = SelectProgram(); if (Value.isEmpty()) return; QTreeWidgetItem* pItem = new QTreeWidgetItem(); + pItem->setCheckState(0, disabled ? Qt::Unchecked : Qt::Checked); SetProgramItem(Value, pItem, 0); + pItem->setFlags(pItem->flags() | Qt::ItemIsEditable); pTree->addTopLevelItem(pItem); - AddProgToGroup(Value, Groupe); -} - -void COptionsWindow::AddProgToGroup(const QString& Value, const QString& Groupe) -{ - QTreeWidgetItem* pGroupItem = NULL; - for (int i = 0; i < ui.treeGroups->topLevelItemCount(); i++) - { - QTreeWidgetItem* pCurItem = ui.treeGroups->topLevelItem(i); - if (pCurItem->data(0, Qt::UserRole).toString().compare(Groupe, Qt::CaseInsensitive) == 0) - { - pGroupItem = pCurItem; - break; - } - } - - if (!pGroupItem) - { - pGroupItem = new QTreeWidgetItem(); - pGroupItem->setText(0, Groupe.mid(1, Groupe.length()-2)); - pGroupItem->setData(0, Qt::UserRole, Groupe); - ui.treeGroups->addTopLevelItem(pGroupItem); - } - - QTreeWidgetItem* pProgItem = new QTreeWidgetItem(); - SetProgramItem(Value, pProgItem, 0); - pGroupItem->addChild(pProgItem); - - m_GroupsChanged = true; - OnOptChanged(); + AddProgramToGroup(Value, Groupe); } void COptionsWindow::DelProgFromGroup(QTreeWidget* pTree, const QString& Groupe) @@ -235,26 +211,31 @@ void COptionsWindow::AddProgramToGroup(const QString& Program, const QString& Gr QTreeWidgetItem* pSubItem = new QTreeWidgetItem(); SetProgramItem(Program, pSubItem, 0); + pSubItem->setFlags(pSubItem->flags() | Qt::ItemIsEditable); pItem->addChild(pSubItem); m_GroupsChanged = true; OnOptChanged(); } -void COptionsWindow::DelProgramFromGroup(const QString& Program, const QString& Group) +bool COptionsWindow::DelProgramFromGroup(const QString& Program, const QString& Group) { QTreeWidgetItem* pItem = FindGroupByName(Group, true); + bool bFound = false; for (int j = 0; j < pItem->childCount(); j++){ QTreeWidgetItem* pProgItem = pItem->child(j); if (pProgItem->data(0, Qt::UserRole).toString().compare(Program, Qt::CaseInsensitive) == 0) { delete pProgItem; + bFound = true; break; } } m_GroupsChanged = true; OnOptChanged(); + + return bFound; } QTreeWidgetItem* COptionsWindow::FindGroupByName(const QString& Group, bool bAdd) @@ -273,6 +254,7 @@ QTreeWidgetItem* COptionsWindow::FindGroupByName(const QString& Group, bool bAdd if (GroupName.length() > 2) GroupName = GroupName.mid(1, GroupName.length() - 2); pItem->setText(0, GroupName); + pItem->setFlags(pItem->flags() | Qt::ItemIsEditable); ui.treeGroups->addTopLevelItem(pItem); return pItem; } @@ -303,6 +285,7 @@ void COptionsWindow::OnAddProg() QTreeWidgetItem* pSubItem = new QTreeWidgetItem(); SetProgramItem(Value, pSubItem, 0); + pSubItem->setFlags(pSubItem->flags() | Qt::ItemIsEditable); pItem->addChild(pSubItem); m_GroupsChanged = true; @@ -326,9 +309,8 @@ void COptionsWindow::OnDelProg() OnOptChanged(); } -void COptionsWindow::CopyGroupToList(const QString& Groupe, QTreeWidget* pTree) +void COptionsWindow::CopyGroupToList(const QString& Groupe, QTreeWidget* pTree, bool disabled) { - pTree->clear(); for (int i = 0; i < ui.treeGroups->topLevelItemCount(); i++) { QTreeWidgetItem* pItem = ui.treeGroups->topLevelItem(i); @@ -339,7 +321,9 @@ void COptionsWindow::CopyGroupToList(const QString& Groupe, QTreeWidget* pTree) QString Value = pItem->child(j)->data(0, Qt::UserRole).toString(); QTreeWidgetItem* pSubItem = new QTreeWidgetItem(); + pSubItem->setCheckState(0, disabled ? Qt::Unchecked : Qt::Checked); SetProgramItem(Value, pSubItem, 0); + pSubItem->setFlags(pSubItem->flags() | Qt::ItemIsEditable); pTree->addTopLevelItem(pSubItem); } break; diff --git a/SandboxiePlus/SandMan/Windows/OptionsNetwork.cpp b/SandboxiePlus/SandMan/Windows/OptionsNetwork.cpp index 9861c39a..4b5af2e8 100644 --- a/SandboxiePlus/SandMan/Windows/OptionsNetwork.cpp +++ b/SandboxiePlus/SandMan/Windows/OptionsNetwork.cpp @@ -20,11 +20,13 @@ void COptionsWindow::CreateNetwork() connect(ui.treeINet, SIGNAL(itemDoubleClicked(QTreeWidgetItem*, int)), this, SLOT(OnINetItemDoubleClicked(QTreeWidgetItem*, int))); connect(ui.treeINet, SIGNAL(itemSelectionChanged()), this, SLOT(OnINetSelectionChanged())); + connect(ui.treeINet, SIGNAL(itemChanged(QTreeWidgetItem *, int)), this, SLOT(OnINetChanged(QTreeWidgetItem *, int))); connect(ui.btnAddFwRule, SIGNAL(clicked(bool)), this, SLOT(OnAddNetFwRule())); connect(ui.btnDelFwRule, SIGNAL(clicked(bool)), this, SLOT(OnDelNetFwRule())); connect(ui.treeNetFw, SIGNAL(itemDoubleClicked(QTreeWidgetItem*, int)), this, SLOT(OnNetFwItemDoubleClicked(QTreeWidgetItem*, int))); connect(ui.treeNetFw, SIGNAL(itemSelectionChanged()), this, SLOT(OnNetFwSelectionChanged())); + connect(ui.treeNetFw, SIGNAL(itemChanged(QTreeWidgetItem *, int)), this, SLOT(OnNetFwChanged(QTreeWidgetItem *, int))); connect(ui.chkShowNetFwTmpl, SIGNAL(clicked(bool)), this, SLOT(OnShowNetFwTmpl())); @@ -74,6 +76,9 @@ int COptionsWindow::GroupToINetMode(const QString& Mode) if (Mode.compare("", Qt::CaseInsensitive) == 0) return 0; if (Mode.compare("", Qt::CaseInsensitive) == 0) return 1; if (Mode.compare("", Qt::CaseInsensitive) == 0) return 2; + if (Mode.compare("", Qt::CaseInsensitive) == 0) return 0 | 0x10; + if (Mode.compare("", Qt::CaseInsensitive) == 0) return 1 | 0x10; + if (Mode.compare("", Qt::CaseInsensitive) == 0) return 2 | 0x10; return -1; } @@ -81,9 +86,12 @@ QString COptionsWindow::INetModeToGroup(int Mode) { switch (Mode) { - case 0: return ""; - case 1: return ""; - case 2: return ""; + case 0: return ""; + case 1: return ""; + case 2: return ""; + case 0 | 0x10: return ""; + case 1 | 0x10: return ""; + case 2 | 0x10: return ""; } return ""; } @@ -120,6 +128,7 @@ void COptionsWindow::LoadBlockINet() QString Value = pGroupItem->child(j)->data(0, Qt::UserRole).toString(); QTreeWidgetItem* pItem = new QTreeWidgetItem(); + pItem->setCheckState(0, (Mode & 0x10) != 0 ? Qt::Unchecked : Qt::Checked); SetProgramItem(Value, pItem, 0); @@ -183,6 +192,31 @@ void COptionsWindow::OnINetItemDoubleClicked(QTreeWidgetItem* pItem, int Column) ui.treeINet->setItemWidget(pItem, 1, pMode); } +void COptionsWindow::OnINetChanged(QTreeWidgetItem* pItem, int Column) +{ + if (Column != 0) + return; + + if (pItem->checkState(0) == Qt::Checked) { + QString Program = pItem->data(0, Qt::UserRole).toString(); + int Mode = pItem->data(1, Qt::UserRole).toInt(); + Mode |= 0x10; + if (DelProgramFromGroup(Program, INetModeToGroup(Mode))) { + Mode &= ~0x10; + AddProgramToGroup(Program, INetModeToGroup(Mode)); + } + } + else { + QString Program = pItem->data(0, Qt::UserRole).toString(); + int Mode = pItem->data(1, Qt::UserRole).toInt(); + Mode &= ~0x10; + if (DelProgramFromGroup(Program, INetModeToGroup(Mode))) { + Mode |= 0x10; + AddProgramToGroup(Program, INetModeToGroup(Mode)); + } + } +} + void COptionsWindow::CloseINetEdit(bool bSave) { for (int i = 0; i < ui.treeINet->topLevelItemCount(); i++) @@ -208,11 +242,15 @@ void COptionsWindow::CloseINetEdit(QTreeWidgetItem* pItem, bool bSave) { QString OldProgram = pItem->data(0, Qt::UserRole).toString(); int OldMode = pItem->data(1, Qt::UserRole).toInt(); + if (pItem->checkState(0) == Qt::Unchecked) + OldMode |= 0x10; DelProgramFromGroup(OldProgram, INetModeToGroup(OldMode)); QString NewProgram = pCombo->currentText(); int NewMode = pMode->currentData().toInt(); + if (pItem->checkState(0) == Qt::Unchecked) + NewMode |= 0x10; AddProgramToGroup(NewProgram, INetModeToGroup(NewMode)); @@ -258,6 +296,7 @@ void COptionsWindow::OnAddINetProg() pItem->setText(1, GetINetModeStr(Mode)); pItem->setData(1, Qt::UserRole, Mode); + pItem->setCheckState(0, Qt::Checked); ui.treeINet->addTopLevelItem(pItem); AddProgramToGroup(Value, INetModeToGroup(Mode)); @@ -274,6 +313,8 @@ void COptionsWindow::OnDelINetProg() QString OldProgram = pItem->data(0, Qt::UserRole).toString(); int OldMode = pItem->data(1, Qt::UserRole).toInt(); + if (pItem->checkState(0) == Qt::Unchecked) + OldMode |= 0x10; DelProgramFromGroup(OldProgram, INetModeToGroup(OldMode)); delete pItem; @@ -306,6 +347,9 @@ void COptionsWindow::LoadNetFwRules() foreach(const QString & Value, m_pBox->GetTextList("NetworkAccess", m_Template)) ParseAndAddFwRule(Value); + foreach(const QString & Value, m_pBox->GetTextList("NetworkAccessDisabled", m_Template)) + ParseAndAddFwRule(Value, true); + LoadNetFwRulesTmpl(); m_NetFwRulesChanged = false; @@ -318,7 +362,7 @@ void COptionsWindow::LoadNetFwRulesTmpl(bool bUpdate) foreach(const QString& Template, m_pBox->GetTemplates()) { foreach(const QString& Value, m_pBox->GetTextListTmpl("NetworkAccess", Template)) - ParseAndAddFwRule(Value, Template); + ParseAndAddFwRule(Value, false, Template); } } else if (bUpdate) @@ -370,7 +414,7 @@ COptionsWindow::ENetWfProt COptionsWindow::GetFwRuleProt(const QString& Value) return eAny; } -void COptionsWindow::ParseAndAddFwRule(const QString& Value, const QString& Template) +void COptionsWindow::ParseAndAddFwRule(const QString& Value, bool disabled, const QString& Template) { QTreeWidgetItem* pItem = new QTreeWidgetItem(); @@ -410,12 +454,15 @@ void COptionsWindow::ParseAndAddFwRule(const QString& Value, const QString& Temp pItem->setText(4, Prot); pItem->setData(4, Qt::UserRole, (int)GetFwRuleProt(Prot)); + if(Template.isEmpty()) + pItem->setCheckState(0, disabled ? Qt::Unchecked : Qt::Checked); ui.treeNetFw->addTopLevelItem(pItem); } void COptionsWindow::SaveNetFwRules() { QList Rules; + QList RulesDisabled; for (int i = 0; i < ui.treeNetFw->topLevelItemCount(); i++) { QTreeWidgetItem* pItem = ui.treeNetFw->topLevelItem(i); @@ -439,9 +486,13 @@ void COptionsWindow::SaveNetFwRules() if (!IP.isEmpty()) Tags.append("Address=" + IP); if (!Prot.isEmpty()) Tags.append("Protocol=" + Prot); - Rules.append(Tags.join(";")); + if(pItem->checkState(0) == Qt::Checked) + Rules.append(Tags.join(";")); + else + RulesDisabled.append(Tags.join(";")); } WriteTextList("NetworkAccess", Rules); + WriteTextList("NetworkAccessDisabled", RulesDisabled); m_NetFwRulesChanged = false; } @@ -513,6 +564,15 @@ void COptionsWindow::OnNetFwItemDoubleClicked(QTreeWidgetItem* pItem, int Column ui.treeNetFw->setItemWidget(pItem, 4, pProt); } +void COptionsWindow::OnNetFwChanged(QTreeWidgetItem* pItem, int Column) +{ + if (Column != 0) + return; + + m_NetFwRulesChanged = true; + OnOptChanged(); +} + void COptionsWindow::CloseNetFwEdit(bool bSave) { for (int i = 0; i < ui.treeNetFw->topLevelItemCount(); i++) @@ -580,6 +640,7 @@ void COptionsWindow::OnAddNetFwRule() pItem->setText(1, GetFwRuleActionStr(eBlock)); pItem->setData(1, Qt::UserRole, (int)eBlock); + pItem->setCheckState(0, Qt::Checked); ui.treeNetFw->addTopLevelItem(pItem); m_NetFwRulesChanged = true; diff --git a/SandboxiePlus/SandMan/Windows/OptionsStart.cpp b/SandboxiePlus/SandMan/Windows/OptionsStart.cpp index 0c9fb785..87b324db 100644 --- a/SandboxiePlus/SandMan/Windows/OptionsStart.cpp +++ b/SandboxiePlus/SandMan/Windows/OptionsStart.cpp @@ -54,6 +54,21 @@ void COptionsWindow::OnAddStartProg() void COptionsWindow::OnDelStartProg() { DelProgFromGroup(ui.treeStart, ""); + DelProgFromGroup(ui.treeStart, ""); //m_StartChanged = true; //OnOptChanged(); } + +void COptionsWindow::OnStartChanged(QTreeWidgetItem* pItem, int Index) +{ + if (pItem->checkState(0) == Qt::Checked) { + if(DelProgramFromGroup(pItem->data(0, Qt::UserRole).toString(), "")) + AddProgramToGroup(pItem->data(0, Qt::UserRole).toString(), ""); + } + else { + if(DelProgramFromGroup(pItem->data(0, Qt::UserRole).toString(), "")) + AddProgramToGroup(pItem->data(0, Qt::UserRole).toString(), ""); + } + //m_StartChanged = true; + //OnOptChanged(); +} \ No newline at end of file diff --git a/SandboxiePlus/SandMan/Windows/OptionsStop.cpp b/SandboxiePlus/SandMan/Windows/OptionsStop.cpp index 123f9770..37b601ad 100644 --- a/SandboxiePlus/SandMan/Windows/OptionsStop.cpp +++ b/SandboxiePlus/SandMan/Windows/OptionsStop.cpp @@ -16,9 +16,15 @@ void COptionsWindow::LoadStop() foreach(const QString& Value, m_pBox->GetTextList("LingerProcess", m_Template)) AddStopEntry(Value, 1); + foreach(const QString& Value, m_pBox->GetTextList("LingerProcessDisabled", m_Template)) + AddStopEntry(Value, 1, true); + foreach(const QString& Value, m_pBox->GetTextList("LeaderProcess", m_Template)) AddStopEntry(Value, 2); + foreach(const QString& Value, m_pBox->GetTextList("LeaderProcessDisabled", m_Template)) + AddStopEntry(Value, 2, true); + LoadStopTmpl(); m_StopChanged = false; @@ -31,10 +37,10 @@ void COptionsWindow::LoadStopTmpl(bool bUpdate) foreach(const QString & Template, m_pBox->GetTemplates()) { foreach(const QString & Value, m_pBox->GetTextListTmpl("LingerProcess", Template)) - AddStopEntry(Value, 1, Template); + AddStopEntry(Value, 1, false, Template); foreach(const QString & Value, m_pBox->GetTextListTmpl("LeaderProcess", Template)) - AddStopEntry(Value, 2, Template); + AddStopEntry(Value, 2, false, Template); } } else if (bUpdate) @@ -52,12 +58,15 @@ void COptionsWindow::LoadStopTmpl(bool bUpdate) } } -void COptionsWindow::AddStopEntry(const QString& Name, int type, const QString& Template) +void COptionsWindow::AddStopEntry(const QString& Name, int type, bool disabled, const QString& Template) { QTreeWidgetItem* pItem = new QTreeWidgetItem(); + pItem->setCheckState(0, disabled ? Qt::Unchecked : Qt::Checked); pItem->setText(0, (type == 1 ? tr("Lingerer") : tr("Leader")) + (Template.isEmpty() ? "" : (" (" + Template + ")"))); pItem->setData(0, Qt::UserRole, Template.isEmpty() ? type : -1); SetProgramItem(Name, pItem, 1); + if(Template.isEmpty()) + pItem->setFlags(pItem->flags() | Qt::ItemIsEditable); ui.treeStop->addTopLevelItem(pItem); } diff --git a/SandboxiePlus/SandMan/Windows/OptionsWindow.cpp b/SandboxiePlus/SandMan/Windows/OptionsWindow.cpp index 2e5f43d0..1c7c3301 100644 --- a/SandboxiePlus/SandMan/Windows/OptionsWindow.cpp +++ b/SandboxiePlus/SandMan/Windows/OptionsWindow.cpp @@ -8,6 +8,108 @@ #include "../MiscHelpers/Common/SettingsWidgets.h" #include "Helpers/WinAdmin.h" +class NoEditDelegate : public QStyledItemDelegate { +public: + NoEditDelegate(QObject* parent = 0) : QStyledItemDelegate(parent) {} + + virtual QWidget* createEditor(QWidget* parent, const QStyleOptionViewItem& option, const QModelIndex& index) const { + return NULL; + } +}; + +class QTreeWidgetHacker : public QTreeWidget +{ +public: + friend class ProgramsDelegate; + //QModelIndex indexFromItem(const QTreeWidgetItem *item, int column = 0) const; + //QTreeWidgetItem *itemFromIndex(const QModelIndex &index) const; +}; + +class ProgramsDelegate : public QStyledItemDelegate { +public: + ProgramsDelegate(COptionsWindow* pOptions, QTreeWidget* pTree, int Column, QObject* parent = 0) : QStyledItemDelegate(parent) { m_pOptions = pOptions; m_pTree = pTree; m_Column = Column; } + + virtual QWidget* createEditor(QWidget* parent, const QStyleOptionViewItem& option, const QModelIndex& index) const { + QTreeWidgetItem* pItem = ((QTreeWidgetHacker*)m_pTree)->itemFromIndex(index); + if (!pItem->data(index.column(), Qt::UserRole).isValid()) + return NULL; + + if (m_Column == -1 || pItem->data(m_Column, Qt::UserRole).toInt() == COptionsWindow::eProcess) { + QComboBox* pBox = new QComboBox(parent); + pBox->setEditable(true); + foreach(const QString Group, m_pOptions->GetCurrentGroups()) { + QString GroupName = Group.mid(1, Group.length() - 2); + pBox->addItem(tr("Group: %1").arg(GroupName), Group); + } + foreach(const QString & Name, m_pOptions->GetPrograms()) + pBox->addItem(Name, Name); + + connect(pBox->lineEdit(), &QLineEdit::textEdited, [pBox](const QString& text){ + /*if (pBox->currentIndex() != -1) { + int pos = pBox->lineEdit()->cursorPosition(); + pBox->setCurrentIndex(-1); + pBox->setCurrentText(text); + pBox->lineEdit()->setCursorPosition(pos); + }*/ + pBox->setProperty("value", text); + }); + + connect(pBox, qOverload(&QComboBox::currentIndexChanged), [pBox](int index){ + if (index != -1) + pBox->setProperty("value", pBox->itemData(index)); + }); + + return pBox; + } + else if (pItem->data(0, Qt::UserRole).toInt() == COptionsWindow::ePath) + return QStyledItemDelegate::createEditor(parent, option, index); + else + return NULL; + } + + virtual void setEditorData(QWidget* editor, const QModelIndex& index) const { + QComboBox* pBox = qobject_cast(editor); + if (pBox) { + QTreeWidgetItem* pItem = ((QTreeWidgetHacker*)m_pTree)->itemFromIndex(index); + QString Program = pItem->data(index.column(), Qt::UserRole).toString(); + + pBox->setProperty("value", Program); + + int Index = pBox->findData(Program); + pBox->setCurrentIndex(Index); + if (Index == -1) + pBox->setCurrentText(Program); + } + else + QStyledItemDelegate::setEditorData(editor, index); + } + + virtual void setModelData(QWidget* editor, QAbstractItemModel* model, const QModelIndex& index) const { + + QComboBox* pBox = qobject_cast(editor); + if (pBox) { + QTreeWidgetItem* pItem = ((QTreeWidgetHacker*)m_pTree)->itemFromIndex(index); + QString Value = pBox->property("value").toString(); + pItem->setText(index.column(), pBox->currentText()); + //QString Text = pBox->currentText(); + //QVariant Data = pBox->currentData(); + pItem->setData(index.column(), Qt::UserRole, Value); + } + + QLineEdit* pEdit = qobject_cast(editor); + if (pEdit) { + QTreeWidgetItem* pItem = ((QTreeWidgetHacker*)m_pTree)->itemFromIndex(index); + pItem->setText(index.column(), pEdit->text()); + pItem->setData(index.column(), Qt::UserRole, pEdit->text()); + } + } + +protected: + COptionsWindow* m_pOptions; + QTreeWidget* m_pTree; + int m_Column; +}; + COptionsWindow::COptionsWindow(const QSharedPointer& pBox, const QString& Name, QWidget *parent) : QDialog(parent) @@ -93,6 +195,8 @@ COptionsWindow::COptionsWindow(const QSharedPointer& pBox, const QStri connect(ui.btnAddProg, SIGNAL(clicked(bool)), this, SLOT(OnAddProg())); connect(ui.btnDelProg, SIGNAL(clicked(bool)), this, SLOT(OnDelProg())); connect(ui.chkShowGroupTmpl, SIGNAL(clicked(bool)), this, SLOT(OnShowGroupTmpl())); + ui.treeGroups->setItemDelegateForColumn(0, new ProgramsDelegate(this, ui.treeGroups, -1, this)); + connect(ui.treeGroups, SIGNAL(itemChanged(QTreeWidgetItem *, int)), this, SLOT(OnGroupsChanged(QTreeWidgetItem *, int))); // // Force @@ -100,6 +204,10 @@ COptionsWindow::COptionsWindow(const QSharedPointer& pBox, const QStri connect(ui.btnForceDir, SIGNAL(clicked(bool)), this, SLOT(OnForceDir())); connect(ui.btnDelForce, SIGNAL(clicked(bool)), this, SLOT(OnDelForce())); connect(ui.chkShowForceTmpl, SIGNAL(clicked(bool)), this, SLOT(OnShowForceTmpl())); + //ui.treeForced->setEditTriggers(QAbstractItemView::DoubleClicked); + ui.treeForced->setItemDelegateForColumn(0, new NoEditDelegate(this)); + ui.treeForced->setItemDelegateForColumn(1, new ProgramsDelegate(this, ui.treeForced, 0, this)); + connect(ui.treeForced, SIGNAL(itemChanged(QTreeWidgetItem *, int)), this, SLOT(OnForcedChanged(QTreeWidgetItem *, int))); // // Stop @@ -107,6 +215,8 @@ COptionsWindow::COptionsWindow(const QSharedPointer& pBox, const QStri connect(ui.btnAddLeader, SIGNAL(clicked(bool)), this, SLOT(OnAddLeader())); connect(ui.btnDelStopProg, SIGNAL(clicked(bool)), this, SLOT(OnDelStopProg())); connect(ui.chkShowStopTmpl, SIGNAL(clicked(bool)), this, SLOT(OnShowStopTmpl())); + ui.treeStop->setItemDelegateForColumn(1, new ProgramsDelegate(this, ui.treeStop, -1, this)); + connect(ui.treeStop, SIGNAL(itemChanged(QTreeWidgetItem *, int)), this, SLOT(OnStopChanged(QTreeWidgetItem *, int))); // // Start @@ -116,6 +226,8 @@ COptionsWindow::COptionsWindow(const QSharedPointer& pBox, const QStri connect(ui.btnAddStartProg, SIGNAL(clicked(bool)), this, SLOT(OnAddStartProg())); connect(ui.btnDelStartProg, SIGNAL(clicked(bool)), this, SLOT(OnDelStartProg())); connect(ui.chkStartBlockMsg, SIGNAL(clicked(bool)), this, SLOT(OnStartChanged())); + ui.treeStart->setItemDelegateForColumn(0, new ProgramsDelegate(this, ui.treeStart, -1, this)); + connect(ui.treeStart, SIGNAL(itemChanged(QTreeWidgetItem *, int)), this, SLOT(OnStartChanged(QTreeWidgetItem *, int))); // CreateNetwork(); @@ -500,7 +612,7 @@ QString COptionsWindow::SelectProgram(bool bOrGroup) { foreach(const QString Group, GetCurrentGroups()){ QString GroupName = Group.mid(1, Group.length() - 2); - progDialog.addItem(tr("Group: %1").arg(Group), GroupName); + progDialog.addItem(tr("Group: %1").arg(GroupName), Group); } } @@ -547,7 +659,9 @@ void COptionsWindow::UpdateCurrentTab() ui.radStartExcept->setChecked(true); else ui.radStartAll->setChecked(true); + ui.treeStart->clear(); CopyGroupToList("", ui.treeStart); + CopyGroupToList("", ui.treeStart, true); OnRestrictStart(); } diff --git a/SandboxiePlus/SandMan/Windows/OptionsWindow.h b/SandboxiePlus/SandMan/Windows/OptionsWindow.h index 54237ab0..4b50bc9e 100644 --- a/SandboxiePlus/SandMan/Windows/OptionsWindow.h +++ b/SandboxiePlus/SandMan/Windows/OptionsWindow.h @@ -15,6 +15,17 @@ public: virtual void accept() {} virtual void reject(); + QStringList GetCurrentGroups(); + QSet GetPrograms() { return m_Programs; } + + enum EntryTypes { + eUndefined = 0, + eProcess, + ePath, + eText, + eTemplate + }; + signals: void OptionsChanged(); void Closed(); @@ -47,30 +58,36 @@ private slots: void OnAddProg(); void OnDelProg(); void OnShowGroupTmpl() { LoadGroupsTmpl(true); } + void OnGroupsChanged(QTreeWidgetItem* pItem, int Index) { m_GroupsChanged = true; OnOptChanged(); } void OnForceProg(); void OnForceDir(); void OnDelForce(); void OnShowForceTmpl() { LoadForcedTmpl(true); } + void OnForcedChanged(QTreeWidgetItem* pItem, int Index); void OnAddLingering(); void OnAddLeader(); void OnDelStopProg(); void OnShowStopTmpl() { LoadStopTmpl(true); } + void OnStopChanged(QTreeWidgetItem* pItem, int Index) { m_StopChanged = true; OnOptChanged(); } void OnRestrictStart(); void OnAddStartProg(); void OnDelStartProg(); + void OnStartChanged(QTreeWidgetItem* pItem, int Index); // net void OnINetItemDoubleClicked(QTreeWidgetItem* pItem, int Column); void OnINetSelectionChanged() { CloseINetEdit(); OnOptChanged();} + void OnINetChanged(QTreeWidgetItem* pItem, int Column); void OnBlockINet(); void OnAddINetProg(); void OnDelINetProg(); void OnNetFwItemDoubleClicked(QTreeWidgetItem* pItem, int Column); void OnNetFwSelectionChanged() { CloseNetFwEdit(); OnOptChanged();} + void OnNetFwChanged(QTreeWidgetItem* pItem, int Column); void OnAddNetFwRule(); void OnDelNetFwRule(); @@ -84,6 +101,7 @@ private slots: //void OnAccessItemClicked(QTreeWidgetItem* pItem, int Column); void OnAccessItemDoubleClicked(QTreeWidgetItem* pItem, int Column); void OnAccessSelectionChanged() { CloseAccessEdit(); OnOptChanged();} + void OnAccessChanged(QTreeWidgetItem* pItem, int Column); void OnAddFile() { AddAccessEntry(eFile, eOpen, "", ""); m_AccessChanged = true; OnOptChanged(); } void OnBrowseFile(); @@ -213,15 +231,14 @@ protected: QString SelectProgram(bool bOrGroup = true); void AddProgramToGroup(const QString& Program, const QString& Group); - void DelProgramFromGroup(const QString& Program, const QString& Group); + bool DelProgramFromGroup(const QString& Program, const QString& Group); QTreeWidgetItem* FindGroupByName(const QString& Group, bool bAdd = false); - void CopyGroupToList(const QString& Groupe, QTreeWidget* pTree); + void CopyGroupToList(const QString& Groupe, QTreeWidget* pTree, bool disabled = false); QTreeWidgetItem* GetAccessEntry(EAccessType Type, const QString& Program, EAccessMode Mode, const QString& Path); void SetAccessEntry(EAccessType Type, const QString& Program, EAccessMode Mode, const QString& Path); void DelAccessEntry(EAccessType Type, const QString& Program, EAccessMode Mode, const QString& Path); - void AddProgToGroup(QTreeWidget* pTree, const QString& Groupe); - void AddProgToGroup(const QString& Value, const QString& Groupe); + void AddProgToGroup(QTreeWidget* pTree, const QString& Groupe, bool disabled = false); void DelProgFromGroup(QTreeWidget* pTree, const QString& Groupe); void LoadConfig(); @@ -239,16 +256,15 @@ protected: void LoadGroups(); void LoadGroupsTmpl(bool bUpdate = false); void SaveGroups(); - QStringList GetCurrentGroups(); void LoadForced(); void LoadForcedTmpl(bool bUpdate = false); - void AddForcedEntry(const QString& Name, int type, const QString& Template = QString()); + void AddForcedEntry(const QString& Name, int type, bool disabled = false, const QString& Template = QString()); void SaveForced(); void LoadStop(); void LoadStopTmpl(bool bUpdate = false); - void AddStopEntry(const QString& Name, int type, const QString& Template = QString()); + void AddStopEntry(const QString& Name, int type, bool disabled = false, const QString& Template = QString()); void SaveStop(); void LoadStart(); @@ -268,7 +284,7 @@ protected: void LoadINetAccess(); void SaveINetAccess(); - void ParseAndAddFwRule(const QString& Value, const QString& Template = QString()); + void ParseAndAddFwRule(const QString& Value, bool disabled = false, const QString& Template = QString()); void CloseNetFwEdit(bool bSave = true); void CloseNetFwEdit(QTreeWidgetItem* pItem, bool bSave = true); ENetWfProt GetFwRuleProt(const QString& Value); @@ -287,8 +303,8 @@ protected: void LoadAccessListTmpl(bool bUpdate = false); QString GetAccessTypeStr(EAccessType Type); QString GetAccessModeStr(EAccessMode Mode); - void ParseAndAddAccessEntry(EAccessEntry EntryType, const QString& Value, const QString& Template = QString()); - void AddAccessEntry(EAccessType Type, EAccessMode Mode, QString Program, const QString& Path, const QString& Template = QString()); + void ParseAndAddAccessEntry(EAccessEntry EntryType, const QString& Value, bool disabled = false, const QString& Template = QString()); + void AddAccessEntry(EAccessType Type, EAccessMode Mode, QString Program, const QString& Path, bool disabled = false, const QString& Template = QString()); QString MakeAccessStr(EAccessType Type, EAccessMode Mode); void SaveAccessList(); QList GetAccessModes(EAccessType Type);