From 9917fca64d4c802c3436e69ec7c61add20ef3efb Mon Sep 17 00:00:00 2001 From: Vekhir Date: Thu, 9 Apr 2026 00:26:08 +0200 Subject: [PATCH 1/3] feat: New podcast preferences dialog The new podcast preferences dialog replaces the small checkbox list. It allows direct adjustment of audio recording device, bit rate, and frame rate. For each profile of "Full", "Medium", and "Small", the bit rate, frame rate and video size are reported based on the chosen settings. The dialog is based off the recently added color preferences dialog. Each profile has its own tab. The selected tabs' profile is used for recording. The audio device can be no input, default input, or a specified device. The UI handles the invalid states, so that the user cannot enter invalid combinations. --- resources/darkTheme.qss | 100 ++++++ resources/forms/mainWindow.ui | 12 + resources/lightTheme.qss | 118 +++++++ src/podcast/CMakeLists.txt | 2 + src/podcast/UBPodcastController.cpp | 93 ++++- src/podcast/UBPodcastController.h | 6 + src/podcast/UBPodcastPreferencesDialog.cpp | 386 +++++++++++++++++++++ src/podcast/UBPodcastPreferencesDialog.h | 101 ++++++ src/podcast/UBPodcastRecordingPalette.cpp | 2 +- src/podcast/podcast.pri | 2 + 10 files changed, 807 insertions(+), 15 deletions(-) create mode 100644 src/podcast/UBPodcastPreferencesDialog.cpp create mode 100644 src/podcast/UBPodcastPreferencesDialog.h diff --git a/resources/darkTheme.qss b/resources/darkTheme.qss index 944b7eeac..63d8dde85 100644 --- a/resources/darkTheme.qss +++ b/resources/darkTheme.qss @@ -1020,6 +1020,106 @@ QDialog#colorPreferencesDialog QDialogButtonBox#colorPreferencesButtonBox QPushB font-weight: 600; } +QDialog#podcastPreferencesDialog { + background-color: #353535; +} + +QDialog#podcastPreferencesDialog QWidget#podcastPreferencesHeader { + background-color: #2b2b2b; + border: 1px solid #555555; + border-radius: 8px; +} + +QDialog#podcastPreferencesDialog QLabel#podcastPreferencesHeaderLabel { + color: #f8fafc; + font-size: 14px; + font-weight: 600; + background: transparent; +} + +QDialog#podcastPreferencesDialog QSlider#podcastPreferencesSpinBox { + min-width: 190px; + background: transparent; +} + +QDialog#podcastPreferencesDialog QTabWidget#podcastPreferencesTabWidget::pane { + border: none; + background: transparent; + top: -1px; +} + +QDialog#podcastPreferencesDialog QTabBar::tab, +QDialog#podcastPreferencesDialog QTabBar::tab:top { + background: #2b2b2b; + color: #b7c3d4; + border: 1px solid #555555; + border-radius: 4px; + padding: 8px 18px; + margin-right: 8px; + font-weight: 600; +} + +QDialog#podcastPreferencesDialog QTabBar::tab:selected { + background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #2a82da, stop: 1 #1e5fa0); + color: #ffffff; + border: 1px solid #2a82da; +} + +QDialog#podcastPreferencesDialog QTabBar::tab:hover:!selected { + background: #404040; + color: #ffffff; +} + +QDialog#podcastPreferencesDialog QLabel#podcastPreferencesProfileTabValue { + min-width: 32px; + padding: 4px 8px; + background: #2a2a2a; + color: #f8fafc; + border: 1px solid #555555; + border-radius: 4px; + font-size: 14px; + font-weight: 600; +} + +QDialog#podcastPreferencesDialog QWidget#podcastPreferencesHint { + background: #4b4324; + border: 1px solid #7b6b33; + border-radius: 6px; +} + +QDialog#podcastPreferencesDialog QLabel#podcastPreferencesHintIcon { + background: transparent; + min-width: 20px; +} + +QDialog#podcastPreferencesDialog QLabel#podcastPreferencesHintText { + background: transparent; + color: #f1e3a8; + font-size: 12px; + line-height: 1.3em; +} + +QDialog#podcastPreferencesDialog QPushButton#podcastPreferencesResetButton { + padding: 7px 14px; + background: #454545; + color: #f8fafc; + border: 1px solid #555555; + border-radius: 4px; + font-weight: 600; +} + +QDialog#podcastPreferencesDialog QPushButton#podcastPreferencesResetButton:hover { + background: #505050; + border: 1px solid #6a6a6a; +} + +QDialog#podcastPreferencesDialog QDialogButtonBox#podcastPreferencesButtonBox QPushButton { + min-width: 92px; + padding: 8px 18px; + border-radius: 4px; + font-weight: 600; +} + QWidget#UBFeaturesActionBar QToolButton { padding: 0px; diff --git a/resources/forms/mainWindow.ui b/resources/forms/mainWindow.ui index 09673691f..5f1e0ab53 100644 --- a/resources/forms/mainWindow.ui +++ b/resources/forms/mainWindow.ui @@ -1671,6 +1671,18 @@ Pause Podcast Recording + + + + :/images/toolbar/settings.png:/images/toolbar/settings.png + + + Podcast Config + + + Configure Podcast Recording + + diff --git a/resources/lightTheme.qss b/resources/lightTheme.qss index dd81d453d..3f3d50e23 100644 --- a/resources/lightTheme.qss +++ b/resources/lightTheme.qss @@ -563,6 +563,124 @@ QDialog#colorPreferencesDialog QDialogButtonBox#colorPreferencesButtonBox QPushB border: 1px solid #2a82da; } +QDialog#podcastPreferencesDialog { + background-color: #f2f6fa; +} + +QDialog#podcastPreferencesDialog QWidget#podcastPreferencesHeader { + background-color: #edf2f7; + border: 1px solid #d9e0e8; + border-radius: 10px; +} + +QDialog#podcastPreferencesDialog QLabel#podcastPreferencesHeaderLabel { + color: #0f172a; + font-size: 14px; + font-weight: 600; + background: transparent; +} + +QDialog#podcastPreferencesDialog QSlider#podcastPreferencesSpinBox { + min-width: 190px; + background: transparent; +} + +QDialog#podcastPreferencesDialog QTabWidget#podcastPreferencesTabWidget::pane { + border: none; + background: transparent; + top: -1px; +} + +QDialog#podcastPreferencesDialog QTabBar::tab, +QDialog#podcastPreferencesDialog QTabBar::tab:top { + background: #e2eaf3; + color: #475569; + border: 1px solid #d9e0e8; + border-radius: 6px; + padding: 8px 18px; + margin-right: 8px; + font-weight: 600; +} + +QDialog#podcastPreferencesDialog QTabBar::tab:selected { + background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #5aa5e0, stop: 1 #3d8fd1); + color: #ffffff; + border: 1px solid #2a82da; +} + +QDialog#podcastPreferencesDialog QTabBar::tab:hover:!selected { + background: #e8eff7; + color: #1e293b; +} + +QDialog#podcastPreferencesDialog QLabel#podcastPreferencesProfileTabValue { + min-width: 32px; + padding: 4px 8px; + background: #ffffff; + color: #0f172a; + border: 1px solid #d9e0e8; + border-radius: 6px; + font-size: 14px; + font-weight: 600; +} + +QDialog#podcastPreferencesDialog QWidget#podcastPreferencesHint { + background: #fff8db; + border: 1px solid #ead9a2; + border-radius: 8px; +} + +QDialog#podcastPreferencesDialog QLabel#podcastPreferencesHintIcon { + background: transparent; + min-width: 20px; +} + +QDialog#podcastPreferencesDialog QLabel#podcastPreferencesHintText { + background: transparent; + color: #5b4b1f; + font-size: 12px; + line-height: 1.3em; +} + +QDialog#podcastPreferencesDialog QPushButton#podcastPreferencesResetButton { + padding: 7px 14px; + background: #f7f9fc; + color: #334155; + border: 1px solid #d9e0e8; + border-radius: 6px; + font-weight: 600; +} + +QDialog#podcastPreferencesDialog QPushButton#podcastPreferencesResetButton:hover { + background: #eef6ff; + border: 1px solid #d3e4f6; +} + +QDialog#podcastPreferencesDialog QPushButton#podcastPreferencesResetButton:focus, +QDialog#podcastPreferencesDialog QPushButton#podcastPreferencesResetButton:pressed, +QDialog#podcastPreferencesDialog QPushButton#podcastPreferencesResetButton:checked, +QDialog#podcastPreferencesDialog QPushButton#podcastPreferencesResetButton:default { + background: #3d8fd1; + color: #ffffff; + border: 1px solid #2a82da; +} + +QDialog#podcastPreferencesDialog QDialogButtonBox#podcastPreferencesButtonBox QPushButton { + min-width: 92px; + padding: 8px 18px; + border-radius: 6px; + font-weight: 600; +} + +QDialog#podcastPreferencesDialog QDialogButtonBox#podcastPreferencesButtonBox QPushButton:focus, +QDialog#podcastPreferencesDialog QDialogButtonBox#podcastPreferencesButtonBox QPushButton:pressed, +QDialog#podcastPreferencesDialog QDialogButtonBox#podcastPreferencesButtonBox QPushButton:checked, +QDialog#podcastPreferencesDialog QDialogButtonBox#podcastPreferencesButtonBox QPushButton:default { + background-color: #3d8fd1; + color: #ffffff; + border: 1px solid #2a82da; +} + QCheckBox, QRadioButton { color: #1f2937; diff --git a/src/podcast/CMakeLists.txt b/src/podcast/CMakeLists.txt index ca7087809..e5d81e906 100644 --- a/src/podcast/CMakeLists.txt +++ b/src/podcast/CMakeLists.txt @@ -3,6 +3,8 @@ target_sources(${PROJECT_NAME} PRIVATE UBAbstractVideoEncoder.h UBPodcastController.cpp UBPodcastController.h + UBPodcastPreferencesDialog.cpp + UBPodcastPreferencesDialog.h UBPodcastRecordingPalette.cpp UBPodcastRecordingPalette.h intranet/UBIntranetPodcastPublisher.cpp diff --git a/src/podcast/UBPodcastController.cpp b/src/podcast/UBPodcastController.cpp index b15caa706..fd7b1e02f 100644 --- a/src/podcast/UBPodcastController.cpp +++ b/src/podcast/UBPodcastController.cpp @@ -111,6 +111,8 @@ UBPodcastController::UBPodcastController(QObject* pParent) connect(UBApplication::webController, SIGNAL(activeWebPageChanged(WebView*)), this, SLOT(webActiveWebPageChanged(WebView*))); + connect(UBApplication::mainWindow->actionPodcastPreferences, SIGNAL(triggered()), this, SLOT(openPodcastPreferencesDialog())); + connect(UBApplication::mainWindow, &UBMainWindow::closeEvent_Signal, this, &UBPodcastController::applicationAboutToQuit); } @@ -151,6 +153,73 @@ void UBPodcastController::actionToggled(bool checked) updateActionState(); } +void UBPodcastController::openPodcastPreferencesDialog() +{ + if (mPodcastPreferencesDialog) + { + mPodcastPreferencesDialog->raise(); + mPodcastPreferencesDialog->activateWindow(); + return; + } + + UBSettings* settings = UBSettings::settings(); + + QString podcastAudioRecordingDeviceSetting = settings->podcastAudioRecordingDevice->get().toString(); + if (podcastAudioRecordingDeviceSetting != "Default" && + podcastAudioRecordingDeviceSetting != "None" && + !audioRecordingDevices().contains(podcastAudioRecordingDeviceSetting)) + { + podcastAudioRecordingDeviceSetting = settings->podcastAudioRecordingDevice->reset().toString(); + } + const QString podcastAudioRecordingDevice = podcastAudioRecordingDeviceSetting; + const QStringList podcastProfileNames = QStringList({"Full", "Medium", "Small"}); + if (!podcastProfileNames.contains(settings->podcastVideoSize->get().toString())) + { + settings->podcastVideoSize->reset().toString(); + } + const QString podcastProfile = settings->podcastVideoSize->get().toString(); + mVideoFramesPerSecondAtStart = settings->podcastFramesPerSecond->get().toInt(); + const int fullBitRate = settings->podcastWindowsMediaBitsPerSecond->get().toInt(); + const QSize viewportSize = UBApplication::boardController->controlView()->size(); + + const QList podcastBitRateDivisors = QList({1, 2, 4}); + const QList podcastVerticalResolution = QList({viewportSize.height(), 768, 480}); + const QList podcastHorizontalResolution = QList({viewportSize.width(), 1024, 640}); + + mPodcastPreferencesDialog = new UBPodcastPreferencesDialog(UBApplication::mainWindow, + audioRecordingDevices(), + podcastAudioRecordingDevice, + podcastProfileNames, + podcastProfile, + mVideoFramesPerSecondAtStart, + fullBitRate, + podcastBitRateDivisors, + podcastVerticalResolution, + podcastHorizontalResolution); + mPodcastPreferencesDialog->setAttribute(Qt::WA_DeleteOnClose); + connect(mPodcastPreferencesDialog, SIGNAL(accepted()), this, SLOT(podcastPreferencesDialogAccepted())); + mPodcastPreferencesDialog->open(); +} + +void UBPodcastController::podcastPreferencesDialogAccepted() +{ + UBPodcastPreferencesDialog* dialog = qobject_cast(sender()); + if (!dialog) + return; + + UBSettings* settings = UBSettings::settings(); + const QString podcastAudioRecordingDevice = dialog->podcastAudioRecordingOption(); + settings->podcastAudioRecordingDevice->set(podcastAudioRecordingDevice); + + const QString podcastProfile = dialog->podcastProfile(); + settings->podcastVideoSize->set(podcastProfile); + + mVideoBitsPerSecondAtStart = dialog->podcastBitRate(); + settings->podcastWindowsMediaBitsPerSecond->set(QVariant::fromValue(mVideoBitsPerSecondAtStart)); + + mVideoFramesPerSecondAtStart = dialog->podcastFrameRate(); + settings->podcastFramesPerSecond->set(mVideoFramesPerSecondAtStart); +} void UBPodcastController::updateActionState() { @@ -282,19 +351,21 @@ void UBPodcastController::start() QSize recommendedSize(1024, 768); - int fullBitRate = UBSettings::settings()->podcastWindowsMediaBitsPerSecond->get().toInt(); + UBSettings* settings = UBSettings::settings(); + int fullBitRate = settings->podcastWindowsMediaBitsPerSecond->get().toInt(); + QString podcastProfile = settings->podcastVideoSize->get().toString(); - if (mSmallVideoSizeAction && mSmallVideoSizeAction->isChecked()) + if (podcastProfile == "Small") { recommendedSize = QSize(640, 480); mVideoBitsPerSecondAtStart = fullBitRate / 4; } - else if (mMediumVideoSizeAction && mMediumVideoSizeAction->isChecked()) + else if (podcastProfile == "Medium") { recommendedSize = QSize(1024, 768); mVideoBitsPerSecondAtStart = fullBitRate / 2; } - else if (mFullVideoSizeAction && mFullVideoSizeAction->isChecked()) + else if (podcastProfile == "Full") { recommendedSize = UBApplication::boardController->controlView()->size(); mVideoBitsPerSecondAtStart = fullBitRate; @@ -337,20 +408,14 @@ void UBPodcastController::start() , mRecordingPalette, SLOT(audioLevelChanged(quint8))); } - mVideoEncoder->setRecordAudio(!mNoAudioInputDeviceAction->isChecked()); + QString podcastAudioRecordingOption = settings->podcastAudioRecordingDevice->get().toString(); + mVideoEncoder->setRecordAudio(podcastAudioRecordingOption != "None"); QString recordingDevice = ""; - if (!mNoAudioInputDeviceAction->isChecked() && !mDefaultAudioInputDeviceAction->isChecked()) + if (podcastAudioRecordingOption != "None" && podcastAudioRecordingOption != "Default") { - foreach(QAction* audioDevice, mAudioInputDevicesActions) - { - if (audioDevice->isChecked()) - { - recordingDevice = audioDevice->text(); - break; - } - } + recordingDevice = podcastAudioRecordingOption; } mVideoEncoder->setAudioRecordingDevice(recordingDevice); diff --git a/src/podcast/UBPodcastController.h b/src/podcast/UBPodcastController.h index 89143892b..948fdd736 100644 --- a/src/podcast/UBPodcastController.h +++ b/src/podcast/UBPodcastController.h @@ -33,6 +33,7 @@ #include #include "UBAbstractVideoEncoder.h" +#include "UBPodcastPreferencesDialog.h" #include "core/UBApplicationController.h" @@ -88,6 +89,9 @@ class UBPodcastController : public QObject void recordToggled(bool record); void pauseToggled(bool pause); + void openPodcastPreferencesDialog(); + void podcastPreferencesDialogAccepted(); + protected: virtual void setSourceWidget(QWidget* pWidget); @@ -180,6 +184,8 @@ class UBPodcastController : public QObject QList mAudioInputDevicesActions; QList mVideoSizesActions; + QPointer mPodcastPreferencesDialog; + QAction* mSmallVideoSizeAction; QAction* mMediumVideoSizeAction; QAction* mFullVideoSizeAction; diff --git a/src/podcast/UBPodcastPreferencesDialog.cpp b/src/podcast/UBPodcastPreferencesDialog.cpp new file mode 100644 index 000000000..9af808812 --- /dev/null +++ b/src/podcast/UBPodcastPreferencesDialog.cpp @@ -0,0 +1,386 @@ +/* + * Copyright (C) 2015-2022 Département de l'Instruction Publique (DIP-SEM) + * + * Copyright (C) 2013 Open Education Foundation + * + * Copyright (C) 2010-2013 Groupement d'Intérêt Public pour + * l'Education Numérique en Afrique (GIP ENA) + * + * This file is part of OpenBoard. + * + * OpenBoard is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3 of the License, + * with a specific linking exception for the OpenSSL project's + * "OpenSSL" library (or with modified versions of it that use the + * same license as the "OpenSSL" library). + * + * OpenBoard is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with OpenBoard. If not, see . + */ + +#include "UBPodcastPreferencesDialog.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "core/UBApplication.h" +#include "core/UBSettings.h" +#include "gui/UBMainWindow.h" + + +UBPodcastPreferencesDialog::UBPodcastPreferencesDialog(QWidget* parent, + const QStringList& podcastAudioRecordingDevices, + const QString podcastAudioRecordingOption, + const QStringList& podcastProfileNames, + const QString podcastProfile, + const int podcastFrameRate, + const int podcastBitRate, + const QList& podcastBitRateDivisor, + const QList& podcastVerticalResolution, + const QList& podcastHorizontalResolution) + : QDialog(parent) + , mPodcastAudioRecordingDevices(podcastAudioRecordingDevices) + , mPodcastProfileNames(podcastProfileNames) + , mPodcastBitRateDivisor(podcastBitRateDivisor) +{ + setModal(true); + setWindowTitle(tr("Podcast Preferences")); + setMinimumWidth(520); + setObjectName(QStringLiteral("podcastPreferencesDialog")); + + QVBoxLayout* mainLayout = new QVBoxLayout(this); + mainLayout->setContentsMargins(20, 18, 20, 18); + mainLayout->setSpacing(16); + + const QString audioDeviceSelectorToolTip = tr("The selected audio device applies to all profiles."); + + QWidget* audioWidget = new QWidget(this); + audioWidget->setObjectName(QStringLiteral("podcastPreferencesHeader")); + QHBoxLayout* audioLayout = new QHBoxLayout(audioWidget); + audioLayout->setContentsMargins(14, 12, 14, 12); + audioLayout->setSpacing(12); + + QLabel* audioLabel = new QLabel(tr("Audio Recording Device"), audioWidget); + audioLabel->setObjectName(QStringLiteral("podcastPreferencesHeaderLabel")); + audioLabel->setToolTip(audioDeviceSelectorToolTip); + mNoAudioCheckBox = new QCheckBox(tr("Don't record audio")); + mNoAudioCheckBox->setToolTip(audioDeviceSelectorToolTip); + mDefaultAudioCheckBox = new QCheckBox(tr("Use default audio input")); + mDefaultAudioCheckBox->setToolTip(audioDeviceSelectorToolTip); + mAudioDeviceSelector = new QComboBox(audioWidget); + mAudioDeviceSelector->addItems(mPodcastAudioRecordingDevices); + mAudioDeviceSelector->setToolTip(audioDeviceSelectorToolTip); + connect(mNoAudioCheckBox, SIGNAL(toggled(bool)), this, SLOT(toggleNoAudioDevice(bool))); + connect(mDefaultAudioCheckBox, SIGNAL(toggled(bool)), this, SLOT(toggleDefaultAudioDevice(bool))); + if (podcastAudioRecordingOption == "None") + { + setNoAudioDevice(); + } + else if (podcastAudioRecordingOption == "Default") + { + setDefaultAudioDevice(); + } + else + { + mAudioDeviceSelector->setCurrentIndex(mPodcastAudioRecordingDevices.indexOf(podcastAudioRecordingOption)); + } + audioLayout->addWidget(audioLabel); + audioLayout->addWidget(mNoAudioCheckBox); + audioLayout->addWidget(mDefaultAudioCheckBox); + audioLayout->addWidget(mAudioDeviceSelector); + mainLayout->addWidget(audioWidget); + + const QString frameRateFormToolTip = tr("The global frame rate applies to all profiles."); + + QWidget* frameRateFormWidget = new QWidget(this); + frameRateFormWidget->setObjectName(QStringLiteral("podcastPreferencesSpinBox")); + QHBoxLayout* frameRateFormLayout = new QHBoxLayout(frameRateFormWidget); + frameRateFormLayout->setContentsMargins(14, 12, 14, 12); + frameRateFormLayout->setSpacing(12); + mFrameRateSpinBox = new QSpinBox(frameRateFormWidget); + mFrameRateSpinBox->setRange(0, 1000000); + mFrameRateSpinBox->setValue(podcastFrameRate); + mFrameRateSpinBox->setSingleStep(1); + mFrameRateSpinBox->setToolTip(frameRateFormToolTip); + connect(mFrameRateSpinBox, SIGNAL(valueChanged(int)), this, SLOT(frameRateChanged(int))); + QLabel* frameRateLabel = new QLabel(tr("Global frame rate"), frameRateFormWidget); + frameRateLabel->setObjectName(QStringLiteral("podcastPreferencesHeaderLabel")); + frameRateLabel->setToolTip(frameRateFormToolTip); + frameRateFormLayout->addWidget(frameRateLabel); + frameRateFormLayout->addWidget(mFrameRateSpinBox); + mainLayout->addWidget(frameRateFormWidget); + + const QString bitRateFormToolTip = tr("The base bit rate is scaled depending on the profile."); + + QWidget* bitRateFormWidget = new QWidget(this); + bitRateFormWidget->setObjectName(QStringLiteral("podcastPreferencesSpinBox")); + QHBoxLayout* bitRateFormLayout = new QHBoxLayout(bitRateFormWidget); + bitRateFormLayout->setContentsMargins(14, 12, 14, 12); + bitRateFormLayout->setSpacing(12); + mBitRateSpinBox = new QSpinBox(bitRateFormWidget); + mBitRateSpinBox->setRange(0, 1000000000); + mBitRateSpinBox->setValue(podcastBitRate); + mBitRateSpinBox->setSingleStep(1000); + mBitRateSpinBox->setToolTip(bitRateFormToolTip); + connect(mBitRateSpinBox, SIGNAL(valueChanged(int)), this, SLOT(bitRateChanged(int))); + QLabel* bitRateLabel = new QLabel(tr("Base bit rate"), bitRateFormWidget); + bitRateLabel->setObjectName(QStringLiteral("podcastPreferencesHeaderLabel")); + bitRateLabel->setToolTip(bitRateFormToolTip); + bitRateFormLayout->addWidget(bitRateLabel); + bitRateFormLayout->addWidget(mBitRateSpinBox); + mainLayout->addWidget(bitRateFormWidget); + + mTabWidget = new QTabWidget(this); + mTabWidget->setObjectName(QStringLiteral("podcastPreferencesTabWidget")); + mTabWidget->setIconSize(QSize(18, 18)); + + for (int i = 0; i < mPodcastProfileNames.size(); ++i) + { + const QString tabLabel = mPodcastProfileNames[i] == QString("Full") ? tr("Full") + : mPodcastProfileNames[i] == QString("Medium") ? tr("Medium") + : mPodcastProfileNames[i] == QString("Small") ? tr("Small") + : mPodcastProfileNames[i]; + QWidget* tab = createProfileTab(mBitRateProfileValues.emplaceBack(), + mFrameRateProfileValues.emplaceBack(), + podcastBitRate / mPodcastBitRateDivisor[i], + podcastFrameRate, + podcastVerticalResolution[i], + podcastHorizontalResolution[i]); + tab->setObjectName(QStringLiteral("podcastPreferencesPenTab")); + mTabWidget->addTab(tab, tabLabel); + } + mTabWidget->setCurrentIndex(mPodcastProfileNames.indexOf(podcastProfile)); + mainLayout->addWidget(mTabWidget); + + QWidget* hintWidget = new QWidget(this); + hintWidget->setObjectName(QStringLiteral("podcastPreferencesHint")); + QHBoxLayout* hintLayout = new QHBoxLayout(hintWidget); + hintLayout->setContentsMargins(14, 10, 14, 10); + hintLayout->setSpacing(10); + + QLabel* hintIcon = new QLabel(hintWidget); + hintIcon->setObjectName(QStringLiteral("podcastPreferencesHintIcon")); + hintIcon->setPixmap(QIcon(QStringLiteral(":/images/toolbar/tip.png")).pixmap(20, 20)); + hintIcon->setAlignment(Qt::AlignTop | Qt::AlignHCenter); + + QLabel* hintLabel = new QLabel( + tr("Frame rate and bit rate are dynamically adjusted during recording to record changes while keeping the file size small."), + hintWidget); + hintLabel->setObjectName(QStringLiteral("podcastPreferencesHintText")); + hintLabel->setWordWrap(true); + + hintLayout->addWidget(hintIcon, 0, Qt::AlignTop); + hintLayout->addWidget(hintLabel, 1); + mainLayout->addWidget(hintWidget); + + QDialogButtonBox* buttons = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel, this); + buttons->setObjectName(QStringLiteral("podcastPreferencesButtonBox")); + QPushButton* defaultSettingsButton = buttons->addButton(tr("Default settings"), QDialogButtonBox::ResetRole); + defaultSettingsButton->setObjectName(QStringLiteral("podcastPreferencesResetButton")); + connect(defaultSettingsButton, SIGNAL(clicked()), this, SLOT(resetDefaultSettings())); + connect(buttons, SIGNAL(accepted()), this, SLOT(accept())); + connect(buttons, SIGNAL(rejected()), this, SLOT(reject())); + mainLayout->addWidget(buttons); +} + + +QString UBPodcastPreferencesDialog::podcastAudioRecordingOption() const +{ + if (mNoAudioCheckBox && mNoAudioCheckBox->isChecked()) + { + return "None"; + } + if (mDefaultAudioCheckBox && mDefaultAudioCheckBox->isChecked()) + { + return "Default"; + } + const int currentIndex = mAudioDeviceSelector->currentIndex(); + if (0 <= currentIndex && currentIndex < mPodcastAudioRecordingDevices.size()) + { + return mPodcastAudioRecordingDevices[currentIndex]; + } + return ""; +} + +QString UBPodcastPreferencesDialog::podcastProfile() const +{ + const int currentIndex = mTabWidget->currentIndex(); + if (0 <= currentIndex && currentIndex < mPodcastProfileNames.size()) + { + return mPodcastProfileNames[currentIndex]; + } + return ""; +} + +int UBPodcastPreferencesDialog::podcastBitRate() const +{ + return mBitRateSpinBox->value(); +} + +int UBPodcastPreferencesDialog::podcastFrameRate() const +{ + return mFrameRateSpinBox->value(); +} + +void UBPodcastPreferencesDialog::bitRateChanged(int bitRate) +{ + for (int i = 0; i < mBitRateProfileValues.size(); ++i) + { + mBitRateProfileValues[i]->setNum(bitRate / mPodcastBitRateDivisor[i]); + } +} + +void UBPodcastPreferencesDialog::frameRateChanged(int frameRate) +{ + for (QLabel* label : mFrameRateProfileValues) + { + label->setNum(frameRate); + } +} + +void UBPodcastPreferencesDialog::toggleNoAudioDevice(bool checked) +{ + if (checked) + { + setNoAudioDevice(); + } + else + { + setDefaultAudioDevice(); + } +} + +void UBPodcastPreferencesDialog::setNoAudioDevice() +{ + mNoAudioCheckBox->setChecked(true); + mNoAudioCheckBox->setEnabled(true); + mDefaultAudioCheckBox->setChecked(false); + mDefaultAudioCheckBox->setEnabled(false); + mAudioDeviceSelector->setEnabled(false); +} + +void UBPodcastPreferencesDialog::toggleDefaultAudioDevice(bool checked) +{ + if (checked) + { + setDefaultAudioDevice(); + } + else if (mNoAudioCheckBox && !mNoAudioCheckBox->isChecked()) + { + mAudioDeviceSelector->setEnabled(true); + } +} + +void UBPodcastPreferencesDialog::setDefaultAudioDevice() +{ + mNoAudioCheckBox->setChecked(false); + mNoAudioCheckBox->setEnabled(true); + mDefaultAudioCheckBox->setChecked(true); + mDefaultAudioCheckBox->setEnabled(true); + mAudioDeviceSelector->setEnabled(false); +} + +void UBPodcastPreferencesDialog::resetDefaultSettings() +{ + setDefaultAudioDevice(); + mTabWidget->setCurrentIndex(mPodcastProfileNames.indexOf("Medium")); + mBitRateSpinBox->setValue(1700000); + mFrameRateSpinBox->setValue(10); +} + + +QWidget* UBPodcastPreferencesDialog::createProfileTab(QLabel* &bitRateValue, + QLabel* &frameRateValue, + const int bitRate, + const int frameRate, + const int height, + const int width) +{ + QWidget* tab = new QWidget(this); + QVBoxLayout* tabLayout = new QVBoxLayout(tab); + tabLayout->setContentsMargins(8, 14, 8, 6); + tabLayout->setSpacing(14); + + const QString bitRateToolTip = tr("The bit rate determines the quality of each frame."); + QWidget* bitRateWidget = new QWidget(this); + bitRateWidget->setObjectName(QStringLiteral("podcastPreferencesHeader")); + QHBoxLayout* bitRateLayout = new QHBoxLayout(bitRateWidget); + bitRateLayout->setContentsMargins(14, 12, 14, 12); + bitRateLayout->setSpacing(12); + QLabel* bitRateLabel = new QLabel(tr("Bit rate"), bitRateWidget); + bitRateLabel->setAlignment(Qt::AlignCenter); + bitRateLabel->setToolTip(bitRateToolTip); + bitRateValue = new QLabel(QString::number(bitRate), bitRateWidget); + bitRateValue->setObjectName(QStringLiteral("podcastPreferencesProfileTabValue")); + bitRateValue->setAlignment(Qt::AlignCenter); + bitRateValue->setToolTip(bitRateToolTip); + bitRateLayout->addWidget(bitRateLabel); + bitRateLayout->addWidget(bitRateValue); + tabLayout->addWidget(bitRateWidget); + + const QString frameRateToolTip = tr("The frame rate determines how fast changes are recorded."); + QWidget* frameRateWidget = new QWidget(this); + frameRateWidget->setObjectName(QStringLiteral("podcastPreferencesHeader")); + QHBoxLayout* frameRateLayout = new QHBoxLayout(frameRateWidget); + frameRateLayout->setContentsMargins(14, 12, 14, 12); + frameRateLayout->setSpacing(12); + QLabel* frameRateLabel = new QLabel(tr("Frame rate"), frameRateWidget); + frameRateLabel->setAlignment(Qt::AlignCenter); + frameRateLabel->setToolTip(frameRateToolTip); + frameRateValue = new QLabel(QString::number(frameRate), frameRateWidget); + frameRateValue->setObjectName(QStringLiteral("podcastPreferencesProfileTabValue")); + frameRateValue->setAlignment(Qt::AlignCenter); + frameRateValue->setToolTip(frameRateToolTip); + frameRateLayout->addWidget(frameRateLabel); + frameRateLayout->addWidget(frameRateValue); + tabLayout->addWidget(frameRateWidget); + + const QString widthToolTip = tr("The width determines the horizontal detail of each frame."); + QWidget* widthWidget = new QWidget(this); + widthWidget->setObjectName(QStringLiteral("podcastPreferencesHeader")); + QHBoxLayout* widthLayout = new QHBoxLayout(widthWidget); + widthLayout->setContentsMargins(14, 12, 14, 12); + widthLayout->setSpacing(12); + QLabel* widthLabel = new QLabel(tr("Horizontal Resolution"), widthWidget); + widthLabel->setAlignment(Qt::AlignCenter); + widthLabel->setToolTip(widthToolTip); + QLabel* widthValue = new QLabel(QString::number(width), widthWidget); + widthValue->setObjectName(QStringLiteral("podcastPreferencesProfileTabValue")); + widthValue->setAlignment(Qt::AlignCenter); + widthValue->setToolTip(widthToolTip); + widthLayout->addWidget(widthLabel); + widthLayout->addWidget(widthValue); + tabLayout->addWidget(widthWidget); + + const QString heightToolTip = tr("The height determines the vertical detail of each frame."); + QWidget* heightWidget = new QWidget(this); + heightWidget->setObjectName(QStringLiteral("podcastPreferencesHeader")); + QHBoxLayout* heightLayout = new QHBoxLayout(heightWidget); + heightLayout->setContentsMargins(14, 12, 14, 12); + heightLayout->setSpacing(12); + QLabel* heightLabel = new QLabel(tr("Vertical Resolution"), heightWidget); + heightLabel->setAlignment(Qt::AlignCenter); + heightLabel->setToolTip(heightToolTip); + QLabel* heightValue = new QLabel(QString::number(height), heightWidget); + heightValue->setObjectName(QStringLiteral("podcastPreferencesProfileTabValue")); + heightValue->setAlignment(Qt::AlignCenter); + heightValue->setToolTip(heightToolTip); + heightLayout->addWidget(heightLabel); + heightLayout->addWidget(heightValue); + tabLayout->addWidget(heightWidget); + + return tab; +} diff --git a/src/podcast/UBPodcastPreferencesDialog.h b/src/podcast/UBPodcastPreferencesDialog.h new file mode 100644 index 000000000..ad0333152 --- /dev/null +++ b/src/podcast/UBPodcastPreferencesDialog.h @@ -0,0 +1,101 @@ +/* + * Copyright (C) 2015-2022 Département de l'Instruction Publique (DIP-SEM) + * + * Copyright (C) 2013 Open Education Foundation + * + * Copyright (C) 2010-2013 Groupement d'Intérêt Public pour + * l'Education Numérique en Afrique (GIP ENA) + * + * This file is part of OpenBoard. + * + * OpenBoard is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3 of the License, + * with a specific linking exception for the OpenSSL project's + * "OpenSSL" library (or with modified versions of it that use the + * same license as the "OpenSSL" library). + * + * OpenBoard is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with OpenBoard. If not, see . + */ + + + + +#ifndef UBPODCASTPREFERENCESDIALOG_H +#define UBPODCASTPREFERENCESDIALOG_H + +#include +#include +#include +#include +#include +#include +#include + +class QWidget; +class QLabel; +class QTabWidget; +class QPushButton; + +class UBPodcastPreferencesDialog : public QDialog +{ + Q_OBJECT + + public: + UBPodcastPreferencesDialog(QWidget* parent, + const QStringList& podcastAudioRecordingOptions, + const QString podcastAudioRecordingDevice, + const QStringList& podcastProfileNames, + const QString podcastProfile, + const int podcastFrameRate, + const int podcastBitRate, + const QList& podcastBitRateDivisors, + const QList& podcastVerticalResolution, + const QList& podcastHorizontalResolution); + + QString podcastAudioRecordingOption() const; + QString podcastProfile() const; + int podcastBitRate() const; + int podcastFrameRate() const; + + private slots: + void bitRateChanged(int bitRate); + void frameRateChanged(int frameRate); + void toggleNoAudioDevice(bool checked); + void toggleDefaultAudioDevice(bool checked); + void resetDefaultSettings(); + + private: + QWidget* createProfileTab(QLabel* &bitRateValue, + QLabel* &frameRateValue, + const int bitRate, + const int frameRate, + const int height, + const int width); + void setNoAudioDevice(); + void setDefaultAudioDevice(); + + QCheckBox* mDefaultAudioCheckBox{nullptr}; + QCheckBox* mNoAudioCheckBox{nullptr}; + QComboBox* mAudioDeviceSelector{nullptr}; + QSpinBox* mBitRateSpinBox{nullptr}; + QSpinBox* mFrameRateSpinBox{nullptr}; + QTabWidget* mTabWidget{nullptr}; + QPushButton* mResetPenButton{nullptr}; + QPushButton* mResetMarkerButton{nullptr}; + QList mBitRateProfileValues; + QList mFrameRateProfileValues; + QStringList mPodcastAudioRecordingDevices; + QStringList mPodcastProfileNames; + QList mPodcastBitRateDivisor; +}; + + + +#endif // UBPODCASTPREFERENCESDIALOG_H diff --git a/src/podcast/UBPodcastRecordingPalette.cpp b/src/podcast/UBPodcastRecordingPalette.cpp index 8082f27b2..b561b1b6b 100644 --- a/src/podcast/UBPodcastRecordingPalette.cpp +++ b/src/podcast/UBPodcastRecordingPalette.cpp @@ -56,7 +56,7 @@ UBPodcastRecordingPalette::UBPodcastRecordingPalette(QWidget *parent) mLevelMeter->setMinimumSize(6, 32); layout()->addWidget(mLevelMeter); - + addAction(UBApplication::mainWindow->actionPodcastPreferences); addAction(UBApplication::mainWindow->actionPodcastConfig); #if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)) diff --git a/src/podcast/podcast.pri b/src/podcast/podcast.pri index 22bab613e..561565686 100644 --- a/src/podcast/podcast.pri +++ b/src/podcast/podcast.pri @@ -1,12 +1,14 @@ HEADERS += src/podcast/UBPodcastController.h \ src/podcast/UBAbstractVideoEncoder.h \ + src/podcast/UBPodcastPreferencesDialog.h \ src/podcast/UBPodcastRecordingPalette.h \ src/podcast/youtube/UBYouTubePublisher.h \ src/podcast/intranet/UBIntranetPodcastPublisher.h \ SOURCES += src/podcast/UBPodcastController.cpp \ src/podcast/UBAbstractVideoEncoder.cpp \ + src/podcast/UBPodcastPreferencesDialog.cpp \ src/podcast/UBPodcastRecordingPalette.cpp \ src/podcast/youtube/UBYouTubePublisher.cpp \ src/podcast/intranet/UBIntranetPodcastPublisher.cpp \ From 2e753eb2c6b6fb09599fa974b1e8a2a9d3824037 Mon Sep 17 00:00:00 2001 From: Vekhir Date: Thu, 9 Apr 2026 02:49:13 +0200 Subject: [PATCH 2/3] feat: Upload dialog in podcast preferences The upload dialog contains options related to uploading the recorded videos. --- src/podcast/UBPodcastController.cpp | 18 +++++-- src/podcast/UBPodcastPreferencesDialog.cpp | 60 ++++++++++++++++++---- src/podcast/UBPodcastPreferencesDialog.h | 8 ++- 3 files changed, 70 insertions(+), 16 deletions(-) diff --git a/src/podcast/UBPodcastController.cpp b/src/podcast/UBPodcastController.cpp index fd7b1e02f..061a6ffad 100644 --- a/src/podcast/UBPodcastController.cpp +++ b/src/podcast/UBPodcastController.cpp @@ -186,6 +186,9 @@ void UBPodcastController::openPodcastPreferencesDialog() const QList podcastVerticalResolution = QList({viewportSize.height(), 768, 480}); const QList podcastHorizontalResolution = QList({viewportSize.width(), 1024, 640}); + const bool podcastPublishToIntranet = settings->podcastPublishToIntranet->get().toBool(); + const bool podcastPublishToYoutube = settings->podcastPublishToYoutube->get().toBool(); + mPodcastPreferencesDialog = new UBPodcastPreferencesDialog(UBApplication::mainWindow, audioRecordingDevices(), podcastAudioRecordingDevice, @@ -195,7 +198,9 @@ void UBPodcastController::openPodcastPreferencesDialog() fullBitRate, podcastBitRateDivisors, podcastVerticalResolution, - podcastHorizontalResolution); + podcastHorizontalResolution, + podcastPublishToIntranet, + podcastPublishToYoutube); mPodcastPreferencesDialog->setAttribute(Qt::WA_DeleteOnClose); connect(mPodcastPreferencesDialog, SIGNAL(accepted()), this, SLOT(podcastPreferencesDialogAccepted())); mPodcastPreferencesDialog->open(); @@ -219,6 +224,11 @@ void UBPodcastController::podcastPreferencesDialogAccepted() mVideoFramesPerSecondAtStart = dialog->podcastFrameRate(); settings->podcastFramesPerSecond->set(mVideoFramesPerSecondAtStart); + + const bool podcastPublishToIntranet = dialog->podcastPublishToIntranet(); + UBSettings::settings()->podcastPublishToIntranet->set(podcastPublishToIntranet); + const bool podcastPublishToYoutube = dialog->podcastPublishToYoutube(); + UBSettings::settings()->podcastPublishToYoutube->set(podcastPublishToYoutube); } void UBPodcastController::updateActionState() @@ -432,7 +442,7 @@ void UBPodcastController::start() QString videoFileName; - if (mIntranetPublicationAction && mIntranetPublicationAction->isChecked()) + if (settings->podcastPublishToIntranet->get().toBool()) { videoFileName = mPodcastRecordingPath + "/" + "Podcast-" + QDateTime::currentDateTime().toString("yyyyMMddhhmmss") @@ -822,13 +832,13 @@ void UBPodcastController::encodingFinished(bool ok) UBApplication::showMessage(tr("Podcast created %1").arg(location), false); - if (mIntranetPublicationAction && mIntranetPublicationAction->isChecked()) + if (UBSettings::settings()->podcastPublishToIntranet->get().toBool()) { UBIntranetPodcastPublisher* intranet = new UBIntranetPodcastPublisher(this); // Self destroyed intranet->publishVideo(mVideoEncoder->videoFileName(), elapsedRecordingMs()); } - if (mYoutubePublicationAction && mYoutubePublicationAction->isChecked()) + if (UBSettings::settings()->podcastPublishToYoutube->get().toBool()) { UBYouTubePublisher* youTube = new UBYouTubePublisher(this); // Self destroyed youTube->uploadVideo(mVideoEncoder->videoFileName()); diff --git a/src/podcast/UBPodcastPreferencesDialog.cpp b/src/podcast/UBPodcastPreferencesDialog.cpp index 9af808812..3f152cff6 100644 --- a/src/podcast/UBPodcastPreferencesDialog.cpp +++ b/src/podcast/UBPodcastPreferencesDialog.cpp @@ -50,7 +50,9 @@ UBPodcastPreferencesDialog::UBPodcastPreferencesDialog(QWidget* parent, const int podcastBitRate, const QList& podcastBitRateDivisor, const QList& podcastVerticalResolution, - const QList& podcastHorizontalResolution) + const QList& podcastHorizontalResolution, + const bool podcastPublishToIntranet, + const bool podcastPublishToYoutube) : QDialog(parent) , mPodcastAudioRecordingDevices(podcastAudioRecordingDevices) , mPodcastProfileNames(podcastProfileNames) @@ -65,9 +67,14 @@ UBPodcastPreferencesDialog::UBPodcastPreferencesDialog(QWidget* parent, mainLayout->setContentsMargins(20, 18, 20, 18); mainLayout->setSpacing(16); + QWidget* recordingWidget = new QWidget(this); + QVBoxLayout* recordingLayout = new QVBoxLayout(recordingWidget); + recordingLayout->setContentsMargins(20, 18, 20, 18); + recordingLayout->setSpacing(16); + const QString audioDeviceSelectorToolTip = tr("The selected audio device applies to all profiles."); - QWidget* audioWidget = new QWidget(this); + QWidget* audioWidget = new QWidget(recordingWidget); audioWidget->setObjectName(QStringLiteral("podcastPreferencesHeader")); QHBoxLayout* audioLayout = new QHBoxLayout(audioWidget); audioLayout->setContentsMargins(14, 12, 14, 12); @@ -101,11 +108,11 @@ UBPodcastPreferencesDialog::UBPodcastPreferencesDialog(QWidget* parent, audioLayout->addWidget(mNoAudioCheckBox); audioLayout->addWidget(mDefaultAudioCheckBox); audioLayout->addWidget(mAudioDeviceSelector); - mainLayout->addWidget(audioWidget); + recordingLayout->addWidget(audioWidget); const QString frameRateFormToolTip = tr("The global frame rate applies to all profiles."); - QWidget* frameRateFormWidget = new QWidget(this); + QWidget* frameRateFormWidget = new QWidget(recordingWidget); frameRateFormWidget->setObjectName(QStringLiteral("podcastPreferencesSpinBox")); QHBoxLayout* frameRateFormLayout = new QHBoxLayout(frameRateFormWidget); frameRateFormLayout->setContentsMargins(14, 12, 14, 12); @@ -121,11 +128,11 @@ UBPodcastPreferencesDialog::UBPodcastPreferencesDialog(QWidget* parent, frameRateLabel->setToolTip(frameRateFormToolTip); frameRateFormLayout->addWidget(frameRateLabel); frameRateFormLayout->addWidget(mFrameRateSpinBox); - mainLayout->addWidget(frameRateFormWidget); + recordingLayout->addWidget(frameRateFormWidget); const QString bitRateFormToolTip = tr("The base bit rate is scaled depending on the profile."); - QWidget* bitRateFormWidget = new QWidget(this); + QWidget* bitRateFormWidget = new QWidget(recordingWidget); bitRateFormWidget->setObjectName(QStringLiteral("podcastPreferencesSpinBox")); QHBoxLayout* bitRateFormLayout = new QHBoxLayout(bitRateFormWidget); bitRateFormLayout->setContentsMargins(14, 12, 14, 12); @@ -141,9 +148,9 @@ UBPodcastPreferencesDialog::UBPodcastPreferencesDialog(QWidget* parent, bitRateLabel->setToolTip(bitRateFormToolTip); bitRateFormLayout->addWidget(bitRateLabel); bitRateFormLayout->addWidget(mBitRateSpinBox); - mainLayout->addWidget(bitRateFormWidget); + recordingLayout->addWidget(bitRateFormWidget); - mTabWidget = new QTabWidget(this); + mTabWidget = new QTabWidget(recordingWidget); mTabWidget->setObjectName(QStringLiteral("podcastPreferencesTabWidget")); mTabWidget->setIconSize(QSize(18, 18)); @@ -163,9 +170,9 @@ UBPodcastPreferencesDialog::UBPodcastPreferencesDialog(QWidget* parent, mTabWidget->addTab(tab, tabLabel); } mTabWidget->setCurrentIndex(mPodcastProfileNames.indexOf(podcastProfile)); - mainLayout->addWidget(mTabWidget); + recordingLayout->addWidget(mTabWidget); - QWidget* hintWidget = new QWidget(this); + QWidget* hintWidget = new QWidget(recordingWidget); hintWidget->setObjectName(QStringLiteral("podcastPreferencesHint")); QHBoxLayout* hintLayout = new QHBoxLayout(hintWidget); hintLayout->setContentsMargins(14, 10, 14, 10); @@ -184,7 +191,26 @@ UBPodcastPreferencesDialog::UBPodcastPreferencesDialog(QWidget* parent, hintLayout->addWidget(hintIcon, 0, Qt::AlignTop); hintLayout->addWidget(hintLabel, 1); - mainLayout->addWidget(hintWidget); + recordingLayout->addWidget(hintWidget); + + QWidget* publish = new QWidget(this); + QVBoxLayout* publishLayout = new QVBoxLayout(publish); + publishLayout->setContentsMargins(8, 14, 8, 6); + publishLayout->setSpacing(14); + + mPublishToIntranet = new QCheckBox(tr("Publish to Intranet")); + mPublishToIntranet->setChecked(podcastPublishToIntranet); + mPublishToYoutube = new QCheckBox(tr("Publish to Youtube")); + mPublishToYoutube->setChecked(podcastPublishToYoutube); + publishLayout->addWidget(mPublishToIntranet); + publishLayout->addWidget(mPublishToYoutube); + + publishLayout->addStretch(); + + QTabWidget* mainTabs = new QTabWidget(this); + mainTabs->addTab(recordingWidget, tr("Recording")); + mainTabs->addTab(publish, tr("Upload")); + mainLayout->addWidget(mainTabs); QDialogButtonBox* buttons = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel, this); buttons->setObjectName(QStringLiteral("podcastPreferencesButtonBox")); @@ -235,6 +261,16 @@ int UBPodcastPreferencesDialog::podcastFrameRate() const return mFrameRateSpinBox->value(); } +bool UBPodcastPreferencesDialog::podcastPublishToIntranet() const +{ + return mPublishToIntranet->isChecked(); +} + +bool UBPodcastPreferencesDialog::podcastPublishToYoutube() const +{ + return mPublishToYoutube->isChecked(); +} + void UBPodcastPreferencesDialog::bitRateChanged(int bitRate) { for (int i = 0; i < mBitRateProfileValues.size(); ++i) @@ -299,6 +335,8 @@ void UBPodcastPreferencesDialog::resetDefaultSettings() mTabWidget->setCurrentIndex(mPodcastProfileNames.indexOf("Medium")); mBitRateSpinBox->setValue(1700000); mFrameRateSpinBox->setValue(10); + mPublishToIntranet->setChecked(false); + mPublishToYoutube->setChecked(false); } diff --git a/src/podcast/UBPodcastPreferencesDialog.h b/src/podcast/UBPodcastPreferencesDialog.h index ad0333152..87e8a4c14 100644 --- a/src/podcast/UBPodcastPreferencesDialog.h +++ b/src/podcast/UBPodcastPreferencesDialog.h @@ -57,12 +57,16 @@ class UBPodcastPreferencesDialog : public QDialog const int podcastBitRate, const QList& podcastBitRateDivisors, const QList& podcastVerticalResolution, - const QList& podcastHorizontalResolution); + const QList& podcastHorizontalResolution, + const bool podcastPublishToIntranet, + const bool podcastPublishToYoutube); QString podcastAudioRecordingOption() const; QString podcastProfile() const; int podcastBitRate() const; int podcastFrameRate() const; + bool podcastPublishToIntranet() const; + bool podcastPublishToYoutube() const; private slots: void bitRateChanged(int bitRate); @@ -87,6 +91,8 @@ class UBPodcastPreferencesDialog : public QDialog QSpinBox* mBitRateSpinBox{nullptr}; QSpinBox* mFrameRateSpinBox{nullptr}; QTabWidget* mTabWidget{nullptr}; + QCheckBox* mPublishToIntranet{nullptr}; + QCheckBox* mPublishToYoutube{nullptr}; QPushButton* mResetPenButton{nullptr}; QPushButton* mResetMarkerButton{nullptr}; QList mBitRateProfileValues; From 42937b3f701d29ec362f7f064e5f7e530804cdc4 Mon Sep 17 00:00:00 2001 From: Vekhir Date: Thu, 9 Apr 2026 03:30:27 +0200 Subject: [PATCH 3/3] refactor: Remove redundant recording preferences --- resources/forms/mainWindow.ui | 12 -- src/podcast/UBPodcastController.cpp | 162 ---------------------- src/podcast/UBPodcastController.h | 25 ---- src/podcast/UBPodcastRecordingPalette.cpp | 50 +------ 4 files changed, 4 insertions(+), 245 deletions(-) diff --git a/resources/forms/mainWindow.ui b/resources/forms/mainWindow.ui index 5f1e0ab53..557cc8f81 100644 --- a/resources/forms/mainWindow.ui +++ b/resources/forms/mainWindow.ui @@ -1683,18 +1683,6 @@ Configure Podcast Recording - - - - :/images/toolbar/settings.png:/images/toolbar/settings.png - - - Podcast Config - - - Configure Podcast Recording - - diff --git a/src/podcast/UBPodcastController.cpp b/src/podcast/UBPodcastController.cpp index 061a6ffad..5e7f8341f 100644 --- a/src/podcast/UBPodcastController.cpp +++ b/src/podcast/UBPodcastController.cpp @@ -94,13 +94,6 @@ UBPodcastController::UBPodcastController(QObject* pParent) , mRecordingState(Stopped) , mApplicationIsClosing(false) , mRecordingTimestampOffset(0) - , mDefaultAudioInputDeviceAction(0) - , mNoAudioInputDeviceAction(0) - , mSmallVideoSizeAction(0) - , mMediumVideoSizeAction(0) - , mFullVideoSizeAction(0) - , mYoutubePublicationAction(0) - , mIntranetPublicationAction(0) { connect(UBApplication::applicationController, SIGNAL(mainModeChanged(UBApplicationController::MainMode)), this, SLOT(applicationMainModeChanged(UBApplicationController::MainMode))); @@ -139,20 +132,6 @@ void UBPodcastController::applicationAboutToQuit() } } - -void UBPodcastController::groupActionTriggered(QAction* action) -{ - Q_UNUSED(action); - updateActionState(); -} - - -void UBPodcastController::actionToggled(bool checked) -{ - Q_UNUSED(checked); - updateActionState(); -} - void UBPodcastController::openPodcastPreferencesDialog() { if (mPodcastPreferencesDialog) @@ -231,37 +210,6 @@ void UBPodcastController::podcastPreferencesDialogAccepted() UBSettings::settings()->podcastPublishToYoutube->set(podcastPublishToYoutube); } -void UBPodcastController::updateActionState() -{ - if (mSmallVideoSizeAction && mSmallVideoSizeAction->isChecked()) - UBSettings::settings()->podcastVideoSize->set("Small"); - else if (mFullVideoSizeAction && mFullVideoSizeAction->isChecked()) - UBSettings::settings()->podcastVideoSize->set("Full"); - else - UBSettings::settings()->podcastVideoSize->reset(); - - UBSettings::settings()->podcastAudioRecordingDevice->reset(); - - if (mDefaultAudioInputDeviceAction && mDefaultAudioInputDeviceAction->isChecked()) - UBSettings::settings()->podcastAudioRecordingDevice->set("Default"); - else if (mNoAudioInputDeviceAction && mNoAudioInputDeviceAction->isChecked()) - UBSettings::settings()->podcastAudioRecordingDevice->set("None"); - else - { - foreach(QAction* action, mAudioInputDevicesActions) - { - if (action->isChecked()) - { - UBSettings::settings()->podcastAudioRecordingDevice->set(action->text()); - break; - } - } - } - - UBSettings::settings()->podcastPublishToYoutube->set(mYoutubePublicationAction && mYoutubePublicationAction->isChecked()); - UBSettings::settings()->podcastPublishToIntranet->set(mIntranetPublicationAction && mIntranetPublicationAction->isChecked()); - -} void UBPodcastController::widgetSizeChanged(const QSizeF size) { @@ -1001,113 +949,3 @@ void UBPodcastController::setRecordingState(RecordingState pRecordingState) } } - -QList UBPodcastController::audioRecordingDevicesActions() -{ - if (mAudioInputDevicesActions.length() == 0) - { - QString settingsDevice = UBSettings::settings()->podcastAudioRecordingDevice->get().toString(); - - mDefaultAudioInputDeviceAction = new QAction(tr("Default Audio Input"), this); - QAction *checkedAction = mDefaultAudioInputDeviceAction; - - mNoAudioInputDeviceAction = new QAction(tr("No Audio Recording"), this); - - if (settingsDevice == "None") - checkedAction = mNoAudioInputDeviceAction; - - mAudioInputDevicesActions << mNoAudioInputDeviceAction; - mAudioInputDevicesActions << mDefaultAudioInputDeviceAction; - - foreach(QString audioDevice, audioRecordingDevices()) - { - QAction* act = new QAction(audioDevice, this); - act->setCheckable(true); - mAudioInputDevicesActions << act; - if (settingsDevice == audioDevice) - checkedAction = act; - } - - QActionGroup* audioInputActionGroup = new QActionGroup(this); - audioInputActionGroup->setExclusive(true); - - foreach(QAction* action, mAudioInputDevicesActions) - { - audioInputActionGroup->addAction(action); - action->setCheckable(true); - } - checkedAction->setChecked(true); - - connect(audioInputActionGroup, SIGNAL(triggered(QAction*)), this, SLOT(groupActionTriggered(QAction*))); - } - - return mAudioInputDevicesActions; - -} - - -QList UBPodcastController::videoSizeActions() -{ - if (mVideoSizesActions.length() == 0) - { - mSmallVideoSizeAction = new QAction(tr("Small"), this); - mMediumVideoSizeAction = new QAction(tr("Medium"), this); - mFullVideoSizeAction = new QAction(tr("Full"), this); - - mVideoSizesActions << mSmallVideoSizeAction; - mVideoSizesActions << mMediumVideoSizeAction; - mVideoSizesActions << mFullVideoSizeAction; - - QActionGroup* videoSizeActionGroup = new QActionGroup(this); - videoSizeActionGroup->setExclusive(true); - - foreach(QAction* videoSizeAction, mVideoSizesActions) - { - videoSizeAction->setCheckable(true); - videoSizeActionGroup->addAction(videoSizeAction); - } - - QString videoSize = UBSettings::settings()->podcastVideoSize->get().toString(); - - if (videoSize == "Small") - mSmallVideoSizeAction->setChecked(true); - else if (videoSize == "Full") - mFullVideoSizeAction->setChecked(true); - else - mMediumVideoSizeAction->setChecked(true); - - connect(videoSizeActionGroup, SIGNAL(triggered(QAction*)), this, SLOT(groupActionTriggered(QAction*))); - } - - return mVideoSizesActions; -} - - -QList UBPodcastController::podcastPublicationActions() -{ - if (mPodcastPublicationActions.length() == 0) - { - mIntranetPublicationAction = new QAction(tr("Publish to Intranet"), this); - - mIntranetPublicationAction->setCheckable(true); - mIntranetPublicationAction->setChecked(UBSettings::settings()->podcastPublishToIntranet->get().toBool()); - - mPodcastPublicationActions << mIntranetPublicationAction; - - mYoutubePublicationAction = new QAction(tr("Publish to Youtube"), this); - mYoutubePublicationAction->setCheckable(true); - mYoutubePublicationAction->setChecked(UBSettings::settings()->podcastPublishToYoutube->get().toBool()); - - mPodcastPublicationActions << mYoutubePublicationAction; - - foreach(QAction* publicationAction, mPodcastPublicationActions) - { - connect(publicationAction, SIGNAL(toggled(bool)), this, SLOT(actionToggled(bool))); - } - } - - return mPodcastPublicationActions; -} - - - diff --git a/src/podcast/UBPodcastController.h b/src/podcast/UBPodcastController.h index 948fdd736..90fb1d45e 100644 --- a/src/podcast/UBPodcastController.h +++ b/src/podcast/UBPodcastController.h @@ -60,11 +60,6 @@ class UBPodcastController : public QObject virtual QStringList audioRecordingDevices(); - QList audioRecordingDevicesActions(); - QList videoSizeActions(); - - QList podcastPublicationActions(); - enum RecordingState { Stopped = 0, Recording, Paused, Stopping @@ -122,11 +117,6 @@ class UBPodcastController : public QObject void applicationAboutToQuit(); - void groupActionTriggered(QAction*); - void actionToggled(bool); - - void updateActionState(); - private: void widgetSizeChanged(const QSizeF size); @@ -178,23 +168,8 @@ class UBPodcastController : public QObject QTime mTimeAtPaused; long mRecordingTimestampOffset; - QAction *mDefaultAudioInputDeviceAction; - QAction *mNoAudioInputDeviceAction; - - QList mAudioInputDevicesActions; - QList mVideoSizesActions; - QPointer mPodcastPreferencesDialog; - QAction* mSmallVideoSizeAction; - QAction* mMediumVideoSizeAction; - QAction* mFullVideoSizeAction; - - QList mPodcastPublicationActions; - - QAction *mYoutubePublicationAction; - QAction *mIntranetPublicationAction; - QString mPodcastRecordingPath; #ifdef Q_OS_LINUX diff --git a/src/podcast/UBPodcastRecordingPalette.cpp b/src/podcast/UBPodcastRecordingPalette.cpp index b561b1b6b..caf42f272 100644 --- a/src/podcast/UBPodcastRecordingPalette.cpp +++ b/src/podcast/UBPodcastRecordingPalette.cpp @@ -57,48 +57,6 @@ UBPodcastRecordingPalette::UBPodcastRecordingPalette(QWidget *parent) layout()->addWidget(mLevelMeter); addAction(UBApplication::mainWindow->actionPodcastPreferences); - addAction(UBApplication::mainWindow->actionPodcastConfig); - -#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)) - foreach(QObject* menuWidget, UBApplication::mainWindow->actionPodcastConfig->associatedObjects()) -#else - foreach(QWidget* menuWidget, UBApplication::mainWindow->actionPodcastConfig->associatedWidgets()) -#endif - { - QToolButton *tb = qobject_cast(menuWidget); - - tb->setIconSize(QSize(16, 16)); - - if (tb && !tb->menu()) - { - tb->setObjectName("ubButtonMenu"); - tb->setPopupMode(QToolButton::InstantPopup); - QMenu* menu = new QMenu(this); - - foreach(QAction* audioInputAction, UBPodcastController::instance()->audioRecordingDevicesActions()) - { - menu->addAction(audioInputAction); - } - - menu->addSeparator(); - - foreach(QAction* videoSizeAction, UBPodcastController::instance()->videoSizeActions()) - { - menu->addAction(videoSizeAction); - } - - menu->addSeparator(); - - QList podcastPublication = UBPodcastController::instance()->podcastPublicationActions(); - - foreach(QAction* publicationAction, podcastPublication) - { - menu->addAction(publicationAction); - } - - tb->setMenu(menu); - } - } } @@ -120,7 +78,7 @@ void UBPodcastRecordingPalette::recordingStateChanged(UBPodcastController::Recor //UBApplication::mainWindow->actionPodcastMic->setEnabled(false); - UBApplication::mainWindow->actionPodcastConfig->setEnabled(false); + UBApplication::mainWindow->actionPodcastPreferences->setEnabled(false); } else if (state == UBPodcastController::Stopped) { @@ -131,7 +89,7 @@ void UBPodcastRecordingPalette::recordingStateChanged(UBPodcastController::Recor UBApplication::mainWindow->actionPodcastPause->setEnabled(false); //UBApplication::mainWindow->actionPodcastMic->setEnabled(true); - UBApplication::mainWindow->actionPodcastConfig->setEnabled(true); + UBApplication::mainWindow->actionPodcastPreferences->setEnabled(true); } else if (state == UBPodcastController::Paused) { @@ -142,13 +100,13 @@ void UBPodcastRecordingPalette::recordingStateChanged(UBPodcastController::Recor UBApplication::mainWindow->actionPodcastPause->setEnabled(true); //UBApplication::mainWindow->actionPodcastMic->setEnabled(false); - UBApplication::mainWindow->actionPodcastConfig->setEnabled(false); + UBApplication::mainWindow->actionPodcastPreferences->setEnabled(false); } else { UBApplication::mainWindow->actionPodcastRecord->setEnabled(false); UBApplication::mainWindow->actionPodcastPause->setEnabled(false); - UBApplication::mainWindow->actionPodcastConfig->setEnabled(false); + UBApplication::mainWindow->actionPodcastPreferences->setEnabled(false); } }