Something went wrong. Try again.
OpenMW is an open implementation of the Morrowind engine
Something went wrong. Try again.
C++
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245#include "extendedcommandconfigurator.hpp"
#include <algorithm>#include <type_traits>#include <utility>
#include <QCheckBox>#include <QGroupBox>#include <QLayout>#include <QPushButton>
#include "../../model/doc/document.hpp"
#include "../../model/world/commanddispatcher.hpp"#include "../../model/world/data.hpp"
#include <apps/opencs/model/world/universalid.hpp>
CSVWorld::ExtendedCommandConfigurator::ExtendedCommandConfigurator( CSMDoc::Document& document, const CSMWorld::UniversalId& id, QWidget* parent) : QWidget(parent) , mNumUsedCheckBoxes(0) , mNumChecked(0) , mMode(Mode_None) , mData(document.getData()) , mEditLock(false){ mCommandDispatcher = new CSMWorld::CommandDispatcher(document, id, this);
connect(&mData, &CSMWorld::Data::idListChanged, this, &ExtendedCommandConfigurator::dataIdListChanged);
mPerformButton = new QPushButton(this); mPerformButton->setDefault(true); mPerformButton->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); connect(mPerformButton, &QPushButton::clicked, this, &ExtendedCommandConfigurator::performExtendedCommand);
mCancelButton = new QPushButton("Cancel", this); mCancelButton->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); connect(mCancelButton, &QPushButton::clicked, this, &ExtendedCommandConfigurator::done);
mTypeGroup = new QGroupBox(this);
QGridLayout* groupLayout = new QGridLayout(mTypeGroup); groupLayout->setAlignment(Qt::AlignLeft | Qt::AlignVCenter); mTypeGroup->setLayout(groupLayout);
QHBoxLayout* mainLayout = new QHBoxLayout(this); mainLayout->setSizeConstraint(QLayout::SetNoConstraint); mainLayout->setContentsMargins(0, 0, 0, 0); mainLayout->addWidget(mTypeGroup); mainLayout->addWidget(mPerformButton); mainLayout->addWidget(mCancelButton);}
void CSVWorld::ExtendedCommandConfigurator::configure( CSVWorld::ExtendedCommandConfigurator::Mode mode, const std::vector<std::string>& selectedIds){ mMode = mode; if (mMode != Mode_None) { mPerformButton->setText((mMode == Mode_Delete) ? "Extended Delete" : "Extended Revert"); mSelectedIds = selectedIds; mCommandDispatcher->setSelection(mSelectedIds);
setupCheckBoxes(mCommandDispatcher->getExtendedTypes()); setupGroupLayout(); lockWidgets(mEditLock); }}
void CSVWorld::ExtendedCommandConfigurator::setEditLock(bool locked){ if (mEditLock != locked) { mEditLock = locked; lockWidgets(mEditLock); }}
void CSVWorld::ExtendedCommandConfigurator::resizeEvent(QResizeEvent* event){ QWidget::resizeEvent(event); setupGroupLayout();}
void CSVWorld::ExtendedCommandConfigurator::setupGroupLayout(){ if (mMode == Mode_None) { return; }
int groupWidth = mTypeGroup->geometry().width(); QGridLayout* layout = qobject_cast<QGridLayout*>(mTypeGroup->layout());
// Find the optimal number of rows to place the checkboxes within the available space int divider = 1; do { while (layout->itemAt(0) != nullptr) { layout->removeItem(layout->itemAt(0)); }
int counter = 0; int itemsPerRow = mNumUsedCheckBoxes / divider; CheckBoxMap::const_iterator current = mTypeCheckBoxes.begin(); CheckBoxMap::const_iterator end = mTypeCheckBoxes.end(); for (; current != end; ++current) { if (counter < mNumUsedCheckBoxes) { int row = counter / itemsPerRow; int column = counter - (counter / itemsPerRow) * itemsPerRow; layout->addWidget(current->first, row, column); } ++counter; } divider *= 2; } while (groupWidth < mTypeGroup->sizeHint().width() && divider <= mNumUsedCheckBoxes);}
void CSVWorld::ExtendedCommandConfigurator::setupCheckBoxes(const std::vector<CSMWorld::UniversalId>& types){ // Make sure that we have enough checkboxes int numTypes = static_cast<int>(types.size()); int numCheckBoxes = static_cast<int>(mTypeCheckBoxes.size()); if (numTypes > numCheckBoxes) { for (int i = numTypes - numCheckBoxes; i > 0; --i) { QCheckBox* checkBox = new QCheckBox(mTypeGroup);#if QT_VERSION >= QT_VERSION_CHECK(6, 7, 0) connect(checkBox, &QCheckBox::checkStateChanged, this, &ExtendedCommandConfigurator::checkBoxStateChanged);#else connect(checkBox, &QCheckBox::stateChanged, this, &ExtendedCommandConfigurator::checkBoxStateChanged);#endif mTypeCheckBoxes.insert(std::make_pair(checkBox, CSMWorld::UniversalId::Type_None)); } }
// Set up the checkboxes int counter = 0; CheckBoxMap::iterator current = mTypeCheckBoxes.begin(); CheckBoxMap::iterator end = mTypeCheckBoxes.end(); for (; current != end; ++current) { if (counter < numTypes) { CSMWorld::UniversalId type = types[counter]; current->first->setText(QString::fromUtf8(type.getTypeName().c_str())); current->first->setChecked(true); current->second = std::move(type); ++counter; } else { current->first->hide(); } } mNumChecked = mNumUsedCheckBoxes = numTypes;}
void CSVWorld::ExtendedCommandConfigurator::lockWidgets(bool locked){ mPerformButton->setEnabled(!mEditLock && mNumChecked > 0);
CheckBoxMap::const_iterator current = mTypeCheckBoxes.begin(); CheckBoxMap::const_iterator end = mTypeCheckBoxes.end(); for (int i = 0; current != end && i < mNumUsedCheckBoxes; ++current, ++i) { current->first->setEnabled(!mEditLock); }}
void CSVWorld::ExtendedCommandConfigurator::performExtendedCommand(){ std::vector<CSMWorld::UniversalId> types;
CheckBoxMap::const_iterator current = mTypeCheckBoxes.begin(); CheckBoxMap::const_iterator end = mTypeCheckBoxes.end(); for (; current != end; ++current) { if (current->first->isChecked()) { types.push_back(current->second); } }
mCommandDispatcher->setExtendedTypes(types); if (mMode == Mode_Delete) { mCommandDispatcher->executeExtendedDelete(); } else { mCommandDispatcher->executeExtendedRevert(); } emit done();}
void CSVWorld::ExtendedCommandConfigurator::checkBoxStateChanged(int state){ switch (state) { case Qt::Unchecked: --mNumChecked; break; case Qt::Checked: ++mNumChecked; break; case Qt::PartiallyChecked: // Not used break; }
mPerformButton->setEnabled(mNumChecked > 0);}
void CSVWorld::ExtendedCommandConfigurator::dataIdListChanged(){ bool idsRemoved = false; for (int i = 0; i < static_cast<int>(mSelectedIds.size()); ++i) { if (!mData.hasId(mSelectedIds[i])) { std::swap(mSelectedIds[i], mSelectedIds.back()); mSelectedIds.pop_back(); idsRemoved = true; --i; } }
// If all selected IDs were removed, cancel the configurator if (mSelectedIds.empty()) { emit done(); return; }
if (idsRemoved) { mCommandDispatcher->setSelection(mSelectedIds); }}