Commit 0ab0c9ee authored by Jean-Baptiste Mardelle's avatar Jean-Baptiste Mardelle
Browse files

Fix several crashes on exit (double deltion, etc)

parent ae52d25c
......@@ -21,7 +21,6 @@
#include "assetlistwidget.hpp"
#include "assets/assetlist/view/qmltypes/asseticonprovider.hpp"
#include "kdenlivesettings.h"
#include <KDeclarative/KDeclarative>
#include <QQmlContext>
......@@ -30,17 +29,17 @@
AssetListWidget::AssetListWidget(QWidget *parent)
: QQuickWidget(parent)
{
}
void AssetListWidget::setup()
, m_assetIconProvider(nullptr)
{
KDeclarative::KDeclarative kdeclarative;
kdeclarative.setDeclarativeEngine(engine());
kdeclarative.setupBindings();
}
void AssetListWidget::setup()
{
setResizeMode(QQuickWidget::SizeRootObjectToView);
engine()->addImageProvider(QStringLiteral("asseticon"), m_assetIconProvider.get());
engine()->addImageProvider(QStringLiteral("asseticon"), m_assetIconProvider);
setSource(QUrl(QStringLiteral("qrc:/qml/assetList.qml")));
setFocusPolicy(Qt::StrongFocus);
}
......@@ -81,13 +80,4 @@ void AssetListWidget::activate(const QModelIndex &ix)
emit activateAsset(data);
}
bool AssetListWidget::showDescription() const
{
return KdenliveSettings::showeffectinfo();
}
void AssetListWidget::setShowDescription(bool show)
{
KdenliveSettings::setShoweffectinfo(show);
emit showDescriptionChanged();
}
......@@ -37,39 +37,36 @@ class AssetListWidget : public QQuickWidget
Q_OBJECT
/* @brief Should the descriptive info box be displayed
*/
Q_PROPERTY(bool showDescription READ showDescription WRITE setShowDescription NOTIFY showDescriptionChanged)
public:
AssetListWidget(QWidget *parent = Q_NULLPTR);
/* @brief Returns the name of the asset given its model index */
Q_INVOKABLE QString getName(const QModelIndex &index) const;
QString getName(const QModelIndex &index) const;
/* @brief Returns the description of the asset given its model index */
Q_INVOKABLE QString getDescription(const QModelIndex &index) const;
QString getDescription(const QModelIndex &index) const;
/* @brief Sets the pattern against which the assets' names are filtered */
Q_INVOKABLE void setFilterName(const QString &pattern);
void setFilterName(const QString &pattern);
/*@brief Return mime type used for drag and drop. It can be kdenlive/effect,
kdenlive/composition or kdenlive/transition*/
virtual QString getMimeType(const QString &assetId) const = 0;
Q_INVOKABLE QVariantMap getMimeData(const QString &assetId) const;
QVariantMap getMimeData(const QString &assetId) const;
Q_INVOKABLE void activate(const QModelIndex &ix);
Q_INVOKABLE bool showDescription() const;
Q_INVOKABLE void setShowDescription(bool);
void activate(const QModelIndex &ix);
protected:
void setup();
std::unique_ptr<AssetTreeModel> m_model;
std::unique_ptr<AssetFilter> m_proxyModel;
std::unique_ptr<AssetIconProvider> m_assetIconProvider;
// the QmlEngine takes ownership of the image provider
AssetIconProvider *m_assetIconProvider;
signals:
void activateAsset(const QVariantMap data);
void showDescriptionChanged();
};
#endif
......@@ -55,7 +55,7 @@ Core::~Core()
delete m_monitorManager;
}
delete m_producerQueue;
delete m_binWidget;
//delete m_binWidget;
delete m_projectManager;
}
......@@ -92,8 +92,8 @@ void Core::build(const QString &MltPath)
}
// Init producer shown for unavailable media
// TODO make it a more proper image
ClipController::mediaUnavailable = std::make_shared<Mlt::Producer>(ProfileRepository::get()->getProfile(m_self->m_profile)->profile(), "color", "blue");
// TODO make it a more proper image, it currently causes a crash on exit
ClipController::mediaUnavailable = std::make_shared<Mlt::Producer>(ProfileRepository::get()->getProfile(m_self->m_profile)->profile(), "color:blue");
ClipController::mediaUnavailable->set("length", 99999999);
}
......
......@@ -38,16 +38,21 @@ EffectListWidget::EffectListWidget(QWidget *parent)
m_proxyModel->setSourceModel(m_model.get());
m_proxyModel->setSortRole(EffectTreeModel::NameRole);
m_proxyModel->sort(0, Qt::AscendingOrder);
rootContext()->setContextProperty("assetlist", this);
m_proxy = new EffectListWidgetProxy(this);
rootContext()->setContextProperty("assetlist", m_proxy);
rootContext()->setContextProperty("assetListModel", m_proxyModel.get());
rootContext()->setContextProperty("isEffectList", true);
m_assetIconProvider.reset(new AssetIconProvider(true));
m_assetIconProvider = new AssetIconProvider(true);
setup();
}
EffectListWidget::~EffectListWidget()
{
delete m_proxy;
qDebug()<<" - - -Deleting effect list widget";
}
void EffectListWidget::setFilterType(const QString &type)
{
if (type == "video") {
......
......@@ -23,23 +23,82 @@
#define EFFECTLISTWIDGET_H
#include "assets/assetlist/view/assetlistwidget.hpp"
#include "kdenlivesettings.h"
/* @brief This class is a widget that display the list of available effects
*/
class EffectFilter;
class EffectTreeModel;
class EffectListWidgetProxy;
class EffectListWidget : public AssetListWidget
{
Q_OBJECT
public:
EffectListWidget(QWidget *parent = Q_NULLPTR);
Q_INVOKABLE void setFilterType(const QString &type);
~EffectListWidget();
void setFilterType(const QString &type);
/*@brief Return mime type used for drag and drop. It will be kdenlive/effect*/
Q_INVOKABLE QString getMimeType(const QString &assetId) const override;
QString getMimeType(const QString &assetId) const override;
private:
EffectListWidgetProxy *m_proxy;
};
//see https://bugreports.qt.io/browse/QTBUG-57714, don't expose a QWidget as a context property
class EffectListWidgetProxy : public QObject
{
Q_OBJECT
Q_PROPERTY(bool showDescription READ showDescription WRITE setShowDescription NOTIFY showDescriptionChanged)
public:
EffectListWidgetProxy(EffectListWidget *parent) :
QObject(parent),
q(parent)
{
}
Q_INVOKABLE QString getName(const QModelIndex &index) const {
return q->getName(index);
}
Q_INVOKABLE QString getDescription(const QModelIndex &index) const {
return q->getDescription(index);
}
Q_INVOKABLE QVariantMap getMimeData(const QString &assetId) const {
return q->getMimeData(assetId);
}
Q_INVOKABLE void activate(const QModelIndex &ix) {
q->activate(ix);
}
Q_INVOKABLE void setFilterType(const QString &type) {
q->setFilterType(type);
}
Q_INVOKABLE void setFilterName(const QString &pattern) {
q->setFilterName(pattern);
}
Q_INVOKABLE QString getMimeType(const QString &assetId) const {
return q->getMimeType(assetId);
}
bool showDescription() const
{
return KdenliveSettings::showeffectinfo();
}
void setShowDescription(bool show)
{
KdenliveSettings::setShoweffectinfo(show);
emit showDescriptionChanged();
}
signals:
void showDescriptionChanged();
private:
EffectListWidget* q;
};
#endif
......@@ -63,6 +63,7 @@
#include "timeline/track.h"
#include "timeline2/view/timelinetabs.hpp"
#include "timeline2/view/timelinewidget.h"
#include "timeline2/view/timelinecontroller.h"
#include "titler/titlewidget.h"
#include "transitions/transitionlist/view/transitionlistwidget.hpp"
#include "transitions/transitionsrepository.hpp"
......@@ -322,15 +323,15 @@ void MainWindow::init()
m_effectList = new EffectsListView();
// m_effectListDock = addDock(i18n("Effects"), QStringLiteral("effect_list"), m_effectList);
auto effectList = new EffectListWidget(this);
connect(effectList, &EffectListWidget::activateAsset, pCore->projectManager(), &ProjectManager::activateAsset);
m_effectListDock = addDock(i18n("Effects"), QStringLiteral("effect_list"), effectList);
m_effectList2 = new EffectListWidget(this);
connect(m_effectList2, &EffectListWidget::activateAsset, pCore->projectManager(), &ProjectManager::activateAsset);
m_effectListDock = addDock(i18n("Effects"), QStringLiteral("effect_list"), m_effectList2);
m_transitionList = new EffectsListView(EffectsListView::TransitionMode);
auto transitionList = new TransitionListWidget(this);
m_transitionList2 = new TransitionListWidget(this);
// m_transitionListDock = addDock(i18n("Transitions"), QStringLiteral("transition_list"), m_transitionList);
m_transitionListDock = addDock(i18n("Transitions"), QStringLiteral("transition_list"), transitionList);
m_transitionListDock = addDock(i18n("Transitions"), QStringLiteral("transition_list"), m_transitionList2);
// Add monitors here to keep them at the right of the window
m_clipMonitorDock = addDock(i18n("Clip Monitor"), QStringLiteral("clip_monitor"), m_clipMonitor);
......@@ -733,8 +734,10 @@ MainWindow::~MainWindow()
delete m_projectMonitor;
delete m_clipMonitor;
delete m_shortcutRemoveFocus;
delete m_effectList2;
delete m_transitionList2;
qDeleteAll(m_transitions);
Mlt::Factory::close();
//Mlt::Factory::close();
}
// virtual
......@@ -2219,7 +2222,7 @@ void MainWindow::slotSwitchAudioThumbs()
void MainWindow::slotSwitchMarkersComments()
{
KdenliveSettings::setShowmarkers(!KdenliveSettings::showmarkers());
getMainTimeline()->showMarkersChanged();
getMainTimeline()->controller()->showMarkersChanged();
m_buttonShowMarkers->setChecked(KdenliveSettings::showmarkers());
}
......@@ -2253,7 +2256,7 @@ void MainWindow::slotDeleteItem()
}
// effect stack has no focus
m_timelineTabs->getCurrentTimeline()->deleteSelectedClips();
m_timelineTabs->getCurrentTimeline()->controller()->deleteSelectedClips();
}
}
......@@ -2789,7 +2792,7 @@ void MainWindow::customEvent(QEvent *e)
void MainWindow::slotSnapRewind()
{
if (m_projectMonitor->isActive()) {
m_timelineTabs->getCurrentTimeline()->gotoPreviousSnap();
m_timelineTabs->getCurrentTimeline()->controller()->gotoPreviousSnap();
} else {
m_clipMonitor->slotSeekToPreviousSnap();
}
......@@ -2798,7 +2801,7 @@ void MainWindow::slotSnapRewind()
void MainWindow::slotSnapForward()
{
if (m_projectMonitor->isActive()) {
m_timelineTabs->getCurrentTimeline()->gotoNextSnap();
m_timelineTabs->getCurrentTimeline()->controller()->gotoNextSnap();
} else {
m_clipMonitor->slotSeekToNextSnap();
}
......@@ -3024,12 +3027,12 @@ QString::number(zone.y()) << "-consumer" << "xml:" + url->url().path());
void MainWindow::slotResizeItemStart()
{
m_timelineTabs->getCurrentTimeline()->setInPoint();
m_timelineTabs->getCurrentTimeline()->controller()->setInPoint();
}
void MainWindow::slotResizeItemEnd()
{
m_timelineTabs->getCurrentTimeline()->setOutPoint();
m_timelineTabs->getCurrentTimeline()->controller()->setOutPoint();
}
int MainWindow::getNewStuff(const QString &configFile)
......@@ -3608,7 +3611,7 @@ void MainWindow::slotUpdateTimecodeFormat(int ix)
// m_effectStack->transitionConfig()->updateTimecodeFormat();
// m_effectStack->updateTimecodeFormat();
pCore->bin()->updateTimecodeFormat();
getMainTimeline()->frameFormatChanged();
getMainTimeline()->controller()->frameFormatChanged();
m_timeFormatButton->setFont(QFontDatabase::systemFont(QFontDatabase::FixedFont));
}
......
......@@ -48,6 +48,8 @@
class AssetPanel;
class AudioGraphSpectrum;
class EffectStackView2;
class EffectListWidget;
class TransitionListWidget;
class EffectStackView;
class EffectsListView;
class KIconLoader;
......@@ -149,6 +151,8 @@ private:
EffectsListView *m_effectList;
QDockWidget *m_transitionListDock;
EffectsListView *m_transitionList;
TransitionListWidget *m_transitionList2;
EffectListWidget *m_effectList2;
AssetPanel *m_assetPanel;
QDockWidget *m_effectStackDock;
......
......@@ -33,6 +33,7 @@ BinController::BinController(const QString &profileName)
BinController::~BinController()
{
qDebug()<<"/// delete bincontroller";
destroyBin();
}
......
......@@ -30,12 +30,6 @@ NotesPlugin::NotesPlugin(ProjectManager *projectManager)
connect(projectManager, &ProjectManager::docOpened, this, &NotesPlugin::setProject);
}
NotesPlugin::~NotesPlugin()
{
delete m_widget;
delete m_notesDock;
}
void NotesPlugin::setProject(KdenliveDoc *document)
{
connect(m_widget, &NotesWidget::seekProject, pCore->monitorManager()->projectMonitor()->render, &Render::seekToFrame);
......
......@@ -33,7 +33,6 @@ public:
explicit NotesPlugin(ProjectManager *projectManager);
NotesWidget *widget();
void clear();
~NotesPlugin();
private slots:
void setProject(KdenliveDoc *document);
......
......@@ -31,6 +31,7 @@ the Free Software Foundation, either version 3 of the License, or
#include "timeline/timeline.h"
#include "timeline2/model/builders/meltBuilder.hpp"
#include "timeline2/view/timelinewidget.h"
#include "timeline2/view/timelinecontroller.h"
#include "transitionsettings.h"
#include "utils/KoIconUtils.h"
......@@ -86,10 +87,7 @@ ProjectManager::ProjectManager(QObject *parent)
ProjectManager::~ProjectManager()
{
delete m_notesPlugin;
delete m_trackView;
delete m_project;
}
void ProjectManager::slotLoadOnOpen()
......@@ -893,5 +891,5 @@ void ProjectManager::updateTimeline(Mlt::Tractor tractor)
void ProjectManager::activateAsset(const QVariantMap data)
{
pCore->window()->getMainTimeline()->addAsset(data);
pCore->window()->getMainTimeline()->controller()->addAsset(data);
}
......@@ -9,6 +9,7 @@ set(kdenlive_SRCS
timeline2/model/snapmodel.cpp
timeline2/model/builders/meltBuilder.cpp
timeline2/view/timelinetabs.cpp
timeline2/view/timelinecontroller.cpp
timeline2/view/timelinewidget.cpp
timeline2/view/qml/timelineitems.cpp
timeline2/view/qmltypes/thumbnailprovider.cpp
......
/***************************************************************************
* Copyright (C) 2017 by Jean-Baptiste Mardelle *
* This file is part of Kdenlive. See www.kdenlive.org. *
* *
* 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 *
* 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 this program. If not, see <http://www.gnu.org/licenses/>. *
***************************************************************************/
#include "timelinecontroller.h"
#include "kdenlivesettings.h"
#include "core.h"
#include "bin/bin.h"
#include "bin/projectclip.h"
#include "timeline2/model/timelineitemmodel.hpp"
#include "dialogs/markerdialog.h"
#include "bin/model/markerlistmodel.hpp"
#include "project/projectmanager.h"
#include "doc/kdenlivedoc.h"
#include "timelinewidget.h"
#include <QQuickItem>
#include <KActionCollection>
#include <QApplication>
int TimelineController::m_duration = 0;
TimelineController::TimelineController(KActionCollection *actionCollection, TimelineWidget *parent) :
QObject(parent)
, q(parent)
, m_actionCollection(actionCollection)
, m_position(0)
, m_seekPosition(-1)
, m_scale(3.0)
{
}
void TimelineController::setModel(std::shared_ptr<TimelineItemModel> model)
{
m_model = std::move(model);
}
Mlt::Tractor *TimelineController::tractor()
{
return m_model->tractor();
}
void TimelineController::addSelection(int newSelection)
{
if (m_selection.selectedClips.contains(newSelection)) {
return;
}
m_selection.selectedClips << newSelection;
emit selectionChanged();
if (!m_selection.selectedClips.isEmpty())
emitSelectedFromSelection();
else
emit selected(nullptr);
}
double TimelineController::scaleFactor() const
{
return m_scale;
}
void TimelineController::setScaleFactor(double scale)
{
/*if (m_duration * scale < width() - 160) {
// Don't allow scaling less than full project's width
scale = (width() - 160.0) / m_duration;
}*/
m_scale = scale;
emit scaleFactorChanged();
}
int TimelineController::duration() const
{
return m_duration;
}
void TimelineController::checkDuration()
{
int currentLength = m_model->duration();
if (currentLength != m_duration) {
m_duration = currentLength;
emit durationChanged();
}
}
void TimelineController::setSelection(const QList<int> &newSelection, int trackIndex, bool isMultitrack)
{
if (newSelection != selection() || trackIndex != m_selection.selectedTrack || isMultitrack != m_selection.isMultitrackSelected) {
qDebug() << "Changing selection to" << newSelection << " trackIndex" << trackIndex << "isMultitrack" << isMultitrack;
m_selection.selectedClips = newSelection;
m_selection.selectedTrack = trackIndex;
m_selection.isMultitrackSelected = isMultitrack;
emit selectionChanged();
if (!m_selection.selectedClips.isEmpty())
emitSelectedFromSelection();
else
emit selected(nullptr);
}
}
void TimelineController::emitSelectedFromSelection()
{
/*if (!m_model.trackList().count()) {
if (m_model.tractor())
selectMultitrack();
else
emit selected(0);
return;
}
int trackIndex = currentTrack();
int clipIndex = selection().isEmpty()? 0 : selection().first();
Mlt::ClipInfo* info = getClipInfo(trackIndex, clipIndex);
if (info && info->producer && info->producer->is_valid()) {
delete m_updateCommand;
m_updateCommand = new Timeline::UpdateCommand(*this, trackIndex, clipIndex, info->start);
// We need to set these special properties so time-based filters
// can get information about the cut while still applying filters
// to the cut parent.
info->producer->set(kFilterInProperty, info->frame_in);
info->producer->set(kFilterOutProperty, info->frame_out);
if (MLT.isImageProducer(info->producer))
info->producer->set("out", info->cut->get_int("out"));
info->producer->set(kMultitrackItemProperty, 1);
m_ignoreNextPositionChange = true;
emit selected(info->producer);
delete info;
}*/
}
QList<int> TimelineController::selection() const
{
if (!q->rootObject()) return QList<int>();
return m_selection.selectedClips;
}
void TimelineController::selectMultitrack()
{
setSelection(QList<int>(), -1, true);
QMetaObject::invokeMethod(q->rootObject(), "selectMultitrack");
// emit selected(m_model.tractor());
}
bool TimelineController::snap()
{
return true;
}
bool TimelineController::ripple()
{
return false;
}
bool TimelineController::scrub()
{
return false;
}
int TimelineController::insertClip(int tid, int position, const QString &data_str, bool logUndo)
{
int id;
if (!m_model->requestClipInsertion(data_str, tid, position, id, logUndo)) {
id = -1;
}
return id;
}
int TimelineController::insertComposition(int tid, int position, const QString &transitionId, bool logUndo)
{
int id;
if (!m_model->requestCompositionInsertion(transitionId, tid, position, 100, id, logUndo)) {
id = -1;
}
return id;
}
void TimelineController::deleteSelectedClips()
{
if (m_selection.selectedClips.isEmpty()) {
qDebug() << " * * *NO selection, aborting";
return;
}