You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
nmWTAI-Platform/Src/nmNum/nmSubWxs/nmWxPebiResultAnimationExpo...

624 lines
23 KiB
C++

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

#include "nmWxPebiResultAnimationExportDlg.h"
#include "nmFFmpegVideoWriter.h"
#include "ZxBaseUtil.h"
#include <QButtonGroup>
#include <QComboBox>
#include <QCoreApplication>
#include <QDialogButtonBox>
#include <QDir>
#include <QFileDialog>
#include <QFileInfo>
#include <QGridLayout>
#include <QGroupBox>
#include <QIcon>
#include <QLabel>
#include <QLineEdit>
#include <QMessageBox>
#include <QPushButton>
#include <QRadioButton>
#include <QSizePolicy>
#include <QSpinBox>
#include <QVBoxLayout>
#include <QVariant>
namespace {
QString exportDialogIconPath(const QString& sFileName)
{
const QString sApplicationDir = QCoreApplication::applicationDirPath();
return sApplicationDir.section('/', 0, -2) +
"/Res/Icon/" + sFileName;
}
QLabel* createRightAlignedLabel(const QString& sText, QWidget* pParent)
{
QLabel* pLabel = new QLabel(sText, pParent);
pLabel->setAlignment(Qt::AlignRight | Qt::AlignVCenter);
return pLabel;
}
QString formatPixelSize(int nWidth, int nHeight)
{
QString sText = QString::number(nWidth);
sText.append(' ');
sText.append(QChar(0x00D7));
sText.append(QString::fromLatin1(" %1 px").arg(nHeight));
return sText;
}
}
nmWxPebiResultAnimationExportDlg::nmWxPebiResultAnimationExportDlg(
const QVector<double>& vecFrameTimesHours,
const QSize& oCurrentViewportSize,
QWidget* pParent)
: iDlgBase(pParent),
m_vecFrameTimesHours(vecFrameTimesHours),
m_pFpsSpinBox(nullptr),
m_pStartFrameCombo(nullptr),
m_pEndFrameCombo(nullptr),
m_pSamplingIntervalSpinBox(nullptr),
m_pResolutionButtonGroup(nullptr),
m_pCurrentSizeRadioButton(nullptr),
m_p720pRadioButton(nullptr),
m_p1080pRadioButton(nullptr),
m_pCustomSizeRadioButton(nullptr),
m_pWidthSpinBox(nullptr),
m_pHeightSpinBox(nullptr),
m_pVideoFormatCombo(nullptr),
m_pTargetPathEdit(nullptr),
m_pOutputFrameCountLabel(nullptr),
m_pEstimatedDurationLabel(nullptr),
m_pErrorLabel(nullptr)
{
int nCurrentWidth = oCurrentViewportSize.width();
int nCurrentHeight = oCurrentViewportSize.height();
if(nCurrentWidth <= 0 || nCurrentHeight <= 0) {
nCurrentWidth = 1280;
nCurrentHeight = 720;
}
m_oEffectiveCurrentViewportSize = QSize(
normalizeEvenDimension(nCurrentWidth),
normalizeEvenDimension(nCurrentHeight));
createUi();
populateFrameItems();
populateVideoFormats();
setTargetFilePath(getSuggestedTargetFilePath());
onResolutionPresetChanged(Resolution_CurrentView);
onFrameRangeChanged();
}
nmPebiResultAnimationExportSettings
nmWxPebiResultAnimationExportDlg::getSettings() const
{
return m_oAcceptedSettings;
}
QString nmWxPebiResultAnimationExportDlg::getTargetFilePath() const
{
return m_sAcceptedTargetFilePath;
}
void nmWxPebiResultAnimationExportDlg::onFrameRangeChanged()
{
const int nStartIndex = m_pStartFrameCombo->currentIndex();
if(nStartIndex >= 0 &&
m_pEndFrameCombo->currentIndex() < nStartIndex) {
const bool bBlocked = m_pEndFrameCombo->blockSignals(true);
m_pEndFrameCombo->setCurrentIndex(nStartIndex);
m_pEndFrameCombo->blockSignals(bBlocked);
}
const int nRangeLength = qMax(1,
m_pEndFrameCombo->currentIndex() -
m_pStartFrameCombo->currentIndex());
m_pSamplingIntervalSpinBox->setMaximum(nRangeLength);
updateSummary();
}
void nmWxPebiResultAnimationExportDlg::onResolutionPresetChanged(
int nPresetId)
{
const bool bCustom = nPresetId == Resolution_Custom;
m_pWidthSpinBox->setEnabled(bCustom);
m_pHeightSpinBox->setEnabled(bCustom);
updateSummary();
}
void nmWxPebiResultAnimationExportDlg::normalizeCustomDimensions()
{
// editingFinished后再回写,避免valueChanged期间干扰用户键盘输入。
m_pWidthSpinBox->setValue(
normalizeEvenDimension(m_pWidthSpinBox->value()));
m_pHeightSpinBox->setValue(
normalizeEvenDimension(m_pHeightSpinBox->value()));
updateSummary();
}
void nmWxPebiResultAnimationExportDlg::updateSummary()
{
const nmPebiResultAnimationExportSettings oSettings =
collectSettings();
const int nOutputFrameCount = oSettings.getOutputFrameCount();
m_pOutputFrameCountLabel->setText(
tr("%1 frames").arg(nOutputFrameCount));
const double dDuration = oSettings.m_nFramesPerSecond > 0
? static_cast<double>(nOutputFrameCount) /
static_cast<double>(oSettings.m_nFramesPerSecond)
: 0.0;
m_pEstimatedDurationLabel->setText(
tr("%1 s").arg(QString::number(dDuration, 'g', 4)));
clearError();
}
void nmWxPebiResultAnimationExportDlg::onVideoFormatChanged(int nIndex)
{
Q_UNUSED(nIndex);
if(m_pTargetPathEdit != nullptr &&
!m_pTargetPathEdit->text().isEmpty()) {
setTargetFilePath(normalizeTargetFilePath(
m_pTargetPathEdit->text()));
}
clearError();
}
void nmWxPebiResultAnimationExportDlg::browseTargetFile()
{
const QString sExtension = getSelectedVideoExtension();
if(sExtension.isEmpty()) {
showError(tr("The selected video format is unsupported."));
return;
}
const QString sInitialPath = m_pTargetPathEdit->text().isEmpty()
? getSuggestedTargetFilePath() : m_pTargetPathEdit->text();
const QFileInfo oInitialFileInfo(sInitialPath);
QFileDialog oFileDialog(this, tr("Save Result Animation"));
oFileDialog.setAcceptMode(QFileDialog::AcceptSave);
oFileDialog.setFileMode(QFileDialog::AnyFile);
oFileDialog.setNameFilter(getSelectedVideoFilter());
oFileDialog.setDefaultSuffix(sExtension);
oFileDialog.setOption(QFileDialog::DontConfirmOverwrite, true);
oFileDialog.setDirectory(oInitialFileInfo.absolutePath());
oFileDialog.selectFile(oInitialFileInfo.fileName());
if(oFileDialog.exec() != QDialog::Accepted ||
oFileDialog.selectedFiles().isEmpty()) {
return;
}
const QString sTargetPath = normalizeTargetFilePath(
oFileDialog.selectedFiles().first());
const QFileInfo oTargetFileInfo(sTargetPath);
setTargetFilePath(oTargetFileInfo.absoluteFilePath());
ZxBaseUtil::setLastDir(oTargetFileInfo.absolutePath());
clearError();
}
void nmWxPebiResultAnimationExportDlg::acceptSettings()
{
// 只有自定义模式需要把编辑值回写为编码器最终使用的偶数尺寸。
if(m_pCustomSizeRadioButton->isChecked()) {
normalizeCustomDimensions();
}
const nmPebiResultAnimationExportSettings oSettings =
collectSettings();
if(!oSettings.isValid(m_vecFrameTimesHours.size())) {
showError(tr("The animation export settings are invalid."));
return;
}
if(m_pTargetPathEdit->text().isEmpty()) {
showError(tr("Please select an output file."));
return;
}
const QString sExtension = getSelectedVideoExtension();
if(sExtension.isEmpty()) {
showError(tr("The selected video format is unsupported."));
return;
}
const QString sTargetPath = QFileInfo(normalizeTargetFilePath(
m_pTargetPathEdit->text())).absoluteFilePath();
const QFileInfo oTargetFileInfo(sTargetPath);
if(oTargetFileInfo.suffix().compare(
sExtension, Qt::CaseInsensitive) != 0) {
showError(tr("The selected video file extension does not match "
"the selected format."));
return;
}
if(oTargetFileInfo.isDir()) {
showError(tr("The selected output path is a directory."));
return;
}
if(!QDir(oTargetFileInfo.absolutePath()).exists()) {
showError(tr("The selected output directory does not exist."));
return;
}
setTargetFilePath(sTargetPath);
if(oTargetFileInfo.exists() &&
QMessageBox::question(
this, tr("Export Animation"),
tr("The selected file already exists. Replace it?"),
QMessageBox::Yes | QMessageBox::No,
QMessageBox::No) != QMessageBox::Yes) {
return;
}
m_oAcceptedSettings = oSettings;
m_sAcceptedTargetFilePath = sTargetPath;
accept();
}
void nmWxPebiResultAnimationExportDlg::createUi()
{
setWindowTitle(tr("Export Animation"));
setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
setMinimumWidth(460);
QVBoxLayout* pMainLayout = new QVBoxLayout(this);
pMainLayout->setContentsMargins(12, 10, 12, 10);
pMainLayout->setSpacing(8);
QGroupBox* pFrameGroup = new QGroupBox(tr("Frame Settings"), this);
QGridLayout* pFrameGrid = new QGridLayout(pFrameGroup);
pFrameGrid->setHorizontalSpacing(8);
pFrameGrid->setVerticalSpacing(6);
pFrameGrid->setColumnStretch(1, 1);
const QSizePolicy oFieldSizePolicy(
QSizePolicy::Expanding, QSizePolicy::Fixed);
m_pFpsSpinBox = new QSpinBox(pFrameGroup);
m_pFpsSpinBox->setRange(1, 5000);
m_pFpsSpinBox->setValue(15);
m_pFpsSpinBox->setSuffix(tr(" FPS"));
m_pFpsSpinBox->setSizePolicy(oFieldSizePolicy);
pFrameGrid->addWidget(
createRightAlignedLabel(tr("Frame rate"), pFrameGroup), 0, 0);
pFrameGrid->addWidget(m_pFpsSpinBox, 0, 1);
m_pStartFrameCombo = new QComboBox(pFrameGroup);
m_pStartFrameCombo->setSizePolicy(oFieldSizePolicy);
pFrameGrid->addWidget(
createRightAlignedLabel(tr("Start time"), pFrameGroup), 1, 0);
pFrameGrid->addWidget(m_pStartFrameCombo, 1, 1);
m_pEndFrameCombo = new QComboBox(pFrameGroup);
m_pEndFrameCombo->setSizePolicy(oFieldSizePolicy);
pFrameGrid->addWidget(
createRightAlignedLabel(tr("End time"), pFrameGroup), 2, 0);
pFrameGrid->addWidget(m_pEndFrameCombo, 2, 1);
m_pSamplingIntervalSpinBox = new QSpinBox(pFrameGroup);
m_pSamplingIntervalSpinBox->setRange(1, 1);
m_pSamplingIntervalSpinBox->setSizePolicy(oFieldSizePolicy);
pFrameGrid->addWidget(
createRightAlignedLabel(tr("Frame step"), pFrameGroup), 3, 0);
pFrameGrid->addWidget(m_pSamplingIntervalSpinBox, 3, 1);
pMainLayout->addWidget(pFrameGroup);
QGroupBox* pOutputSizeGroup = new QGroupBox(tr("Output Size"), this);
QGridLayout* pOutputSizeGrid = new QGridLayout(pOutputSizeGroup);
pOutputSizeGrid->setHorizontalSpacing(6);
pOutputSizeGrid->setVerticalSpacing(6);
m_pResolutionButtonGroup = new QButtonGroup(this);
m_pCurrentSizeRadioButton = new QRadioButton(
tr("Current image size") + QString::fromLatin1(" ") +
formatPixelSize(m_oEffectiveCurrentViewportSize.width(),
m_oEffectiveCurrentViewportSize.height()),
pOutputSizeGroup);
m_p720pRadioButton = new QRadioButton(
formatPixelSize(1280, 720), pOutputSizeGroup);
m_p1080pRadioButton = new QRadioButton(
formatPixelSize(1920, 1080), pOutputSizeGroup);
m_pCustomSizeRadioButton = new QRadioButton(
tr("Custom size"), pOutputSizeGroup);
m_pResolutionButtonGroup->addButton(
m_pCurrentSizeRadioButton, Resolution_CurrentView);
m_pResolutionButtonGroup->addButton(
m_p720pRadioButton, Resolution_720p);
m_pResolutionButtonGroup->addButton(
m_p1080pRadioButton, Resolution_1080p);
m_pResolutionButtonGroup->addButton(
m_pCustomSizeRadioButton, Resolution_Custom);
m_pCurrentSizeRadioButton->setChecked(true);
pOutputSizeGrid->addWidget(
m_pCurrentSizeRadioButton, 0, 1, 1, 5, Qt::AlignLeft);
pOutputSizeGrid->addWidget(
m_p720pRadioButton, 1, 1, 1, 5, Qt::AlignLeft);
pOutputSizeGrid->addWidget(
m_p1080pRadioButton, 2, 1, 1, 5, Qt::AlignLeft);
pOutputSizeGrid->addWidget(m_pCustomSizeRadioButton, 3, 1, Qt::AlignLeft);
m_pWidthSpinBox = new QSpinBox(pOutputSizeGroup);
m_pHeightSpinBox = new QSpinBox(pOutputSizeGroup);
m_pWidthSpinBox->setRange(2, 8192);
m_pHeightSpinBox->setRange(2, 8192);
m_pWidthSpinBox->setSingleStep(2);
m_pHeightSpinBox->setSingleStep(2);
m_pWidthSpinBox->setMinimumWidth(90);
m_pWidthSpinBox->setMaximumWidth(110);
m_pHeightSpinBox->setMinimumWidth(90);
m_pHeightSpinBox->setMaximumWidth(110);
m_pWidthSpinBox->setValue(m_oEffectiveCurrentViewportSize.width());
m_pHeightSpinBox->setValue(m_oEffectiveCurrentViewportSize.height());
QLabel* pMultiplyLabel = new QLabel(
QString(QChar(0x00D7)), pOutputSizeGroup);
pMultiplyLabel->setAlignment(Qt::AlignCenter);
QLabel* pPixelLabel = new QLabel(
QString::fromLatin1("px"), pOutputSizeGroup);
pOutputSizeGrid->addWidget(m_pWidthSpinBox, 3, 2);
pOutputSizeGrid->addWidget(pMultiplyLabel, 3, 3, Qt::AlignCenter);
pOutputSizeGrid->addWidget(m_pHeightSpinBox, 3, 4);
pOutputSizeGrid->addWidget(pPixelLabel, 3, 5, Qt::AlignLeft);
// 两侧等权留白使完整尺寸选项块居中,块内控件仍保持左对齐。
pOutputSizeGrid->setColumnStretch(0, 1);
pOutputSizeGrid->setColumnStretch(6, 1);
pMainLayout->addWidget(pOutputSizeGroup);
QGroupBox* pOutputFileGroup = new QGroupBox(
tr("Output File"), this);
QGridLayout* pOutputFileGrid = new QGridLayout(pOutputFileGroup);
pOutputFileGrid->setHorizontalSpacing(8);
pOutputFileGrid->setVerticalSpacing(6);
pOutputFileGrid->setColumnStretch(1, 1);
m_pVideoFormatCombo = new QComboBox(pOutputFileGroup);
m_pVideoFormatCombo->setSizePolicy(oFieldSizePolicy);
pOutputFileGrid->addWidget(
createRightAlignedLabel(
tr("File format"), pOutputFileGroup), 0, 0);
pOutputFileGrid->addWidget(m_pVideoFormatCombo, 0, 1, 1, 2);
m_pTargetPathEdit = new QLineEdit(pOutputFileGroup);
m_pTargetPathEdit->setReadOnly(true);
m_pTargetPathEdit->setSizePolicy(oFieldSizePolicy);
QPushButton* pBrowseButton = new QPushButton(
tr("Browse..."), pOutputFileGroup);
pBrowseButton->setMinimumWidth(72);
pOutputFileGrid->addWidget(
createRightAlignedLabel(
tr("Save location"), pOutputFileGroup), 1, 0);
pOutputFileGrid->addWidget(m_pTargetPathEdit, 1, 1);
pOutputFileGrid->addWidget(pBrowseButton, 1, 2);
pMainLayout->addWidget(pOutputFileGroup);
QGroupBox* pInformationGroup = new QGroupBox(
tr("Export Information"), this);
QGridLayout* pInformationGrid = new QGridLayout(pInformationGroup);
pInformationGrid->setHorizontalSpacing(8);
pInformationGrid->setVerticalSpacing(6);
m_pOutputFrameCountLabel = new QLabel(pInformationGroup);
m_pEstimatedDurationLabel = new QLabel(pInformationGroup);
m_pOutputFrameCountLabel->setTextInteractionFlags(
Qt::TextSelectableByMouse);
m_pEstimatedDurationLabel->setTextInteractionFlags(
Qt::TextSelectableByMouse);
pInformationGrid->addWidget(
createRightAlignedLabel(
tr("Output frames"), pInformationGroup), 0, 1);
pInformationGrid->addWidget(
m_pOutputFrameCountLabel, 0, 2, Qt::AlignLeft);
pInformationGrid->addWidget(
createRightAlignedLabel(
tr("Estimated duration"), pInformationGroup), 1, 1);
pInformationGrid->addWidget(
m_pEstimatedDurationLabel, 1, 2, Qt::AlignLeft);
// 标签列和数值列作为一个整体居中,保留内部左右对齐关系。
pInformationGrid->setColumnStretch(0, 1);
pInformationGrid->setColumnStretch(3, 1);
pMainLayout->addWidget(pInformationGroup);
m_pErrorLabel = new QLabel(this);
m_pErrorLabel->setStyleSheet("QLabel { color: #a32626; }");
m_pErrorLabel->setWordWrap(true);
m_pErrorLabel->hide();
pMainLayout->addWidget(m_pErrorLabel);
QDialogButtonBox* pButtonBox = new QDialogButtonBox(
QDialogButtonBox::Ok | QDialogButtonBox::Cancel,
Qt::Horizontal, this);
QPushButton* pOkButton = pButtonBox->button(QDialogButtonBox::Ok);
QPushButton* pCancelButton = pButtonBox->button(QDialogButtonBox::Cancel);
pOkButton->setIcon(QIcon(exportDialogIconPath("OK.png")));
pCancelButton->setIcon(QIcon(exportDialogIconPath("Cancel.png")));
pOkButton->setIconSize(QSize(16, 16));
pCancelButton->setIconSize(QSize(16, 16));
pOkButton->setMinimumWidth(72);
pCancelButton->setMinimumWidth(72);
pMainLayout->addWidget(pButtonBox, 0, Qt::AlignRight);
connect(m_pStartFrameCombo, SIGNAL(currentIndexChanged(int)),
this, SLOT(onFrameRangeChanged()));
connect(m_pEndFrameCombo, SIGNAL(currentIndexChanged(int)),
this, SLOT(onFrameRangeChanged()));
connect(m_pSamplingIntervalSpinBox, SIGNAL(valueChanged(int)),
this, SLOT(updateSummary()));
connect(m_pFpsSpinBox, SIGNAL(valueChanged(int)),
this, SLOT(updateSummary()));
connect(m_pResolutionButtonGroup, SIGNAL(buttonClicked(int)),
this, SLOT(onResolutionPresetChanged(int)));
connect(m_pVideoFormatCombo, SIGNAL(currentIndexChanged(int)),
this, SLOT(onVideoFormatChanged(int)));
connect(pBrowseButton, SIGNAL(clicked()),
this, SLOT(browseTargetFile()));
connect(m_pWidthSpinBox, SIGNAL(valueChanged(int)),
this, SLOT(updateSummary()));
connect(m_pHeightSpinBox, SIGNAL(valueChanged(int)),
this, SLOT(updateSummary()));
connect(m_pWidthSpinBox, SIGNAL(editingFinished()),
this, SLOT(normalizeCustomDimensions()));
connect(m_pHeightSpinBox, SIGNAL(editingFinished()),
this, SLOT(normalizeCustomDimensions()));
connect(pButtonBox, SIGNAL(accepted()),
this, SLOT(acceptSettings()));
connect(pButtonBox, SIGNAL(rejected()),
this, SLOT(reject()));
}
void nmWxPebiResultAnimationExportDlg::populateFrameItems()
{
for(int nFrameIndex = 0;
nFrameIndex < m_vecFrameTimesHours.size(); ++nFrameIndex) {
const QString sText = tr("%1 h").arg(QString::number(
m_vecFrameTimesHours[nFrameIndex], 'g', 8));
m_pStartFrameCombo->addItem(sText, nFrameIndex);
m_pEndFrameCombo->addItem(sText, nFrameIndex);
}
if(!m_vecFrameTimesHours.isEmpty()) {
m_pStartFrameCombo->setCurrentIndex(0);
m_pEndFrameCombo->setCurrentIndex(
m_vecFrameTimesHours.size() - 1);
}
}
void nmWxPebiResultAnimationExportDlg::populateVideoFormats()
{
// itemData只保存稳定扩展名,界面翻译不会参与格式识别。
m_pVideoFormatCombo->addItem(
tr("MP4 Video (*.mp4)"), QString::fromLatin1("mp4"));
m_pVideoFormatCombo->addItem(
tr("AVI Video (*.avi)"), QString::fromLatin1("avi"));
m_pVideoFormatCombo->addItem(
tr("QuickTime Video (*.mov)"), QString::fromLatin1("mov"));
m_pVideoFormatCombo->addItem(
tr("MPEG Video (*.mpg)"), QString::fromLatin1("mpg"));
m_pVideoFormatCombo->addItem(
tr("WebM Video (*.webm)"), QString::fromLatin1("webm"));
m_pVideoFormatCombo->addItem(
tr("Matroska Video (*.mkv)"), QString::fromLatin1("mkv"));
m_pVideoFormatCombo->addItem(
tr("Windows Media Video (*.wmv)"), QString::fromLatin1("wmv"));
m_pVideoFormatCombo->addItem(
tr("Flash Video (*.flv)"), QString::fromLatin1("flv"));
m_pVideoFormatCombo->setCurrentIndex(0);
}
nmPebiResultAnimationExportSettings
nmWxPebiResultAnimationExportDlg::collectSettings() const
{
nmPebiResultAnimationExportSettings oSettings;
oSettings.m_nFramesPerSecond = m_pFpsSpinBox->value();
oSettings.m_nStartFrameIndex =
m_pStartFrameCombo->itemData(
m_pStartFrameCombo->currentIndex()).toInt();
oSettings.m_nEndFrameIndex =
m_pEndFrameCombo->itemData(
m_pEndFrameCombo->currentIndex()).toInt();
oSettings.m_nSamplingInterval =
m_pSamplingIntervalSpinBox->value();
const QSize oOutputSize = getSelectedOutputSize();
oSettings.m_nOutputWidth = oOutputSize.width();
oSettings.m_nOutputHeight = oOutputSize.height();
return oSettings;
}
QSize nmWxPebiResultAnimationExportDlg::getSelectedOutputSize() const
{
const int nPresetId = m_pResolutionButtonGroup == nullptr
? Resolution_CurrentView :
m_pResolutionButtonGroup->checkedId();
if(nPresetId == Resolution_720p) {
return QSize(1280, 720);
}
if(nPresetId == Resolution_1080p) {
return QSize(1920, 1080);
}
if(nPresetId == Resolution_Custom) {
return QSize(
normalizeEvenDimension(m_pWidthSpinBox->value()),
normalizeEvenDimension(m_pHeightSpinBox->value()));
}
return m_oEffectiveCurrentViewportSize;
}
QString nmWxPebiResultAnimationExportDlg::getSelectedVideoExtension() const
{
if(m_pVideoFormatCombo == nullptr ||
m_pVideoFormatCombo->currentIndex() < 0) {
return QString();
}
const QString sExtension = m_pVideoFormatCombo->itemData(
m_pVideoFormatCombo->currentIndex()).toString().toLower();
return nmFFmpegVideoWriter::isSupportedExtension(sExtension)
? sExtension : QString();
}
QString nmWxPebiResultAnimationExportDlg::getSelectedVideoFilter() const
{
return m_pVideoFormatCombo == nullptr
? QString() : m_pVideoFormatCombo->currentText();
}
QString nmWxPebiResultAnimationExportDlg::normalizeTargetFilePath(
const QString& sPath) const
{
const QString sExtension = getSelectedVideoExtension();
if(sPath.isEmpty() || sExtension.isEmpty()) {
return QString();
}
QString sNormalizedPath = QDir::fromNativeSeparators(sPath);
const QString sExistingExtension =
QFileInfo(sNormalizedPath).suffix().toLower();
if(sExistingExtension.isEmpty()) {
if(!sNormalizedPath.endsWith('.')) {
sNormalizedPath.append('.');
}
sNormalizedPath.append(sExtension);
} else if(nmFFmpegVideoWriter::isSupportedExtension(
sExistingExtension)) {
sNormalizedPath.chop(sExistingExtension.length());
sNormalizedPath.append(sExtension);
} else {
sNormalizedPath.append(
QString::fromLatin1(".%1").arg(sExtension));
}
return QDir::cleanPath(sNormalizedPath);
}
QString nmWxPebiResultAnimationExportDlg::getSuggestedTargetFilePath() const
{
QString sDirectory = ZxBaseUtil::getLastDir();
if(sDirectory.isEmpty() || !QDir(sDirectory).exists()) {
sDirectory = QDir::homePath();
}
return QDir(sDirectory).absoluteFilePath(
QString::fromLatin1("PEBI-result.%1").arg(
getSelectedVideoExtension()));
}
void nmWxPebiResultAnimationExportDlg::setTargetFilePath(
const QString& sPath)
{
const QString sDisplayPath = QDir::toNativeSeparators(sPath);
m_pTargetPathEdit->setText(sDisplayPath);
m_pTargetPathEdit->setToolTip(sDisplayPath);
}
void nmWxPebiResultAnimationExportDlg::showError(const QString& sError)
{
m_pErrorLabel->setText(sError);
m_pErrorLabel->show();
}
void nmWxPebiResultAnimationExportDlg::clearError()
{
m_pErrorLabel->clear();
m_pErrorLabel->hide();
}
int nmWxPebiResultAnimationExportDlg::normalizeEvenDimension(int nValue)
{
nValue = qBound(2, nValue, 8192);
if((nValue % 2) != 0) {
++nValue;
}
return qMin(nValue, 8192);
}