From b4a840f589403d8a72f1e8470050e116345a1d92 Mon Sep 17 00:00:00 2001 From: Warchamp7 Date: Fri, 8 May 2026 14:34:57 -0400 Subject: [PATCH 1/3] frontend: Avoid reinterpret_cast when casting QObjects When casting between QObjects, qobject_cast should always be used for dynamic casts. This increases performance as there is no RTTI (Run Time Type Information) with qobject_cast, like there is with dynamic_cast. In other cases where we are sure or assume the cast is valid, use static_cast. Using reinterpret_cast is bad practice, as you should use it in very specific cases. Co-Authored-By: Clayton Groeneveld <19962531+cg2121@users.noreply.github.com> --- frontend/components/SourceTree.cpp | 2 +- frontend/components/SourceTree.hpp | 4 +- frontend/components/VolumeControl.cpp | 6 +- frontend/dialogs/OBSBasicAdvAudio.cpp | 2 +- frontend/dialogs/OBSBasicFilters.cpp | 2 +- frontend/dialogs/OBSBasicSourceSelect.cpp | 4 +- frontend/dialogs/OBSYoutubeActions.cpp | 1 + frontend/docks/YouTubeAppDock.cpp | 2 +- .../ImporterEntryPathItemDelegate.cpp | 2 +- .../plugin-manager/PluginManagerWindow.cpp | 2 +- frontend/settings/OBSBasicSettings.cpp | 22 +- frontend/settings/OBSBasicSettings_Stream.cpp | 2 +- frontend/settings/OBSHotkeyWidget.hpp | 2 +- frontend/utility/ExtraBrowsersDelegate.cpp | 8 +- frontend/utility/ExtraBrowsersModel.cpp | 10 +- .../utility/RemuxEntryPathItemDelegate.cpp | 2 +- frontend/utility/YoutubeApiWrappers.cpp | 2 +- frontend/utility/audio-encoders.cpp | 9 +- frontend/widgets/OBSBasic.cpp | 2 +- frontend/widgets/OBSBasic_Clipboard.cpp | 4 +- frontend/widgets/OBSBasic_ContextToolbar.cpp | 4 +- frontend/widgets/OBSBasic_Docks.cpp | 5 +- frontend/widgets/OBSBasic_Profiles.cpp | 3 +- .../widgets/OBSBasic_SceneCollections.cpp | 3 +- frontend/widgets/OBSBasic_SceneItems.cpp | 42 ++- frontend/widgets/OBSBasic_Scenes.cpp | 2 +- frontend/widgets/OBSBasic_Transitions.cpp | 8 +- frontend/widgets/OBSBasic_YouTube.cpp | 2 +- frontend/wizards/AutoConfigStartPage.cpp | 12 +- frontend/wizards/AutoConfigStartPage.hpp | 5 + frontend/wizards/AutoConfigStreamPage.cpp | 106 ++++---- frontend/wizards/AutoConfigStreamPage.hpp | 5 + frontend/wizards/AutoConfigTestPage.cpp | 255 +++++++++--------- frontend/wizards/AutoConfigTestPage.hpp | 5 + frontend/wizards/AutoConfigVideoPage.cpp | 44 +-- frontend/wizards/AutoConfigVideoPage.hpp | 5 + shared/properties-view/properties-view.cpp | 18 +- .../idian/include/Idian/StateEventFilter.cpp | 2 +- 38 files changed, 333 insertions(+), 283 deletions(-) diff --git a/frontend/components/SourceTree.cpp b/frontend/components/SourceTree.cpp index 9dff949509ac09..e1d5f3f283315f 100644 --- a/frontend/components/SourceTree.cpp +++ b/frontend/components/SourceTree.cpp @@ -486,7 +486,7 @@ bool SourceTree::Edit(int row) QModelIndex index = stm->createIndex(row, 0); QWidget *widget = indexWidget(index); - SourceTreeItem *itemWidget = reinterpret_cast(widget); + SourceTreeItem *itemWidget = static_cast(widget); if (itemWidget->IsEditing()) { #ifdef __APPLE__ itemWidget->ExitEditMode(true); diff --git a/frontend/components/SourceTree.hpp b/frontend/components/SourceTree.hpp index 60cacaa3bdfe0b..2bc89b1c70c6c2 100644 --- a/frontend/components/SourceTree.hpp +++ b/frontend/components/SourceTree.hpp @@ -29,13 +29,13 @@ class SourceTree : public QListView { void UpdateWidget(const QModelIndex &idx, obs_sceneitem_t *item); void UpdateWidgets(bool force = false); - inline SourceTreeModel *GetStm() const { return reinterpret_cast(model()); } + inline SourceTreeModel *GetStm() const { return static_cast(model()); } public: inline SourceTreeItem *GetItemWidget(int idx) { QWidget *widget = indexWidget(GetStm()->createIndex(idx, 0)); - return reinterpret_cast(widget); + return static_cast(widget); } explicit SourceTree(QWidget *parent = nullptr); diff --git a/frontend/components/VolumeControl.cpp b/frontend/components/VolumeControl.cpp index 5661dbbe34299e..47696de0353ece 100644 --- a/frontend/components/VolumeControl.cpp +++ b/frontend/components/VolumeControl.cpp @@ -505,7 +505,11 @@ void VolumeControl::showVolumeControlMenu(QPoint pos) void VolumeControl::renameSource() { - QAction *action = reinterpret_cast(sender()); + QAction *action = qobject_cast(sender()); + if (!action) { + return; + } + OBSSource source = action->property("source").value(); std::string uuid = obs_source_get_uuid(source); diff --git a/frontend/dialogs/OBSBasicAdvAudio.cpp b/frontend/dialogs/OBSBasicAdvAudio.cpp index 860be203092aed..5aa6c5ccb1c371 100644 --- a/frontend/dialogs/OBSBasicAdvAudio.cpp +++ b/frontend/dialogs/OBSBasicAdvAudio.cpp @@ -176,7 +176,7 @@ void OBSBasicAdvAudio::SetIconsVisible(bool visible) showVisible = visible; QLayoutItem *item = ui->mainLayout->itemAtPosition(0, 0); - QLabel *headerLabel = qobject_cast(item->widget()); + QWidget *headerLabel = item->widget(); visible ? headerLabel->show() : headerLabel->hide(); for (size_t i = 0; i < controls.size(); i++) { diff --git a/frontend/dialogs/OBSBasicFilters.cpp b/frontend/dialogs/OBSBasicFilters.cpp index e34e6b5c92fb06..06e78f4f67b11e 100644 --- a/frontend/dialogs/OBSBasicFilters.cpp +++ b/frontend/dialogs/OBSBasicFilters.cpp @@ -946,7 +946,7 @@ void OBSBasicFilters::FilterNameEdited(QWidget *editor, QListWidget *list) { QListWidgetItem *listItem = list->currentItem(); OBSSource filter = listItem->data(Qt::UserRole).value(); - QLineEdit *edit = qobject_cast(editor); + QLineEdit *edit = static_cast(editor); string name = edit->text().trimmed().toStdString(); const char *prevName = obs_source_get_name(filter); diff --git a/frontend/dialogs/OBSBasicSourceSelect.cpp b/frontend/dialogs/OBSBasicSourceSelect.cpp index 7cd5f39ff011ec..17452e52645c50 100644 --- a/frontend/dialogs/OBSBasicSourceSelect.cpp +++ b/frontend/dialogs/OBSBasicSourceSelect.cpp @@ -496,7 +496,7 @@ void OBSBasicSourceSelect::rebuildSourceTypeList() { ui->sourceTypeList->clear(); - OBSBasic *main = qobject_cast(App()->GetMainWindow()); + OBSBasic *main = OBSBasic::Get(); const char *unversioned_type; const char *type; @@ -763,7 +763,7 @@ void OBSBasicSourceSelect::createNew() OBSSceneItem item = addResult.value(); - OBSBasic *main = reinterpret_cast(App()->GetMainWindow()); + OBSBasic *main = OBSBasic::Get(); std::string sceneUuid = obs_source_get_uuid(main->GetCurrentSceneSource()); auto undo = [sceneUuid](const std::string &data) { OBSBasic *main = OBSBasic::Get(); diff --git a/frontend/dialogs/OBSYoutubeActions.cpp b/frontend/dialogs/OBSYoutubeActions.cpp index 7fa137398ea10e..01fc17e9f5b5d3 100644 --- a/frontend/dialogs/OBSYoutubeActions.cpp +++ b/frontend/dialogs/OBSYoutubeActions.cpp @@ -20,6 +20,7 @@ const QString IndexOfGamingCategory = "20"; OBSYoutubeActions::OBSYoutubeActions(QWidget *parent, Auth *auth, bool broadcastReady) : QDialog(parent), ui(new Ui::OBSYoutubeActions), + // FIXME: https://github.com/obsproject/obs-studio/issues/13443 apiYouTube(dynamic_cast(auth)), workerThread(new WorkerThread(apiYouTube)), broadcastReady(broadcastReady) diff --git a/frontend/docks/YouTubeAppDock.cpp b/frontend/docks/YouTubeAppDock.cpp index a5b283484da1a7..95e827250ad157 100644 --- a/frontend/docks/YouTubeAppDock.cpp +++ b/frontend/docks/YouTubeAppDock.cpp @@ -381,7 +381,7 @@ YoutubeApiWrappers *YouTubeAppDock::GetYTApi() { Auth *auth = OBSBasic::Get()->GetAuth(); if (auth) { - YoutubeApiWrappers *apiYouTube(dynamic_cast(auth)); + YoutubeApiWrappers *apiYouTube(qobject_cast(auth)); if (apiYouTube) { return apiYouTube; } else { diff --git a/frontend/importer/ImporterEntryPathItemDelegate.cpp b/frontend/importer/ImporterEntryPathItemDelegate.cpp index 520dc5ef90e17f..726a8167143357 100644 --- a/frontend/importer/ImporterEntryPathItemDelegate.cpp +++ b/frontend/importer/ImporterEntryPathItemDelegate.cpp @@ -154,7 +154,7 @@ void ImporterEntryPathItemDelegate::handleClear(QWidget *container) void ImporterEntryPathItemDelegate::updateText() { - QLineEdit *lineEdit = dynamic_cast(sender()); + QLineEdit *lineEdit = static_cast(sender()); QWidget *editor = lineEdit->parentWidget(); emit commitData(editor); } diff --git a/frontend/plugin-manager/PluginManagerWindow.cpp b/frontend/plugin-manager/PluginManagerWindow.cpp index b29cb12c89f72f..c9bdecd28d8351 100644 --- a/frontend/plugin-manager/PluginManagerWindow.cpp +++ b/frontend/plugin-manager/PluginManagerWindow.cpp @@ -116,7 +116,7 @@ PluginManagerWindow::PluginManagerWindow(std::vector const &modules, row++; } - QVBoxLayout *layout = qobject_cast(ui->modulesList->layout()); + QVBoxLayout *layout = static_cast(ui->modulesList->layout()); if (safe_mode) { QLabel *safeModeLabel = new QLabel(ui->modulesList); safeModeLabel->setText(QTStr("PluginManager.SafeMode")); diff --git a/frontend/settings/OBSBasicSettings.cpp b/frontend/settings/OBSBasicSettings.cpp index f974a1defa0513..cf2bf276a303a9 100644 --- a/frontend/settings/OBSBasicSettings.cpp +++ b/frontend/settings/OBSBasicSettings.cpp @@ -135,7 +135,7 @@ static inline bool SetInvalidValue(QComboBox *combo, const QString &name, const { combo->insertItem(0, name, data); - QStandardItemModel *model = dynamic_cast(combo->model()); + QStandardItemModel *model = static_cast(combo->model()); if (!model) return false; @@ -271,12 +271,12 @@ static std::tuple aspect_ratio(int cx, int cy) static inline void HighlightGroupBoxLabel(QGroupBox *gb, QWidget *widget, QString objectName) { - QFormLayout *layout = qobject_cast(gb->layout()); + QFormLayout *layout = static_cast(gb->layout()); if (!layout) return; - QLabel *label = qobject_cast(layout->labelForField(widget)); + QLabel *label = static_cast(layout->labelForField(widget)); if (label) { label->setObjectName(objectName); @@ -314,7 +314,7 @@ void RestrictResetBitrates(initializer_list boxes, int maxbitrate); OBSBasicSettings::OBSBasicSettings(QWidget *parent) : QDialog(parent), - main(qobject_cast(parent)), + main(OBSBasic::Get()), ui(new Ui::OBSBasicSettings) { string path; @@ -1216,7 +1216,7 @@ void OBSBasicSettings::LoadBranchesList() // Disable item if branch is disabled if (!branch.is_enabled) { - QStandardItemModel *model = dynamic_cast(ui->updateChannelBox->model()); + QStandardItemModel *model = static_cast(ui->updateChannelBox->model()); QStandardItem *item = model->item(ui->updateChannelBox->count() - 1); item->setFlags(Qt::NoItemFlags); } @@ -4311,7 +4311,7 @@ void OBSBasicSettings::SearchHotkeys(const QString &text, obs_key_combination_t if (!hotkeys) return; - QFormLayout *hotkeysLayout = qobject_cast(hotkeys->layout()); + QFormLayout *hotkeysLayout = static_cast(hotkeys->layout()); hotkeysLayout->setEnabled(false); QString needle = text.toLower(); @@ -4503,7 +4503,7 @@ static void DisableIncompatibleCodecs(QComboBox *cbox, const QString &format, co is_compatible = FFCodecAndFormatCompatible(codec, ext.c_str()); } - QStandardItemModel *model = dynamic_cast(cbox->model()); + QStandardItemModel *model = static_cast(cbox->model()); QStandardItem *item = model->item(idx); if (is_compatible) { @@ -4561,7 +4561,7 @@ static void ResetInvalidSelection(QComboBox *cbox) if (idx < 0) return; - QStandardItemModel *model = dynamic_cast(cbox->model()); + QStandardItemModel *model = static_cast(cbox->model()); QStandardItem *item = model->item(idx); if (item->isEnabled()) @@ -4893,7 +4893,7 @@ void OBSBasicSettings::SimpleStreamingEncoderChanged() * with their setups without them knowing. */ if (ui->simpleOutPreset->findData(curPreset) == -1) { ui->simpleOutPreset->addItem(curPreset, curPreset); - QStandardItemModel *model = qobject_cast(ui->simpleOutPreset->model()); + QStandardItemModel *model = static_cast(ui->simpleOutPreset->model()); QStandardItem *item = model->item(model->rowCount() - 1); item->setEnabled(false); } @@ -5112,7 +5112,7 @@ static void DisableIncompatibleSimpleCodecs(QComboBox *cbox, const QString &form codec = obs_get_encoder_codec(encoder_id); } - QStandardItemModel *model = dynamic_cast(cbox->model()); + QStandardItemModel *model = static_cast(cbox->model()); QStandardItem *item = model->item(idx); if (ContainerSupportsCodec(format.toStdString(), codec.toStdString())) { @@ -5142,7 +5142,7 @@ static void DisableIncompatibleSimpleContainer(QComboBox *cbox, const QString &c QString format = cbox->itemData(idx).toString(); string formatStr = format.toStdString(); - QStandardItemModel *model = dynamic_cast(cbox->model()); + QStandardItemModel *model = static_cast(cbox->model()); QStandardItem *item = model->item(idx); if (ContainerSupportsCodec(formatStr, vCodec) && ContainerSupportsCodec(formatStr, aCodec)) { diff --git a/frontend/settings/OBSBasicSettings_Stream.cpp b/frontend/settings/OBSBasicSettings_Stream.cpp index c7806c7443eb6f..e78306eff7eb9f 100644 --- a/frontend/settings/OBSBasicSettings_Stream.cpp +++ b/frontend/settings/OBSBasicSettings_Stream.cpp @@ -787,7 +787,7 @@ OBSService OBSBasicSettings::SpawnTempService() void OBSBasicSettings::OnOAuthStreamKeyConnected() { - OAuthStreamKey *a = reinterpret_cast(auth.get()); + OAuthStreamKey *a = qobject_cast(auth.get()); if (a) { bool validKey = !a->key().empty(); diff --git a/frontend/settings/OBSHotkeyWidget.hpp b/frontend/settings/OBSHotkeyWidget.hpp index 12f15f2829b162..e1715ac1dcf0f4 100644 --- a/frontend/settings/OBSHotkeyWidget.hpp +++ b/frontend/settings/OBSHotkeyWidget.hpp @@ -87,7 +87,7 @@ class OBSHotkeyWidget : public QWidget { bool ignoreChangedBindings = false; OBSBasicSettings *settings; - QVBoxLayout *layout() const { return dynamic_cast(QWidget::layout()); } + QVBoxLayout *layout() const { return static_cast(QWidget::layout()); } private slots: void HandleChangedBindings(obs_hotkey_id id_); diff --git a/frontend/utility/ExtraBrowsersDelegate.cpp b/frontend/utility/ExtraBrowsersDelegate.cpp index e984797fb409de..3c7aede78462a3 100644 --- a/frontend/utility/ExtraBrowsersDelegate.cpp +++ b/frontend/utility/ExtraBrowsersDelegate.cpp @@ -21,7 +21,7 @@ QWidget *ExtraBrowsersDelegate::createEditor(QWidget *parent, const QStyleOption void ExtraBrowsersDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const { - QLineEdit *text = reinterpret_cast(editor); + QLineEdit *text = static_cast(editor); text->blockSignals(true); text->setText(index.data().toString()); text->blockSignals(false); @@ -29,7 +29,7 @@ void ExtraBrowsersDelegate::setEditorData(QWidget *editor, const QModelIndex &in bool ExtraBrowsersDelegate::eventFilter(QObject *object, QEvent *event) { - QLineEdit *edit = qobject_cast(object); + QLineEdit *edit = static_cast(object); if (!edit) return false; @@ -65,7 +65,7 @@ bool ExtraBrowsersDelegate::ValidName(const QString &name) const void ExtraBrowsersDelegate::RevertText(QLineEdit *edit_) { - EditWidget *edit = reinterpret_cast(edit_); + EditWidget *edit = static_cast(edit_); int row = edit->index.row(); int col = edit->index.column(); bool newItem = (row == model->items.size()); @@ -82,7 +82,7 @@ void ExtraBrowsersDelegate::RevertText(QLineEdit *edit_) bool ExtraBrowsersDelegate::UpdateText(QLineEdit *edit_) { - EditWidget *edit = reinterpret_cast(edit_); + EditWidget *edit = static_cast(edit_); int row = edit->index.row(); int col = edit->index.column(); bool newItem = (row == model->items.size()); diff --git a/frontend/utility/ExtraBrowsersModel.cpp b/frontend/utility/ExtraBrowsersModel.cpp index 5409c3c1939af5..89d294856ac689 100644 --- a/frontend/utility/ExtraBrowsersModel.cpp +++ b/frontend/utility/ExtraBrowsersModel.cpp @@ -92,7 +92,7 @@ Qt::ItemFlags ExtraBrowsersModel::flags(const QModelIndex &index) const } void ExtraBrowsersModel::AddDeleteButton(int idx) { - QTableView *widget = reinterpret_cast(parent()); + QTableView *widget = static_cast(parent()); QModelIndex index = createIndex(idx, (int)Column::Delete, nullptr); @@ -134,7 +134,7 @@ void ExtraBrowsersModel::UpdateItem(Item &item) int idx = item.prevIdx; OBSBasic *main = OBSBasic::Get(); - BrowserDock *dock = reinterpret_cast(main->extraBrowserDocks[idx].get()); + BrowserDock *dock = static_cast(main->extraBrowserDocks[idx].get()); dock->setWindowTitle(item.title); dock->setObjectName(item.title + OBJ_NAME_SUFFIX); @@ -152,9 +152,9 @@ void ExtraBrowsersModel::UpdateItem(Item &item) void ExtraBrowsersModel::DeleteItem() { - QTableView *widget = reinterpret_cast(parent()); + QTableView *widget = static_cast(parent()); - DelButton *del = reinterpret_cast(sender()); + DelButton *del = static_cast(sender()); int row = del->index.row(); /* there's some sort of internal bug in Qt and deleting certain index @@ -211,7 +211,7 @@ void ExtraBrowsersModel::Apply() void ExtraBrowsersModel::TabSelection(bool forward) { - QListView *widget = reinterpret_cast(parent()); + QListView *widget = static_cast(parent()); QItemSelectionModel *selModel = widget->selectionModel(); QModelIndex sel = selModel->currentIndex(); diff --git a/frontend/utility/RemuxEntryPathItemDelegate.cpp b/frontend/utility/RemuxEntryPathItemDelegate.cpp index bcaa43f83bc52c..5073ce0f18f553 100644 --- a/frontend/utility/RemuxEntryPathItemDelegate.cpp +++ b/frontend/utility/RemuxEntryPathItemDelegate.cpp @@ -205,7 +205,7 @@ void RemuxEntryPathItemDelegate::handleClear(QWidget *container) void RemuxEntryPathItemDelegate::updateText() { - QLineEdit *lineEdit = dynamic_cast(sender()); + QLineEdit *lineEdit = static_cast(sender()); QWidget *editor = lineEdit->parentWidget(); emit commitData(editor); } diff --git a/frontend/utility/YoutubeApiWrappers.cpp b/frontend/utility/YoutubeApiWrappers.cpp index 4d1a2a1ea598f4..3d52308422f8e5 100644 --- a/frontend/utility/YoutubeApiWrappers.cpp +++ b/frontend/utility/YoutubeApiWrappers.cpp @@ -41,7 +41,7 @@ bool IsUserSignedIntoYT() { Auth *auth = OBSBasic::Get()->GetAuth(); if (auth) { - YoutubeApiWrappers *apiYouTube(dynamic_cast(auth)); + YoutubeApiWrappers *apiYouTube(qobject_cast(auth)); if (apiYouTube) { return true; } diff --git a/frontend/utility/audio-encoders.cpp b/frontend/utility/audio-encoders.cpp index 8ad2431e3229a4..934632cd3dce81 100644 --- a/frontend/utility/audio-encoders.cpp +++ b/frontend/utility/audio-encoders.cpp @@ -1,8 +1,8 @@ #include "audio-encoders.hpp" +#include #include #include -#include #include #include @@ -65,12 +65,7 @@ static void HandleSampleRate(obs_property_t *prop, const char *id) return; } - auto main = reinterpret_cast(App()->GetMainWindow()); - if (!main) { - blog(LOG_ERROR, "Failed to get main window while populating " - "bitrate map"); - return; - } + OBSBasic *main = OBSBasic::Get(); uint32_t sampleRate = config_get_uint(main->Config(), "Audio", "SampleRate"); diff --git a/frontend/widgets/OBSBasic.cpp b/frontend/widgets/OBSBasic.cpp index 7ce72dbce62312..517fee56155ac2 100644 --- a/frontend/widgets/OBSBasic.cpp +++ b/frontend/widgets/OBSBasic.cpp @@ -2105,7 +2105,7 @@ void OBSBasic::UpdateTitleBar() OBSBasic *OBSBasic::Get() { - return reinterpret_cast(App()->GetMainWindow()); + return static_cast(App()->GetMainWindow()); } void OBSBasic::UpdatePatronJson(const std::string &text, const std::string &error) diff --git a/frontend/widgets/OBSBasic_Clipboard.cpp b/frontend/widgets/OBSBasic_Clipboard.cpp index 8f8207f8265b8d..b828ceb94b2500 100644 --- a/frontend/widgets/OBSBasic_Clipboard.cpp +++ b/frontend/widgets/OBSBasic_Clipboard.cpp @@ -187,7 +187,7 @@ void OBSBasic::SourcePasteFilters(OBSSource source, OBSSource dstSource) void OBSBasic::actionCopyFilters() { - QAction *action = reinterpret_cast(sender()); + QAction *action = static_cast(sender()); obs_source_t *source = action->property("source").value(); if (!source) { @@ -200,7 +200,7 @@ void OBSBasic::actionCopyFilters() void OBSBasic::actionPasteFilters() { - QAction *action = reinterpret_cast(sender()); + QAction *action = static_cast(sender()); obs_source_t *dstSource = action->property("source").value(); if (!dstSource) { diff --git a/frontend/widgets/OBSBasic_ContextToolbar.cpp b/frontend/widgets/OBSBasic_ContextToolbar.cpp index ff16156c2a2fe9..78f0d73cd0ebfe 100644 --- a/frontend/widgets/OBSBasic_ContextToolbar.cpp +++ b/frontend/widgets/OBSBasic_ContextToolbar.cpp @@ -145,10 +145,10 @@ void OBSBasic::UpdateContextBar(bool force) bool updateNeeded = true; QLayoutItem *la = ui->emptySpace->layout()->itemAt(0); if (la) { - if (SourceToolbar *toolbar = dynamic_cast(la->widget())) { + if (SourceToolbar *toolbar = qobject_cast(la->widget())) { if (toolbar->GetSource() == source) updateNeeded = false; - } else if (MediaControls *toolbar = dynamic_cast(la->widget())) { + } else if (MediaControls *toolbar = qobject_cast(la->widget())) { if (toolbar->GetSource() == source) updateNeeded = false; } diff --git a/frontend/widgets/OBSBasic_Docks.cpp b/frontend/widgets/OBSBasic_Docks.cpp index b35839ef0079b5..02bf908667f2b4 100644 --- a/frontend/widgets/OBSBasic_Docks.cpp +++ b/frontend/widgets/OBSBasic_Docks.cpp @@ -237,7 +237,10 @@ void OBSBasic::setDockCornersVertical(bool vertical) void OBSBasic::RepairCustomExtraDockName() { - QDockWidget *dock = reinterpret_cast(sender()); + QDockWidget *dock = qobject_cast(sender()); + if (!dock) { + return; + } int idx = extraCustomDocks.indexOf(dock); QSignalBlocker block(dock); diff --git a/frontend/widgets/OBSBasic_Profiles.cpp b/frontend/widgets/OBSBasic_Profiles.cpp index 0555357011ae7f..f9eb8074a2a395 100644 --- a/frontend/widgets/OBSBasic_Profiles.cpp +++ b/frontend/widgets/OBSBasic_Profiles.cpp @@ -249,8 +249,7 @@ void OBSBasic::DeleteProfile(const QString &name) void OBSBasic::ChangeProfile() { - QAction *action = reinterpret_cast(sender()); - + QAction *action = qobject_cast(sender()); if (!action) { return; } diff --git a/frontend/widgets/OBSBasic_SceneCollections.cpp b/frontend/widgets/OBSBasic_SceneCollections.cpp index 0aa3e6331c8ae6..3d019cda24f295 100644 --- a/frontend/widgets/OBSBasic_SceneCollections.cpp +++ b/frontend/widgets/OBSBasic_SceneCollections.cpp @@ -337,8 +337,7 @@ void OBSBasic::DeleteSceneCollection(const QString &name) void OBSBasic::ChangeSceneCollection() { - QAction *action = reinterpret_cast(sender()); - + QAction *action = qobject_cast(sender()); if (!action) { return; } diff --git a/frontend/widgets/OBSBasic_SceneItems.cpp b/frontend/widgets/OBSBasic_SceneItems.cpp index 7f8c4fec773f85..37e374aa192510 100644 --- a/frontend/widgets/OBSBasic_SceneItems.cpp +++ b/frontend/widgets/OBSBasic_SceneItems.cpp @@ -249,7 +249,11 @@ void OBSBasic::ResetAudioDevice(const char *sourceId, const char *deviceId, cons void OBSBasic::SetDeinterlacingMode() { - QAction *action = reinterpret_cast(sender()); + QAction *action = qobject_cast(sender()); + if (!action) { + return; + } + obs_deinterlace_mode mode = (obs_deinterlace_mode)action->property("mode").toInt(); OBSSceneItem sceneItem = GetCurrentSceneItem(); obs_source_t *source = obs_sceneitem_get_source(sceneItem); @@ -277,7 +281,11 @@ void OBSBasic::SetDeinterlacingMode() void OBSBasic::SetDeinterlacingOrder() { - QAction *action = reinterpret_cast(sender()); + QAction *action = qobject_cast(sender()); + if (!action) { + return; + } + obs_deinterlace_field_order order = (obs_deinterlace_field_order)action->property("order").toInt(); OBSSceneItem sceneItem = GetCurrentSceneItem(); obs_source_t *source = obs_sceneitem_get_source(sceneItem); @@ -343,7 +351,11 @@ QMenu *OBSBasic::AddDeinterlacingMenu(QMenu *menu, obs_source_t *source) void OBSBasic::SetScaleFilter() { - QAction *action = reinterpret_cast(sender()); + QAction *action = qobject_cast(sender()); + if (!action) { + return; + } + obs_scale_type mode = (obs_scale_type)action->property("mode").toInt(); OBSSceneItem sceneItem = GetCurrentSceneItem(); @@ -398,7 +410,11 @@ QMenu *OBSBasic::AddScaleFilteringMenu(QMenu *menu, obs_sceneitem_t *item) void OBSBasic::SetBlendingMethod() { - QAction *action = reinterpret_cast(sender()); + QAction *action = qobject_cast(sender()); + if (!action) { + return; + } + obs_blending_method method = (obs_blending_method)action->property("method").toInt(); OBSSceneItem sceneItem = GetCurrentSceneItem(); @@ -449,7 +465,11 @@ QMenu *OBSBasic::AddBlendingMethodMenu(QMenu *menu, obs_sceneitem_t *item) void OBSBasic::SetBlendingMode() { - QAction *action = reinterpret_cast(sender()); + QAction *action = qobject_cast(sender()); + if (!action) { + return; + } + obs_blending_type mode = (obs_blending_type)action->property("mode").toInt(); OBSSceneItem sceneItem = GetCurrentSceneItem(); @@ -747,7 +767,11 @@ void OBSBasic::CreateSourcePopupMenu(int idx, bool preview) void OBSBasic::actionOpenSourceFilters() { - QAction *action = reinterpret_cast(sender()); + QAction *action = qobject_cast(sender()); + if (!action) { + return; + } + if (!action->property("source").isValid()) { return; } @@ -759,7 +783,11 @@ void OBSBasic::actionOpenSourceFilters() void OBSBasic::actionOpenSourceProperties() { - QAction *action = reinterpret_cast(sender()); + QAction *action = qobject_cast(sender()); + if (!action) { + return; + } + if (!action->property("source").isValid()) { return; } diff --git a/frontend/widgets/OBSBasic_Scenes.cpp b/frontend/widgets/OBSBasic_Scenes.cpp index 2e08b19a582fb3..07a68affcd56ff 100644 --- a/frontend/widgets/OBSBasic_Scenes.cpp +++ b/frontend/widgets/OBSBasic_Scenes.cpp @@ -902,7 +902,7 @@ static void RenameListItem(OBSBasic *parent, QListWidget *listWidget, obs_source void OBSBasic::SceneNameEdited(QWidget *editor) { OBSScene scene = GetCurrentScene(); - QLineEdit *edit = qobject_cast(editor); + QLineEdit *edit = static_cast(editor); string text = edit->text().trimmed().toStdString(); if (!scene) diff --git a/frontend/widgets/OBSBasic_Transitions.cpp b/frontend/widgets/OBSBasic_Transitions.cpp index 235f4e7b8c52ad..6ade5a89df21b7 100644 --- a/frontend/widgets/OBSBasic_Transitions.cpp +++ b/frontend/widgets/OBSBasic_Transitions.cpp @@ -1159,7 +1159,7 @@ void OBSBasic::AddQuickTransitionId(int id) button->setMenu(buttonMenu); connect(button, &QAbstractButton::clicked, this, &OBSBasic::QuickTransitionClicked); - QVBoxLayout *programLayout = reinterpret_cast(programOptions->layout()); + QVBoxLayout *programLayout = static_cast(programOptions->layout()); int idx = 3; for (;; idx++) { @@ -1209,7 +1209,7 @@ void OBSBasic::ClearQuickTransitions() if (!programOptions) return; - QVBoxLayout *programLayout = reinterpret_cast(programOptions->layout()); + QVBoxLayout *programLayout = static_cast(programOptions->layout()); for (int idx = 0;; idx++) { QLayoutItem *item = programLayout->itemAt(idx); @@ -1290,7 +1290,7 @@ void OBSBasic::ClearQuickTransitionWidgets() if (!IsPreviewProgramMode()) return; - QVBoxLayout *programLayout = reinterpret_cast(programOptions->layout()); + QVBoxLayout *programLayout = static_cast(programOptions->layout()); for (int idx = 0;; idx++) { QLayoutItem *item = programLayout->itemAt(idx); @@ -1332,7 +1332,7 @@ void OBSBasic::EnableTransitionWidgets(bool enable) if (!IsPreviewProgramMode()) return; - QVBoxLayout *programLayout = reinterpret_cast(programOptions->layout()); + QVBoxLayout *programLayout = static_cast(programOptions->layout()); for (int idx = 0;; idx++) { QLayoutItem *item = programLayout->itemAt(idx); diff --git a/frontend/widgets/OBSBasic_YouTube.cpp b/frontend/widgets/OBSBasic_YouTube.cpp index 8a2285515b3543..7fc35917cfaf48 100644 --- a/frontend/widgets/OBSBasic_YouTube.cpp +++ b/frontend/widgets/OBSBasic_YouTube.cpp @@ -55,7 +55,7 @@ void OBSBasic::YouTubeActionDialogOk(const std::string &broadcastId, const std:: void OBSBasic::YoutubeStreamCheck(const std::string &key) { - YoutubeApiWrappers *apiYouTube(dynamic_cast(GetAuth())); + YoutubeApiWrappers *apiYouTube(qobject_cast(GetAuth())); if (!apiYouTube) { /* technically we should never get here -Lain */ QMetaObject::invokeMethod(this, "ForceStopStreaming", Qt::QueuedConnection); diff --git a/frontend/wizards/AutoConfigStartPage.cpp b/frontend/wizards/AutoConfigStartPage.cpp index 706123a6fe1b58..235b7d28f1e37c 100644 --- a/frontend/wizards/AutoConfigStartPage.cpp +++ b/frontend/wizards/AutoConfigStartPage.cpp @@ -6,8 +6,6 @@ #include "moc_AutoConfigStartPage.cpp" -#define wiz reinterpret_cast(wizard()) - AutoConfigStartPage::AutoConfigStartPage(QWidget *parent) : QWizardPage(parent), ui(new Ui_AutoConfigStartPage) { ui->setupUi(this); @@ -18,7 +16,7 @@ AutoConfigStartPage::AutoConfigStartPage(QWidget *parent) : QWizardPage(parent), if (main->VCamEnabled()) { QRadioButton *prioritizeVCam = new QRadioButton(QTStr("Basic.AutoConfig.StartPage.PrioritizeVirtualCam"), this); - QBoxLayout *box = reinterpret_cast(layout()); + QBoxLayout *box = static_cast(layout()); box->insertWidget(2, prioritizeVCam); connect(prioritizeVCam, &QPushButton::clicked, this, &AutoConfigStartPage::PrioritizeVCam); @@ -29,20 +27,20 @@ AutoConfigStartPage::~AutoConfigStartPage() {} int AutoConfigStartPage::nextId() const { - return wiz->type == AutoConfig::Type::VirtualCam ? AutoConfig::TestPage : AutoConfig::VideoPage; + return autoConfig()->type == AutoConfig::Type::VirtualCam ? AutoConfig::TestPage : AutoConfig::VideoPage; } void AutoConfigStartPage::on_prioritizeStreaming_clicked() { - wiz->type = AutoConfig::Type::Streaming; + autoConfig()->type = AutoConfig::Type::Streaming; } void AutoConfigStartPage::on_prioritizeRecording_clicked() { - wiz->type = AutoConfig::Type::Recording; + autoConfig()->type = AutoConfig::Type::Recording; } void AutoConfigStartPage::PrioritizeVCam() { - wiz->type = AutoConfig::Type::VirtualCam; + autoConfig()->type = AutoConfig::Type::VirtualCam; } diff --git a/frontend/wizards/AutoConfigStartPage.hpp b/frontend/wizards/AutoConfigStartPage.hpp index 73cff283831887..f6aba93e5e8d4c 100644 --- a/frontend/wizards/AutoConfigStartPage.hpp +++ b/frontend/wizards/AutoConfigStartPage.hpp @@ -1,5 +1,7 @@ #pragma once +#include + #include class Ui_AutoConfigStartPage; @@ -11,6 +13,9 @@ class AutoConfigStartPage : public QWizardPage { std::unique_ptr ui; +protected: + AutoConfig *autoConfig() const { return static_cast(wizard()); } + public: AutoConfigStartPage(QWidget *parent = nullptr); ~AutoConfigStartPage(); diff --git a/frontend/wizards/AutoConfigStreamPage.cpp b/frontend/wizards/AutoConfigStreamPage.cpp index 925b9adfe7e98c..f8ba19d4bafde6 100644 --- a/frontend/wizards/AutoConfigStreamPage.cpp +++ b/frontend/wizards/AutoConfigStreamPage.cpp @@ -23,8 +23,6 @@ enum class ListOpt : int { struct QCef; extern QCef *cef; -#define wiz reinterpret_cast(wizard()) - AutoConfigStreamPage::AutoConfigStreamPage(QWidget *parent) : QWizardPage(parent), ui(new Ui_AutoConfigStreamPage) { ui->setupUi(this); @@ -101,11 +99,13 @@ bool AutoConfigStreamPage::validatePage() { OBSDataAutoRelease service_settings = obs_data_create(); - wiz->customServer = IsCustomService(); + AutoConfig *autoConfig = this->autoConfig(); + + autoConfig->customServer = IsCustomService(); - const char *serverType = wiz->customServer ? "rtmp_custom" : "rtmp_common"; + const char *serverType = autoConfig->customServer ? "rtmp_custom" : "rtmp_common"; - if (!wiz->customServer) { + if (!autoConfig->customServer) { obs_data_set_string(service_settings, "service", QT_TO_UTF8(ui->service->currentText())); } @@ -114,17 +114,17 @@ bool AutoConfigStreamPage::validatePage() int bitrate; if (!ui->doBandwidthTest->isChecked()) { bitrate = ui->bitrate->value(); - wiz->idealBitrate = bitrate; + autoConfig->idealBitrate = bitrate; } else { /* Default test target is 10 Mbps */ bitrate = 10000; #ifdef YOUTUBE_ENABLED - if (IsYouTubeService(wiz->serviceName)) { + if (IsYouTubeService(autoConfig->serviceName)) { /* Adjust upper bound to YouTube limits * for resolutions above 1080p */ - if (wiz->baseResolutionCY > 1440) + if (autoConfig->baseResolutionCY > 1440) bitrate = 51000; - else if (wiz->baseResolutionCY > 1080) + else if (autoConfig->baseResolutionCY > 1080) bitrate = 18000; } #endif @@ -134,50 +134,48 @@ bool AutoConfigStreamPage::validatePage() obs_data_set_int(settings, "bitrate", bitrate); obs_service_apply_encoder_settings(service, settings, nullptr); - if (wiz->customServer) { + if (autoConfig->customServer) { QString server = ui->customServer->text().trimmed(); - const std::string name = server.toStdString(); - wiz->server = name; - wiz->serverName = name; + autoConfig->server = autoConfig->serverName = QT_TO_UTF8(server); } else { - wiz->serverName = ui->server->currentText().toStdString(); - wiz->server = ui->server->currentData().toString().toStdString(); + autoConfig->serverName = QT_TO_UTF8(ui->server->currentText()); + autoConfig->server = QT_TO_UTF8(ui->server->currentData().toString()); } - wiz->bandwidthTest = ui->doBandwidthTest->isChecked(); - wiz->startingBitrate = (int)obs_data_get_int(settings, "bitrate"); - wiz->idealBitrate = wiz->startingBitrate; - wiz->regionUS = ui->regionUS->isChecked(); - wiz->regionEU = ui->regionEU->isChecked(); - wiz->regionAsia = ui->regionAsia->isChecked(); - wiz->regionOther = ui->regionOther->isChecked(); - wiz->serviceName = ui->service->currentText().toStdString(); + autoConfig->bandwidthTest = ui->doBandwidthTest->isChecked(); + autoConfig->startingBitrate = (int)obs_data_get_int(settings, "bitrate"); + autoConfig->idealBitrate = autoConfig->startingBitrate; + autoConfig->regionUS = ui->regionUS->isChecked(); + autoConfig->regionEU = ui->regionEU->isChecked(); + autoConfig->regionAsia = ui->regionAsia->isChecked(); + autoConfig->regionOther = ui->regionOther->isChecked(); + autoConfig->serviceName = QT_TO_UTF8(ui->service->currentText()); if (ui->preferHardware) - wiz->preferHardware = ui->preferHardware->isChecked(); - wiz->key = ui->key->text().toStdString(); + autoConfig->preferHardware = ui->preferHardware->isChecked(); + autoConfig->key = QT_TO_UTF8(ui->key->text()); - if (!wiz->customServer) { - if (wiz->serviceName == "Twitch") - wiz->service = AutoConfig::Service::Twitch; + if (!autoConfig->customServer) { + if (autoConfig->serviceName == "Twitch") + autoConfig->service = AutoConfig::Service::Twitch; #ifdef YOUTUBE_ENABLED - else if (IsYouTubeService(wiz->serviceName)) - wiz->service = AutoConfig::Service::YouTube; + else if (IsYouTubeService(autoConfig->serviceName)) + autoConfig->service = AutoConfig::Service::YouTube; #endif - else if (wiz->serviceName == "Amazon IVS") - wiz->service = AutoConfig::Service::AmazonIVS; + else if (autoConfig->serviceName == "Amazon IVS") + autoConfig->service = AutoConfig::Service::AmazonIVS; else - wiz->service = AutoConfig::Service::Other; + autoConfig->service = AutoConfig::Service::Other; } else { - wiz->service = AutoConfig::Service::Other; + autoConfig->service = AutoConfig::Service::Other; } - if (wiz->service == AutoConfig::Service::Twitch) { - wiz->testMultitrackVideo = ui->useMultitrackVideo->isChecked(); + if (autoConfig->service == AutoConfig::Service::Twitch) { + autoConfig->testMultitrackVideo = ui->useMultitrackVideo->isChecked(); - if (wiz->testMultitrackVideo) { + if (autoConfig->testMultitrackVideo) { std::vector canvases; canvases.emplace_back(obs_get_main_canvas()); - auto postData = constructGoLivePost(QString::fromStdString(wiz->key), std::nullopt, + auto postData = constructGoLivePost(QString::fromStdString(autoConfig->key), std::nullopt, std::nullopt, false, canvases); OBSDataAutoRelease service_settings = obs_service_get_settings(service); @@ -199,7 +197,7 @@ bool AutoConfigStreamPage::validatePage() if (pos != address.npos) address.erase(pos); - wiz->serviceConfigServers.push_back({address, address}); + autoConfig->serviceConfigServers.push_back({address, address}); } int multitrackVideoBitrate = 0; @@ -217,10 +215,10 @@ bool AutoConfigStreamPage::validatePage() } if (multitrackVideoBitrate > 0) { - wiz->startingBitrate = multitrackVideoBitrate; - wiz->idealBitrate = multitrackVideoBitrate; - wiz->multitrackVideo.targetBitrate = multitrackVideoBitrate; - wiz->multitrackVideo.testSuccessful = true; + autoConfig->startingBitrate = multitrackVideoBitrate; + autoConfig->idealBitrate = multitrackVideoBitrate; + autoConfig->multitrackVideo.targetBitrate = multitrackVideoBitrate; + autoConfig->multitrackVideo.testSuccessful = true; } } catch (const MultitrackVideoError & /*err*/) { // FIXME: do something sensible @@ -228,8 +226,8 @@ bool AutoConfigStreamPage::validatePage() } } - if (wiz->service != AutoConfig::Service::Twitch && wiz->service != AutoConfig::Service::YouTube && - wiz->service != AutoConfig::Service::AmazonIVS && wiz->bandwidthTest) { + if (autoConfig->service != AutoConfig::Service::Twitch && autoConfig->service != AutoConfig::Service::YouTube && + autoConfig->service != AutoConfig::Service::AmazonIVS && autoConfig->bandwidthTest) { QMessageBox::StandardButton button; #define WARNING_TEXT(x) QTStr("Basic.AutoConfig.StreamPage.StreamWarning." x) button = OBSMessageBox::question(this, WARNING_TEXT("Title"), WARNING_TEXT("Text")); @@ -255,7 +253,7 @@ void AutoConfigStreamPage::on_show_clicked() void AutoConfigStreamPage::OnOAuthStreamKeyConnected() { - OAuthStreamKey *a = reinterpret_cast(auth.get()); + OAuthStreamKey *a = qobject_cast(auth.get()); if (a) { bool validKey = !a->key().empty(); @@ -281,7 +279,7 @@ void AutoConfigStreamPage::OnOAuthStreamKeyConnected() ui->connectedAccountText->setText(QTStr("Auth.LoadingChannel.Title")); - YoutubeApiWrappers *ytAuth = reinterpret_cast(a); + YoutubeApiWrappers *ytAuth = qobject_cast(a); ChannelDescription cd; if (ytAuth->GetChannelDescription(cd)) { ui->connectedAccountText->setText(cd.title); @@ -395,7 +393,7 @@ void AutoConfigStreamPage::reset_service_ui_fields(std::string &service) { #ifdef YOUTUBE_ENABLED // when account is already connected: - OAuthStreamKey *a = reinterpret_cast(auth.get()); + OAuthStreamKey *a = qobject_cast(auth.get()); if (a && service == a->service() && IsYouTubeService(a->service())) { ui->connectedAccountLabel->setVisible(true); ui->connectedAccountText->setVisible(true); @@ -471,17 +469,19 @@ void AutoConfigStreamPage::ServiceChanged() QTStr("MultitrackVideo.Info").arg(multitrack_video_name, service.c_str())); } + AutoConfig *autoConfig = this->autoConfig(); + ui->multitrackVideoInfo->setVisible(ertmp_multitrack_video_available); ui->useMultitrackVideo->setVisible(ertmp_multitrack_video_available); ui->useMultitrackVideo->setText( QTStr("Basic.AutoConfig.StreamPage.UseMultitrackVideo").arg(multitrack_video_name)); - ui->multitrackVideoInfo->setEnabled(wiz->hardwareEncodingAvailable); - ui->useMultitrackVideo->setEnabled(wiz->hardwareEncodingAvailable); + ui->multitrackVideoInfo->setEnabled(autoConfig->hardwareEncodingAvailable); + ui->useMultitrackVideo->setEnabled(autoConfig->hardwareEncodingAvailable); reset_service_ui_fields(service); /* Test three closest servers if "Auto" is available for Twitch */ - if ((service == "Twitch" && wiz->twitchAuto) || (service == "Amazon IVS" && wiz->amazonIVSAuto)) + if ((service == "Twitch" && autoConfig->twitchAuto) || (service == "Amazon IVS" && autoConfig->amazonIVSAuto)) regionBased = false; ui->streamkeyPageLayout->removeWidget(ui->serverLabel); @@ -504,7 +504,7 @@ void AutoConfigStreamPage::ServiceChanged() ui->serverLabel->setHidden(testBandwidth); } - wiz->testRegions = regionBased && testBandwidth; + autoConfig->testRegions = regionBased && testBandwidth; ui->bitrateLabel->setHidden(testBandwidth); ui->bitrate->setHidden(testBandwidth); @@ -687,7 +687,7 @@ void AutoConfigStreamPage::UpdateCompleted() if (custom) { ready = !ui->customServer->text().isEmpty(); } else { - ready = !wiz->testRegions || ui->regionUS->isChecked() || ui->regionEU->isChecked() || + ready = !autoConfig()->testRegions || ui->regionUS->isChecked() || ui->regionEU->isChecked() || ui->regionAsia->isChecked() || ui->regionOther->isChecked(); } } diff --git a/frontend/wizards/AutoConfigStreamPage.hpp b/frontend/wizards/AutoConfigStreamPage.hpp index 89216c461c67d1..5d4c3eeaa6b232 100644 --- a/frontend/wizards/AutoConfigStreamPage.hpp +++ b/frontend/wizards/AutoConfigStreamPage.hpp @@ -1,5 +1,7 @@ #pragma once +#include + #include class Auth; @@ -24,6 +26,9 @@ class AutoConfigStreamPage : public QWizardPage { void LoadServices(bool showAll); inline bool IsCustomService() const; +protected: + AutoConfig *autoConfig() const { return static_cast(wizard()); } + public: AutoConfigStreamPage(QWidget *parent = nullptr); ~AutoConfigStreamPage(); diff --git a/frontend/wizards/AutoConfigTestPage.cpp b/frontend/wizards/AutoConfigTestPage.cpp index 2ff88e9cafa3dc..4017c030bd6380 100644 --- a/frontend/wizards/AutoConfigTestPage.cpp +++ b/frontend/wizards/AutoConfigTestPage.cpp @@ -27,8 +27,6 @@ #define TEST_RESULT_SE TEST_STR("Result.StreamingEncoder") #define TEST_RESULT_RE TEST_STR("Result.RecordingEncoder") -#define wiz reinterpret_cast(wizard()) - using namespace std; void AutoConfigTestPage::StartBandwidthStage() @@ -52,7 +50,7 @@ void AutoConfigTestPage::StartRecordingEncoderStage() void AutoConfigTestPage::GetServers(std::vector &servers) { OBSDataAutoRelease settings = obs_data_create(); - obs_data_set_string(settings, "service", wiz->serviceName.c_str()); + obs_data_set_string(settings, "service", autoConfig()->serviceName.c_str()); OBSProperties ppts = obs_get_service_properties("rtmp_common"); obs_property_t *p = obs_properties_get(ppts, "service"); @@ -66,7 +64,7 @@ void AutoConfigTestPage::GetServers(std::vector &servers) const char *name = obs_property_list_item_name(p, i); const char *server = obs_property_list_item_string(p, i); - if (wiz->CanTestServer(name)) { + if (autoConfig()->CanTestServer(name)) { ServerInfo info(name, server); servers.push_back(info); } @@ -115,7 +113,7 @@ void AutoConfigTestPage::TestBandwidthThread() /* -----------------------------------*/ /* create obs objects */ - const char *serverType = wiz->customServer ? "rtmp_custom" : "rtmp_common"; + const char *serverType = autoConfig()->customServer ? "rtmp_custom" : "rtmp_common"; OBSEncoderAutoRelease vencoder = obs_video_encoder_create("obs_x264", "test_x264", nullptr, nullptr); OBSEncoderAutoRelease aencoder = obs_audio_encoder_create("ffmpeg_aac", "test_aac", nullptr, 0, nullptr); @@ -136,19 +134,20 @@ void AutoConfigTestPage::TestBandwidthThread() OBSDataAutoRelease aencoder_settings = obs_data_create(); OBSDataAutoRelease output_settings = obs_data_create(); - std::string key = wiz->key; - if (wiz->service == AutoConfig::Service::Twitch || wiz->service == AutoConfig::Service::AmazonIVS) { + std::string key = autoConfig()->key; + if (autoConfig()->service == AutoConfig::Service::Twitch || + autoConfig()->service == AutoConfig::Service::AmazonIVS) { string_depad_key(key); key += "?bandwidthtest"; - } else if (wiz->serviceName == "Restream.io" || wiz->serviceName == "Restream.io - RTMP") { + } else if (autoConfig()->serviceName == "Restream.io" || autoConfig()->serviceName == "Restream.io - RTMP") { string_depad_key(key); key += "?test=true"; } - obs_data_set_string(service_settings, "service", wiz->serviceName.c_str()); + obs_data_set_string(service_settings, "service", autoConfig()->serviceName.c_str()); obs_data_set_string(service_settings, "key", key.c_str()); - obs_data_set_int(vencoder_settings, "bitrate", wiz->startingBitrate); + obs_data_set_int(vencoder_settings, "bitrate", autoConfig()->startingBitrate); obs_data_set_string(vencoder_settings, "rate_control", "CBR"); obs_data_set_string(vencoder_settings, "preset", "veryfast"); obs_data_set_int(vencoder_settings, "keyint_sec", 2); @@ -166,35 +165,36 @@ void AutoConfigTestPage::TestBandwidthThread() /* determine which servers to test */ std::vector servers; - if (wiz->customServer) - servers.emplace_back(wiz->server.c_str(), wiz->server.c_str()); + if (autoConfig()->customServer) + servers.emplace_back(autoConfig()->server.c_str(), autoConfig()->server.c_str()); else GetServers(servers); /* just use the first server if it only has one alternate server, * or if using Restream or Nimo TV due to their "auto" servers */ - if (servers.size() < 3 || wiz->serviceName.substr(0, 11) == "Restream.io" || wiz->serviceName == "Nimo TV") { + if (servers.size() < 3 || autoConfig()->serviceName.substr(0, 11) == "Restream.io" || + autoConfig()->serviceName == "Nimo TV") { servers.resize(1); - } else if ((wiz->service == AutoConfig::Service::Twitch && wiz->twitchAuto) || - (wiz->service == AutoConfig::Service::AmazonIVS && wiz->amazonIVSAuto)) { + } else if ((autoConfig()->service == AutoConfig::Service::Twitch && autoConfig()->twitchAuto) || + (autoConfig()->service == AutoConfig::Service::AmazonIVS && autoConfig()->amazonIVSAuto)) { /* if using Twitch and "Auto" is available, test 3 closest * server */ servers.erase(servers.begin() + 1); servers.resize(3); - } else if (wiz->service == AutoConfig::Service::YouTube) { + } else if (autoConfig()->service == AutoConfig::Service::YouTube) { /* Only test first set of primary + backup servers */ servers.resize(2); } - if (!wiz->serviceConfigServers.empty()) { - if (wiz->service == AutoConfig::Service::Twitch && wiz->twitchAuto) { + if (!autoConfig()->serviceConfigServers.empty()) { + if (autoConfig()->service == AutoConfig::Service::Twitch && autoConfig()->twitchAuto) { // servers from Twitch service config replace the "auto" entry servers.erase(servers.begin()); } - for (auto it = std::rbegin(wiz->serviceConfigServers); it != std::rend(wiz->serviceConfigServers); - it++) { + for (auto it = std::rbegin(autoConfig()->serviceConfigServers); + it != std::rend(autoConfig()->serviceConfigServers); it++) { auto same_server = std::find_if(std::begin(servers), std::end(servers), [&](const ServerInfo &si) { return si.address == it->address; }); @@ -203,7 +203,7 @@ void AutoConfigTestPage::TestBandwidthThread() servers.emplace(std::begin(servers), it->name.c_str(), it->address.c_str()); } - if (wiz->service == AutoConfig::Service::Twitch && wiz->twitchAuto) { + if (autoConfig()->service == AutoConfig::Service::Twitch && autoConfig()->twitchAuto) { // see above, only test 3 servers // rtmps urls are currently counted as separate servers servers.resize(3); @@ -216,8 +216,8 @@ void AutoConfigTestPage::TestBandwidthThread() obs_service_update(service, service_settings); obs_service_apply_encoder_settings(service, vencoder_settings, aencoder_settings); - if (wiz->multitrackVideo.testSuccessful) { - obs_data_set_int(vencoder_settings, "bitrate", wiz->startingBitrate); + if (autoConfig()->multitrackVideo.testSuccessful) { + obs_data_set_int(vencoder_settings, "bitrate", autoConfig()->startingBitrate); } /* -----------------------------------*/ @@ -380,10 +380,11 @@ void AutoConfigTestPage::TestBandwidthThread() int total_bytes = (int)obs_output_get_total_bytes(output) - start_bytes; uint64_t bitrate = util_mul_div64(total_bytes, 8ULL * 1000000000ULL / 1000ULL, total_time); - if (obs_output_get_frames_dropped(output) || (int)bitrate < (wiz->startingBitrate * 75 / 100)) { + if (obs_output_get_frames_dropped(output) || + (int)bitrate < (autoConfig()->startingBitrate * 75 / 100)) { server.bitrate = (int)bitrate * 70 / 100; } else { - server.bitrate = wiz->startingBitrate; + server.bitrate = autoConfig()->startingBitrate; } server.ms = obs_output_get_connect_time_ms(output); @@ -411,9 +412,9 @@ void AutoConfigTestPage::TestBandwidthThread() } } - wiz->server = std::move(bestServer); - wiz->serverName = std::move(bestServerName); - wiz->idealBitrate = bestBitrate; + autoConfig()->server = std::move(bestServer); + autoConfig()->serverName = std::move(bestServerName); + autoConfig()->idealBitrate = bestBitrate; QMetaObject::invokeMethod(this, "NextStage"); } @@ -491,9 +492,9 @@ bool AutoConfigTestPage::TestSoftwareEncoding() OBSDataAutoRelease vencoder_settings = obs_data_create(); obs_data_set_int(aencoder_settings, "bitrate", 32); - if (wiz->type != AutoConfig::Type::Recording) { + if (autoConfig()->type != AutoConfig::Type::Recording) { obs_data_set_int(vencoder_settings, "keyint_sec", 2); - obs_data_set_int(vencoder_settings, "bitrate", wiz->idealBitrate); + obs_data_set_int(vencoder_settings, "bitrate", autoConfig()->idealBitrate); obs_data_set_string(vencoder_settings, "rate_control", "CBR"); obs_data_set_string(vencoder_settings, "profile", "main"); obs_data_set_string(vencoder_settings, "preset", "veryfast"); @@ -537,8 +538,8 @@ bool AutoConfigTestPage::TestSoftwareEncoding() /* -----------------------------------*/ /* calculate starting resolution */ - int baseCX = wiz->baseResolutionCX; - int baseCY = wiz->baseResolutionCY; + int baseCX = autoConfig()->baseResolutionCX; + int baseCY = autoConfig()->baseResolutionCY; CalcBaseRes(baseCX, baseCY); /* -----------------------------------*/ @@ -583,17 +584,17 @@ bool AutoConfigTestPage::TestSoftwareEncoding() return true; if (!fps_num || !fps_den) { - fps_num = wiz->specificFPSNum; - fps_den = wiz->specificFPSDen; + fps_num = autoConfig()->specificFPSNum; + fps_den = autoConfig()->specificFPSDen; } long double fps = ((long double)fps_num / (long double)fps_den); int cx = int(((long double)baseCX / (long double)baseCY) * (long double)cy); - if (!force && wiz->type != AutoConfig::Type::Recording) { + if (!force && autoConfig()->type != AutoConfig::Type::Recording) { int est = EstimateMinBitrate(cx, cy, fps_num, fps_den); - if (est > wiz->idealBitrate) + if (est > autoConfig()->idealBitrate) return true; } @@ -638,7 +639,7 @@ bool AutoConfigTestPage::TestSoftwareEncoding() return !cancel; }; - if (wiz->specificFPSNum && wiz->specificFPSDen) { + if (autoConfig()->specificFPSNum && autoConfig()->specificFPSDen) { count = 7; if (!testRes(2160, 0, 0, false)) return false; @@ -691,7 +692,7 @@ bool AutoConfigTestPage::TestSoftwareEncoding() int minArea = 960 * 540 + 1000; - if (!wiz->specificFPSNum && wiz->preferHighFPS && results.size() > 1) { + if (!autoConfig()->specificFPSNum && autoConfig()->preferHighFPS && results.size() > 1) { Result &result1 = results[0]; Result &result2 = results[1]; @@ -703,26 +704,26 @@ bool AutoConfigTestPage::TestSoftwareEncoding() } Result result = results.front(); - wiz->idealResolutionCX = result.cx; - wiz->idealResolutionCY = result.cy; - wiz->idealFPSNum = result.fps_num; - wiz->idealFPSDen = result.fps_den; + autoConfig()->idealResolutionCX = result.cx; + autoConfig()->idealResolutionCY = result.cy; + autoConfig()->idealFPSNum = result.fps_num; + autoConfig()->idealFPSDen = result.fps_den; long double fUpperBitrate = EstimateUpperBitrate(result.cx, result.cy, result.fps_num, result.fps_den); int upperBitrate = int(floor(fUpperBitrate / 50.0l) * 50.0l); - if (wiz->streamingEncoder != AutoConfig::Encoder::x264) { + if (autoConfig()->streamingEncoder != AutoConfig::Encoder::x264) { upperBitrate *= 114; upperBitrate /= 100; } - if (wiz->testMultitrackVideo && wiz->multitrackVideo.testSuccessful && - !wiz->multitrackVideo.bitrate.has_value()) - wiz->multitrackVideo.bitrate = wiz->idealBitrate; + if (autoConfig()->testMultitrackVideo && autoConfig()->multitrackVideo.testSuccessful && + !autoConfig()->multitrackVideo.bitrate.has_value()) + autoConfig()->multitrackVideo.bitrate = autoConfig()->idealBitrate; - if (wiz->idealBitrate > upperBitrate) - wiz->idealBitrate = upperBitrate; + if (autoConfig()->idealBitrate > upperBitrate) + autoConfig()->idealBitrate = upperBitrate; softwareTested = true; return true; @@ -730,8 +731,8 @@ bool AutoConfigTestPage::TestSoftwareEncoding() void AutoConfigTestPage::FindIdealHardwareResolution() { - int baseCX = wiz->baseResolutionCX; - int baseCY = wiz->baseResolutionCY; + int baseCX = autoConfig()->baseResolutionCX; + int baseCY = autoConfig()->baseResolutionCY; CalcBaseRes(baseCX, baseCY); vector results; @@ -752,8 +753,8 @@ void AutoConfigTestPage::FindIdealHardwareResolution() return; if (!fps_num || !fps_den) { - fps_num = wiz->specificFPSNum; - fps_den = wiz->specificFPSDen; + fps_num = autoConfig()->specificFPSNum; + fps_den = autoConfig()->specificFPSDen; } long double fps = ((long double)fps_num / (long double)fps_den); @@ -764,7 +765,7 @@ void AutoConfigTestPage::FindIdealHardwareResolution() if (!force && rate > maxDataRate) return; - AutoConfig::Encoder encType = wiz->streamingEncoder; + AutoConfig::Encoder encType = autoConfig()->streamingEncoder; bool nvenc = encType == AutoConfig::Encoder::NVENC; int minBitrate = EstimateMinBitrate(cx, cy, fps_num, fps_den); @@ -776,13 +777,13 @@ void AutoConfigTestPage::FindIdealHardwareResolution() if (!nvenc) minBitrate = minBitrate * 114 / 100; - if (wiz->type == AutoConfig::Type::Recording) + if (autoConfig()->type == AutoConfig::Type::Recording) force = true; - if (force || wiz->idealBitrate >= minBitrate) + if (force || autoConfig()->idealBitrate >= minBitrate) results.emplace_back(cx, cy, fps_num, fps_den); }; - if (wiz->specificFPSNum && wiz->specificFPSDen) { + if (autoConfig()->specificFPSNum && autoConfig()->specificFPSDen) { testRes(2160, 0, 0, false); testRes(1440, 0, 0, false); testRes(1080, 0, 0, false); @@ -809,7 +810,7 @@ void AutoConfigTestPage::FindIdealHardwareResolution() int minArea = 960 * 540 + 1000; - if (!wiz->specificFPSNum && wiz->preferHighFPS && results.size() > 1) { + if (!autoConfig()->specificFPSNum && autoConfig()->preferHighFPS && results.size() > 1) { Result &result1 = results[0]; Result &result2 = results[1]; @@ -821,17 +822,17 @@ void AutoConfigTestPage::FindIdealHardwareResolution() } Result result = results.front(); - wiz->idealResolutionCX = result.cx; - wiz->idealResolutionCY = result.cy; - wiz->idealFPSNum = result.fps_num; - wiz->idealFPSDen = result.fps_den; + autoConfig()->idealResolutionCX = result.cx; + autoConfig()->idealResolutionCY = result.cy; + autoConfig()->idealFPSNum = result.fps_num; + autoConfig()->idealFPSDen = result.fps_den; } void AutoConfigTestPage::TestStreamEncoderThread() { - bool preferHardware = wiz->preferHardware; + bool preferHardware = autoConfig()->preferHardware; if (!softwareTested) { - if (!preferHardware || !wiz->hardwareEncodingAvailable) { + if (!preferHardware || !autoConfig()->hardwareEncodingAvailable) { if (!TestSoftwareEncoding()) { return; } @@ -839,29 +840,29 @@ void AutoConfigTestPage::TestStreamEncoderThread() } if (!softwareTested) { - if (wiz->nvencAvailable) - wiz->streamingEncoder = AutoConfig::Encoder::NVENC; - else if (wiz->qsvAvailable) - wiz->streamingEncoder = AutoConfig::Encoder::QSV; - else if (wiz->appleAvailable) - wiz->streamingEncoder = AutoConfig::Encoder::Apple; + if (autoConfig()->nvencAvailable) + autoConfig()->streamingEncoder = AutoConfig::Encoder::NVENC; + else if (autoConfig()->qsvAvailable) + autoConfig()->streamingEncoder = AutoConfig::Encoder::QSV; + else if (autoConfig()->appleAvailable) + autoConfig()->streamingEncoder = AutoConfig::Encoder::Apple; else - wiz->streamingEncoder = AutoConfig::Encoder::AMD; + autoConfig()->streamingEncoder = AutoConfig::Encoder::AMD; } else { - wiz->streamingEncoder = AutoConfig::Encoder::x264; + autoConfig()->streamingEncoder = AutoConfig::Encoder::x264; } #ifdef __linux__ // On linux CBR rate control is not guaranteed so fallback to x264. - if (wiz->streamingEncoder == AutoConfig::Encoder::QSV) { - wiz->streamingEncoder = AutoConfig::Encoder::x264; + if (autoConfig()->streamingEncoder == AutoConfig::Encoder::QSV) { + autoConfig()->streamingEncoder = AutoConfig::Encoder::x264; if (!TestSoftwareEncoding()) { return; } } #endif - if (preferHardware && !softwareTested && wiz->hardwareEncodingAvailable) + if (preferHardware && !softwareTested && autoConfig()->hardwareEncodingAvailable) FindIdealHardwareResolution(); QMetaObject::invokeMethod(this, "NextStage"); @@ -869,36 +870,36 @@ void AutoConfigTestPage::TestStreamEncoderThread() void AutoConfigTestPage::TestRecordingEncoderThread() { - if (!wiz->hardwareEncodingAvailable && !softwareTested) { + if (!autoConfig()->hardwareEncodingAvailable && !softwareTested) { if (!TestSoftwareEncoding()) { return; } } - if (wiz->type == AutoConfig::Type::Recording && wiz->hardwareEncodingAvailable) + if (autoConfig()->type == AutoConfig::Type::Recording && autoConfig()->hardwareEncodingAvailable) FindIdealHardwareResolution(); - wiz->recordingQuality = AutoConfig::Quality::High; + autoConfig()->recordingQuality = AutoConfig::Quality::High; - bool recordingOnly = wiz->type == AutoConfig::Type::Recording; + bool recordingOnly = autoConfig()->type == AutoConfig::Type::Recording; - if (wiz->hardwareEncodingAvailable) { - if (wiz->nvencAvailable) - wiz->recordingEncoder = AutoConfig::Encoder::NVENC; - else if (wiz->qsvAvailable) - wiz->recordingEncoder = AutoConfig::Encoder::QSV; - else if (wiz->appleAvailable) - wiz->recordingEncoder = AutoConfig::Encoder::Apple; + if (autoConfig()->hardwareEncodingAvailable) { + if (autoConfig()->nvencAvailable) + autoConfig()->recordingEncoder = AutoConfig::Encoder::NVENC; + else if (autoConfig()->qsvAvailable) + autoConfig()->recordingEncoder = AutoConfig::Encoder::QSV; + else if (autoConfig()->appleAvailable) + autoConfig()->recordingEncoder = AutoConfig::Encoder::Apple; else - wiz->recordingEncoder = AutoConfig::Encoder::AMD; + autoConfig()->recordingEncoder = AutoConfig::Encoder::AMD; } else { - wiz->recordingEncoder = AutoConfig::Encoder::x264; + autoConfig()->recordingEncoder = AutoConfig::Encoder::x264; } - if (wiz->recordingEncoder != AutoConfig::Encoder::NVENC) { + if (autoConfig()->recordingEncoder != AutoConfig::Encoder::NVENC) { if (!recordingOnly) { - wiz->recordingEncoder = AutoConfig::Encoder::Stream; - wiz->recordingQuality = AutoConfig::Quality::Stream; + autoConfig()->recordingEncoder = AutoConfig::Encoder::Stream; + autoConfig()->recordingQuality = AutoConfig::Quality::Stream; } } @@ -965,21 +966,21 @@ void AutoConfigTestPage::FinalizeResults() return new QLabel(QTStr(str), this); }; - if (wiz->type == AutoConfig::Type::Streaming) { - const char *serverType = wiz->customServer ? "rtmp_custom" : "rtmp_common"; + if (autoConfig()->type == AutoConfig::Type::Streaming) { + const char *serverType = autoConfig()->customServer ? "rtmp_custom" : "rtmp_common"; OBSServiceAutoRelease service = obs_service_create(serverType, "temp_service", nullptr, nullptr); OBSDataAutoRelease service_settings = obs_data_create(); OBSDataAutoRelease vencoder_settings = obs_data_create(); - if (wiz->testMultitrackVideo && wiz->multitrackVideo.testSuccessful && - !wiz->multitrackVideo.bitrate.has_value()) - wiz->multitrackVideo.bitrate = wiz->idealBitrate; + if (autoConfig()->testMultitrackVideo && autoConfig()->multitrackVideo.testSuccessful && + !autoConfig()->multitrackVideo.bitrate.has_value()) + autoConfig()->multitrackVideo.bitrate = autoConfig()->idealBitrate; - obs_data_set_int(vencoder_settings, "bitrate", wiz->idealBitrate); + obs_data_set_int(vencoder_settings, "bitrate", autoConfig()->idealBitrate); - obs_data_set_string(service_settings, "service", wiz->serviceName.c_str()); + obs_data_set_string(service_settings, "service", autoConfig()->serviceName.c_str()); obs_service_update(service, service_settings); obs_service_apply_encoder_settings(service, vencoder_settings, nullptr); @@ -990,51 +991,53 @@ void AutoConfigTestPage::FinalizeResults() obs_service_get_max_fps(service, &maxFPS); if (res_list) { - set_closest_res(wiz->idealResolutionCX, wiz->idealResolutionCY, res_list, res_count); + set_closest_res(autoConfig()->idealResolutionCX, autoConfig()->idealResolutionCY, res_list, + res_count); } if (maxFPS) { - double idealFPS = (double)wiz->idealFPSNum / (double)wiz->idealFPSDen; + double idealFPS = (double)autoConfig()->idealFPSNum / (double)autoConfig()->idealFPSDen; if (idealFPS > (double)maxFPS) { - wiz->idealFPSNum = maxFPS; - wiz->idealFPSDen = 1; + autoConfig()->idealFPSNum = maxFPS; + autoConfig()->idealFPSDen = 1; } } - wiz->idealBitrate = (int)obs_data_get_int(vencoder_settings, "bitrate"); + autoConfig()->idealBitrate = (int)obs_data_get_int(vencoder_settings, "bitrate"); - if (!wiz->customServer) + if (!autoConfig()->customServer) form->addRow(newLabel("Basic.AutoConfig.StreamPage.Service"), - new QLabel(wiz->serviceName.c_str(), ui->finishPage)); + new QLabel(autoConfig()->serviceName.c_str(), ui->finishPage)); form->addRow(newLabel("Basic.AutoConfig.StreamPage.Server"), - new QLabel(wiz->serverName.c_str(), ui->finishPage)); + new QLabel(autoConfig()->serverName.c_str(), ui->finishPage)); form->addRow(newLabel("Basic.Settings.Stream.MultitrackVideoLabel"), - newLabel(wiz->multitrackVideo.testSuccessful ? "Yes" : "No")); + newLabel(autoConfig()->multitrackVideo.testSuccessful ? "Yes" : "No")); - if (wiz->multitrackVideo.testSuccessful) { + if (autoConfig()->multitrackVideo.testSuccessful) { form->addRow(newLabel("Basic.Settings.Output.VideoBitrate"), newLabel("Automatic")); form->addRow(newLabel(TEST_RESULT_SE), newLabel("Automatic")); form->addRow(newLabel("Basic.AutoConfig.TestPage.Result.StreamingResolution"), newLabel("Automatic")); } else { form->addRow(newLabel("Basic.Settings.Output.VideoBitrate"), - new QLabel(QString::number(wiz->idealBitrate), ui->finishPage)); + new QLabel(QString::number(autoConfig()->idealBitrate), ui->finishPage)); form->addRow(newLabel(TEST_RESULT_SE), - new QLabel(encName(wiz->streamingEncoder), ui->finishPage)); + new QLabel(encName(autoConfig()->streamingEncoder), ui->finishPage)); } } - QString baseRes = - QString("%1x%2").arg(QString::number(wiz->baseResolutionCX), QString::number(wiz->baseResolutionCY)); - QString scaleRes = - QString("%1x%2").arg(QString::number(wiz->idealResolutionCX), QString::number(wiz->idealResolutionCY)); + QString baseRes = QString("%1x%2").arg(QString::number(autoConfig()->baseResolutionCX), + QString::number(autoConfig()->baseResolutionCY)); + QString scaleRes = QString("%1x%2").arg(QString::number(autoConfig()->idealResolutionCX), + QString::number(autoConfig()->idealResolutionCY)); - if (wiz->recordingEncoder != AutoConfig::Encoder::Stream || - wiz->recordingQuality != AutoConfig::Quality::Stream) - form->addRow(newLabel(TEST_RESULT_RE), new QLabel(encName(wiz->recordingEncoder), ui->finishPage)); + if (autoConfig()->recordingEncoder != AutoConfig::Encoder::Stream || + autoConfig()->recordingQuality != AutoConfig::Quality::Stream) + form->addRow(newLabel(TEST_RESULT_RE), + new QLabel(encName(autoConfig()->recordingEncoder), ui->finishPage)); QString recQuality; - switch (wiz->recordingQuality) { + switch (autoConfig()->recordingQuality) { case AutoConfig::Quality::High: recQuality = QTStr(QUALITY_HIGH); break; @@ -1045,9 +1048,9 @@ void AutoConfigTestPage::FinalizeResults() form->addRow(newLabel("Basic.Settings.Output.Simple.RecordingQuality"), new QLabel(recQuality, ui->finishPage)); - long double fps = (long double)wiz->idealFPSNum / (long double)wiz->idealFPSDen; + long double fps = (long double)autoConfig()->idealFPSNum / (long double)autoConfig()->idealFPSDen; - QString fpsStr = (wiz->idealFPSDen > 1) ? QString::number(fps, 'f', 2) : QString::number(fps, 'g', 2); + QString fpsStr = (autoConfig()->idealFPSDen > 1) ? QString::number(fps, 'f', 2) : QString::number(fps, 'g', 2); form->addRow(newLabel("Basic.Settings.Video.BaseResolution"), new QLabel(baseRes, ui->finishPage)); form->addRow(newLabel("Basic.Settings.Video.ScaledResolution"), new QLabel(scaleRes, ui->finishPage)); @@ -1075,9 +1078,9 @@ void AutoConfigTestPage::NextStage() started = true; } - if (wiz->type != AutoConfig::Type::Streaming) { + if (autoConfig()->type != AutoConfig::Type::Streaming) { stage = Stage::StreamEncoder; - } else if (!wiz->bandwidthTest) { + } else if (!autoConfig()->bandwidthTest) { stage = Stage::BandwidthTest; } } @@ -1142,11 +1145,11 @@ AutoConfigTestPage::~AutoConfigTestPage() void AutoConfigTestPage::initializePage() { - if (wiz->type == AutoConfig::Type::VirtualCam) { - wiz->idealResolutionCX = wiz->baseResolutionCX; - wiz->idealResolutionCY = wiz->baseResolutionCY; - wiz->idealFPSNum = 30; - wiz->idealFPSDen = 1; + if (autoConfig()->type == AutoConfig::Type::VirtualCam) { + autoConfig()->idealResolutionCX = autoConfig()->baseResolutionCX; + autoConfig()->idealResolutionCY = autoConfig()->baseResolutionCY; + autoConfig()->idealFPSNum = 30; + autoConfig()->idealFPSDen = 1; stage = Stage::Finished; } else { stage = Stage::Starting; diff --git a/frontend/wizards/AutoConfigTestPage.hpp b/frontend/wizards/AutoConfigTestPage.hpp index 5d2d414a67b571..4e85a657ff29f5 100644 --- a/frontend/wizards/AutoConfigTestPage.hpp +++ b/frontend/wizards/AutoConfigTestPage.hpp @@ -1,5 +1,7 @@ #pragma once +#include + #include #include @@ -61,6 +63,9 @@ class AutoConfigTestPage : public QWizardPage { void GetServers(std::vector &servers); +protected: + AutoConfig *autoConfig() const { return static_cast(wizard()); } + public: AutoConfigTestPage(QWidget *parent = nullptr); ~AutoConfigTestPage(); diff --git a/frontend/wizards/AutoConfigVideoPage.cpp b/frontend/wizards/AutoConfigVideoPage.cpp index 69de8e2ecbfa03..19aab14d61ae23 100644 --- a/frontend/wizards/AutoConfigVideoPage.cpp +++ b/frontend/wizards/AutoConfigVideoPage.cpp @@ -15,8 +15,6 @@ #define FPS_PREFER_HIGH_FPS RES_TEXT("FPS.PreferHighFPS") #define FPS_PREFER_HIGH_RES RES_TEXT("FPS.PreferHighRes") -#define wiz reinterpret_cast(wizard()) - AutoConfigVideoPage::AutoConfigVideoPage(QWidget *parent) : QWizardPage(parent), ui(new Ui_AutoConfigVideoPage) { ui->setupUi(this); @@ -85,44 +83,46 @@ AutoConfigVideoPage::~AutoConfigVideoPage() {} int AutoConfigVideoPage::nextId() const { - return wiz->type == AutoConfig::Type::Recording ? AutoConfig::TestPage : AutoConfig::StreamPage; + return autoConfig()->type == AutoConfig::Type::Recording ? AutoConfig::TestPage : AutoConfig::StreamPage; } bool AutoConfigVideoPage::validatePage() { + AutoConfig *autoConfig = this->autoConfig(); + int encRes = ui->canvasRes->currentData().toInt(); - wiz->baseResolutionCX = encRes >> 16; - wiz->baseResolutionCY = encRes & 0xFFFF; - wiz->fpsType = (AutoConfig::FPSType)ui->fps->currentData().toInt(); + autoConfig->baseResolutionCX = encRes >> 16; + autoConfig->baseResolutionCY = encRes & 0xFFFF; + autoConfig->fpsType = (AutoConfig::FPSType)ui->fps->currentData().toInt(); obs_video_info ovi; obs_get_video_info(&ovi); - switch (wiz->fpsType) { + switch (autoConfig->fpsType) { case AutoConfig::FPSType::PreferHighFPS: - wiz->specificFPSNum = 0; - wiz->specificFPSDen = 0; - wiz->preferHighFPS = true; + autoConfig->specificFPSNum = 0; + autoConfig->specificFPSDen = 0; + autoConfig->preferHighFPS = true; break; case AutoConfig::FPSType::PreferHighRes: - wiz->specificFPSNum = 0; - wiz->specificFPSDen = 0; - wiz->preferHighFPS = false; + autoConfig->specificFPSNum = 0; + autoConfig->specificFPSDen = 0; + autoConfig->preferHighFPS = false; break; case AutoConfig::FPSType::UseCurrent: - wiz->specificFPSNum = ovi.fps_num; - wiz->specificFPSDen = ovi.fps_den; - wiz->preferHighFPS = false; + autoConfig->specificFPSNum = ovi.fps_num; + autoConfig->specificFPSDen = ovi.fps_den; + autoConfig->preferHighFPS = false; break; case AutoConfig::FPSType::fps30: - wiz->specificFPSNum = 30; - wiz->specificFPSDen = 1; - wiz->preferHighFPS = false; + autoConfig->specificFPSNum = 30; + autoConfig->specificFPSDen = 1; + autoConfig->preferHighFPS = false; break; case AutoConfig::FPSType::fps60: - wiz->specificFPSNum = 60; - wiz->specificFPSDen = 1; - wiz->preferHighFPS = false; + autoConfig->specificFPSNum = 60; + autoConfig->specificFPSDen = 1; + autoConfig->preferHighFPS = false; break; } diff --git a/frontend/wizards/AutoConfigVideoPage.hpp b/frontend/wizards/AutoConfigVideoPage.hpp index b6a441d2c48d5a..8fc0f392f425d5 100644 --- a/frontend/wizards/AutoConfigVideoPage.hpp +++ b/frontend/wizards/AutoConfigVideoPage.hpp @@ -1,5 +1,7 @@ #pragma once +#include + #include class Ui_AutoConfigVideoPage; @@ -11,6 +13,9 @@ class AutoConfigVideoPage : public QWizardPage { std::unique_ptr ui; +protected: + AutoConfig *autoConfig() const { return static_cast(wizard()); } + public: AutoConfigVideoPage(QWidget *parent = nullptr); ~AutoConfigVideoPage(); diff --git a/shared/properties-view/properties-view.cpp b/shared/properties-view/properties-view.cpp index c47758ac63275c..d5026d4a725948 100644 --- a/shared/properties-view/properties-view.cpp +++ b/shared/properties-view/properties-view.cpp @@ -1909,7 +1909,7 @@ void WidgetInfo::GroupChanged(const char *setting) void WidgetInfo::EditableListChanged() { const char *setting = obs_property_name(property); - QListWidget *list = reinterpret_cast(widget); + QListWidget *list = static_cast(widget); OBSDataArrayAutoRelease array = obs_data_array_create(); for (int i = 0; i < list->count(); i++) { @@ -1958,7 +1958,7 @@ void WidgetInfo::ButtonClicked() void WidgetInfo::TogglePasswordText(bool show) { - reinterpret_cast(widget)->setEchoMode(show ? QLineEdit::Normal : QLineEdit::Password); + static_cast(widget)->setEchoMode(show ? QLineEdit::Normal : QLineEdit::Password); } void WidgetInfo::ControlChanged() @@ -2151,7 +2151,7 @@ void WidgetInfo::EditListAdd() void WidgetInfo::EditListAddText() { - QListWidget *list = reinterpret_cast(widget); + QListWidget *list = static_cast(widget); const char *desc = obs_property_description(property); EditableItemDialog dialog(widget->window(), QString(), false); @@ -2173,7 +2173,7 @@ void WidgetInfo::EditListAddText() void WidgetInfo::EditListAddFiles() { - QListWidget *list = reinterpret_cast(widget); + QListWidget *list = static_cast(widget); const char *desc = obs_property_description(property); const char *filter = obs_property_editable_list_filter(property); const char *default_path = obs_property_editable_list_default_path(property); @@ -2200,7 +2200,7 @@ void WidgetInfo::EditListAddFiles() void WidgetInfo::EditListAddDir() { - QListWidget *list = reinterpret_cast(widget); + QListWidget *list = static_cast(widget); const char *desc = obs_property_description(property); const char *default_path = obs_property_editable_list_default_path(property); @@ -2224,7 +2224,7 @@ void WidgetInfo::EditListAddDir() void WidgetInfo::EditListRemove() { - QListWidget *list = reinterpret_cast(widget); + QListWidget *list = static_cast(widget); QList items = list->selectedItems(); for (QListWidgetItem *item : items) @@ -2234,7 +2234,7 @@ void WidgetInfo::EditListRemove() void WidgetInfo::EditListEdit() { - QListWidget *list = reinterpret_cast(widget); + QListWidget *list = static_cast(widget); enum obs_editable_list_type type = obs_property_editable_list_type(property); const char *desc = obs_property_description(property); const char *filter = obs_property_editable_list_filter(property); @@ -2278,7 +2278,7 @@ void WidgetInfo::EditListEdit() void WidgetInfo::EditListUp() { - QListWidget *list = reinterpret_cast(widget); + QListWidget *list = static_cast(widget); int lastItemRow = -1; for (int i = 0; i < list->count(); i++) { @@ -2303,7 +2303,7 @@ void WidgetInfo::EditListUp() void WidgetInfo::EditListDown() { - QListWidget *list = reinterpret_cast(widget); + QListWidget *list = static_cast(widget); int lastItemRow = list->count(); for (int i = list->count() - 1; i >= 0; i--) { diff --git a/shared/qt/idian/include/Idian/StateEventFilter.cpp b/shared/qt/idian/include/Idian/StateEventFilter.cpp index 9fca1f6a56b5a7..8243ee918bed84 100644 --- a/shared/qt/idian/include/Idian/StateEventFilter.cpp +++ b/shared/qt/idian/include/Idian/StateEventFilter.cpp @@ -37,7 +37,7 @@ bool StateEventFilter::eventFilter(QObject *obj, QEvent *event) return QObject::eventFilter(obj, event); } - QWidget *widget = qobject_cast(obj); + QWidget *widget = static_cast(obj); QFocusEvent *focusEvent = nullptr; bool updateIconColors = true; From 0d70b719023762e9f198d7afb2fea129c3506c32 Mon Sep 17 00:00:00 2001 From: Warchamp7 Date: Mon, 18 May 2026 16:38:45 -0400 Subject: [PATCH 2/3] squashme: Add fixme notes --- frontend/components/VolumeControl.cpp | 2 ++ .../importer/ImporterEntryPathItemDelegate.cpp | 2 ++ frontend/utility/ExtraBrowsersModel.cpp | 3 +++ frontend/utility/RemuxEntryPathItemDelegate.cpp | 2 ++ frontend/widgets/OBSBasic_Clipboard.cpp | 4 ++++ frontend/widgets/OBSBasic_Docks.cpp | 2 ++ frontend/widgets/OBSBasic_Profiles.cpp | 2 ++ frontend/widgets/OBSBasic_SceneCollections.cpp | 2 ++ frontend/widgets/OBSBasic_SceneItems.cpp | 16 ++++++++++++++++ 9 files changed, 35 insertions(+) diff --git a/frontend/components/VolumeControl.cpp b/frontend/components/VolumeControl.cpp index 47696de0353ece..bb927341981d98 100644 --- a/frontend/components/VolumeControl.cpp +++ b/frontend/components/VolumeControl.cpp @@ -505,6 +505,8 @@ void VolumeControl::showVolumeControlMenu(QPoint pos) void VolumeControl::renameSource() { + // FIXME: https://github.com/obsproject/obs-studio/issues/13444 + // sender() is a brittle and outdated way to work with signals/slots. QAction *action = qobject_cast(sender()); if (!action) { return; diff --git a/frontend/importer/ImporterEntryPathItemDelegate.cpp b/frontend/importer/ImporterEntryPathItemDelegate.cpp index 726a8167143357..047e565e20c674 100644 --- a/frontend/importer/ImporterEntryPathItemDelegate.cpp +++ b/frontend/importer/ImporterEntryPathItemDelegate.cpp @@ -154,6 +154,8 @@ void ImporterEntryPathItemDelegate::handleClear(QWidget *container) void ImporterEntryPathItemDelegate::updateText() { + // FIXME: https://github.com/obsproject/obs-studio/issues/13444 + // sender() is a brittle and outdated way to work with signals/slots. QLineEdit *lineEdit = static_cast(sender()); QWidget *editor = lineEdit->parentWidget(); emit commitData(editor); diff --git a/frontend/utility/ExtraBrowsersModel.cpp b/frontend/utility/ExtraBrowsersModel.cpp index 89d294856ac689..059094e577f49c 100644 --- a/frontend/utility/ExtraBrowsersModel.cpp +++ b/frontend/utility/ExtraBrowsersModel.cpp @@ -152,8 +152,11 @@ void ExtraBrowsersModel::UpdateItem(Item &item) void ExtraBrowsersModel::DeleteItem() { + // This is brittle and should be moved up to the caller when the sender() usage is cleaned up. QTableView *widget = static_cast(parent()); + // FIXME: https://github.com/obsproject/obs-studio/issues/13444 + // sender() is a brittle and outdated way to work with signals/slots. DelButton *del = static_cast(sender()); int row = del->index.row(); diff --git a/frontend/utility/RemuxEntryPathItemDelegate.cpp b/frontend/utility/RemuxEntryPathItemDelegate.cpp index 5073ce0f18f553..c115b8269db8b6 100644 --- a/frontend/utility/RemuxEntryPathItemDelegate.cpp +++ b/frontend/utility/RemuxEntryPathItemDelegate.cpp @@ -205,6 +205,8 @@ void RemuxEntryPathItemDelegate::handleClear(QWidget *container) void RemuxEntryPathItemDelegate::updateText() { + // FIXME: https://github.com/obsproject/obs-studio/issues/13444 + // sender() is a brittle and outdated way to work with signals/slots. QLineEdit *lineEdit = static_cast(sender()); QWidget *editor = lineEdit->parentWidget(); emit commitData(editor); diff --git a/frontend/widgets/OBSBasic_Clipboard.cpp b/frontend/widgets/OBSBasic_Clipboard.cpp index b828ceb94b2500..1306cc023337b9 100644 --- a/frontend/widgets/OBSBasic_Clipboard.cpp +++ b/frontend/widgets/OBSBasic_Clipboard.cpp @@ -187,6 +187,8 @@ void OBSBasic::SourcePasteFilters(OBSSource source, OBSSource dstSource) void OBSBasic::actionCopyFilters() { + // FIXME: https://github.com/obsproject/obs-studio/issues/13444 + // sender() is a brittle and outdated way to work with signals/slots. QAction *action = static_cast(sender()); obs_source_t *source = action->property("source").value(); @@ -200,6 +202,8 @@ void OBSBasic::actionCopyFilters() void OBSBasic::actionPasteFilters() { + // FIXME: https://github.com/obsproject/obs-studio/issues/13444 + // sender() is a brittle and outdated way to work with signals/slots. QAction *action = static_cast(sender()); obs_source_t *dstSource = action->property("source").value(); diff --git a/frontend/widgets/OBSBasic_Docks.cpp b/frontend/widgets/OBSBasic_Docks.cpp index 02bf908667f2b4..f4c1ea9e15c4fc 100644 --- a/frontend/widgets/OBSBasic_Docks.cpp +++ b/frontend/widgets/OBSBasic_Docks.cpp @@ -237,6 +237,8 @@ void OBSBasic::setDockCornersVertical(bool vertical) void OBSBasic::RepairCustomExtraDockName() { + // FIXME: https://github.com/obsproject/obs-studio/issues/13444 + // sender() is a brittle and outdated way to work with signals/slots. QDockWidget *dock = qobject_cast(sender()); if (!dock) { return; diff --git a/frontend/widgets/OBSBasic_Profiles.cpp b/frontend/widgets/OBSBasic_Profiles.cpp index f9eb8074a2a395..1c7e8208ce6504 100644 --- a/frontend/widgets/OBSBasic_Profiles.cpp +++ b/frontend/widgets/OBSBasic_Profiles.cpp @@ -249,6 +249,8 @@ void OBSBasic::DeleteProfile(const QString &name) void OBSBasic::ChangeProfile() { + // FIXME: https://github.com/obsproject/obs-studio/issues/13444 + // sender() is a brittle and outdated way to work with signals/slots. QAction *action = qobject_cast(sender()); if (!action) { return; diff --git a/frontend/widgets/OBSBasic_SceneCollections.cpp b/frontend/widgets/OBSBasic_SceneCollections.cpp index 3d019cda24f295..838afb1e8d7acf 100644 --- a/frontend/widgets/OBSBasic_SceneCollections.cpp +++ b/frontend/widgets/OBSBasic_SceneCollections.cpp @@ -337,6 +337,8 @@ void OBSBasic::DeleteSceneCollection(const QString &name) void OBSBasic::ChangeSceneCollection() { + // FIXME: https://github.com/obsproject/obs-studio/issues/13444 + // sender() is a brittle and outdated way to work with signals/slots. QAction *action = qobject_cast(sender()); if (!action) { return; diff --git a/frontend/widgets/OBSBasic_SceneItems.cpp b/frontend/widgets/OBSBasic_SceneItems.cpp index 37e374aa192510..8409529a19e6fd 100644 --- a/frontend/widgets/OBSBasic_SceneItems.cpp +++ b/frontend/widgets/OBSBasic_SceneItems.cpp @@ -249,6 +249,8 @@ void OBSBasic::ResetAudioDevice(const char *sourceId, const char *deviceId, cons void OBSBasic::SetDeinterlacingMode() { + // FIXME: https://github.com/obsproject/obs-studio/issues/13444 + // sender() is a brittle and outdated way to work with signals/slots. QAction *action = qobject_cast(sender()); if (!action) { return; @@ -281,6 +283,8 @@ void OBSBasic::SetDeinterlacingMode() void OBSBasic::SetDeinterlacingOrder() { + // FIXME: https://github.com/obsproject/obs-studio/issues/13444 + // sender() is a brittle and outdated way to work with signals/slots. QAction *action = qobject_cast(sender()); if (!action) { return; @@ -351,6 +355,8 @@ QMenu *OBSBasic::AddDeinterlacingMenu(QMenu *menu, obs_source_t *source) void OBSBasic::SetScaleFilter() { + // FIXME: https://github.com/obsproject/obs-studio/issues/13444 + // sender() is a brittle and outdated way to work with signals/slots. QAction *action = qobject_cast(sender()); if (!action) { return; @@ -410,6 +416,8 @@ QMenu *OBSBasic::AddScaleFilteringMenu(QMenu *menu, obs_sceneitem_t *item) void OBSBasic::SetBlendingMethod() { + // FIXME: https://github.com/obsproject/obs-studio/issues/13444 + // sender() is a brittle and outdated way to work with signals/slots. QAction *action = qobject_cast(sender()); if (!action) { return; @@ -465,6 +473,8 @@ QMenu *OBSBasic::AddBlendingMethodMenu(QMenu *menu, obs_sceneitem_t *item) void OBSBasic::SetBlendingMode() { + // FIXME: https://github.com/obsproject/obs-studio/issues/13444 + // sender() is a brittle and outdated way to work with signals/slots. QAction *action = qobject_cast(sender()); if (!action) { return; @@ -767,6 +777,8 @@ void OBSBasic::CreateSourcePopupMenu(int idx, bool preview) void OBSBasic::actionOpenSourceFilters() { + // FIXME: https://github.com/obsproject/obs-studio/issues/13444 + // sender() is a brittle and outdated way to work with signals/slots. QAction *action = qobject_cast(sender()); if (!action) { return; @@ -783,6 +795,8 @@ void OBSBasic::actionOpenSourceFilters() void OBSBasic::actionOpenSourceProperties() { + // FIXME: https://github.com/obsproject/obs-studio/issues/13444 + // sender() is a brittle and outdated way to work with signals/slots. QAction *action = qobject_cast(sender()); if (!action) { return; @@ -823,6 +837,8 @@ static inline bool should_show_properties(obs_source_t *source, const char *id) void OBSBasic::AddSourceDialog() { + // FIXME: https://github.com/obsproject/obs-studio/issues/13444 + // sender() is a brittle and outdated way to work with signals/slots. QAction *action = qobject_cast(sender()); if (!action) { return; From c788f7f5ffe658fd4d662a9b2f18d0a45eeb1df7 Mon Sep 17 00:00:00 2001 From: Warchamp7 Date: Mon, 18 May 2026 16:39:42 -0400 Subject: [PATCH 3/3] squashme: Fix source tree model cast SourceTree is designed for SourceTreeModel and should avoid using any other model. Enforce this on the SourceTree itself --- frontend/components/SourceTree.cpp | 90 ++++++++++++-------------- frontend/components/SourceTree.hpp | 21 +++--- frontend/components/SourceTreeItem.cpp | 4 +- 3 files changed, 56 insertions(+), 59 deletions(-) diff --git a/frontend/components/SourceTree.cpp b/frontend/components/SourceTree.cpp index e1d5f3f283315f..3eb8dd9f6f88e9 100644 --- a/frontend/components/SourceTree.cpp +++ b/frontend/components/SourceTree.cpp @@ -41,30 +41,32 @@ SourceTree::SourceTree(QWidget *parent_) : QListView(parent_) setItemDelegate(new SourceTreeDelegate(this)); } +void SourceTree::setModel(SourceTreeModel *model) +{ + treeModel = model; + QListView::setModel(model); +} + void SourceTree::UpdateIcons() { - SourceTreeModel *stm = GetStm(); - stm->SceneChanged(); + model()->SceneChanged(); } void SourceTree::SetIconsVisible(bool visible) { - SourceTreeModel *stm = GetStm(); - iconsVisible = visible; - stm->SceneChanged(); + model()->SceneChanged(); } void SourceTree::ResetWidgets() { OBSScene scene = GetCurrentScene(); - SourceTreeModel *stm = GetStm(); - stm->UpdateGroupState(false); + model()->UpdateGroupState(false); - for (int i = 0; i < stm->items.count(); i++) { - QModelIndex index = stm->createIndex(i, 0, nullptr); - setIndexWidget(index, new SourceTreeItem(this, stm->items[i])); + for (int i = 0; i < model()->items.count(); i++) { + QModelIndex index = model()->createIndex(i, 0, nullptr); + setIndexWidget(index, new SourceTreeItem(this, model()->items[i])); } } @@ -75,14 +77,12 @@ void SourceTree::UpdateWidget(const QModelIndex &idx, obs_sceneitem_t *item) void SourceTree::UpdateWidgets(bool force) { - SourceTreeModel *stm = GetStm(); - - for (int i = 0; i < stm->items.size(); i++) { - obs_sceneitem_t *item = stm->items[i]; + for (int i = 0; i < model()->items.size(); i++) { + obs_sceneitem_t *item = model()->items[i]; SourceTreeItem *widget = GetItemWidget(i); if (!widget) { - UpdateWidget(stm->createIndex(i, 0), item); + UpdateWidget(model()->createIndex(i, 0), item); } else { widget->Update(force); } @@ -91,18 +91,17 @@ void SourceTree::UpdateWidgets(bool force) void SourceTree::SelectItem(obs_sceneitem_t *sceneitem, bool select) { - SourceTreeModel *stm = GetStm(); int i = 0; - for (; i < stm->items.count(); i++) { - if (stm->items[i] == sceneitem) + for (; i < model()->items.count(); i++) { + if (model()->items[i] == sceneitem) break; } - if (i == stm->items.count()) + if (i == model()->items.count()) return; - QModelIndex index = stm->createIndex(i, 0); + QModelIndex index = model()->createIndex(i, 0); if (index.isValid() && select != selectionModel()->isSelected(index)) selectionModel()->select(index, select ? QItemSelectionModel::Select : QItemSelectionModel::Deselect); } @@ -124,8 +123,8 @@ void SourceTree::dropEvent(QDropEvent *event) OBSScene scene = GetCurrentScene(); obs_source_t *scenesource = obs_scene_get_source(scene); - SourceTreeModel *stm = GetStm(); - auto &items = stm->items; + + auto &items = model()->items; QModelIndexList indices = selectedIndexes(); DropIndicatorPosition indicator = dropIndicatorPosition(); @@ -172,7 +171,7 @@ void SourceTree::dropEvent(QDropEvent *event) indicator == QAbstractItemView::OnViewport) row++; - if (row < 0 || row > stm->items.count()) { + if (row < 0 || row > model()->items.count()) { QListView::dropEvent(event); return; } @@ -194,10 +193,10 @@ void SourceTree::dropEvent(QDropEvent *event) /* below another group */ obs_sceneitem_t *itemBelow; - if (row == stm->items.count()) + if (row == model()->items.count()) itemBelow = nullptr; else - itemBelow = stm->items[row]; + itemBelow = model()->items[row]; if (hasGroups) { if (!itemBelow || obs_sceneitem_get_group(scene, itemBelow) != dropGroup) { @@ -253,7 +252,7 @@ void SourceTree::dropEvent(QDropEvent *event) obs_sceneitem_t *subitemGroup = obs_sceneitem_get_group(scene, subitem); if (subitemGroup == item) { - QModelIndex idx = stm->createIndex(j, 0); + QModelIndex idx = model()->createIndex(j, 0); indices.insert(i + 1, idx); } } @@ -283,9 +282,9 @@ void SourceTree::dropEvent(QDropEvent *event) itemTo--; if (itemTo != from) { - stm->beginMoveRows(QModelIndex(), from, from, QModelIndex(), to); + model()->beginMoveRows(QModelIndex(), from, from, QModelIndex(), to); MoveItem(items, from, itemTo); - stm->endMoveRows(); + model()->endMoveRows(); } r = persistentIdx.row() + 1; @@ -397,9 +396,9 @@ void SourceTree::dropEvent(QDropEvent *event) /* group */ if (dropOnCollapsed) { - stm->beginRemoveRows(QModelIndex(), firstIdx, lastIdx); + model()->beginRemoveRows(QModelIndex(), firstIdx, lastIdx); items.remove(firstIdx, lastIdx - firstIdx + 1); - stm->endRemoveRows(); + model()->endRemoveRows(); } /* --------------------------------------- */ @@ -423,19 +422,18 @@ void SourceTree::selectionChanged(const QItemSelection &selected, const QItemSel { QSignalBlocker sourcesSignalBlocker(this); - SourceTreeModel *stm = GetStm(); QModelIndexList selectedIdxs = selected.indexes(); QModelIndexList deselectedIdxs = deselected.indexes(); for (int i = 0; i < selectedIdxs.count(); i++) { int idx = selectedIdxs[i].row(); - obs_sceneitem_select(stm->items[idx], true); + obs_sceneitem_select(model()->items[idx], true); } for (int i = 0; i < deselectedIdxs.count(); i++) { int idx = deselectedIdxs[i].row(); - obs_sceneitem_select(stm->items[idx], false); + obs_sceneitem_select(model()->items[idx], false); } OBSBasic::Get()->UpdateContextBarDeferred(); @@ -480,11 +478,11 @@ void SourceTree::NewGroupEdit(int row) bool SourceTree::Edit(int row) { - SourceTreeModel *stm = GetStm(); - if (row < 0 || row >= stm->items.count()) + if (row < 0 || row >= model()->items.count()) { return false; + } - QModelIndex index = stm->createIndex(row, 0); + QModelIndex index = model()->createIndex(row, 0); QWidget *widget = indexWidget(index); SourceTreeItem *itemWidget = static_cast(widget); if (itemWidget->IsEditing()) { @@ -501,7 +499,6 @@ bool SourceTree::Edit(int row) bool SourceTree::MultipleBaseSelected() const { - SourceTreeModel *stm = GetStm(); QModelIndexList selectedIndices = selectedIndexes(); OBSScene scene = GetCurrentScene(); @@ -511,7 +508,7 @@ bool SourceTree::MultipleBaseSelected() const } for (auto &idx : selectedIndices) { - obs_sceneitem_t *item = stm->items[idx.row()]; + obs_sceneitem_t *item = model()->items[idx.row()]; if (obs_sceneitem_is_group(item)) { return false; } @@ -527,7 +524,6 @@ bool SourceTree::MultipleBaseSelected() const bool SourceTree::GroupsSelected() const { - SourceTreeModel *stm = GetStm(); QModelIndexList selectedIndices = selectedIndexes(); OBSScene scene = GetCurrentScene(); @@ -537,7 +533,7 @@ bool SourceTree::GroupsSelected() const } for (auto &idx : selectedIndices) { - obs_sceneitem_t *item = stm->items[idx.row()]; + obs_sceneitem_t *item = model()->items[idx.row()]; if (!obs_sceneitem_is_group(item)) { return false; } @@ -548,7 +544,6 @@ bool SourceTree::GroupsSelected() const bool SourceTree::GroupedItemsSelected() const { - SourceTreeModel *stm = GetStm(); QModelIndexList selectedIndices = selectedIndexes(); OBSScene scene = GetCurrentScene(); @@ -557,7 +552,7 @@ bool SourceTree::GroupedItemsSelected() const } for (auto &idx : selectedIndices) { - obs_sceneitem_t *item = stm->items[idx.row()]; + obs_sceneitem_t *item = model()->items[idx.row()]; obs_scene *itemScene = obs_sceneitem_get_scene(item); if (itemScene != scene) { @@ -571,7 +566,7 @@ bool SourceTree::GroupedItemsSelected() const void SourceTree::Remove(OBSSceneItem item, OBSScene scene) { OBSBasic *main = OBSBasic::Get(); - GetStm()->Remove(item); + model()->Remove(item); main->SaveProject(); if (!main->SavingDisabled()) { @@ -586,18 +581,18 @@ void SourceTree::GroupSelectedItems() { QModelIndexList indices = selectedIndexes(); std::sort(indices.begin(), indices.end()); - GetStm()->GroupSelectedItems(indices); + model()->GroupSelectedItems(indices); } void SourceTree::UngroupSelectedGroups() { QModelIndexList indices = selectedIndexes(); - GetStm()->UngroupSelectedGroups(indices); + model()->UngroupSelectedGroups(indices); } void SourceTree::AddGroup() { - GetStm()->AddGroup(); + model()->AddGroup(); } void SourceTree::UpdateNoSourcesMessage() @@ -615,8 +610,7 @@ void SourceTree::UpdateNoSourcesMessage() void SourceTree::paintEvent(QPaintEvent *event) { - SourceTreeModel *stm = GetStm(); - if (stm && !stm->items.count()) { + if (model() && !model()->items.count()) { QPainter p(viewport()); if (!textPrepared) { diff --git a/frontend/components/SourceTree.hpp b/frontend/components/SourceTree.hpp index 2bc89b1c70c6c2..de60da2d79ff25 100644 --- a/frontend/components/SourceTree.hpp +++ b/frontend/components/SourceTree.hpp @@ -21,6 +21,8 @@ class SourceTree : public QListView { OBSData undoSceneData; + SourceTreeModel *treeModel; + bool iconsVisible = true; void UpdateNoSourcesMessage(); @@ -29,23 +31,24 @@ class SourceTree : public QListView { void UpdateWidget(const QModelIndex &idx, obs_sceneitem_t *item); void UpdateWidgets(bool force = false); - inline SourceTreeModel *GetStm() const { return static_cast(model()); } - public: inline SourceTreeItem *GetItemWidget(int idx) { - QWidget *widget = indexWidget(GetStm()->createIndex(idx, 0)); + QWidget *widget = indexWidget(model()->createIndex(idx, 0)); return static_cast(widget); } explicit SourceTree(QWidget *parent = nullptr); + void setModel(SourceTreeModel *model); + SourceTreeModel *model() const { return treeModel; } + inline bool IgnoreReorder() const { return ignoreReorder; } - inline void Clear() { GetStm()->Clear(); } + inline void Clear() { model()->Clear(); } - inline void Add(obs_sceneitem_t *item) { GetStm()->Add(item); } - inline OBSSceneItem Get(int idx) { return GetStm()->Get(idx); } - inline QString GetNewGroupName() { return GetStm()->GetNewGroupName(); } + inline void Add(obs_sceneitem_t *item) { model()->Add(item); } + inline OBSSceneItem Get(int idx) { return model()->Get(idx); } + inline QString GetNewGroupName() { return model()->GetNewGroupName(); } void SelectItem(obs_sceneitem_t *sceneitem, bool select); @@ -57,8 +60,8 @@ class SourceTree : public QListView { void SetIconsVisible(bool visible); public slots: - inline void ReorderItems() { GetStm()->ReorderItems(); } - inline void RefreshItems() { GetStm()->SceneChanged(); } + inline void ReorderItems() { model()->ReorderItems(); } + inline void RefreshItems() { model()->SceneChanged(); } void Remove(OBSSceneItem item, OBSScene scene); void GroupSelectedItems(); void UngroupSelectedGroups(); diff --git a/frontend/components/SourceTreeItem.cpp b/frontend/components/SourceTreeItem.cpp index 35d2d9256c0a63..ef1bad228f7d52 100644 --- a/frontend/components/SourceTreeItem.cpp +++ b/frontend/components/SourceTreeItem.cpp @@ -555,9 +555,9 @@ void SourceTreeItem::ExpandClicked(bool checked) obs_data_set_bool(data, "collapsed", checked); if (!checked) - tree->GetStm()->ExpandGroup(sceneitem); + tree->model()->ExpandGroup(sceneitem); else - tree->GetStm()->CollapseGroup(sceneitem); + tree->model()->CollapseGroup(sceneitem); } void SourceTreeItem::Select()