Skip to content

Commit 7c188a7

Browse files
Warchamp7RytoEX
authored andcommitted
frontend: Fix removal of missing plugins
Updates the plugin manager window rows to use a local copy of ModuleInfo. Passing around a pointer to the actual entry within the modules_ vector felt like a sensible optimization for updating the enabled state of entries. However when deleting entries from the Missing category it means pointers to anything after the deleted entry become incorrect or invalidated.
1 parent ace3980 commit 7c188a7

4 files changed

Lines changed: 37 additions & 24 deletions

File tree

β€Žfrontend/plugin-manager/InstalledPluginRow.cppβ€Ž

Lines changed: 8 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -27,12 +27,12 @@ constexpr std::string_view kLegacyPluginInfoLink{"https://obsproject.com/go/lega
2727
namespace OBS {
2828
InstalledPluginRow::InstalledPluginRow(QWidget *parent, const PluginManagerWindow::Entry &entry) : idian::Row(parent)
2929
{
30-
OBS::ModuleInfo *metadata = entry.module;
30+
const OBS::ModuleInfo &metadata = entry.module;
3131

3232
setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
3333
QString name = entry.name;
3434

35-
QString version = metadata && !metadata->version.empty() ? metadata->version.c_str() : "";
35+
QString version = !metadata.version.empty() ? metadata.version.c_str() : "";
3636

3737
auto *moduleText = new QWidget{this};
3838
moduleText->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
@@ -49,7 +49,7 @@ InstalledPluginRow::InstalledPluginRow(QWidget *parent, const PluginManagerWindo
4949
nameLabel->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Minimum);
5050
nameLabel->setIndent(0);
5151
idian::Utils::addClass(nameLabel, "title");
52-
if (metadata && !metadata->enabledAtLaunch) {
52+
if (!metadata.enabledAtLaunch) {
5353
idian::Utils::addClass(nameLabel, "text-muted");
5454
}
5555
headerLayout->addWidget(nameLabel);
@@ -118,7 +118,7 @@ InstalledPluginRow::InstalledPluginRow(QWidget *parent, const PluginManagerWindo
118118
detailsLayout->addWidget(legacyNotice);
119119
}
120120

121-
if (metadata && !metadata->enabledAtLaunch) {
121+
if (!metadata.enabledAtLaunch) {
122122
statusChip = new InfoChip{QTStr("PluginManager.Status.Disabled"), moduleText};
123123
idian::Utils::addClass(statusChip, "bg-info");
124124
idian::Utils::addClass(statusChip, "text-muted");
@@ -129,17 +129,14 @@ InstalledPluginRow::InstalledPluginRow(QWidget *parent, const PluginManagerWindo
129129
headerLayout->addWidget(statusChip);
130130
}
131131

132-
if (metadata) {
132+
if (entry.hasLoadedBefore) {
133133
auto toggleSwitch = new idian::ToggleSwitch(this);
134-
toggleSwitch->setChecked(metadata->enabled);
134+
toggleSwitch->setChecked(metadata.enabled);
135135
addWidget(toggleSwitch);
136136
toggleSwitch->setAccessibleDescription(QTStr("PluginManager.Button.Enable").arg(name));
137137

138-
connect(toggleSwitch, &idian::ToggleSwitch::toggled, this, [this, metadata](bool checked) {
139-
metadata->enabled = checked;
140-
141-
emit toggleChanged();
142-
});
138+
connect(toggleSwitch, &idian::ToggleSwitch::toggled, this,
139+
[this](bool checked) { emit toggleChanged(checked); });
143140
}
144141

145142
if (entry.category == PluginManagerWindow::Category::Missing) {

β€Žfrontend/plugin-manager/InstalledPluginRow.hppβ€Ž

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ class InstalledPluginRow : public idian::Row {
3030
InstalledPluginRow(QWidget *parent, const PluginManagerWindow::Entry &entry);
3131

3232
signals:
33-
void toggleChanged();
33+
void toggleChanged(bool enabled);
3434
void trashClicked();
3535

3636
private:

β€Žfrontend/plugin-manager/PluginManagerWindow.cppβ€Ž

Lines changed: 26 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -177,18 +177,24 @@ void PluginManagerWindow::setupInstalledPage(std::vector<std::string> failedModu
177177
: metadata.module_name.c_str();
178178
QString version = !metadata.version.empty() ? metadata.version.c_str() : "";
179179

180-
Entry newEntry{&metadata, name, category, isLegacyModule};
180+
Entry newEntry{metadata, name, category, isLegacyModule};
181181
installedPluginEntries.push_back(newEntry);
182182
}
183183

184184
for (const std::string &moduleName : failedModules) {
185185
// This failed module is not in the plugin manager cache which means it has never been loaded successfully.
186186
// Create a dummy visual entry for it.
187+
OBS::ModuleInfo dummyModule;
187188
QString name = QString::fromStdString(moduleName.data());
188189
Category category{Category::Error};
189190
bool isLegacy{false};
191+
bool hasLoadedBefore{false};
190192

191-
Entry newEntry{nullptr, name, category, isLegacy};
193+
dummyModule.module_name = moduleName;
194+
dummyModule.enabled = false;
195+
dummyModule.enabledAtLaunch = false;
196+
197+
Entry newEntry{dummyModule, name, category, isLegacy, hasLoadedBefore};
192198
installedPluginEntries.push_back(newEntry);
193199
}
194200

@@ -217,25 +223,34 @@ void PluginManagerWindow::setupInstalledPage(std::vector<std::string> failedModu
217223

218224
if (entry.category == Category::Installed) {
219225
installedPluginList->addRow(newRow);
220-
221-
connect(newRow, &InstalledPluginRow::toggleChanged, this,
222-
[this]() { ui->manageRestartLabel->setVisible(isEnabledPluginsChanged()); });
223-
224226
} else if (entry.category == Category::Error) {
225227
errorPluginList->addRow(newRow);
226228
} else if (entry.category == Category::Missing) {
227229
missingPluginList->addRow(newRow);
228230

229-
connect(newRow, &InstalledPluginRow::trashClicked, this, [this, newRow, entry]() {
230-
auto it = std::find_if(modules_.begin(), modules_.end(), [&entry](const auto &module) {
231-
return &module == entry.module;
232-
});
231+
connect(newRow, &InstalledPluginRow::trashClicked, this, [this, entry]() {
232+
auto it = std::find_if(modules_.begin(), modules_.end(),
233+
[&entry](const ModuleInfo &module) {
234+
return module.module_name == entry.module.module_name;
235+
});
233236

234237
if (it != modules_.end()) {
235238
modules_.erase(it);
236239
}
237240
});
238241
}
242+
243+
connect(newRow, &InstalledPluginRow::toggleChanged, this, [this, entry](bool enabled) {
244+
auto it = std::find_if(modules_.begin(), modules_.end(), [&entry](const ModuleInfo &module) {
245+
return module.module_name == entry.module.module_name;
246+
});
247+
248+
if (it != modules_.end()) {
249+
it->enabled = enabled;
250+
}
251+
252+
ui->manageRestartLabel->setVisible(isEnabledPluginsChanged());
253+
});
239254
}
240255

241256
setTabOrder(previousRow, ui->buttonBox);
@@ -293,7 +308,7 @@ bool PluginManagerWindow::isEnabledPluginsChanged()
293308
bool result = false;
294309
for (auto &entry : installedPluginEntries) {
295310
// Only prompt for restart when a loadable plugin entry changed.
296-
if (entry.category == Category::Installed && entry.module->enabledAtLaunch != entry.module->enabled) {
311+
if (entry.category == Category::Installed && entry.module.enabledAtLaunch != entry.module.enabled) {
297312
result = true;
298313
break;
299314
}

β€Žfrontend/plugin-manager/PluginManagerWindow.hppβ€Ž

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,10 +34,11 @@ class PluginManagerWindow : public QDialog {
3434
enum class Category { Invalid = 0, Installed, Error, Missing };
3535

3636
struct Entry {
37-
OBS::ModuleInfo *module{nullptr};
37+
OBS::ModuleInfo module;
3838
QString name{};
3939
Category category{Category::Invalid};
4040
bool isLegacy{false};
41+
bool hasLoadedBefore{true};
4142
};
4243

4344
enum class Page { Installed };

0 commit comments

Comments
Β (0)