Commit 6bc54d5d authored by Jean-Baptiste Mardelle's avatar Jean-Baptiste Mardelle
Browse files

Fix crash when closing project while an effect monitor overlay was active

parent 24532f22
......@@ -16,7 +16,6 @@ set(kdenlive_SRCS
# assets/view/widgets/animationwidget.cpp
......@@ -301,7 +301,6 @@ void AssetPanel::clear()
This diff is collapsed.
* Copyright (C) 2016 by Jean-Baptiste Mardelle ( *
* This file is part of Kdenlive. See *
* *
* This program 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; either version 2 of *
* the License or (at your option) version 3 or any later version *
* accepted by the membership of KDE e.V. (or its successor approved *
* by the membership of KDE e.V.), which shall act as a proxy *
* defined in Section 14 of version 3 of the license. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program. If not, see <>. *
#include <QDomElement>
#include <QList>
#include <QWidget>
#include "assets/view/widgets/abstractparamwidget.hpp"
#include "mlt++/MltAnimation.h"
#include "mlt++/MltProperties.h"
#include "timecodedisplay.h"
class AnimKeyframeRuler;
class Monitor;
class KDualAction;
struct EffectMetaInfo;
class DoubleWidget;
class KSelectAction;
class QComboBox;
class DragValue;
class AnimationWidget : public AbstractParamWidget
AnimationWidget(std::shared_ptr<AssetParameterModel> model, QModelIndex index, QPair<int, int> range, QWidget *parent);
// explicit AnimationWidget(EffectMetaInfo *info, int clipPos, int min, int max, int effectIn, const QString &effectId, const QDomElement &xml,QWidget
// *parent = nullptr);
virtual ~AnimationWidget();
void updateTimecodeFormat();
void addParameter(QModelIndex ix);
const QMap<QString, QString> getAnimation();
static QString getDefaultKeyframes(int start, const QString &defaultValue, bool linearOnly = false);
void setActiveKeyframe(int frame);
void finishSetup();
/** @brief Returns true if currently active param is name */
bool isActive(const QString &name) const;
/** @brief Effect was selected / deselected, update monitor connections */
void connectMonitor(bool activate);
/** @brief Adds an offset to all keyframes (translate by x frames) */
void offsetAnimation(int offset);
/** @brief Effect param @tag was changed, reload keyframes */
void reload(const QString &tag, const QString &data);
AnimKeyframeRuler *m_ruler;
Monitor *m_monitor;
QSize m_frameSize;
QSize m_monitorSize;
TimecodeDisplay *m_timePos;
KDualAction *m_addKeyframe;
QComboBox *m_presetCombo;
QAction *m_previous;
QAction *m_next;
/** @brief True if effect is currently selected in stack */
bool m_active;
int m_clipPos;
int m_inPoint;
int m_outPoint;
/** @brief the keyframe position currently edited in slider */
int m_editedKeyframe;
/** @brief name of currently active animated parameter */
QString m_inTimeline;
/** @brief name of geometry animated parameter */
QString m_rectParameter;
/** @brief the keyframe position which should be attached to end (negative frame) */
int m_attachedToEnd;
QDomElement m_xml;
QList<QPair<QModelIndex, QString>> m_parameters;
QString m_effectId;
Mlt::Animation m_animController;
Mlt::Properties m_animProperties;
KSelectAction *m_selectType;
QAction *m_endAttach;
QList<QDomElement> m_params;
QMap<QString, DoubleWidget *> m_doubleWidgets;
DragValue *m_spinX;
DragValue *m_spinY;
DragValue *m_spinWidth;
DragValue *m_spinHeight;
DragValue *m_spinSize;
DragValue *m_spinOpacity;
QAction *m_originalSize;
QAction *m_lockRatio;
int m_offset;
void parseKeyframes();
void rebuildKeyframes();
void updateToolbar();
void loadPresets(QString currentText = QString());
void loadPreset(const QString &path);
/** @brief update the parameter slider to reflect value of current position / selected keyframe */
void updateSlider(int pos);
void updateRect(int pos);
/** @brief Create widget to adjust param value */
void buildSliderWidget(const QString &paramTag, QModelIndex ix);
void buildRectWidget(const QString &paramTag, QModelIndex ix);
/** @brief Calculate path for keyframes centers and send to monitor */
void setupMonitor(QRect r = QRect());
/** @brief Returns the default value for a parameter from its name */
QString defaultValue(const QString &paramName);
/** @brief Add a keyframe in all geometries */
void doAddKeyframe(int pos, QString paramName, bool directUpdate);
public slots:
void slotSyncPosition(int relTimelinePos);
void slotPositionChanged(int pos = -1, bool seek = true);
/** @brief Toggle the comments on or off
void slotShowComment(bool show) override;
/** @brief refresh the properties to reflect changes in the model
void slotRefresh() override;
/** @brief update the clip's in/out point
void slotSetRange(QPair<int, int>) override;
private slots:
void slotPrevious();
void slotNext();
void slotAddDeleteKeyframe(bool add, int pos = -1);
void moveKeyframe(int oldPos, int newPos);
void slotEditKeyframeType(QAction *action);
void slotAdjustKeyframeValue(double value);
void slotAdjustRectKeyframeValue();
void slotAddKeyframe(int pos = -1);
void slotDeleteKeyframe(int pos = -1);
void slotReverseKeyframeType(bool reverse);
void applyPreset(int ix);
void savePreset();
void deletePreset();
void slotCopyKeyframes();
void slotImportKeyframes();
void slotSetDefaultInterp(QAction *action);
void slotUpdateVisibleParameter(bool display);
void slotUpdateGeometryRect(const QRect r);
void slotUpdateCenters(const QVariantList &centers);
void slotSeekToKeyframe(int ix);
void slotAdjustToSource();
void slotAdjustToFrameSize();
void slotFitToWidth();
void slotFitToHeight();
void slotResize(double value);
/** @brief Delete all keyframes after current cursor pos. */
void slotRemoveNext();
/** @brief Moves the rect to the left frame border (x position = 0). */
void slotMoveLeft();
/** @brief Centers the rect horizontally. */
void slotCenterH();
/** @brief Moves the rect to the right frame border (x position = frame width - rect width). */
void slotMoveRight();
/** @brief Moves the rect to the top frame border (y position = 0). */
void slotMoveTop();
/** @brief Centers the rect vertically. */
void slotCenterV();
/** @brief Moves the rect to the bottom frame border (y position = frame height - rect height). */
void slotMoveBottom();
/** @brief Un/Lock aspect ratio for size in effect parameter. */
void slotLockRatio();
void slotAdjustRectHeight();
void slotAdjustRectWidth();
/** @brief Seek monitor. */
void requestSeek(int pos);
/** @brief monitor seek pos changed. */
void monitorSeek(int pos);
/** @brief keyframes dropped / pasted on widget, import them. */
void setKeyframes(const QString &);
......@@ -126,6 +126,8 @@ KeyframeWidget::KeyframeWidget(std::shared_ptr<AssetParameterModel> model, QMode
Monitor *monitor = pCore->getMonitor(m_model->monitorId);
connect(monitor, &Monitor::seekPosition, this, &KeyframeWidget::monitorSeek, Qt::UniqueConnection);
connect(pCore.get(), &Core::disconnectEffectStack, this, &KeyframeWidget::disconnectEffectStack);
m_time = new TimecodeDisplay(pCore->timecode(), this);
m_time->setRange(0, duration - 1);
......@@ -312,6 +314,12 @@ KeyframeWidget::~KeyframeWidget()
delete m_time;
void KeyframeWidget::disconnectEffectStack()
Monitor *monitor = pCore->getMonitor(m_model->monitorId);
disconnect(monitor, &Monitor::seekPosition, this, &KeyframeWidget::monitorSeek);
void KeyframeWidget::monitorSeek(int pos)
int in = 0;
......@@ -74,13 +74,14 @@ private slots:
/* brief Update the value of the widgets to reflect keyframe change */
void slotRefreshParams();
void slotAtKeyframe(bool atKeyframe, bool singleKeyframe);
void monitorSeek(int pos);
void slotEditKeyframeType(QAction *action);
void slotUpdateKeyframesFromMonitor(const QPersistentModelIndex &index, const QVariant &res);
void slotCopyKeyframes();
void slotImportKeyframes();
void slotRemoveNextKeyframes();
void slotSeekToKeyframe(int ix);
void monitorSeek(int pos);
void disconnectEffectStack();
QVBoxLayout *m_lay;
......@@ -1054,11 +1054,11 @@ Bin::Bin(std::shared_ptr<ProjectItemModel> model, QWidget *parent)
QAction *disableEffects = new QAction(i18n("Disable Bin Effects"), this);
connect(disableEffects, &QAction::triggered, this, [this](bool disable) { this->setBinEffectsEnabled(!disable); });
connect(disableEffects, &QAction::triggered, this, [this](bool disable) { this->setBinEffectsEnabled(!disable); });
pCore->window()->actionCollection()->addAction(QStringLiteral("disable_bin_effects"), disableEffects);
QAction *hoverPreview = new QAction(i18n("Show video preview in thumbnails"), this);
......@@ -1067,8 +1067,6 @@ Bin::Bin(std::shared_ptr<ProjectItemModel> model, QWidget *parent)
connect(hoverPreview, &QAction::triggered, [] (bool checked) {
connect(disableEffects, &QAction::triggered, this, [this](bool disable) { this->setBinEffectsEnabled(!disable); });
connect(listType, static_cast<void (KSelectAction::*)(QAction *)>(&KSelectAction::triggered), this, &Bin::slotInitView);
......@@ -1757,7 +1755,16 @@ void Bin::setDocument(KdenliveDoc *project)
// connect(m_itemModel, SIGNAL(updateCurrentItem()), this, SLOT(autoSelect()));
bool binEffectsDisabled = getDocumentProperty(QStringLiteral("disablebineffects")).toInt() == 1;
setBinEffectsEnabled(!binEffectsDisabled, false);
QAction *disableEffects = pCore->window()->actionCollection()->action(QStringLiteral("disable_bin_effects"));
if (disableEffects) {
if (binEffectsDisabled != disableEffects->isChecked()) {
QSignalBlocker bk(disableEffects);
//setBinEffectsEnabled(!binEffectsDisabled, false);
QMap <QString, QString> projectTags = m_doc->getProjectTags();
......@@ -3928,15 +3935,6 @@ void Bin::showSlideshowWidget(const std::shared_ptr<ProjectClip> &clip)
void Bin::setBinEffectsEnabled(bool enabled, bool refreshMonitor)
QAction *disableEffects = pCore->window()->actionCollection()->action(QStringLiteral("disable_bin_effects"));
if (disableEffects) {
if (enabled == disableEffects->isChecked()) {
pCore->projectManager()->disableBinEffects(!enabled, refreshMonitor);
......@@ -315,6 +315,8 @@ signals:
void updateVoskAvailability();
/** @brief Update current effect zone */
void updateEffectZone(const QPoint p, bool withUndo);
/** @brief The effect stask is about to be deleted, disconnect everything */
void disconnectEffectStack();
......@@ -406,11 +406,12 @@ void EffectStackView::unsetModel(bool reset)
disconnect(m_model.get(), &EffectStackModel::enabledStateChanged, this, &EffectStackView::changeEnabledState);
disconnect(this, &EffectStackView::removeCurrentEffect, m_model.get(), &EffectStackModel::removeCurrentEffect);
disconnect(&m_timerHeight, &QTimer::timeout, this, &EffectStackView::updateTreeHeight);
emit pCore->disconnectEffectStack();
if (reset) {
QMutexLocker lock(&m_mutex);
if (id != Kdenlive::NoMonitor) {
......@@ -404,7 +404,7 @@ void MainWindow::init(const QString &mltPath)
// Don't raise effect stack on clip bin in case it is docked with bin or clip monitor
// m_effectStackDock->raise();
connect(this, &MainWindow::clearAssetPanel, m_assetPanel, &AssetPanel::clearAssetPanel);
connect(this, &MainWindow::clearAssetPanel, m_assetPanel, &AssetPanel::clearAssetPanel, Qt::DirectConnection);
connect(this, &MainWindow::assetPanelWarning, m_assetPanel, &AssetPanel::assetPanelWarning);
connect(m_assetPanel, &AssetPanel::seekToPos, this, [this](int pos) {
ObjectId oId = m_assetPanel->effectStackOwner();
......@@ -283,8 +283,8 @@ bool ProjectManager::closeCurrentDocument(bool saveChanges, bool quit)
if (!quit && !qApp->isSavingSession()) {
if (m_project) {
emit pCore->window()->clearAssetPanel();
delete m_project;
m_project = nullptr;
......@@ -777,7 +777,7 @@ void ProjectManager::disableBinEffects(bool disable, bool refreshMonitor)
if (m_project) {
if (disable) {
m_project->setDocumentProperty(QStringLiteral("disablebineffects"), QString::number(true));
m_project->setDocumentProperty(QStringLiteral("disablebineffects"), QString::number(1));
} else {
m_project->setDocumentProperty(QStringLiteral("disablebineffects"), QString());
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