diff --git a/CMakeLists.txt b/CMakeLists.txt index 213c9bda7..54f675fc7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -60,6 +60,7 @@ set(RGM_SOURCES Models/ResourceModelMap.cpp Models/ImmediateMapper.cpp Models/ProtoModel.cpp + Models/SystemsModel.cpp Models/EventTypesListSortFilterProxyModel.cpp Models/RepeatedSortFilterProxyModel.cpp Components/Utility.cpp @@ -114,6 +115,7 @@ set(RGM_HEADERS Models/RepeatedModel.h Models/EventsListModel.h Models/ModelMapper.h + Models/SystemsModel.h Models/RepeatedSortFilterProxyModel.h Models/TreeSortFilterProxyModel.h main.h @@ -242,16 +244,8 @@ find_package(yaml-cpp CONFIG REQUIRED) target_link_libraries(${EXE} PRIVATE yaml-cpp) #Find gRPC - if (MSVC) # Windows actually does something right for once - find_package(gRPC CONFIG REQUIRED) - target_link_libraries(${EXE} PRIVATE gRPC::gpr gRPC::grpc gRPC::grpc++) - else() # https://tinyurl.com/arch-grpc-bug - find_library(LIB_GRPC_UNSECURE NAMES grpc++_unsecure) - find_library(LIB_GPR NAMES gpr) - find_library(LIB_CARES NAMES cares) - find_library(LIB_ADDRESS_SORTING NAMES address_sorting) - target_link_libraries(${EXE} PRIVATE ${LIB_CARES} ${LIB_ADDRESS_SORTING} ${LIB_GPR} ${LIB_GRPC_UNSECURE}) - endif() + find_package(gRPC CONFIG REQUIRED) + target_link_libraries(${EXE} PRIVATE gRPC::gpr gRPC::grpc gRPC::grpc++) # Find Protobuf include(FindProtobuf) diff --git a/Editors/SettingsEditor.cpp b/Editors/SettingsEditor.cpp index 4e6366f04..4674e1155 100644 --- a/Editors/SettingsEditor.cpp +++ b/Editors/SettingsEditor.cpp @@ -1,4 +1,5 @@ #include "SettingsEditor.h" +#include "Models/SystemsModel.h" #include "MainWindow.h" #include "ui_SettingsEditor.h" @@ -8,85 +9,49 @@ using namespace buffers::resources; -Q_DECLARE_METATYPE(buffers::SystemInfo); +static QMap systemsModels; -static std::string get_combo_system_id(const QComboBox* combo) { - auto data = combo->currentData(); - auto subsystem = data.value(); - return subsystem.id(); +static void initModelCache() { + if (systemsModels.empty()) { + for (const auto& sys : qAsConst(MainWindow::systemCache)) { + systemsModels.insert(QString::fromStdString(sys.name()), new SystemsModel(sys, MainWindow::instance)); + } + } } SettingsEditor::SettingsEditor(MessageModel* model, QWidget* parent) : BaseEditor(model, parent), ui(new Ui::SettingsEditor) { ui->setupUi(this); - QPushButton* saveButton = ui->buttonBox->button(QDialogButtonBox::Save); - saveButton->setIcon(QIcon(":/actions/accept.png")); - connect(saveButton, &QPushButton::clicked, [=]() { - Settings settings; - auto* api = settings.mutable_api(); - api->set_target_audio(get_combo_system_id(ui->audioCombo)); - api->set_target_collision(get_combo_system_id(ui->collisionCombo)); - api->set_target_compiler(get_combo_system_id(ui->compilerCombo)); - api->set_target_graphics(get_combo_system_id(ui->graphicsCombo)); - api->set_target_network(get_combo_system_id(ui->networkCombo)); - api->set_target_platform(get_combo_system_id(ui->platformCombo)); - api->set_target_widgets(get_combo_system_id(ui->widgetsCombo)); - api->add_extensions("Paths"); - - emit MainWindow::setCurrentConfig(settings); - }); - QPushButton* discardButton = ui->buttonBox->button(QDialogButtonBox::Discard); - discardButton->setIcon(QIcon(":/actions/cancel.png")); - pageMap = {{"api", ui->apiPage}, {"extensions", ui->extensionsPage}, {"compiler", ui->compilerPage}, {"controls", ui->controlsPage}, {"graphics", ui->graphicsPage}, {"project info", ui->projectInfoPage}, {"version", ui->versionPage}}; - const QMap systemUIMap = { - {QString("Audio"), ui->audioCombo}, {QString("Platform"), ui->platformCombo}, - {QString("Graphics"), ui->graphicsCombo}, {QString("Widget"), ui->widgetsCombo}, - {QString("Collision"), ui->collisionCombo}, {QString("Compilers"), ui->compilerCombo}, - {QString("Network"), ui->networkCombo}, {QString("Extensions"), ui->extensionsList}, - }; - for (const auto& system : qAsConst(MainWindow::systemCache)) { - const QString systemName = QString::fromStdString(system.name()); - auto it = systemUIMap.find(systemName); - if (it == systemUIMap.end()) continue; - auto widget = it.value(); - const QString className = widget->metaObject()->className(); - QListWidget* listWidget = nullptr; - QComboBox* combo = nullptr; - if (className == "QListWidget") { - listWidget = static_cast(widget); - } else if (className == "QComboBox") { - combo = static_cast(widget); - connect(combo, static_cast(&QComboBox::currentIndexChanged), [=]() { - auto data = combo->currentData(); - auto subsystem = data.value(); - const QString subsystemDesc = QString::fromStdString(subsystem.description()); - const QString subsystemAuthor = QString::fromStdString(subsystem.author()); - ui->authorName->setText(subsystemAuthor); - ui->systemDesc->setPlainText(subsystemDesc); - }); - } - for (const auto &subsystem : system.subsystems()) { - const QString subsystemName = QString::fromStdString(subsystem.name()); - const QString subsystemId = QString::fromStdString(subsystem.id()); - const QString subsystemDesc = QString::fromStdString(subsystem.description()); - if (combo) { - QVariant data; - data.setValue(subsystem); - combo->addItem(subsystemName, data); - } else if (listWidget) { - auto item = new QListWidgetItem(subsystemName, listWidget); - item->setFlags(item->flags() | Qt::ItemFlag::ItemIsUserCheckable); - item->setCheckState(Qt::Unchecked); - item->setToolTip(subsystemDesc); - item->setData(Qt::UserRole, subsystemId); - } - } - } + initModelCache(); + + ui->audioCombo->setModel(systemsModels["Audio"]); + ui->platformCombo->setModel(systemsModels["Platform"]); + ui->compilerCombo->setModel(systemsModels["Compilers"]); + ui->graphicsCombo->setModel(systemsModels["Graphics"]); + ui->widgetsCombo->setModel(systemsModels["Widget"]); + ui->collisionCombo->setModel(systemsModels["Collision"]); + ui->networkCombo->setModel(systemsModels["Network"]); + + SettingsEditor::RebindSubModels(); +} + +void SettingsEditor::RebindSubModels() { + MessageModel* sm = _model->GetSubModel(TreeNode::kSettingsFieldNumber); + + ModelMapper* apiMapper = new ModelMapper(sm->GetSubModel(Settings::kApiFieldNumber)); + apiMapper->addMapping(ui->audioCombo, API::kTargetAudioFieldNumber); + apiMapper->addMapping(ui->platformCombo, API::kTargetPlatformFieldNumber); + apiMapper->addMapping(ui->compilerCombo, API::kTargetCompilerFieldNumber); + apiMapper->addMapping(ui->graphicsCombo, API::kTargetGraphicsFieldNumber); + apiMapper->addMapping(ui->widgetsCombo, API::kTargetWidgetsFieldNumber); + apiMapper->addMapping(ui->networkCombo, API::kTargetNetworkFieldNumber); + + BaseEditor::RebindSubModels(); } SettingsEditor::~SettingsEditor() { delete ui; } diff --git a/Editors/SettingsEditor.h b/Editors/SettingsEditor.h index 57bd34cc7..911408a5e 100644 --- a/Editors/SettingsEditor.h +++ b/Editors/SettingsEditor.h @@ -14,6 +14,7 @@ class SettingsEditor : public BaseEditor { public: explicit SettingsEditor(MessageModel* model, QWidget* parent); + void RebindSubModels() override; ~SettingsEditor(); private slots: diff --git a/Editors/SettingsEditor.ui b/Editors/SettingsEditor.ui index dee6d74bb..5fb7620c5 100644 --- a/Editors/SettingsEditor.ui +++ b/Editors/SettingsEditor.ui @@ -102,6 +102,9 @@ 0 + + 6 + @@ -1215,11 +1218,11 @@ - - - + + + diff --git a/MainWindow.cpp b/MainWindow.cpp index 76318b656..446dde336 100644 --- a/MainWindow.cpp +++ b/MainWindow.cpp @@ -39,7 +39,7 @@ QList MainWindow::EnigmaSearchPaths = {QDir::currentPath(), "./enigma-d "../RadialGM/Submodules/enigma-dev"}; QFileInfo MainWindow::EnigmaRoot = MainWindow::getEnigmaRoot(); QList MainWindow::systemCache; -MainWindow *MainWindow::_instance = nullptr; +MainWindow *MainWindow::instance = nullptr; ResourceModelMap *MainWindow::resourceMap = nullptr; TreeModel *MainWindow::treeModel = nullptr; std::unique_ptr MainWindow::_event_data; @@ -117,7 +117,7 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), _ui(new Ui::MainW ArtManager::Init(); - _instance = this; + instance = this; setCorner(Qt::TopLeftCorner, Qt::LeftDockWidgetArea); setCorner(Qt::TopRightCorner, Qt::RightDockWidgetArea); @@ -191,7 +191,7 @@ MainWindow::~MainWindow() { } void MainWindow::setCurrentConfig(const buffers::resources::Settings &settings) { - emit _instance->CurrentConfigChanged(settings); + emit instance->CurrentConfigChanged(settings); } void MainWindow::readSettings() { diff --git a/MainWindow.h b/MainWindow.h index 58ef30e0d..7dccda394 100644 --- a/MainWindow.h +++ b/MainWindow.h @@ -33,6 +33,7 @@ class MainWindow : public QMainWindow { static MessageModel* resourceModel; static TreeModel* treeModel; static QList systemCache; + static MainWindow *instance; explicit MainWindow(QWidget *parent); ~MainWindow(); @@ -111,8 +112,6 @@ class MainWindow : public QMainWindow { private: void closeEvent(QCloseEvent *event) override; - static MainWindow *_instance; - QHash _subWindows; Ui::MainWindow *_ui; diff --git a/Models/MessageModel.cpp b/Models/MessageModel.cpp index fc06e86ab..3f060395a 100644 --- a/Models/MessageModel.cpp +++ b/Models/MessageModel.cpp @@ -150,7 +150,7 @@ int MessageModel::rowCount(const QModelIndex &parent) const { int MessageModel::columnCount(const QModelIndex & /*parent*/) const { return 1; } bool MessageModel::setData(const QModelIndex &index, const QVariant &value, int role) { - R_EXPECT(index.isValid(), false) << "Supplied index was invalid:" << index; + R_EXPECT(index.isValid(), false) << DebugName() << "Supplied index was invalid:" << index; const Descriptor *desc = _protobuf->GetDescriptor(); const Reflection *refl = _protobuf->GetReflection(); diff --git a/Models/ModelMapper.cpp b/Models/ModelMapper.cpp index 9993bd4a7..e8a9987c4 100644 --- a/Models/ModelMapper.cpp +++ b/Models/ModelMapper.cpp @@ -9,7 +9,11 @@ ModelMapper::ModelMapper(MessageModel *model, BaseEditor *parent) : QObject(pare parent->connect(model, &ProtoModel::DataChanged, parent, &BaseEditor::dataChanged); } -// mapper +ModelMapper::ModelMapper(MessageModel *model) : QObject(model), _model(model) { + _mapper = new ImmediateDataWidgetMapper(this); + _mapper->setOrientation(Qt::Vertical); + _mapper->setModel(model); +} MessageModel *ModelMapper::GetModel() { return _model; } diff --git a/Models/ModelMapper.h b/Models/ModelMapper.h index c5857015b..f24979ec4 100644 --- a/Models/ModelMapper.h +++ b/Models/ModelMapper.h @@ -11,6 +11,7 @@ class BaseEditor; class ModelMapper : public QObject { public: ModelMapper(MessageModel *_model, BaseEditor *parent); + ModelMapper(MessageModel *_model); // mapper void addMapping(QWidget *widget, int section, QByteArray propName = ""); diff --git a/Models/SystemsModel.cpp b/Models/SystemsModel.cpp new file mode 100644 index 000000000..2763363dd --- /dev/null +++ b/Models/SystemsModel.cpp @@ -0,0 +1,24 @@ +#include "SystemsModel.h" + +SystemsModel::SystemsModel(buffers::SystemType system, QObject *parent) : QAbstractListModel(parent), system_(system) +{ + +} + +QVariant SystemsModel::data(const QModelIndex &index, int role) const { + if (!index.isValid()) return QVariant(); + + switch (role) { + case Qt::DisplayRole: return QString::fromStdString(system_.subsystems(index.row()).name()); + //case Qt::ToolTipRole: return QString::fromStdString(system_.subsystems(index.row()).description()); + default: return QVariant(); + } +} + +int SystemsModel::columnCount(const QModelIndex &/*parent*/) const { + return 1; +} + +int SystemsModel::rowCount(const QModelIndex& /*parent*/) const { + return system_.subsystems_size(); +} diff --git a/Models/SystemsModel.h b/Models/SystemsModel.h new file mode 100644 index 000000000..0187340af --- /dev/null +++ b/Models/SystemsModel.h @@ -0,0 +1,23 @@ +#ifndef SYSTEMSMODEL_H +#define SYSTEMSMODEL_H + +#include "compiler.pb.h" +#include "Settings.pb.h" + +#include + +using namespace buffers::resources; + +class SystemsModel : public QAbstractListModel +{ +public: + SystemsModel(buffers::SystemType system, QObject* parent = nullptr); + QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override; + int columnCount(const QModelIndex& parent = QModelIndex()) const override; + int rowCount(const QModelIndex& parent = QModelIndex()) const override; + +private: + buffers::SystemType system_; +}; + +#endif // SYSTEMSMODEL_H diff --git a/Models/TreeModel.cpp b/Models/TreeModel.cpp index 71374524d..05a95e441 100644 --- a/Models/TreeModel.cpp +++ b/Models/TreeModel.cpp @@ -90,7 +90,9 @@ bool TreeModel::setData(const QModelIndex &index, const QVariant &value, int rol MessageModel* model = siblings->GetSubModel(node->row_in_parent)->TryCastAsMessageModel(); QString oldName = model->Data(FieldPath::Of(buffers::TreeNode::kNameFieldNumber)).toString(); buffers::TreeNode::TypeCase type = (buffers::TreeNode::TypeCase)model->OneOfType("type"); - R_EXPECT(MainWindow::resourceMap->ValidName(type, value.toString()), false) << "Invalid resource name"; + if (value.toString() == oldName) return false; + R_EXPECT(MainWindow::resourceMap->ValidName(type, value.toString()), false) << "Invalid resource name: " << + value.toString(); bool ret = model->SetData(FieldPath::Of(buffers::TreeNode::kNameFieldNumber), value); if (!ret) return false; node->DataChanged(); diff --git a/Plugins/ServerPlugin.cpp b/Plugins/ServerPlugin.cpp index 57a9d4452..625a3c7a7 100644 --- a/Plugins/ServerPlugin.cpp +++ b/Plugins/ServerPlugin.cpp @@ -5,6 +5,7 @@ #include #include #include +#include #include #include @@ -324,6 +325,8 @@ ServerPlugin::ServerPlugin(MainWindow& mainWindow) : RGMPlugin(mainWindow) { process->start(program, arguments); process->waitForStarted(); + QThread::sleep(5); + // construct the channel and connect to the server running in the process // Note: gRPC is too dumb to resolve localhost on linux std::shared_ptr channel = CreateChannel("127.0.0.1:37818", InsecureChannelCredentials()); diff --git a/RadialGM.pro b/RadialGM.pro index de72306c4..23a672702 100644 --- a/RadialGM.pro +++ b/RadialGM.pro @@ -76,6 +76,7 @@ SOURCES += \ Models/RepeatedMessageModel.cpp \ Models/RepeatedModel.cpp \ Models/RepeatedSortFilterProxyModel.cpp \ + Models/SystemsModel.cpp \ Utils/FieldPath.cpp \ Utils/ProtoManip.cpp \ Widgets/AssetScrollAreaBackground.cpp \ @@ -141,6 +142,7 @@ HEADERS += \ Models/RepeatedModel.h \ Models/RepeatedPrimitiveModel.h \ Models/RepeatedSortFilterProxyModel.h \ + Models/SystemsModel.h \ Utils/FieldPath.h \ Utils/ProtoManip.h \ Utils/QBoilerplate.h \