Commit 8720afb4 authored by Jean-Baptiste Mardelle's avatar Jean-Baptiste Mardelle
Browse files

Reuse EncodingProfilesChooser in Project Settings to reduce code duplication,...

Reuse EncodingProfilesChooser in Project Settings to reduce code duplication, don't allow selecting incompatible preview profile
parent 5adbacd8
......@@ -5,12 +5,14 @@ SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
*/
#include "encodingprofilesdialog.h"
#include "kdenlivesettings.h"
#include "profiles/profilemodel.hpp"
#include "profiles/profilerepository.hpp"
#include "klocalizedstring.h"
#include <QLineEdit>
#include <QPlainTextEdit>
#include <QStandardItemModel>
#include <QStandardPaths>
#include <QVBoxLayout>
......@@ -182,14 +184,15 @@ void EncodingProfilesDialog::slotEditProfile()
delete d;
}
EncodingProfilesChooser::EncodingProfilesChooser(QWidget *parent, EncodingProfilesManager::ProfileType type, bool showAutoItem, const QString &configName)
EncodingProfilesChooser::EncodingProfilesChooser(QWidget *parent, EncodingProfilesManager::ProfileType type, bool showAutoItem, const QString &configName,
const QString &selectByValue)
: QWidget(parent)
, m_type(type)
, m_showAutoItem(showAutoItem)
{
QVBoxLayout *grid = new QVBoxLayout(this);
grid->setContentsMargins(0, 0, 0, 0);
m_profilesCombo = new QComboBox();
m_profilesCombo = new QComboBox(this);
if (!configName.isEmpty()) {
m_profilesCombo->setObjectName(QStringLiteral("kcfg_%1").arg(configName));
}
......@@ -206,7 +209,7 @@ EncodingProfilesChooser::EncodingProfilesChooser(QWidget *parent, EncodingProfil
m_info = new QPlainTextEdit();
m_info->setReadOnly(true);
m_info->setMaximumHeight(QFontMetrics(font()).lineSpacing() * 4);
QHBoxLayout *hor = new QHBoxLayout(this);
QHBoxLayout *hor = new QHBoxLayout;
hor->addWidget(m_profilesCombo);
hor->addWidget(buttonConfigure);
hor->addWidget(buttonInfo);
......@@ -222,6 +225,16 @@ EncodingProfilesChooser::EncodingProfilesChooser(QWidget *parent, EncodingProfil
int ix = resourceConfig.readEntry(configName).toInt();
m_profilesCombo->setCurrentIndex(ix);
slotUpdateProfile(ix);
} else if (!selectByValue.isEmpty()) {
int ix = m_profilesCombo->findData(selectByValue);
if (ix == -1) {
m_profilesCombo->addItem(i18n("Current Settings"), selectByValue);
ix = m_profilesCombo->findData(selectByValue);
}
if (ix > -1) {
m_profilesCombo->setCurrentIndex(ix);
slotUpdateProfile(ix);
}
}
setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Maximum);
}
......@@ -236,12 +249,15 @@ void EncodingProfilesChooser::slotManageEncodingProfile()
void EncodingProfilesChooser::loadEncodingProfiles()
{
m_profilesCombo->blockSignals(true);
QString currentItem = m_profilesCombo->currentText();
m_profilesCombo->clear();
if (m_showAutoItem) {
m_profilesCombo->addItem(i18n("Automatic"));
if (m_type == EncodingProfilesManager::TimelinePreview && (KdenliveSettings::nvencEnabled() || KdenliveSettings::vaapiEnabled())) {
m_profilesCombo->addItem(QIcon::fromTheme(QStringLiteral("speedometer")), i18n("Automatic"));
} else {
m_profilesCombo->addItem(i18n("Automatic"));
}
}
KConfig conf(QStringLiteral("encodingprofiles.rc"), KConfig::CascadeConfig, QStandardPaths::AppDataLocation);
......@@ -251,6 +267,21 @@ void EncodingProfilesChooser::loadEncodingProfiles()
while (i.hasNext()) {
i.next();
if (!i.key().isEmpty()) {
if (m_type == EncodingProfilesManager::TimelinePreview) {
// We filter out incompatible profiles
if (i.value().contains(QLatin1String("nvenc"))) {
if (KdenliveSettings::nvencEnabled()) {
m_profilesCombo->addItem(QIcon::fromTheme(QStringLiteral("speedometer")), i.key(), i.value());
}
continue;
}
if (i.value().contains(QLatin1String("vaapi"))) {
if (KdenliveSettings::vaapiEnabled()) {
m_profilesCombo->addItem(QIcon::fromTheme(QStringLiteral("speedometer")), i.key(), i.value());
}
continue;
}
}
m_profilesCombo->addItem(i.key(), i.value());
}
}
......@@ -262,6 +293,46 @@ void EncodingProfilesChooser::loadEncodingProfiles()
m_profilesCombo->blockSignals(false);
}
void EncodingProfilesChooser::filterPreviewProfiles(const QString &profile)
{
QStandardItemModel *model = qobject_cast<QStandardItemModel *>(m_profilesCombo->model());
Q_ASSERT(model != nullptr);
int max = m_profilesCombo->count();
int current = m_profilesCombo->currentIndex();
double projectFps = ProfileRepository::get()->getProfile(profile)->fps();
for (int i = 0; i < max; i++) {
QString itemData = m_profilesCombo->itemData(i).toString();
double fps = 0.;
if (itemData.startsWith(QStringLiteral("r="))) {
QString fpsString = itemData.section(QLatin1Char('='), 1).section(QLatin1Char(' '), 0, 0);
fps = fpsString.toDouble();
} else if (itemData.contains(QStringLiteral(" r="))) {
QString fpsString = itemData.section(QLatin1String(" r="), 1).section(QLatin1Char(' '), 0, 0);
// This profile has a hardcoded framerate, chack if same as project
fps = fpsString.toDouble();
}
if (fps > 0. && qAbs(fps - projectFps) > 0.01) {
// Fps does not match, disable
QStandardItem *item = model->item(i);
item->setFlags(item->flags() & ~Qt::ItemIsEnabled);
continue;
}
QStandardItem *item = model->item(i);
item->setFlags(item->flags() | Qt::ItemIsEnabled);
}
QStandardItem *item = model->item(current);
if (!(item->flags() & Qt::ItemIsEnabled)) {
// Currently selected profile is not usable, switch back to automatic
for (int i = 0; i < max; i++) {
if (m_profilesCombo->itemData(i).isNull()) {
m_profilesCombo->setCurrentIndex(i);
emit incompatibleProfile();
break;
}
}
}
}
QString EncodingProfilesChooser::currentExtension()
{
QString profilestr = m_profilesCombo->currentData().toString();
......
......@@ -51,9 +51,12 @@ class EncodingProfilesChooser : public QWidget
Q_OBJECT
public:
EncodingProfilesChooser(QWidget *parent, EncodingProfilesManager::ProfileType, bool showAutoItem = false, const QString &configname = {});
EncodingProfilesChooser(QWidget *parent, EncodingProfilesManager::ProfileType, bool showAutoItem = false, const QString &configname = {},
const QString &selectByValue = {});
QString currentExtension();
QString currentParams();
/** @brief Only enable preview profiles with matching framerate */
void filterPreviewProfiles(const QString &profile);
public slots:
void slotUpdateProfile(int ix);
......@@ -68,4 +71,6 @@ private slots:
void slotManageEncodingProfile();
void loadEncodingProfiles();
signals:
void incompatibleProfile();
};
......@@ -260,16 +260,20 @@ void KdenliveSettingsDialog::initProjectPage()
{
QWidget *p8 = new QWidget;
m_configProject.setupUi(p8);
m_configProject.profileWarning->hide();
// Timeline preview
m_tlPreviewProfiles = new EncodingProfilesChooser(p8, EncodingProfilesManager::TimelinePreview, true, QStringLiteral("preview_profile"));
m_configProject.preview_profile_box->addWidget(m_tlPreviewProfiles);
auto *vbox = new QVBoxLayout;
m_pw = new ProfileWidget(this);
vbox->addWidget(m_pw);
connect(m_pw, &ProfileWidget::profileChanged, this, [this]() { m_tlPreviewProfiles->filterPreviewProfiles(m_pw->selectedProfile()); });
connect(m_tlPreviewProfiles, &EncodingProfilesChooser::incompatibleProfile, m_configProject.profileWarning, &KMessageWidget::animatedShow);
m_configProject.profile_box->setLayout(vbox);
m_configProject.profile_box->setTitle(i18n("Select the Default Profile (preset)"));
// Select profile
m_pw->loadProfile(KdenliveSettings::default_profile().isEmpty() ? pCore->getCurrentProfile()->path() : KdenliveSettings::default_profile());
m_tlPreviewProfiles->filterPreviewProfiles(m_pw->selectedProfile());
connect(m_pw, &ProfileWidget::profileChanged, this, &KdenliveSettingsDialog::slotDialogModified);
m_configProject.projecturl->setMode(KFile::Directory);
m_configProject.projecturl->setUrl(QUrl::fromLocalFile(KdenliveSettings::defaultprojectfolder()));
......
......@@ -11,13 +11,13 @@ SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
#include "bin/projectfolder.h"
#include "bin/projectitemmodel.h"
#include "core.h"
#include "dialogs/encodingprofilesdialog.h"
#include "dialogs/profilesdialog.h"
#include "doc/kdenlivedoc.h"
#include "kdenlivesettings.h"
#include "mainwindow.h"
#include "mltcontroller/clipcontroller.h"
#include "profiles/profilemodel.hpp"
#include "profiles/profilerepository.hpp"
#include "project/dialogs/profilewidget.h"
#include "project/dialogs/temporarydata.h"
#include "titler/titlewidget.h"
......@@ -32,6 +32,7 @@ SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
#include <QDir>
#include <QFileDialog>
#include <QInputDialog>
#include <QStandardItemModel>
#include <QStyledItemDelegate>
#include <QTemporaryFile>
......@@ -60,6 +61,7 @@ ProjectSettings::ProjectSettings(KdenliveDoc *doc, QMap<QString, QString> metada
{
setupUi(this);
tabWidget->setTabBarAutoHide(true);
previewWarning->hide();
auto *vbox = new QVBoxLayout;
vbox->setContentsMargins(0, 0, 0, 0);
m_pw = new ProfileWidget(this);
......@@ -166,9 +168,16 @@ ProjectSettings::ProjectSettings(KdenliveDoc *doc, QMap<QString, QString> metada
proxy_minsize->setEnabled(generate_proxy->isChecked());
proxy_imageminsize->setEnabled(generate_imageproxy->isChecked());
QString currentProfileParams;
if (!m_previewparams.isEmpty() || !m_previewextension.isEmpty()) {
currentProfileParams = QString("%1;%2").arg(m_previewparams, m_previewextension);
}
m_tlPreviewProfiles = new EncodingProfilesChooser(this, EncodingProfilesManager::TimelinePreview, true, QStringLiteral(), currentProfileParams);
preview_profile_box->addWidget(m_tlPreviewProfiles);
connect(m_pw, &ProfileWidget::profileChanged, this, [this]() { m_tlPreviewProfiles->filterPreviewProfiles(m_pw->selectedProfile()); });
connect(m_tlPreviewProfiles, &EncodingProfilesChooser::incompatibleProfile, previewWarning, &KMessageWidget::animatedShow);
m_tlPreviewProfiles->filterPreviewProfiles(currentProf);
loadProxyProfiles();
loadPreviewProfiles();
loadExternalProxyProfiles();
// Proxy GUI stuff
......@@ -189,20 +198,6 @@ ProjectSettings::ProjectSettings(KdenliveDoc *doc, QMap<QString, QString> metada
external_proxy_profile->setToolTip(i18n("Select camcorder profile"));
// Preview GUI stuff
preview_showprofileinfo->setIcon(QIcon::fromTheme(QStringLiteral("help-about")));
preview_showprofileinfo->setToolTip(i18n("Show default profile parameters"));
preview_manageprofile->setIcon(QIcon::fromTheme(QStringLiteral("configure")));
preview_manageprofile->setToolTip(i18n("Manage timeline preview profiles"));
connect(preview_manageprofile, &QAbstractButton::clicked, this, &ProjectSettings::slotManagePreviewProfile);
preview_profile->setToolTip(i18n("Select default preview profile"));
connect(preview_profile, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &ProjectSettings::slotUpdatePreviewParams);
previewparams->setVisible(false);
previewparams->setMaximumHeight(QFontMetrics(font()).lineSpacing() * 5);
connect(preview_showprofileinfo, &QAbstractButton::clicked, previewparams, &QWidget::setVisible);
if (readOnlyTracks) {
video_tracks->setEnabled(false);
audio_tracks->setEnabled(false);
......@@ -492,7 +487,7 @@ void ProjectSettings::slotUpdateFiles(bool cacheOnly)
const QString ProjectSettings::selectedPreview() const
{
return preview_profile->itemData(preview_profile->currentIndex()).toString();
return QString("%1;%2").arg(m_tlPreviewProfiles->currentParams(), m_tlPreviewProfiles->currentExtension());
}
void ProjectSettings::accept()
......@@ -501,7 +496,7 @@ void ProjectSettings::accept()
KMessageBox::error(this, i18n("Please select a video profile"));
return;
}
QString params = preview_profile->itemData(preview_profile->currentIndex()).toString();
QString params = selectedPreview();
if (!params.isEmpty()) {
if (params.section(QLatin1Char(';'), 0, 0) != m_previewparams || params.section(QLatin1Char(';'), 1, 1) != m_previewextension) {
// Timeline preview settings changed, warn if there are existing previews
......@@ -637,14 +632,12 @@ QString ProjectSettings::proxyExtension() const
QString ProjectSettings::previewParams() const
{
QString params = preview_profile->itemData(preview_profile->currentIndex()).toString();
return params.section(QLatin1Char(';'), 0, 0);
return m_tlPreviewProfiles->currentParams();
}
QString ProjectSettings::previewExtension() const
{
QString params = preview_profile->itemData(preview_profile->currentIndex()).toString();
return params.section(QLatin1Char(';'), 1, 1);
return m_tlPreviewProfiles->currentExtension();
}
// static
......@@ -809,12 +802,6 @@ void ProjectSettings::slotUpdateProxyParams()
proxyparams->setPlainText(params.section(QLatin1Char(';'), 0, 0));
}
void ProjectSettings::slotUpdatePreviewParams()
{
QString params = preview_profile->currentData().toString();
previewparams->setPlainText(params.section(QLatin1Char(';'), 0, 0));
}
const QMap<QString, QString> ProjectSettings::metadata() const
{
QMap<QString, QString> metadata;
......@@ -859,14 +846,6 @@ void ProjectSettings::slotManageEncodingProfile()
loadProxyProfiles();
}
void ProjectSettings::slotManagePreviewProfile()
{
QPointer<EncodingProfilesDialog> d = new EncodingProfilesDialog(EncodingProfilesManager::TimelinePreview);
d->exec();
delete d;
loadPreviewProfiles();
}
void ProjectSettings::loadProxyProfiles()
{
// load proxy profiles
......@@ -945,56 +924,6 @@ void ProjectSettings::loadExternalProxyProfiles()
external_proxy_profile->setCurrentIndex(ix);
}
void ProjectSettings::loadPreviewProfiles()
{
// load proxy profiles
KConfig conf(QStringLiteral("encodingprofiles.rc"), KConfig::CascadeConfig, QStandardPaths::AppDataLocation);
KConfigGroup group(&conf, "timelinepreview");
QMap<QString, QString> values = group.entryMap();
QMapIterator<QString, QString> k(values);
int ix = -1;
preview_profile->clear();
while (k.hasNext()) {
k.next();
if (!k.key().isEmpty()) {
QString params = k.value().section(QLatin1Char(';'), 0, 0);
QString extension = k.value().section(QLatin1Char(';'), 1, 1);
if (ix == -1 && (params == m_previewparams && extension == m_previewextension)) {
// this is the current profile
ix = preview_profile->count();
}
if (params.contains(QLatin1String("nvenc"))) {
preview_profile->addItem(KdenliveSettings::nvencEnabled() ? QIcon::fromTheme(QStringLiteral("speedometer"))
: QIcon::fromTheme(QStringLiteral("dialog-cancel")),
k.key(), k.value());
} else {
preview_profile->addItem(k.key(), k.value());
}
}
}
if (ix == -1) {
// Current project proxy settings not found
ix = preview_profile->count();
if (m_previewparams.isEmpty() && m_previewextension.isEmpty()) {
// Leave empty, will be automatically detected
if (KdenliveSettings::nvencEnabled()) {
preview_profile->addItem(QIcon::fromTheme(QStringLiteral("speedometer")), i18n("Automatic"));
} else {
preview_profile->addItem(i18n("Automatic"));
}
} else {
if (m_previewparams.contains(QLatin1String("nvenc"))) {
preview_profile->addItem(QIcon::fromTheme(QStringLiteral("speedometer")), i18n("Current Settings"),
QString(m_previewparams + QLatin1Char(';') + m_previewextension));
} else {
preview_profile->addItem(i18n("Current Settings"), QString(m_previewparams + QLatin1Char(';') + m_previewextension));
}
}
}
preview_profile->setCurrentIndex(ix);
slotUpdatePreviewParams();
}
const QString ProjectSettings::storageFolder() const
{
if (custom_folder->isChecked()) {
......
......@@ -6,6 +6,8 @@ SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
#pragma once
#include "dialogs/encodingprofilesdialog.h"
#include <QDialog>
#include <QPushButton>
......@@ -58,14 +60,12 @@ private slots:
void slotExportToText();
/** @brief Update the displayed proxy parameters when user changes selection. */
void slotUpdateProxyParams();
void slotUpdatePreviewParams();
/** @brief Insert a new metadata field. */
void slotAddMetadataField();
/** @brief Delete current metadata field. */
void slotDeleteMetadataField();
/** @brief Display proxy profiles management dialog. */
void slotManageEncodingProfile();
void slotManagePreviewProfile();
/** @brief Open editor for metadata item. */
void slotEditMetadata(QTreeWidgetItem *, int);
/** @brief Shows external proxy settings. */
......@@ -93,8 +93,9 @@ private:
QString m_previewparams;
QString m_previewextension;
QString m_initialExternalProxyProfile;
EncodingProfilesChooser *m_tlPreviewProfiles;
/** @brief Fill the proxy profiles combobox. */
void loadPreviewProfiles();
// void loadPreviewProfiles();
signals:
/** @brief User deleted proxies, so disable them in project. */
......
......@@ -17,23 +17,19 @@
<property name="topMargin">
<number>0</number>
</property>
<item row="1" column="1">
<widget class="QSpinBox" name="kcfg_videotracks"/>
</item>
<item row="0" column="0" colspan="7">
<widget class="QGroupBox" name="profile_box">
<property name="flat">
<bool>true</bool>
</property>
</widget>
</item>
<item row="1" column="4">
<widget class="QLabel" name="label">
<item row="1" column="2">
<widget class="QLabel" name="label_7">
<property name="text">
<string>Audio channels:</string>
<string>Audio tracks</string>
</property>
</widget>
</item>
<item row="1" column="3">
<widget class="QSpinBox" name="kcfg_audiotracks"/>
</item>
<item row="1" column="1">
<widget class="QSpinBox" name="kcfg_videotracks"/>
</item>
<item row="3" column="0" colspan="6">
<widget class="QCheckBox" name="kcfg_sameprojectfolder">
<property name="text">
......@@ -41,15 +37,18 @@
</property>
</widget>
</item>
<item row="1" column="3">
<widget class="QSpinBox" name="kcfg_audiotracks"/>
</item>
<item row="1" column="2">
<widget class="QLabel" name="label_7">
<property name="text">
<string>Audio tracks</string>
<item row="8" column="0">
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
</widget>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_6">
......@@ -58,6 +57,13 @@
</property>
</widget>
</item>
<item row="0" column="0" colspan="7">
<widget class="QGroupBox" name="profile_box">
<property name="flat">
<bool>true</bool>
</property>
</widget>
</item>
<item row="1" column="5">
<widget class="QComboBox" name="kcfg_audio_channels">
<property name="sizePolicy">
......@@ -83,18 +89,29 @@
</item>
</widget>
</item>
<item row="7" column="0">
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
<item row="6" column="0" colspan="6">
<layout class="QHBoxLayout" name="preview_profile_box">
<item>
<widget class="QLabel" name="label_25">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Timeline Preview</string>
</property>
</widget>
</item>
</layout>
</item>
<item row="1" column="4">
<widget class="QLabel" name="label">
<property name="text">
<string>Audio channels:</string>
</property>
</spacer>
</widget>
</item>
<item row="2" column="0" colspan="6">
<layout class="QHBoxLayout" name="horizontalLayout_2">
......@@ -114,22 +131,16 @@
</item>
</layout>
</item>
<item row="6" column="0" colspan="6">
<layout class="QHBoxLayout" name="preview_profile_box">
<item>
<widget class="QLabel" name="label_25">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Timeline Preview</string>
</property>
</widget>
</item>
</layout>
<item row="7" column="0" colspan="6">
<widget class="KMessageWidget" name="profileWarning">
<property name="text">
<string>Selected Timeline preview profile is not compatible with the project framerate,
reverting to Automatic.</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</widget>
......@@ -140,6 +151,11 @@
<header>kurlrequester.h</header>
<container>1</container>
</customwidget>
<customwidget>
<class>KMessageWidget</class>
<extends>QFrame</extends>
<header>kmessagewidget.h</header>
</customwidget>
</customwidgets>
<tabstops>
<tabstop>kcfg_videotracks</tabstop>
......
......@@ -37,30 +37,50 @@
<string>Settings</string>
</attribute>
<layout class="QGridLayout" name="gridLayout">
<item row="7" column="0" colspan="4">
<widget class="QPlainTextEdit" name="previewparams">
<item row="5" column="3">
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>229</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="3" column="0" colspan="4">
<widget class="QGroupBox" name="profile_box">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Maximum">
<sizepolicy hsizetype="Preferred" vsizetype="MinimumExpanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="readOnly">
<property name="flat">
<bool>true</bool>
</property>
</widget>
</item>
<item row="5" column="0">
<widget class="QLabel" name="label_2">
<item row="7" column="0" colspan="4">
<widget class="KMessageWidget" name="previewWarning">
<property name="text">