Commit 4d266c6f authored by Adam Tokarski's avatar Adam Tokarski Committed by Julius Künzel
Browse files

Save Effect Stack in stack header

Fixes #1131

* `Save Effect Stack` icon is moved to effects stack header
* hamburger menu with save effect is removed, instead is `Save Effect` icon
* When effect (or stack) is saved without provided name, it is just closing silently without any saving - I added `sorry` message for such cases
* also, small typo `wheen` is fixed.
parent f88bfbbb
Pipeline #71553 passed with stage
in 8 minutes and 26 seconds
......@@ -95,6 +95,15 @@ AssetPanel::AssetPanel(QWidget *parent)
// connect(m_switchBuiltStack, &QToolButton::toggled, m_effectStackWidget, &EffectStackView::switchBuiltStack);
buttonToolbar->addWidget(m_switchBuiltStack);
m_saveEffectStack = new QToolButton(this);
m_saveEffectStack->setIcon(QIcon::fromTheme(QStringLiteral("document-save-all")));
m_saveEffectStack->setToolTip(i18n("Save Effect Stack"));
// Would be better to have something like `setVisible(false)` here, but this apparently removes the button.
// See https://stackoverflow.com/a/17645563/5172513
m_saveEffectStack->setEnabled(false);
connect(m_saveEffectStack, &QToolButton::released, this, &AssetPanel::slotSaveStack);
buttonToolbar->addWidget(m_saveEffectStack);
m_splitButton = new KDualAction(i18n("Normal view"), i18n("Compare effect"), this);
m_splitButton->setActiveIcon(QIcon::fromTheme(QStringLiteral("view-right-close")));
m_splitButton->setInactiveIcon(QIcon::fromTheme(QStringLiteral("view-split-left-right")));
......@@ -150,6 +159,8 @@ AssetPanel::AssetPanel(QWidget *parent)
connect(m_transitionWidget, &TransitionStackView::seekToTransPos, this, &AssetPanel::seekToPos);
connect(m_mixWidget, &MixStackView::seekToTransPos, this, &AssetPanel::seekToPos);
connect(m_effectStackWidget, &EffectStackView::updateEnabledState, this, [this]() { m_enableStackButton->setActive(m_effectStackWidget->isStackEnabled()); });
connect(this, &AssetPanel::slotSaveStack, m_effectStackWidget, &EffectStackView::slotSaveStack);
}
void AssetPanel::showTransition(int tid, const std::shared_ptr<AssetParameterModel> &transitionModel)
......@@ -201,6 +212,7 @@ void AssetPanel::showEffectStack(const QString &itemName, const std::shared_ptr<
// Item is not ready
m_splitButton->setVisible(false);
m_enableStackButton->setVisible(false);
m_saveEffectStack->setEnabled(false);
clear();
return;
}
......@@ -244,6 +256,7 @@ void AssetPanel::showEffectStack(const QString &itemName, const std::shared_ptr<
m_assetTitle->setText(title);
m_titleAction->setVisible(true);
m_splitButton->setVisible(showSplit);
m_saveEffectStack->setEnabled(true);
m_enableStackButton->setVisible(id.first != ObjectType::TimelineComposition);
m_enableStackButton->setActive(effectsModel->isStackEnabled());
if (showSplit) {
......@@ -299,6 +312,7 @@ void AssetPanel::clear()
m_mixWidget->unsetModel();
m_effectStackWidget->setVisible(false);
m_splitButton->setVisible(false);
m_saveEffectStack->setEnabled(false);
m_timelineButton->setVisible(false);
m_switchBuiltStack->setVisible(false);
m_effectStackWidget->unsetModel();
......@@ -422,6 +436,7 @@ bool AssetPanel::addEffect(const QString &effectId)
return m_effectStackWidget->addEffect(effectId);
}
void AssetPanel::enableStack(bool enable)
{
if (!m_effectStackWidget->isVisible()) {
......@@ -464,7 +479,7 @@ void AssetPanel::slotCheckWheelEventFilter()
// widget has scroll bar,
blockWheel = true;
}
emit m_effectStackWidget->blockWheenEvent(blockWheel);
emit m_effectStackWidget->blockWheelEvent(blockWheel);
}
void AssetPanel::assetPanelWarning(const QString service, const QString /*id*/, const QString message)
......
......@@ -99,6 +99,7 @@ protected:
private:
QToolButton *m_switchBuiltStack;
QToolButton *m_saveEffectStack;
QComboBox *m_switchCompoButton;
QAction *m_titleAction;
QAction *m_switchAction;
......@@ -123,6 +124,7 @@ signals:
void seekToPos(int);
void reloadEffect(const QString &path);
void switchCurrentComposition(int tid, const QString &compoId);
void slotSaveStack();
};
#endif
......@@ -84,8 +84,9 @@ CollapsibleEffectView::CollapsibleEffectView(const std::shared_ptr<EffectItemMod
collapseButton->setDefaultAction(m_collapse);
m_collapse->setActive(m_model->isCollapsed());
connect(m_collapse, &KDualAction::activeChanged, this, &CollapsibleEffectView::slotSwitch);
if (effectModel->rowCount() == 0) {
// Effect has no paramerter
// Effect has no parameter
m_collapse->setInactiveIcon(QIcon::fromTheme(QStringLiteral("tools-wizard")));
collapseButton->setEnabled(false);
} else {
......@@ -200,6 +201,12 @@ CollapsibleEffectView::CollapsibleEffectView(const std::shared_ptr<EffectItemMod
emit activateEffect(m_model->row());
}
});
if (effectModel->rowCount() == 0) {
// Effect has no parameter
m_view->setVisible(false);
}
connect(m_view, &AssetParameterView::updateHeight, this, &CollapsibleEffectView::updateHeight);
connect(this, &CollapsibleEffectView::refresh, m_view, &AssetParameterView::slotRefresh);
keyframesButton->setVisible(m_view->keyframesAllowed());
......@@ -215,6 +222,7 @@ CollapsibleEffectView::CollapsibleEffectView(const std::shared_ptr<EffectItemMod
}
m_view->toggleKeyframes(toggle);
});
if (!effectParamModel->hasMoreThanOneKeyframe()) {
// No keyframe or only one, allow hiding
bool hideByDefault = effectParamModel->data(effectParamModel->index(0, 0), AssetParameterModel::HideKeyframesFirstRole).toBool();
......@@ -231,17 +239,9 @@ CollapsibleEffectView::CollapsibleEffectView(const std::shared_ptr<EffectItemMod
presetButton->setMenu(m_view->presetMenu());
presetButton->setToolTip(i18n("Presets"));
// Main menu
m_menu = new QMenu(this);
if (effectModel->rowCount() == 0) {
collapseButton->setEnabled(false);
m_view->setVisible(false);
}
m_menu->addAction(QIcon::fromTheme(QStringLiteral("document-save")), i18n("Save Effect"), this, SLOT(slotSaveEffect()));
m_menu->addAction(QIcon::fromTheme(QStringLiteral("document-save-all")), i18n("Save Effect Stack"), this, SIGNAL(saveStack()));
menuButton->setIcon(QIcon::fromTheme(QStringLiteral("kdenlive-menu")));
menuButton->setMenu(m_menu);
connect(saveEffectButton, &QAbstractButton::clicked, this, &CollapsibleEffectView::slotSaveEffect);
saveEffectButton->setIcon(QIcon::fromTheme(QStringLiteral("document-save")));
saveEffectButton->setToolTip(i18n("Save Effect"));
if (!effectModel->isEnabled()) {
title->setEnabled(false);
......@@ -485,22 +485,28 @@ void CollapsibleEffectView::slotSaveEffect()
{
QDialog dialog(this);
QFormLayout form(&dialog);
dialog.setWindowTitle(i18n("Save Effect"));
auto *effectName = new QLineEdit(&dialog);
auto *descriptionBox = new QTextEdit(&dialog);
QString label_Name = QString("Name : ");
form.addRow(label_Name, effectName);
QString label = QString("Comments : ");
form.addRow(label, descriptionBox);
QDialogButtonBox buttonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel, Qt::Horizontal, &dialog);
form.addRow(&buttonBox);
QObject::connect(&buttonBox, SIGNAL(accepted()), &dialog, SLOT(accept()));
QObject::connect(&buttonBox, SIGNAL(rejected()), &dialog, SLOT(reject()));
if(dialog.exec() == QDialog::Accepted)
if (dialog.exec() == QDialog::Accepted)
{
QString name = effectName->text();
QString enteredDescription = descriptionBox->toPlainText();
if (name.trimmed().isEmpty()) {
KMessageBox::sorry(this, i18n("No name provided, effect not saved."));
return;
}
QDir dir(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation) + QStringLiteral("/effects/"));
......@@ -567,6 +573,8 @@ void CollapsibleEffectView::slotSaveEffect()
emit reloadEffect(dir.absoluteFilePath(name + QStringLiteral(".xml")));
}
}
QDomDocument CollapsibleEffectView::toXml() const
{
QDomDocument doc;
......@@ -870,7 +878,7 @@ void CollapsibleEffectView::enableView(bool enabled)
}
}
void CollapsibleEffectView::blockWheenEvent(bool block)
void CollapsibleEffectView::blockWheelEvent(bool block)
{
m_blockWheel = block;
}
......
......@@ -101,7 +101,7 @@ public slots:
void slotActivateEffect(bool active);
void updateHeight();
/** @brief Should we block wheel event (if parent is a view with scrollbar) */
void blockWheenEvent(bool block);
void blockWheelEvent(bool block);
/** @brief Switch between collapsed/expanded state */
void switchCollapsed(int row);
......@@ -177,8 +177,6 @@ signals:
void activateEffect(int row);
void showEffectZone(ObjectId id, QPair <int, int>inOut, bool checked);
void refresh();
/** @brief Requests saving the full effect stack. */
void saveStack();
};
#endif
......@@ -263,19 +263,19 @@ void EffectStackView::loadEffects()
connect(view, &CollapsibleEffectView::reloadEffect, this, &EffectStackView::reloadEffect);
connect(view, &CollapsibleEffectView::switchHeight, this, &EffectStackView::slotAdjustDelegate, Qt::DirectConnection);
connect(view, &CollapsibleEffectView::startDrag, this, &EffectStackView::slotStartDrag);
connect(view, &CollapsibleEffectView::saveStack, this, &EffectStackView::slotSaveStack);
connect(view, &CollapsibleEffectView::activateEffect, this, [=](int row) {
m_model->setActiveEffect(row);
});
connect(view, &CollapsibleEffectView::createGroup, m_model.get(), &EffectStackModel::slotCreateGroup);
connect(view, &CollapsibleEffectView::showEffectZone, pCore.get(), &Core::showEffectZone);
connect(this, &EffectStackView::blockWheenEvent, view, &CollapsibleEffectView::blockWheenEvent);
connect(this, &EffectStackView::blockWheelEvent, view, &CollapsibleEffectView::blockWheelEvent);
connect(view, &CollapsibleEffectView::seekToPos, this, [this](int pos) {
// at this point, the effects returns a pos relative to the clip. We need to convert it to a global time
int clipIn = pCore->getItemPosition(m_model->getOwnerId());
emit seekToPos(pos + clipIn);
});
connect(this, &EffectStackView::switchCollapsedView, view, &CollapsibleEffectView::switchCollapsed);
connect(pCore.get(), &Core::updateEffectZone, view, [=](const QPoint p, bool withUndo) {
// Update current effect zone
if (view->isActive()) {
......@@ -474,10 +474,16 @@ void EffectStackView::slotFocusEffect()
void EffectStackView::slotSaveStack()
{
if (m_model->rowCount() <= 0) {
KMessageBox::sorry(this, i18n("No effect selected."));
return;
}
QString name = QInputDialog::getText(this, i18n("Save Effect Stack"), i18n("Name for saved stack: "));
if (name.trimmed().isEmpty() || m_model->rowCount() <= 0) {
if (name.trimmed().isEmpty()) {
KMessageBox::sorry(this, i18n("No name provided, effect stack not saved."));
return;
}
QDir dir(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation) + QStringLiteral("/effects/"));
if (!dir.exists()) {
dir.mkpath(QStringLiteral("."));
......
......@@ -81,6 +81,11 @@ public:
void slotGoToKeyframe(bool next);
void addRemoveKeyframe();
public slots:
/** @brief Save current effect stack
*/
void slotSaveStack();
protected:
void dragEnterEvent(QDragEnterEvent *event) override;
void dropEvent(QDropEvent *event) override;
......@@ -109,9 +114,6 @@ private slots:
void loadEffects();
void updateTreeHeight();
void slotFocusEffect();
/** @brief Save current effect stack
*/
void slotSaveStack();
/** @brief Refresh the enabled state on widgets
*/
void changeEnabledState();
......@@ -127,7 +129,7 @@ signals:
void reloadEffect(const QString &path);
void updateEnabledState();
void removeCurrentEffect();
void blockWheenEvent(bool block);
void blockWheelEvent(bool block);
void checkScrollBar();
void scrollView(QRect);
};
......
......@@ -166,7 +166,7 @@
</widget>
</item>
<item>
<widget class="QToolButton" name="menuButton">
<widget class="QToolButton" name="saveEffectButton">
<property name="text">
<string>...</string>
</property>
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment