#include "FractoriumPch.h" #include "VariationsDialog.h" /// /// Constructor that takes a parent widget and passes it to the base, then /// sets up the GUI. /// /// Pointer to the global settings object to use /// The parent widget. Default: nullptr. /// The window flags. Default: 0. FractoriumVariationsDialog::FractoriumVariationsDialog(FractoriumSettings* settings, QWidget* p, Qt::WindowFlags f) : QDialog(p, f), m_Settings(settings), m_VariationList(VariationList::Instance()) { ui.setupUi(this); auto table = ui.VariationsTable; m_Vars = m_Settings->Variations(); Populate(); OnSelectAllButtonClicked(true); m_CheckBoxes.push_back(ui.SumCheckBox); m_CheckBoxes.push_back(ui.AssignCheckBox); m_CheckBoxes.push_back(ui.PpSumCheckBox); m_CheckBoxes.push_back(ui.PpAssignCheckBox); m_CheckBoxes.push_back(ui.DcCheckBox); m_CheckBoxes.push_back(ui.StateCheckBox); m_CheckBoxes.push_back(ui.ParamCheckBox); m_CheckBoxes.push_back(ui.NonParamCheckBox); ui.SumCheckBox->setCheckState(Qt::CheckState(m_Settings->value(VARFILTERSUM).toInt())); ui.AssignCheckBox->setCheckState(Qt::CheckState(m_Settings->value(VARFILTERASSIGN).toInt())); ui.PpSumCheckBox->setCheckState(Qt::CheckState(m_Settings->value(VARFILTERPPSUM).toInt())); ui.PpAssignCheckBox->setCheckState(Qt::CheckState(m_Settings->value(VARFILTERPPASSIGN).toInt())); ui.DcCheckBox->setCheckState(Qt::CheckState(m_Settings->value(VARFILTERSDC).toInt())); ui.StateCheckBox->setCheckState(Qt::CheckState(m_Settings->value(VARFILTERSSTATE).toInt())); ui.ParamCheckBox->setCheckState(Qt::CheckState(m_Settings->value(VARFILTERPARAM).toInt())); ui.NonParamCheckBox->setCheckState(Qt::CheckState(m_Settings->value(VARFILTERNONPARAM).toInt())); for (auto& cb : m_CheckBoxes) { if (cb->checkState() == Qt::CheckState::PartiallyChecked) { auto f = cb->font(); f.setStrikeOut(true); cb->setFont(f); } } table->verticalHeader()->setSectionsClickable(true); table->horizontalHeader()->setSectionsClickable(true); table->verticalHeader()->setSectionResizeMode(QHeaderView::ResizeToContents); connect(table, SIGNAL(itemChanged(QTableWidgetItem*)), this, SLOT(OnVariationsTableItemChanged(QTableWidgetItem*)), Qt::QueuedConnection); connect(ui.SelectAllButton, SIGNAL(clicked(bool)), this, SLOT(OnSelectAllButtonClicked(bool)), Qt::QueuedConnection); connect(ui.InvertSelectionButton, SIGNAL(clicked(bool)), this, SLOT(OnInvertSelectionButtonClicked(bool)), Qt::QueuedConnection); connect(ui.SelectNoneButton, SIGNAL(clicked(bool)), this, SLOT(OnSelectNoneButtonClicked(bool)), Qt::QueuedConnection); connect(ui.SumCheckBox , SIGNAL(stateChanged(int)), this, SLOT(OnSelectionCheckBoxStateChanged(int)), Qt::QueuedConnection); connect(ui.AssignCheckBox , SIGNAL(stateChanged(int)), this, SLOT(OnSelectionCheckBoxStateChanged(int)), Qt::QueuedConnection); connect(ui.PpSumCheckBox , SIGNAL(stateChanged(int)), this, SLOT(OnSelectionCheckBoxStateChanged(int)), Qt::QueuedConnection); connect(ui.PpAssignCheckBox, SIGNAL(stateChanged(int)), this, SLOT(OnSelectionCheckBoxStateChanged(int)), Qt::QueuedConnection); connect(ui.DcCheckBox , SIGNAL(stateChanged(int)), this, SLOT(OnSelectionCheckBoxStateChanged(int)), Qt::QueuedConnection); connect(ui.StateCheckBox , SIGNAL(stateChanged(int)), this, SLOT(OnSelectionCheckBoxStateChanged(int)), Qt::QueuedConnection); connect(ui.ParamCheckBox , SIGNAL(stateChanged(int)), this, SLOT(OnSelectionCheckBoxStateChanged(int)), Qt::QueuedConnection); connect(ui.NonParamCheckBox, SIGNAL(stateChanged(int)), this, SLOT(OnSelectionCheckBoxStateChanged(int)), Qt::QueuedConnection); } /// /// A wrapper to iterate over every table widget item and perform the passed in function on it. /// /// Function to call on each object void FractoriumVariationsDialog::ForEachCell(std::function func) { auto table = ui.VariationsTable; auto rows = table->rowCount(); auto cols = table->columnCount(); table->model()->blockSignals(true); for (auto row = 0; row < rows; row++) for (auto col = 0; col < cols; col++) if (auto cb = table->item(row, col)) func(cb); table->model()->blockSignals(false); table->model()->layoutChanged(); } /// /// A wrapper to iterate over every selected table widget item and perform the passed in function on it. /// /// Function to call on each object void FractoriumVariationsDialog::ForEachSelectedCell(std::function func) { auto table = ui.VariationsTable; QList selectedItems = table->selectedItems(); table->model()->blockSignals(true); for (auto item : selectedItems) if (item) func(item); table->model()->blockSignals(false); table->model()->layoutChanged(); } /// /// Copy the values of the checkboxes to the map. /// void FractoriumVariationsDialog::SyncSettings() { QMap m; ForEachCell([&](QTableWidgetItem * cb) { if (!cb->text().isEmpty()) m[cb->text()] = cb->checkState() == Qt::CheckState::Checked; }); m_Settings->Variations(m); m_Settings->setValue(VARFILTERSUM , int(ui.SumCheckBox->checkState())); m_Settings->setValue(VARFILTERASSIGN , int(ui.AssignCheckBox->checkState())); m_Settings->setValue(VARFILTERPPSUM , int(ui.PpSumCheckBox->checkState())); m_Settings->setValue(VARFILTERPPASSIGN, int(ui.PpAssignCheckBox->checkState())); m_Settings->setValue(VARFILTERSDC , int(ui.DcCheckBox->checkState())); m_Settings->setValue(VARFILTERSSTATE , int(ui.StateCheckBox->checkState())); m_Settings->setValue(VARFILTERPARAM , int(ui.ParamCheckBox->checkState())); m_Settings->setValue(VARFILTERNONPARAM, int(ui.NonParamCheckBox->checkState())); } /// /// Return a const reference to the map. /// This will contains the state of the checkboxes after /// the user clicks ok. /// const QMap& FractoriumVariationsDialog::Map() { return m_Vars; } /// /// Clears the type checkboxes without triggering any events. /// void FractoriumVariationsDialog::ClearTypesStealth() { for (auto& cb : m_CheckBoxes) { cb->blockSignals(true); cb->setCheckState(Qt::CheckState::Unchecked); auto f = cb->font(); f.setStrikeOut(cb->checkState() == Qt::CheckState::PartiallyChecked); cb->setFont(f); cb->blockSignals(false); } } /// /// Check all of the checkboxes. /// /// Ignored void FractoriumVariationsDialog::OnSelectAllButtonClicked(bool checked) { ClearTypesStealth(); ForEachCell([&](QTableWidgetItem * cb) { cb->setCheckState(Qt::CheckState::Checked); }); } /// /// Invert the selection state of the checkboxes. /// /// Ignored void FractoriumVariationsDialog::OnInvertSelectionButtonClicked(bool checked) { ClearTypesStealth(); ForEachCell([&](QTableWidgetItem * cb) { if (cb->checkState() != Qt::CheckState::Checked) cb->setCheckState(Qt::CheckState::Checked); else cb->setCheckState(Qt::CheckState::Unchecked); }); } /// /// Uncheck all of the checkboxes. /// /// Ignored void FractoriumVariationsDialog::OnSelectNoneButtonClicked(bool checked) { ClearTypesStealth(); ForEachCell([&](QTableWidgetItem * cb) { cb->setCheckState(Qt::CheckState::Unchecked); }); } /// /// Called when any of the selection checkboxes change state. /// This will re-evaluate the entire grid of checkboxes. /// /// Ignored void FractoriumVariationsDialog::OnSelectionCheckBoxStateChanged(int i) { static vector dc{ "m_ColorX" }; static vector assign{ "outPoint->m_X =", "outPoint->m_Y =", "outPoint->m_Z =", "outPoint->m_X=", "outPoint->m_Y=", "outPoint->m_Z=" }; //static vector*> excluded; static std::set excluded; excluded.clear(); //excluded.reserve(size_t(eVariationId::LAST_VAR)); if (auto s = dynamic_cast(sender())) { auto f = s->font(); f.setStrikeOut(s->checkState() == Qt::CheckState::PartiallyChecked); s->setFont(f); } ForEachCell([&](QTableWidgetItem * cb) { cb->setCheckState(Qt::CheckState::Unchecked); }); ForEachCell([&](QTableWidgetItem * cb) { if (auto var = m_VariationList->GetVariation(cb->text().toStdString())) { if (ui.StateCheckBox->checkState() != Qt::CheckState::Unchecked) { if (!var->StateOpenCLString().empty()) { if (ui.StateCheckBox->checkState() == Qt::CheckState::PartiallyChecked) { cb->setCheckState(Qt::CheckState::Unchecked); excluded.insert(var->VariationId()); } else if (!Contains(excluded, var->VariationId())) cb->setCheckState(Qt::CheckState::Checked); } } if (ui.SumCheckBox->isChecked() != Qt::CheckState::Unchecked) { if (var->VarType() == eVariationType::VARTYPE_REG && !SearchVar(var, assign, false)) { if (ui.SumCheckBox->checkState() == Qt::CheckState::PartiallyChecked) { cb->setCheckState(Qt::CheckState::Unchecked); excluded.insert(var->VariationId()); } else if (!Contains(excluded, var->VariationId())) cb->setCheckState(Qt::CheckState::Checked); } } if (ui.AssignCheckBox->isChecked() != Qt::CheckState::Unchecked) { if (var->VarType() == eVariationType::VARTYPE_REG && SearchVar(var, assign, false)) { if (ui.AssignCheckBox->checkState() == Qt::CheckState::PartiallyChecked) { cb->setCheckState(Qt::CheckState::Unchecked); excluded.insert(var->VariationId()); } else if (!Contains(excluded, var->VariationId())) cb->setCheckState(Qt::CheckState::Checked); } } if (ui.DcCheckBox->isChecked() != Qt::CheckState::Unchecked) { if (SearchVar(var, dc, false)) { if (ui.DcCheckBox->checkState() == Qt::CheckState::PartiallyChecked) { cb->setCheckState(Qt::CheckState::Unchecked); excluded.insert(var->VariationId()); } else if (!Contains(excluded, var->VariationId())) cb->setCheckState(Qt::CheckState::Checked); } } if (ui.NonParamCheckBox->isChecked() != Qt::CheckState::Unchecked) { if (!m_VariationList->GetParametricVariation(cb->text().toStdString())) { if (ui.NonParamCheckBox->checkState() == Qt::CheckState::PartiallyChecked) { cb->setCheckState(Qt::CheckState::Unchecked); excluded.insert(var->VariationId()); } else if (!Contains(excluded, var->VariationId())) cb->setCheckState(Qt::CheckState::Checked); } } } if (ui.PpSumCheckBox->isChecked() != Qt::CheckState::Unchecked) { if (auto pre = m_VariationList->GetPreVariation(cb->text().toStdString())) { if (pre->AssignType() == eVariationAssignType::ASSIGNTYPE_SUM) { if (ui.PpSumCheckBox->checkState() == Qt::CheckState::PartiallyChecked) { cb->setCheckState(Qt::CheckState::Unchecked); excluded.insert(pre->VariationId()); } else if (!Contains(excluded, pre->VariationId())) cb->setCheckState(Qt::CheckState::Checked); } } if (auto post = m_VariationList->GetPostVariation(cb->text().toStdString())) { if (post->AssignType() == eVariationAssignType::ASSIGNTYPE_SUM) { if (ui.PpSumCheckBox->checkState() == Qt::CheckState::PartiallyChecked) { cb->setCheckState(Qt::CheckState::Unchecked); excluded.insert(post->VariationId()); } else if (!Contains(excluded, post->VariationId())) cb->setCheckState(Qt::CheckState::Checked); } } } if (ui.PpAssignCheckBox->isChecked() != Qt::CheckState::Unchecked) { if (auto pre = m_VariationList->GetPreVariation(cb->text().toStdString())) { if (pre->AssignType() == eVariationAssignType::ASSIGNTYPE_SET) { if (ui.PpAssignCheckBox->checkState() == Qt::CheckState::PartiallyChecked) { cb->setCheckState(Qt::CheckState::Unchecked); excluded.insert(pre->VariationId()); } else if (!Contains(excluded, pre->VariationId())) cb->setCheckState(Qt::CheckState::Checked); } } if (auto post = m_VariationList->GetPostVariation(cb->text().toStdString())) { if (post->AssignType() == eVariationAssignType::ASSIGNTYPE_SET) { if (ui.PpAssignCheckBox->checkState() == Qt::CheckState::PartiallyChecked) { cb->setCheckState(Qt::CheckState::Unchecked); excluded.insert(post->VariationId()); } else if (!Contains(excluded, post->VariationId())) cb->setCheckState(Qt::CheckState::Checked); } } } if (ui.ParamCheckBox->isChecked() != Qt::CheckState::Unchecked) { if (auto parVar = m_VariationList->GetParametricVariation(cb->text().toStdString())) { if (ui.ParamCheckBox->checkState() == Qt::CheckState::PartiallyChecked) { cb->setCheckState(Qt::CheckState::Unchecked); excluded.insert(parVar->VariationId()); } else if (!Contains(excluded, parVar->VariationId())) cb->setCheckState(Qt::CheckState::Checked); } } }); } /// /// Create all checkboxes and check them according to the map. /// void FractoriumVariationsDialog::Populate() { auto table = ui.VariationsTable; int size = int(std::max(std::max(m_VariationList->RegSize(), m_VariationList->PreSize()), m_VariationList->PostSize())); table->setRowCount(size); for (auto i = 0; i < size; i++) { if (auto pre = m_VariationList->GetVariation(i, eVariationType::VARTYPE_PRE)) { auto cb = new QTableWidgetItem(pre->Name().c_str()); table->setItem(i, 0, cb); SetCheckFromMap(cb, pre); } if (auto reg = m_VariationList->GetVariation(i, eVariationType::VARTYPE_REG)) { auto cb = new QTableWidgetItem(reg->Name().c_str()); table->setItem(i, 1, cb); SetCheckFromMap(cb, reg); } if (auto post = m_VariationList->GetVariation(i, eVariationType::VARTYPE_POST)) { auto cb = new QTableWidgetItem(post->Name().c_str()); table->setItem(i, 2, cb); SetCheckFromMap(cb, post); } } } /// /// Called when a checkbox changes state. /// There is a slight hack here to apply the change to all selected checkboxes /// if ctrl is pressed. /// Otherwise it will only apply to the checkbox that was clicked. /// /// void FractoriumVariationsDialog::OnVariationsTableItemChanged(QTableWidgetItem* item) { bool ctrl = QGuiApplication::keyboardModifiers().testFlag(Qt::ControlModifier); if (ctrl) ForEachSelectedCell([&](QTableWidgetItem * cb) { cb->setCheckState(item->checkState()); }); } /// /// Called when the user clicks ok. /// Copy the state of the checkboxes to the map. /// void FractoriumVariationsDialog::accept() { GuiToData(); QDialog::accept(); } /// /// Called when the user clicks cancel. /// Reset the state of the the checkboxes to what the map previously was /// when the dialog was shown. /// void FractoriumVariationsDialog::reject() { DataToGui(); QDialog::reject(); } /// /// Copy the state of the map to the checkboxes and show the dialog. /// /// Event, passed to base. void FractoriumVariationsDialog::showEvent(QShowEvent* e) { DataToGui(); QDialog::showEvent(e); } /// /// Copy the values in the map to the state of the checkboxes. /// void FractoriumVariationsDialog::DataToGui() { ForEachCell([&](QTableWidgetItem * cb) { if (auto var = m_VariationList->GetVariation(cb->text().toStdString())) SetCheckFromMap(cb, var); }); } /// /// Copy the state of the checkboxes to the map. /// void FractoriumVariationsDialog::GuiToData() { ForEachCell([&](QTableWidgetItem * cb) { if (auto var = m_VariationList->GetVariation(cb->text().toStdString())) m_Vars[cb->text()] = (cb->checkState() == Qt::Checked); }); } /// /// Set the state of the passed in table item checkbox based on the boolean contained /// in the map for the passed in variation. /// /// The checkbox to check /// That variation to be looked up in the map void FractoriumVariationsDialog::SetCheckFromMap(QTableWidgetItem* cb, const Variation* var) { if (!m_Vars.contains(var->Name().c_str())) { cb->setCheckState(Qt::Checked); } else { bool chk = m_Vars[var->Name().c_str()].toBool(); cb->setCheckState(chk ? Qt::Checked : Qt::Unchecked); } }