# Taken from:
# https://gitlab.archlinux.org/archlinux/packaging/packages/kdenlive/-/blob/main/kdenlive-fixes.patch

diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 68aed69a78..ab614e4b31 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -21,6 +21,7 @@ include:
       - /gitlab-templates/craft-macos-x86-64-qt6.yml
       - /gitlab-templates/craft-macos-arm64-qt6.yml
       - /gitlab-templates/snap-snapcraft-lxd.yml  
+      - /gitlab-templates/documentation.yml
   
 # Customize the job from /gitlab-templates/xml-lint.yml
 # to use our own validate-xml-files.py which has some advanced
diff --git a/data/effects/avfilter/avfilter_hsvhold.xml b/data/effects/avfilter/avfilter_hsvhold.xml
index 50451f2fbf..7b9f025964 100644
--- a/data/effects/avfilter/avfilter_hsvhold.xml
+++ b/data/effects/avfilter/avfilter_hsvhold.xml
@@ -19,7 +19,7 @@
         <comment><![CDATA[Set the value which will<br>
         be used in color difference calculation]]></comment>
     </parameter>
-    <parameter type="animated" name="av.similarity" min="0" max="100" default="0" factor="100" decimals="3" suffix="%">
+    <parameter type="animated" name="av.similarity" min="0.1" max="100" default="0.001" factor="100" decimals="3" suffix="%">
         <name>Similarity</name>
         <comment><![CDATA[Set similarity percentage with the key color]]></comment>
     </parameter>
diff --git a/data/profiles.xml b/data/profiles.xml
index 1f98f30744..b65ae9775c 100644
--- a/data/profiles.xml
+++ b/data/profiles.xml
@@ -101,10 +101,10 @@
   <profile name="Quick Sync Intel H265" extension="mp4" bitrates="30000,1000" defaultbitrate="20000"
            audiobitrates="256,64" defaultaudiobitrate="192"
            args="f=mp4 load_plugin=hevc_hw vcodec=hevc_qsv vbr=off vtag=hvc1 qscale=29 acodec=aac ab=%audiobitrate+'k'"/>
-  <profile name="VAAPI Intel H264" extension="mp4"
-   args="f=mp4 vaapi_device=/dev/dri/renderD128 vf=’format=nv12,hwupload’ vcodec=h264_vaapi vb=30000k acodec=aac ab=192k"/>
-  <profile name="VAAPI AMD H264" extension="mp4"
-   args="f=mp4 hwaccel=vaapi hwaccel_device=renderD129 hwaccel_output_format=vaapi vcodec=h264_vaapi vb=30000k acodec=aac ab=192k"/>
+  <profile name="VAAPI H264" extension="mp4" qualities="15,45" defaultquality="23"
+   args="f=mp4 vcodec=h264_vaapi vq=%quality video_global_quality=%quality acodec=aac ab=192k"/>
+  <profile name="AMF H264" extension="mp4" qualities="15,45" defaultquality="23"
+           args="f=mp4 vcodec=h264_amf vq=%quality video_global_quality=%quality acodec=aac ab=192k"/>
  </group>
  <group name="Audio only" renderer="avformat" type="audio">
   <profile name="AC3" extension="ac3" audiobitrates="192,64" defaultaudiobitrate="160" args="ab=%audiobitrate+'k' vn=1 video_off=1"/>
diff --git a/src/assets/keyframes/model/keyframemodel.cpp b/src/assets/keyframes/model/keyframemodel.cpp
index f62adc53a9..9ceff4269a 100644
--- a/src/assets/keyframes/model/keyframemodel.cpp
+++ b/src/assets/keyframes/model/keyframemodel.cpp
@@ -529,7 +529,8 @@ bool KeyframeModel::updateKeyframe(GenTime pos, QVariant value)
     return res;
 }
 
-KeyframeType::KeyframeEnum convertFromMltType(mlt_keyframe_type type)
+// static
+KeyframeType::KeyframeEnum KeyframeModel::convertFromMltType(mlt_keyframe_type type)
 {
     switch (type) {
     case mlt_keyframe_linear:
diff --git a/src/assets/keyframes/model/keyframemodel.hpp b/src/assets/keyframes/model/keyframemodel.hpp
index 774ee1461a..4c375b170b 100644
--- a/src/assets/keyframes/model/keyframemodel.hpp
+++ b/src/assets/keyframes/model/keyframemodel.hpp
@@ -50,6 +50,7 @@ public:
     friend class KeyframeContainer;
     friend class KeyframeImport;
     friend class AssetMultiKeyframeCommand;
+    static KeyframeType::KeyframeEnum convertFromMltType(mlt_keyframe_type type);
 
 protected:
     /** @brief These methods should ONLY be called by keyframemodellist to ensure synchronisation
diff --git a/src/assets/keyframes/model/keyframemodellist.cpp b/src/assets/keyframes/model/keyframemodellist.cpp
index 7032151fac..5ad097b525 100644
--- a/src/assets/keyframes/model/keyframemodellist.cpp
+++ b/src/assets/keyframes/model/keyframemodellist.cpp
@@ -571,12 +571,10 @@ bool KeyframeModelList::updateMultiKeyframe(GenTime pos, const QStringList &sour
     return true; // NOLINT(clang-analyzer-cplusplus.NewDeleteLeaks)
 }
 
-bool KeyframeModelList::updateKeyframeType(GenTime pos, int type, const QPersistentModelIndex &index)
+bool KeyframeModelList::updateKeyframeType(GenTime pos, int type, const QPersistentModelIndex &index, Fun &undo, Fun &redo)
 {
     QWriteLocker locker(&m_lock);
     Q_ASSERT(m_parameters.count(index) > 0);
-    Fun undo = []() { return true; };
-    Fun redo = []() { return true; };
     if (singleKeyframe()) {
         bool ok = false;
         Keyframe kf = m_parameters.begin()->second->getNextKeyframe(GenTime(-1), &ok);
@@ -587,9 +585,6 @@ bool KeyframeModelList::updateKeyframeType(GenTime pos, int type, const QPersist
     for (const auto &param : m_parameters) {
         res = res && param.second->updateKeyframeType(pos, type, undo, redo);
     }
-    if (res) {
-        PUSH_UNDO(undo, redo, i18n("Update keyframe"));
-    }
     return res;
 }
 
diff --git a/src/assets/keyframes/model/keyframemodellist.hpp b/src/assets/keyframes/model/keyframemodellist.hpp
index 58c2eccbf2..763ab11827 100644
--- a/src/assets/keyframes/model/keyframemodellist.hpp
+++ b/src/assets/keyframes/model/keyframemodellist.hpp
@@ -78,7 +78,7 @@ public:
     */
     bool updateMultiKeyframe(GenTime pos, const QStringList &sourceValues, const QStringList &values, const QList<QModelIndex> &indexes,
                              QUndoCommand *parentCommand = nullptr);
-    bool updateKeyframeType(GenTime pos, int type, const QPersistentModelIndex &index);
+    bool updateKeyframeType(GenTime pos, int type, const QPersistentModelIndex &index, Fun &undo, Fun &redo);
     bool updateKeyframe(GenTime oldPos, GenTime pos, const QVariant &normalizedVal, bool logUndo = true);
     KeyframeType::KeyframeEnum keyframeType(GenTime pos) const;
     /** @brief Returns a keyframe data at given pos
diff --git a/src/assets/keyframes/model/rect/rotatedrecthelper.cpp b/src/assets/keyframes/model/rect/rotatedrecthelper.cpp
index 7a8cd6f7e0..1e608aadbb 100644
--- a/src/assets/keyframes/model/rect/rotatedrecthelper.cpp
+++ b/src/assets/keyframes/model/rect/rotatedrecthelper.cpp
@@ -63,16 +63,9 @@ void RotatedRectHelper::slotUpdateFromMonitorRect(const QRectF &rect)
         return;
     }
 
-    // Get current value to preserve opacity if it exists
-    QString currentValue = m_model->getKeyframeModel()->getInterpolatedValue(0, rectIndex).toString();
-    QStringList parts = currentValue.split(QLatin1Char(' '));
-
     // Create new rect value with updated coordinates
     // Format of AnimatedRect string: "x y width height opacity" (opacity is optional)
     QString newValue = QStringLiteral("%1 %2 %3 %4").arg(int(rect.x())).arg(int(rect.y())).arg(int(rect.width())).arg(int(rect.height()));
-    if (parts.size() > 4) {
-        newValue.append(QStringLiteral(" %1").arg(parts.at(4)));
-    }
 
     // Update the model
     Q_EMIT updateKeyframeData(rectIndex, QVariant(newValue));
diff --git a/src/assets/keyframes/view/keyframeview.cpp b/src/assets/keyframes/view/keyframeview.cpp
index 1ba09092d2..ec8252e86e 100644
--- a/src/assets/keyframes/view/keyframeview.cpp
+++ b/src/assets/keyframes/view/keyframeview.cpp
@@ -147,11 +147,20 @@ const QString KeyframeView::getAssetId()
     return m_model->getAssetId();
 }
 
-void KeyframeView::slotEditType(int type, const QPersistentModelIndex &index)
+void KeyframeView::slotEditFramesType(QList<int> frames, int type, const QPersistentModelIndex &index)
 {
-    int offset = m_relative ? 0 : pCore->getItemIn(m_model->getOwnerId());
-    if (m_model->hasKeyframe(m_position + offset)) {
-        m_model->updateKeyframeType(GenTime(m_position + offset, pCore->getCurrentFps()), type, index);
+    Fun undo = []() { return true; };
+    Fun redo = []() { return true; };
+    bool updated = false;
+    for (auto &f : frames) {
+        if (m_model->hasKeyframe(f)) {
+            if (m_model->updateKeyframeType(GenTime(f, pCore->getCurrentFps()), type, index, undo, redo)) {
+                updated = true;
+            }
+        }
+    }
+    if (updated) {
+        pCore->pushUndo(undo, redo, i18n("Update keyframe"));
     }
 }
 
diff --git a/src/assets/keyframes/view/keyframeview.hpp b/src/assets/keyframes/view/keyframeview.hpp
index 50310a764b..3d2b873f18 100644
--- a/src/assets/keyframes/view/keyframeview.hpp
+++ b/src/assets/keyframes/view/keyframeview.hpp
@@ -40,7 +40,7 @@ public Q_SLOTS:
     void slotModelDisplayChanged();
     void slotOnFocus();
     void slotLoseFocus();
-    void slotEditType(int type, const QPersistentModelIndex &index);
+    void slotEditFramesType(QList<int> frames, int type, const QPersistentModelIndex &index);
     /** @brief Emit initial info for monitor. */
     void initKeyframePos();
     /** @brief Move selected keyframe to cursor position. */
diff --git a/src/assets/view/widgets/keyframecontainer.cpp b/src/assets/view/widgets/keyframecontainer.cpp
index c22355f3b1..1c3ded90d1 100644
--- a/src/assets/view/widgets/keyframecontainer.cpp
+++ b/src/assets/view/widgets/keyframecontainer.cpp
@@ -50,6 +50,62 @@
 #include <QVBoxLayout>
 #include <utility>
 
+struct
+{
+    mlt_keyframe_type t;
+    const QChar s;
+} keyframe_type_map[] = {
+    // Map keyframe type to any single character except numeric values.
+    {mlt_keyframe_discrete, QChar('|')},
+    {mlt_keyframe_discrete, QChar('!')},
+    {mlt_keyframe_linear, QChar()},
+    {mlt_keyframe_smooth, QChar('~')},
+    {mlt_keyframe_smooth_loose, QChar('~')},
+    {mlt_keyframe_smooth_natural, QChar('$')},
+    {mlt_keyframe_smooth_tight, QChar('-')},
+    {mlt_keyframe_sinusoidal_in, QChar('a')},
+    {mlt_keyframe_sinusoidal_out, QChar('b')},
+    {mlt_keyframe_sinusoidal_in_out, QChar('c')},
+    {mlt_keyframe_quadratic_in, QChar('d')},
+    {mlt_keyframe_quadratic_out, QChar('e')},
+    {mlt_keyframe_quadratic_in_out, QChar('f')},
+    {mlt_keyframe_cubic_in, QChar('g')},
+    {mlt_keyframe_cubic_out, QChar('h')},
+    {mlt_keyframe_cubic_in_out, QChar('i')},
+    {mlt_keyframe_quartic_in, QChar('j')},
+    {mlt_keyframe_quartic_out, QChar('k')},
+    {mlt_keyframe_quartic_in_out, QChar('l')},
+    {mlt_keyframe_quintic_in, QChar('m')},
+    {mlt_keyframe_quintic_out, QChar('n')},
+    {mlt_keyframe_quintic_in_out, QChar('o')},
+    {mlt_keyframe_exponential_in, QChar('p')},
+    {mlt_keyframe_exponential_out, QChar('q')},
+    {mlt_keyframe_exponential_in_out, QChar('r')},
+    {mlt_keyframe_circular_in, QChar('s')},
+    {mlt_keyframe_circular_out, QChar('t')},
+    {mlt_keyframe_circular_in_out, QChar('u')},
+    {mlt_keyframe_back_in, QChar('v')},
+    {mlt_keyframe_back_out, QChar('w')},
+    {mlt_keyframe_back_in_out, QChar('x')},
+    {mlt_keyframe_elastic_in, QChar('y')},
+    {mlt_keyframe_elastic_out, QChar('z')},
+    {mlt_keyframe_elastic_in_out, QChar('A')},
+    {mlt_keyframe_bounce_in, QChar('B')},
+    {mlt_keyframe_bounce_out, QChar('C')},
+    {mlt_keyframe_bounce_in_out, QChar('D')},
+};
+
+static mlt_keyframe_type str_to_keyframe_type(const QChar s)
+{
+    int map_count = sizeof(keyframe_type_map) / sizeof(*keyframe_type_map);
+    for (int i = 0; i < map_count; i++) {
+        if (s == keyframe_type_map[i].s) {
+            return keyframe_type_map[i].t;
+        }
+    }
+    return mlt_keyframe_linear;
+}
+
 KeyframeContainer::KeyframeContainer(std::shared_ptr<AssetParameterModel> model, QModelIndex index, QSize frameSize, QWidget *parent, QFormLayout *layout)
     : QObject(parent)
     , m_model(model)
@@ -415,7 +471,18 @@ void KeyframeContainer::monitorSeek(int pos)
 void KeyframeContainer::slotEditKeyframeType(QAction *action)
 {
     int type = action->data().toInt();
-    m_keyframeview->slotEditType(type, m_index);
+    QList<int> frames;
+    if (m_keyframes->selectedKeyframes().count() > 0) {
+        for (auto &p : m_keyframes->selectedKeyframes()) {
+            frames << m_keyframes->getPosAtIndex(p).frames(pCore->getCurrentFps());
+        }
+    } else {
+        frames << getPosition();
+    }
+    if (frames.isEmpty()) {
+        return;
+    }
+    m_keyframeview->slotEditFramesType(frames, type, m_index);
     m_selectType->setIcon(action->icon());
     Q_EMIT activateEffect();
 }
@@ -828,13 +895,26 @@ void KeyframeContainer::connectMonitor(bool active)
 void KeyframeContainer::slotUpdateKeyframesFromMonitor(const QPersistentModelIndex &index, const QVariant &res)
 {
     Q_EMIT activateEffect();
+    QVariant result = res;
     if (m_keyframes->isEmpty()) {
+        QStringList updated = res.toString().split(QLatin1Char(' '), Qt::SkipEmptyParts);
+        if (updated.count() == 4) {
+            // Check if we need to add opacity
+            const QString currentValue = m_model->getKeyframeModel()->getInterpolatedValue(0, index).toString();
+            const QStringList parts = currentValue.split(QLatin1Char(' '), Qt::SkipEmptyParts);
+            if (parts.count() == 5) {
+                // Add missing opacity
+                updated << parts.at(4);
+                result = updated.join(QLatin1Char(' '));
+            }
+        }
+
         GenTime pos(((m_isRelative ? 0 : pCore->getItemIn(m_model->getOwnerId()))) + m_time->getValue(), pCore->getCurrentFps());
         if (m_time->getValue() > 0) {
             // First add keyframe at start of the clip
             GenTime pos0(m_isRelative ? 0 : pCore->getItemIn(m_model->getOwnerId()), pCore->getCurrentFps());
             m_keyframes->addKeyframe(pos0, KeyframeType::Linear);
-            m_keyframes->updateKeyframe(pos0, res, -1, index);
+            m_keyframes->updateKeyframe(pos0, result, -1, index);
             // For rotoscoping, don't add a second keyframe at cursor pos
             auto type = m_model->data(index, AssetParameterModel::TypeRole).value<ParamType>();
             if (type == ParamType::Roto_spline) {
@@ -847,7 +927,7 @@ void KeyframeContainer::slotUpdateKeyframesFromMonitor(const QPersistentModelInd
         }
         // Next add keyframe at playhead position
         m_keyframes->addKeyframe(pos, KeyframeType::Linear);
-        m_keyframes->updateKeyframe(pos, res, -1, index);
+        m_keyframes->updateKeyframe(pos, result, -1, index);
         return;
     }
     int framePos = getPosition();
@@ -862,7 +942,18 @@ void KeyframeContainer::slotUpdateKeyframesFromMonitor(const QPersistentModelInd
         }
     }
     if (m_keyframes->hasKeyframe(framePos) || m_keyframes->singleKeyframe()) {
-        m_keyframes->updateKeyframe(pos, res, -1, index);
+        QStringList updated = res.toString().split(QLatin1Char(' '), Qt::SkipEmptyParts);
+        if (updated.count() == 4) {
+            // Check if we need to add opacity
+            const QString currentValue = m_model->getKeyframeModel()->getInterpolatedValue(framePos, index).toString();
+            const QStringList parts = currentValue.split(QLatin1Char(' '), Qt::SkipEmptyParts);
+            if (parts.count() == 5) {
+                // Add missing opacity
+                updated << parts.at(4);
+                result = updated.join(QLatin1Char(' '));
+            }
+        }
+        m_keyframes->updateKeyframe(pos, result, -1, index);
     } else {
         qDebug() << "==== NO KFR AT: " << framePos;
     }
@@ -914,7 +1005,7 @@ void KeyframeContainer::slotPasteKeyframeFromClipBoard()
         return;
     }
     auto list = json.array();
-    QMap<QString, QMap<int, QVariant>> storedValues;
+    QMap<QString, QMap<std::pair<int, QChar>, QVariant>> storedValues;
     for (const auto &entry : std::as_const(list)) {
         if (!entry.isObject()) {
             qDebug() << "Warning : Skipping invalid marker data";
@@ -928,14 +1019,14 @@ void KeyframeContainer::slotPasteKeyframeFromClipBoard()
 
         ParamType kfrType = entryObj[QLatin1String("type")].toVariant().value<ParamType>();
         if (m_model->isAnimated(kfrType)) {
-            QMap<int, QVariant> values;
+            QMap<std::pair<int, QChar>, QVariant> values;
             if (kfrType == ParamType::Roto_spline) {
                 auto value = entryObj.value(QLatin1String("value"));
                 if (value.isObject()) {
                     QJsonObject obj = value.toObject();
                     QStringList keys = obj.keys();
                     for (auto &k : keys) {
-                        values.insert(k.toInt(), obj.value(k));
+                        values.insert({k.toInt(), QChar()}, obj.value(k));
                     }
                 } else if (value.isArray()) {
                     auto list = value.toArray();
@@ -947,7 +1038,7 @@ void KeyframeContainer::slotPasteKeyframeFromClipBoard()
                         QJsonObject obj = entry.toObject();
                         QStringList keys = obj.keys();
                         for (auto &k : keys) {
-                            values.insert(k.toInt(), obj.value(k));
+                            values.insert({k.toInt(), QChar()}, obj.value(k));
                         }
                     }
                 } else {
@@ -964,15 +1055,21 @@ void KeyframeContainer::slotPasteKeyframeFromClipBoard()
                 }
                 const QStringList stringVals = value.split(QLatin1Char(';'), Qt::SkipEmptyParts);
                 for (auto &val : stringVals) {
-                    int position = m_model->time_to_frames(val.section(QLatin1Char('='), 0, 0));
-                    values.insert(position, val.section(QLatin1Char('='), 1));
+                    QChar separator;
+                    QString timeVal = val.section(QLatin1Char('='), 0, 0);
+                    if (!timeVal.isEmpty() && !timeVal.back().isDigit()) {
+                        separator = timeVal.back();
+                        timeVal.chop(1);
+                    }
+                    int position = m_model->time_to_frames(timeVal);
+                    values.insert({position, separator}, val.section(QLatin1Char('='), 1));
                 }
             }
             storedValues.insert(entryObj[QLatin1String("name")].toString(), values);
         } else {
             const QString value = entryObj.value(QLatin1String("value")).toString();
-            QMap<int, QVariant> values;
-            values.insert(0, value);
+            QMap<std::pair<int, QChar>, QVariant> values;
+            values.insert({0, QChar()}, value);
             storedValues.insert(entryObj[QLatin1String("name")].toString(), values);
         }
     }
@@ -983,12 +1080,14 @@ void KeyframeContainer::slotPasteKeyframeFromClipBoard()
         auto paramName = m_model->data(ix, AssetParameterModel::NameRole).toString();
         if (storedValues.contains(paramName)) {
             KeyframeModel *km = m_keyframes->getKeyModel(ix);
-            const QMap<int, QVariant> values = storedValues.value(paramName);
-            int offset = values.firstKey();
-            QMapIterator<int, QVariant> i(values);
+            const QMap<std::pair<int, QChar>, QVariant> values = storedValues.value(paramName);
+            int offset = values.firstKey().first;
+            QMapIterator<std::pair<int, QChar>, QVariant> i(values);
             while (i.hasNext()) {
                 i.next();
-                km->addKeyframe(GenTime(destPos + i.key() - offset, pCore->getCurrentFps()), KeyframeType::Linear, i.value(), true, undo, redo);
+                mlt_keyframe_type type = str_to_keyframe_type(i.key().second);
+                km->addKeyframe(GenTime(destPos + i.key().first - offset, pCore->getCurrentFps()), KeyframeModel::convertFromMltType(type), i.value(), true,
+                                undo, redo);
             }
         } else {
             qDebug() << "::: NOT FOUND PARAM: " << paramName << " in list: " << storedValues.keys();
diff --git a/src/bin/model/markerlistmodel.cpp b/src/bin/model/markerlistmodel.cpp
index 7d24b7688e..8192acfa0c 100644
--- a/src/bin/model/markerlistmodel.cpp
+++ b/src/bin/model/markerlistmodel.cpp
@@ -506,11 +506,17 @@ bool MarkerListModel::moveMarkers(const QList<CommentedTime> &markers, GenTime f
         GenTime oldPos = marker.time();
         QString oldComment = marker.comment();
         int oldType = marker.markerType();
+        bool oldRanged = marker.hasRange();
+        GenTime oldDuration = marker.duration();
         GenTime newPos = oldPos.operator+(toPos.operator-(fromPos));
 
         res = removeMarker(oldPos, undo, redo);
         if (res) {
-            res = addMarker(newPos, oldComment, oldType, undo, redo);
+            if (oldRanged) {
+                res = addRangeMarker(newPos, oldDuration, oldComment, oldType, undo, redo);
+            } else {
+                res = addMarker(newPos, oldComment, oldType, undo, redo);
+            }
         } else {
             break;
         }
diff --git a/src/core.cpp b/src/core.cpp
index 43eed5fa78..d2576d74ca 100644
--- a/src/core.cpp
+++ b/src/core.cpp
@@ -233,6 +233,164 @@ void Core::buildSplash(bool firstRun, bool showWelcome, bool showCrashRecovery,
     } else {
         m_splash = new Splash(QString(KDENLIVE_VERSION), {}, {}, {}, false, firstRun, showCrashRecovery, wasUpgraded);
     }
+    connect(m_splash, &Splash::resetConfig, this, [this]() {
+        m_abortInitAndRestart = true;
+        QMetaObject::invokeMethod(this, "cleanRestart", Qt::QueuedConnection, Q_ARG(bool, true));
+    });
+    connect(m_splash, &Splash::openBlank, this, [this]() {
+        if (m_splash->hasEventLoop() || !m_guiConstructed) {
+            connect(this, &Core::mainWindowReady, this, [&]() {
+                // Ensure the slot is called once project manager is build.
+                QMetaObject::invokeMethod(m_projectManager, "slotLoadOnOpen", Qt::QueuedConnection);
+            });
+        } else {
+            QMetaObject::invokeMethod(pCore->projectManager(), "slotLoadOnOpen", Qt::QueuedConnection);
+        }
+    });
+    connect(m_splash, &Splash::openLink, this, [this](QString url) { openLink(QUrl(url)); });
+
+    // Check if welcome screen is displayed
+    if (m_splash->welcomeDisplayed()) {
+        connect(this, &Core::closeSplash, this, [this]() {
+            disconnect(this, &Core::loadingMessageNewStage, m_splash, nullptr);
+            disconnect(this, &Core::closeSplash, this, nullptr);
+            m_splash->deleteLater();
+        });
+        connect(m_splash, &Splash::openFile, this, [this](QString url) {
+            // Ensure this can only be called once
+            disconnect(m_splash, &Splash::openFile, this, nullptr);
+            if (m_splash->hasEventLoop() || !m_guiConstructed) {
+                connect(this, &Core::mainWindowReady, this,
+                        [&, url]() { QMetaObject::invokeMethod(m_projectManager, "openFile", Qt::QueuedConnection, Q_ARG(QUrl, QUrl::fromLocalFile(url))); });
+            } else {
+                QMetaObject::invokeMethod(m_projectManager, "openFile", Q_ARG(QUrl, QUrl::fromLocalFile(url)));
+            }
+        });
+        connect(m_splash, &Splash::openOtherFile, this, [this]() {
+            if (m_splash->hasEventLoop() || !m_guiConstructed) {
+                connect(this, &Core::mainWindowReady, [this]() { QMetaObject::invokeMethod(m_projectManager, "slotOpenFile", Qt::QueuedConnection); });
+            } else {
+                QMetaObject::invokeMethod(m_projectManager, "slotOpenFile", Qt::QueuedConnection);
+            }
+        });
+        connect(m_splash, &Splash::closeApp, this, [this]() {
+            if (m_splash->hasEventLoop() || !m_guiConstructed) {
+                QMetaObject::invokeMethod(this, "cleanRestart", Qt::QueuedConnection, Q_ARG(bool, false));
+            } else {
+                QFile lockFile(QDir::temp().absoluteFilePath(QStringLiteral("kdenlivelock")));
+                lockFile.remove();
+                m_splash->deleteLater();
+                delete m_mainWindow;
+                qApp->quit();
+            }
+        });
+        // Switch palette is disabled in crash recovery
+        connect(m_splash, &Splash::switchPalette, this, &Core::switchDarkPalette);
+
+        // History
+        connect(m_splash, &Splash::clearHistory, this, [&]() {
+            if (m_splash->hasEventLoop() || !m_guiConstructed) {
+                connect(this, &Core::mainWindowReady, this, [&]() {
+                    m_projectManager->recentFilesAction()->clear();
+                    m_projectManager->recentFilesAction()->saveEntries(KConfigGroup(KSharedConfig::openConfig(), "Recent Files"));
+                });
+            } else {
+                m_projectManager->recentFilesAction()->clear();
+                m_projectManager->recentFilesAction()->saveEntries(KConfigGroup(KSharedConfig::openConfig(), "Recent Files"));
+            }
+        });
+        connect(m_splash, &Splash::forgetFile, this, [&](const QString path) {
+            if (m_splash->hasEventLoop() || !m_guiConstructed) {
+                connect(this, &Core::mainWindowReady, this, [&, path]() {
+                    m_projectManager->recentFilesAction()->removeUrl(QUrl::fromLocalFile(path));
+                    m_projectManager->recentFilesAction()->saveEntries(KConfigGroup(KSharedConfig::openConfig(), "Recent Files"));
+                });
+            } else {
+                m_projectManager->recentFilesAction()->removeUrl(QUrl::fromLocalFile(path));
+                m_projectManager->recentFilesAction()->saveEntries(KConfigGroup(KSharedConfig::openConfig(), "Recent Files"));
+            }
+        });
+        connect(m_splash, &Splash::clearProfiles, this, [&]() {
+            KdenliveSettings::setRecentProfiles({});
+            KdenliveSettings::setRecentProfileNames({});
+        });
+        connect(m_splash, &Splash::forgetProfile, this, [&](const QString path) {
+            QStringList profileIds = KdenliveSettings::recentProfiles();
+            QStringList profileNames = KdenliveSettings::recentProfileNames();
+            int ix = profileIds.indexOf(path);
+            if (ix > -1) {
+                profileIds.removeAt(ix);
+                profileNames.removeAt(ix);
+                KdenliveSettings::setRecentProfiles(profileIds);
+                KdenliveSettings::setRecentProfileNames(profileNames);
+            }
+        });
+
+        connect(m_splash, &Splash::openTemplate, this, [this](QString url) {
+            if (url.isEmpty()) {
+                // Open project settings
+                if (m_splash->hasEventLoop() || !m_guiConstructed) {
+                    connect(this, &Core::mainWindowReady, this, [&]() {
+                        m_mainWindow->show();
+                        m_splash->fadeOut();
+                        QMetaObject::invokeMethod(m_projectManager, "newFile", Qt::QueuedConnection, Q_ARG(bool, true));
+                    });
+                } else {
+                    m_mainWindow->show();
+                    m_splash->fadeOut();
+                    m_projectManager->newFile(true);
+                }
+            } else {
+                if (m_splash->hasEventLoop() || !m_guiConstructed) {
+                    connect(this, &Core::mainWindowReady, this, [&, url]() {
+                        m_mainWindow->show();
+                        QMetaObject::invokeMethod(m_projectManager, "newFile", Qt::QueuedConnection, Q_ARG(QString, url), Q_ARG(bool, false));
+                    });
+                } else {
+                    m_mainWindow->show();
+                    m_projectManager->newFile(url, false);
+                }
+            }
+        });
+        if (m_splash->hasCrashRecovery()) {
+            connect(m_splash, &Splash::firstStart, this, [&](QString descriptiveString, QString fps, bool interlaced, int vTracks, int aTracks) {
+                connect(this, &Core::mainWindowReady, this, [&, descriptiveString, fps, interlaced, vTracks, aTracks]() {
+                    startFromGuessedProfile(descriptiveString, fps, interlaced, vTracks, aTracks);
+                });
+            });
+        } else {
+            connect(m_splash, &Splash::firstStart, this, [&](QString descriptiveString, QString fps, bool interlaced, int vTracks, int aTracks) {
+                if (!guiReady()) {
+                    connect(this, &Core::mainWindowReady, this, [&, descriptiveString, fps, interlaced, vTracks, aTracks]() {
+                        startFromGuessedProfile(descriptiveString, fps, interlaced, vTracks, aTracks);
+                    });
+                } else {
+                    startFromGuessedProfile(descriptiveString, fps, interlaced, vTracks, aTracks);
+                }
+            });
+        }
+        m_splash->setReady();
+    } else {
+        // Simple splash
+        connect(this, &Core::closeSplash, m_splash, &Splash::fadeOutAndDelete, Qt::QueuedConnection);
+        connect(this, &Core::loadingMessageNewStage, m_splash, &Splash::showProgressMessage, Qt::DirectConnection);
+        /*QObject::connect(pCore.get(), &Core::loadingMessageNewStage, &splash, &Splash::showProgressMessage, Qt::DirectConnection);
+        QObject::connect(pCore.get(), &Core::loadingMessageIncrease, &splash, &Splash::increaseProgressMessage, Qt::DirectConnection);
+        QObject::connect(pCore.get(), &Core::loadingMessageHide, &splash, &Splash::clearMessage, Qt::DirectConnection);*/
+    }
+    if (m_splash->hasEventLoop()) {
+        // Last startup crashed, so stop here until we have a change to reset the config file
+        connect(m_splash, &Splash::releaseLock, this, [&]() {
+            qDebug() << "::::::: EVENT LOOP RELEASED!!!\n\nSSSSSSSSSSSSSSSSSSSSSSSSSSSSS";
+            m_loop.exit();
+            disconnect(m_splash, &Splash::releaseLock, this, nullptr);
+        });
+        m_loop.exec();
+        if (m_abortInitAndRestart) {
+            // We want to restart, no need to continue
+            return;
+        }
+    }
     qApp->processEvents(QEventLoop::AllEvents);
 }
 
@@ -259,163 +417,6 @@ void Core::initGUI(const QString &MltPath, const QUrl &Url, const QStringList &c
         // cleanup
         pCore->updateHideBarsTimer(false);
     });
-
-    if (m_splash) {
-        connect(m_splash, &Splash::resetConfig, this, [this]() {
-            m_abortInitAndRestart = true;
-            QMetaObject::invokeMethod(this, "cleanRestart", Qt::QueuedConnection, Q_ARG(bool, true));
-        });
-        connect(m_splash, &Splash::openBlank, this, [this]() {
-            if (m_splash->hasEventLoop()) {
-                connect(this, &Core::mainWindowReady, m_projectManager, &ProjectManager::slotLoadOnOpen, Qt::QueuedConnection);
-            } else {
-                QMetaObject::invokeMethod(pCore->projectManager(), "slotLoadOnOpen", Qt::QueuedConnection);
-            }
-        });
-        connect(m_splash, &Splash::openLink, this, [this](QString url) { openLink(QUrl(url)); });
-
-        // Check if welcome screen is displayed
-        if (m_splash->welcomeDisplayed()) {
-            connect(this, &Core::closeSplash, this, [this]() {
-                disconnect(this, &Core::loadingMessageNewStage, m_splash, nullptr);
-                disconnect(this, &Core::closeSplash, this, nullptr);
-                m_splash->deleteLater();
-            });
-            connect(m_splash, &Splash::openFile, this, [this](QString url) {
-                // Ensure this can only be called once
-                disconnect(m_splash, &Splash::openFile, this, nullptr);
-                if (m_splash->hasEventLoop()) {
-                    connect(this, &Core::mainWindowReady, this, [&, url]() {
-                        QMetaObject::invokeMethod(m_projectManager, "openFile", Qt::QueuedConnection, Q_ARG(QUrl, QUrl::fromLocalFile(url)));
-                    });
-                } else {
-                    QMetaObject::invokeMethod(m_projectManager, "openFile", Q_ARG(QUrl, QUrl::fromLocalFile(url)));
-                }
-            });
-            connect(m_splash, &Splash::openOtherFile, this, [this]() {
-                if (m_splash->hasEventLoop()) {
-                    connect(this, &Core::mainWindowReady, [this]() { QMetaObject::invokeMethod(m_projectManager, "slotOpenFile", Qt::QueuedConnection); });
-                } else {
-                    QMetaObject::invokeMethod(m_projectManager, "slotOpenFile", Qt::QueuedConnection);
-                }
-            });
-            connect(m_splash, &Splash::closeApp, this, [this]() {
-                if (m_splash->hasEventLoop()) {
-                    QMetaObject::invokeMethod(this, "cleanRestart", Qt::QueuedConnection, Q_ARG(bool, false));
-                } else {
-                    QFile lockFile(QDir::temp().absoluteFilePath(QStringLiteral("kdenlivelock")));
-                    lockFile.remove();
-                    m_splash->deleteLater();
-                    delete m_mainWindow;
-                    qApp->quit();
-                }
-            });
-            // Switch palette is disabled in crash recovery
-            connect(m_splash, &Splash::switchPalette, this, &Core::switchDarkPalette);
-
-            // History
-            connect(m_splash, &Splash::clearHistory, this, [&]() {
-                if (m_splash->hasEventLoop()) {
-                    connect(this, &Core::mainWindowReady, this, [&]() {
-                        m_projectManager->recentFilesAction()->clear();
-                        m_projectManager->recentFilesAction()->saveEntries(KConfigGroup(KSharedConfig::openConfig(), "Recent Files"));
-                    });
-                } else {
-                    m_projectManager->recentFilesAction()->clear();
-                    m_projectManager->recentFilesAction()->saveEntries(KConfigGroup(KSharedConfig::openConfig(), "Recent Files"));
-                }
-            });
-            connect(m_splash, &Splash::forgetFile, this, [&](const QString path) {
-                if (m_splash->hasEventLoop()) {
-                    connect(this, &Core::mainWindowReady, this, [&, path]() {
-                        m_projectManager->recentFilesAction()->removeUrl(QUrl::fromLocalFile(path));
-                        m_projectManager->recentFilesAction()->saveEntries(KConfigGroup(KSharedConfig::openConfig(), "Recent Files"));
-                    });
-                } else {
-                    m_projectManager->recentFilesAction()->removeUrl(QUrl::fromLocalFile(path));
-                    m_projectManager->recentFilesAction()->saveEntries(KConfigGroup(KSharedConfig::openConfig(), "Recent Files"));
-                }
-            });
-            connect(m_splash, &Splash::clearProfiles, this, [&]() {
-                KdenliveSettings::setRecentProfiles({});
-                KdenliveSettings::setRecentProfileNames({});
-            });
-            connect(m_splash, &Splash::forgetProfile, this, [&](const QString path) {
-                QStringList profileIds = KdenliveSettings::recentProfiles();
-                QStringList profileNames = KdenliveSettings::recentProfileNames();
-                int ix = profileIds.indexOf(path);
-                if (ix > -1) {
-                    profileIds.removeAt(ix);
-                    profileNames.removeAt(ix);
-                    KdenliveSettings::setRecentProfiles(profileIds);
-                    KdenliveSettings::setRecentProfileNames(profileNames);
-                }
-            });
-
-            connect(m_splash, &Splash::openTemplate, this, [this](QString url) {
-                if (url.isEmpty()) {
-                    // Open project settings
-                    if (m_splash->hasEventLoop()) {
-                        connect(this, &Core::mainWindowReady, this, [&]() {
-                            m_mainWindow->show();
-                            m_splash->fadeOut();
-                            QMetaObject::invokeMethod(m_projectManager, "newFile", Qt::QueuedConnection, Q_ARG(bool, true));
-                        });
-                    } else {
-                        m_mainWindow->show();
-                        m_splash->fadeOut();
-                        m_projectManager->newFile(true);
-                    }
-                } else {
-                    if (m_splash->hasEventLoop()) {
-                        connect(this, &Core::mainWindowReady, this, [&, url]() {
-                            m_mainWindow->show();
-                            QMetaObject::invokeMethod(m_projectManager, "newFile", Qt::QueuedConnection, Q_ARG(QString, url), Q_ARG(bool, false));
-                        });
-                    } else {
-                        m_mainWindow->show();
-                        m_projectManager->newFile(url, false);
-                    }
-                }
-            });
-            if (m_splash->hasCrashRecovery()) {
-                connect(m_splash, &Splash::firstStart, this, [&](QString descriptiveString, QString fps, bool interlaced, int vTracks, int aTracks) {
-                    connect(this, &Core::mainWindowReady, this, [&, descriptiveString, fps, interlaced, vTracks, aTracks]() {
-                        startFromGuessedProfile(descriptiveString, fps, interlaced, vTracks, aTracks);
-                    });
-                });
-            } else {
-                connect(m_splash, &Splash::firstStart, this, [&](QString descriptiveString, QString fps, bool interlaced, int vTracks, int aTracks) {
-                    if (!guiReady()) {
-                        connect(this, &Core::mainWindowReady, this, [&, descriptiveString, fps, interlaced, vTracks, aTracks]() {
-                            startFromGuessedProfile(descriptiveString, fps, interlaced, vTracks, aTracks);
-                        });
-                    } else {
-                        startFromGuessedProfile(descriptiveString, fps, interlaced, vTracks, aTracks);
-                    }
-                });
-            }
-        } else {
-            // Simple splash
-            connect(this, &Core::closeSplash, m_splash, &Splash::fadeOutAndDelete, Qt::QueuedConnection);
-            connect(this, &Core::loadingMessageNewStage, m_splash, &Splash::showProgressMessage, Qt::DirectConnection);
-            /*QObject::connect(pCore.get(), &Core::loadingMessageNewStage, &splash, &Splash::showProgressMessage, Qt::DirectConnection);
-            QObject::connect(pCore.get(), &Core::loadingMessageIncrease, &splash, &Splash::increaseProgressMessage, Qt::DirectConnection);
-            QObject::connect(pCore.get(), &Core::loadingMessageHide, &splash, &Splash::clearMessage, Qt::DirectConnection);*/
-        }
-        if (m_splash->hasEventLoop()) {
-            // Last startup crashed, so stop here until we have a change to reset the config file
-            connect(m_splash, &Splash::releaseLock, this, [&]() {
-                qDebug() << "::::::: EVENT LOOP RELEASED!!!\n\nSSSSSSSSSSSSSSSSSSSSSSSSSSSSS";
-                m_loop.exit();
-            });
-            m_loop.exec();
-            if (m_abortInitAndRestart) {
-                // We want to restart, no need to continue
-                return;
-            }
-        }
-    }
     m_mainWindow = new MainWindow();
 
     // The MLT Factory will be initiated there, all MLT classes will be usable only after this
@@ -594,13 +595,13 @@ void Core::restoreLayout()
     }
     if (KdenliveSettings::kdockLayout().isEmpty() || !KdenliveSettings::kdockLayout().contains(QStringLiteral("KdenliveKDDock"))) {
         // No existing layout, probably first run
-        Q_EMIT loadLayoutById(QStringLiteral("editing"));
+        Q_EMIT loadLayoutById(QStringLiteral("editing"), true);
     } else {
-        KDDockWidgets::LayoutSaver dockLayout(KDDockWidgets::RestoreOption_AbsoluteFloatingDockWindows);
-        dockLayout.restoreLayout(KdenliveSettings::kdockLayout().toUtf8());
+        Q_EMIT loadLayoutFromData(KdenliveSettings::kdockLayout().toUtf8(), true);
     }
+    m_mainWindow->show();
     if (!KdenliveSettings::showtitlebars()) {
-        Q_EMIT hideBars(!KdenliveSettings::showtitlebars());
+        Q_EMIT pCore->hideBars(true);
     }
 }
 
diff --git a/src/core.h b/src/core.h
index b9619c199b..6574f0ed66 100644
--- a/src/core.h
+++ b/src/core.h
@@ -554,10 +554,10 @@ Q_SIGNALS:
     void updateRenderOffset();
     void hideBars(bool);
     void switchTitleBars();
-    void loadLayoutById(QString layoutId);
+    void loadLayoutById(QString layoutId, bool onlyIfNoPrevious = false);
     void switchDarkPalette(bool dark);
     void mainWindowReady();
-    void loadLayoutFromData(const QString layout);
+    void loadLayoutFromData(const QString layout, bool onlyIfNoPrevious = false);
     /** The project profile changed, check if we have a more appropriate layout (horizontal/vertical) */
     void adjustLayoutToDar();
     /** Should be called when the mainwindow has been constructed and before any dialog is shown to hide the splash screen */
diff --git a/src/dialogs/Simplesplash.qml b/src/dialogs/Simplesplash.qml
index b9ff16e372..57c131fd36 100644
--- a/src/dialogs/Simplesplash.qml
+++ b/src/dialogs/Simplesplash.qml
@@ -16,7 +16,7 @@ Window {
     title: "Splash Screen"
     SystemPalette { id: activePalette }
     modality: Qt.WindowModal
-    flags: Qt.SplashScreen | Qt.FramelessWindowHint | Qt.WindowStaysOnTopHint
+    flags: crashRecovery ? Qt.FramelessWindowHint | Qt.WindowStaysOnTopHint : Qt.SplashScreen | Qt.FramelessWindowHint | Qt.WindowStaysOnTopHint
     property int timeoutInterval: 5000
     property string version
     property bool crashRecovery: false
@@ -73,6 +73,17 @@ Window {
                 activate()
             }
         }
+        Keys.onReturnPressed: {
+            if (splash.wasUpgraded || splash.crashRecovery) {
+                openBlank()
+            }
+        }
+
+        Keys.onEnterPressed: {
+            if (splash.wasUpgraded || splash.crashRecovery) {
+                openBlank()
+            }
+        }
         Keys.onEscapePressed: {
             console.log('ESC PRESSED!!!')
             if (splash.wasUpgraded || splash.crashRecovery) {
diff --git a/src/dialogs/Splash.qml b/src/dialogs/Splash.qml
index 0ef745c378..4cf7afb757 100644
--- a/src/dialogs/Splash.qml
+++ b/src/dialogs/Splash.qml
@@ -27,6 +27,7 @@ Window {
     property var verticalFpsModel: [{value: "25", text: i18n("25 fps")}, {value: "30", text: i18n("30 fps")}, {value: "60", text: i18n("60 fps")}]
     property bool firstRun: true
     property bool crashRecovery: false
+    property bool actionsEnabled: false
     property bool wasUpgraded: false
     property bool palFps: true
     property int border: 10
@@ -61,6 +62,11 @@ Window {
         fadeAnimation.start()
     }
 
+    function enableActions()
+    {
+        actionsEnabled = true
+    }
+
     Component.onCompleted: {
         if (splash.firstRun)
             buttonNext.forceActiveFocus();
@@ -94,6 +100,7 @@ Window {
             from: 1
             to: 0
         }
+        Keys.enabled: splash.actionsEnabled
         Keys.onDownPressed: {
             if (listView.activeFocus) {
                 if (listView.currentIndex < splash.urls.length)
@@ -349,6 +356,7 @@ Window {
                                         id: labelArea
                                         anchors.fill: parent
                                         hoverEnabled: true
+                                        enabled: splash.actionsEnabled
                                         cursorShape: Qt.PointingHandCursor
                                         onPositionChanged: {
                                             if (index != listView.hoveredIndex)
@@ -377,6 +385,7 @@ Window {
                                         height: listLabel.height
                                         width: height
                                         icon.name: "list-remove"
+                                        enabled: splash.actionsEnabled
                                         hoverEnabled: true
                                         ToolTip.text: i18n("Remove file from list")
                                         ToolTip.delay: 1000
@@ -406,8 +415,8 @@ Window {
 
                     Button {
                         id: newProjectButton
-
                         text: i18n("New Project…")
+                        enabled: splash.actionsEnabled
                         icon.name: "document-new"
                         onClicked: splash.openTemplate("")
                         anchors.top: parent.top
@@ -441,6 +450,7 @@ Window {
                                 anchors.right: parent.right
                                 anchors.verticalCenter: parent.verticalCenter
                                 icon.name: "edit-clear-history"
+                                enabled: splash.actionsEnabled
                                 hoverEnabled: true
                                 ToolTip.text: i18n("Clear History of Recent Profiles")
                                 ToolTip.delay: 1000
@@ -505,6 +515,7 @@ Window {
 
                                         anchors.fill: parent
                                         hoverEnabled: true
+                                        enabled: splash.actionsEnabled
                                         cursorShape: Qt.PointingHandCursor
                                         onClicked: {
                                             tlistView.currentIndex = index;
@@ -527,6 +538,7 @@ Window {
                                         anchors.verticalCenter: parent.verticalCenter
                                         height: tlistLabel.height
                                         width: height
+                                        enabled: splash.actionsEnabled
                                         icon.name: "list-remove"
                                         ToolTip.text: i18n("Remove profile from list")
                                         ToolTip.delay: 1000
@@ -611,6 +623,7 @@ Window {
                     anchors.rightMargin: 10
                     text: i18n("Reset")
                     icon.name: "view-refresh"
+                    enabled: splash.actionsEnabled
                     onClicked: resetConfig()
                     KeyNavigation.tab: listView
                 }
@@ -649,6 +662,7 @@ Window {
                     anchors.verticalCenter: parent.verticalCenter
                     anchors.right: parent.right
                     anchors.rightMargin: 10
+                    enabled: splash.actionsEnabled
                     text: i18n("What's New")
                     icon.name: "help-contents"
                     onClicked: openLink("https://kdenlive.org/news/releases/" + splash.version + "?mtm_campaign=kdenlive_inapp&mtm_kwd=splash_upgraded_notes&mtm_content=" + splash.version)
@@ -684,12 +698,14 @@ Window {
                     ToolButton {
                         icon.name: "user-group-new"
                         text: i18n("Contribute…")
+                        enabled: splash.actionsEnabled
                         onClicked: splash.openLink("https://kdenlive.org/get-involved?mtm_campaign=kdenlive_inapp&mtm_kwd=splash_donatebar_contribute&mtm_content=" + splash.version)
                     }
 
                     ToolButton {
                         text: i18n("Donate…")
                         icon.name: "donate"
+                        enabled: splash.actionsEnabled
                         onClicked: splash.openLink("https://kdenlive.org/fund?mtm_campaign=kdenlive_inapp&mtm_kwd=splash_donatebar_donate&mtm_content=" + splash.version)
                         KeyNavigation.tab: listView
                     }
@@ -975,6 +991,7 @@ Window {
                         anchors.verticalCenter: parent.verticalCenter
                         anchors.right: parent.right
                         anchors.rightMargin: 10
+                        enabled: splash.actionsEnabled
                         text: i18n("Reset")
                         icon.name: "view-refresh"
                         onClicked: resetConfig()
@@ -993,6 +1010,7 @@ Window {
                     id: buttonHelp
                     icon.name: "help-browser"
                     text: i18n("Check Online Documentation")
+                    enabled: splash.actionsEnabled
                     Layout.alignment: Qt.AlignLeft
                     onClicked: openLink("https://docs.kdenlive.org?mtm_campaign=kdenlive_inapp&mtm_kwd=splash_dcumentation")
                 }
@@ -1001,6 +1019,7 @@ Window {
                     id: buttonNext
                     icon.name: "go-next"
                     text: i18n("Start Editing")
+                    enabled: splash.actionsEnabled
                     onClicked: {
                         firstStart(profileCombo.currentValue, fpsCombo.currentValue, verticalFrame.checked ? false : interlacedSwitch.enabled ? interlacedSwitch.checked : true, vTracks.value, aTracks.value)
                         splash.hide()
@@ -1018,6 +1037,7 @@ Window {
             anchors.topMargin: 8
             anchors.rightMargin: 8
             icon.name: "window-close"
+            enabled: splash.actionsEnabled
             onClicked: splash.closeApp()
             opacity: 0.6
         }
diff --git a/src/dialogs/renderwidget.cpp b/src/dialogs/renderwidget.cpp
index 0b07d7417d..38660dbbfd 100644
--- a/src/dialogs/renderwidget.cpp
+++ b/src/dialogs/renderwidget.cpp
@@ -2275,7 +2275,12 @@ void RenderWidget::checkDriveSpace()
     QStorageInfo info(QFileInfo(m_view.out_file->url().toLocalFile()).absolutePath());
     m_lastCheckedDevice = info.device();
     DriveSpaceStatus previousState = m_freeSpaceStatus;
+#ifdef Q_OS_MAC
+    // Device always returns readonly on Mac
+    if (!info.isReady() || !info.isValid()) {
+#else
     if (!info.isReady() || !info.isValid() || info.isReadOnly()) {
+#endif
         m_freeSpaceStatus = SpaceNotWritable;
         if (!info.isReady()) {
             // Drive may be mounting, check again in a few seconds
diff --git a/src/dialogs/splash.cpp b/src/dialogs/splash.cpp
index b80523a2a4..95f0a6199d 100644
--- a/src/dialogs/splash.cpp
+++ b/src/dialogs/splash.cpp
@@ -91,20 +91,20 @@ Splash::Splash(const QString version, const QStringList urls, const QStringList
         connect(m_rootObject, SIGNAL(clearProfiles()), this, SIGNAL(clearProfiles()));
         connect(m_rootObject, SIGNAL(forgetFile(QString)), this, SIGNAL(forgetFile(QString)));
         connect(m_rootObject, SIGNAL(forgetProfile(QString)), this, SIGNAL(forgetProfile(QString)));
-        if (m_hasCrashRecovery) {
-            // All signals should also trigger a release lock
-            connect(m_rootObject, SIGNAL(resetConfig()), this, SIGNAL(resetConfig()));
-            connect(m_rootObject, SIGNAL(openBlank()), this, SIGNAL(releaseLock()));
-            connect(m_rootObject, SIGNAL(openOtherFile()), this, SIGNAL(releaseLock()));
-            connect(m_rootObject, SIGNAL(openFile(QString)), this, SIGNAL(releaseLock()));
-            connect(m_rootObject, SIGNAL(openTemplate(QString)), this, SIGNAL(releaseLock()));
-            connect(m_rootObject, SIGNAL(firstStart(QString, QString, bool, int, int)), this, SIGNAL(releaseLock()));
-        }
+
+        // All signals should also trigger a release lock
+        connect(m_rootObject, SIGNAL(resetConfig()), this, SIGNAL(resetConfig()));
+        connect(m_rootObject, SIGNAL(openBlank()), this, SIGNAL(releaseLock()));
+        connect(m_rootObject, SIGNAL(openOtherFile()), this, SIGNAL(releaseLock()));
+        connect(m_rootObject, SIGNAL(openFile(QString)), this, SIGNAL(releaseLock()));
+        connect(m_rootObject, SIGNAL(openTemplate(QString)), this, SIGNAL(releaseLock()));
+        connect(m_rootObject, SIGNAL(firstStart(QString, QString, bool, int, int)), this, SIGNAL(releaseLock()));
         connect(m_rootObject, SIGNAL(firstStart(QString, QString, bool, int, int)), this, SIGNAL(firstStart(QString, QString, bool, int, int)));
     } else {
         if (m_hasCrashRecovery || m_wasUpgraded) {
             connect(m_rootObject, SIGNAL(resetConfig()), this, SIGNAL(resetConfig()));
             connect(m_rootObject, SIGNAL(openLink(QString)), this, SIGNAL(openLink(QString)));
+            connect(m_rootObject, SIGNAL(openBlank()), this, SIGNAL(openBlank()));
             connect(m_rootObject, SIGNAL(openBlank()), this, SIGNAL(releaseLock()));
         }
     }
@@ -132,7 +132,7 @@ bool Splash::hasCrashRecovery() const
 
 bool Splash::hasEventLoop() const
 {
-    return m_hasCrashRecovery || (!m_showWelcome && m_wasUpgraded);
+    return m_hasCrashRecovery || m_showWelcome || (!m_showWelcome && m_wasUpgraded);
 }
 
 bool Splash::wasUpgraded() const
@@ -157,6 +157,11 @@ void Splash::fadeOut()
     QMetaObject::invokeMethod(m_rootObject, "fade");
 }
 
+void Splash::setReady()
+{
+    QMetaObject::invokeMethod(m_rootObject, "enableActions");
+}
+
 void Splash::showProgressMessage(const QString &message, int)
 {
     QMetaObject::invokeMethod(m_rootObject, "displayProgress", Qt::DirectConnection, Q_ARG(QVariant, message));
diff --git a/src/dialogs/splash.hpp b/src/dialogs/splash.hpp
index 2ccea45552..124d96f9ca 100644
--- a/src/dialogs/splash.hpp
+++ b/src/dialogs/splash.hpp
@@ -20,6 +20,7 @@ public:
     bool hasCrashRecovery() const;
     bool wasUpgraded() const;
     bool hasEventLoop() const;
+    void setReady();
 
 private:
     QQmlApplicationEngine *m_engine;
diff --git a/src/doc/kdenlivedoc.cpp b/src/doc/kdenlivedoc.cpp
index 35ed2bf3dd..b64f595cff 100644
--- a/src/doc/kdenlivedoc.cpp
+++ b/src/doc/kdenlivedoc.cpp
@@ -1842,6 +1842,8 @@ void KdenliveDoc::loadDocumentProperties()
             if (name == QLatin1String("layout")) {
                 const QString layoutData = e.firstChild().nodeValue();
                 Q_EMIT pCore->loadLayoutFromData(layoutData);
+                // clear layout
+                e.firstChild().clear();
                 continue;
             }
             if (name == QLatin1String("storagefolder")) {
diff --git a/src/effects/effectstack/view/collapsibleeffectview.cpp b/src/effects/effectstack/view/collapsibleeffectview.cpp
index e881dcb5d6..409252f50c 100644
--- a/src/effects/effectstack/view/collapsibleeffectview.cpp
+++ b/src/effects/effectstack/view/collapsibleeffectview.cpp
@@ -31,6 +31,7 @@
 #include <QMimeData>
 #include <QPointer>
 #include <QProgressBar>
+#include <QPushButton>
 #include <QSpinBox>
 #include <QStandardPaths>
 #include <QTextEdit>
@@ -42,6 +43,7 @@
 #include <KDualAction>
 #include <KLocalizedString>
 #include <KMessageBox>
+#include <KMessageWidget>
 #include <KRecentDirs>
 #include <KSqueezedTextLabel>
 
@@ -663,6 +665,11 @@ void CollapsibleEffectView::slotSaveEffect(const QString title, const QString de
 
     effectName->setText(title);
     descriptionBox->setText(description);
+    KMessageWidget mw;
+    mw.setMessageType(KMessageWidget::Warning);
+    mw.setText(i18n("A profile with that name already exists"));
+    mw.setVisible(false);
+    form.addRow(&mw);
 
     QDialogButtonBox buttonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel, Qt::Horizontal, &dialog);
     form.addRow(&buttonBox);
@@ -670,6 +677,18 @@ void CollapsibleEffectView::slotSaveEffect(const QString title, const QString de
 
     QObject::connect(&buttonBox, &QDialogButtonBox::accepted, &dialog, &QDialog::accept);
     QObject::connect(&buttonBox, &QDialogButtonBox::rejected, &dialog, &QDialog::reject);
+    connect(effectName, &QLineEdit::textChanged, this, [&buttonBox, &mw](QString name) {
+        if (name.isEmpty()) {
+            buttonBox.button(QDialogButtonBox::Ok)->setEnabled(false);
+            mw.setVisible(false);
+        } else if (EffectsRepository::get()->exists(name)) {
+            buttonBox.button(QDialogButtonBox::Ok)->setEnabled(false);
+            mw.setVisible(true);
+        } else {
+            buttonBox.button(QDialogButtonBox::Ok)->setEnabled(true);
+            mw.setVisible(false);
+        }
+    });
 
     if (dialog.exec() == QDialog::Accepted) {
         QString name = effectName->text().simplified();
diff --git a/src/kdenliveui.rc b/src/kdenliveui.rc
index 005ceb5046..8f1819b276 100644
--- a/src/kdenliveui.rc
+++ b/src/kdenliveui.rc
@@ -368,4 +368,6 @@
     <text>Extra Toolbar</text>
     <Action name="project_render_button"/>
   </ToolBar>
+  <!-- keep this for compatibility with Kdenlive < 25.08.3 -->
+  <Menu name="marker_menu" />
 </kpartgui>
diff --git a/src/layouts/layoutcollection.cpp b/src/layouts/layoutcollection.cpp
index d11061e631..9cd1329983 100644
--- a/src/layouts/layoutcollection.cpp
+++ b/src/layouts/layoutcollection.cpp
@@ -127,9 +127,17 @@ void LayoutCollection::loadLayouts()
         while (it.hasNext()) {
             const QFileInfo fInfo(dir.absoluteFilePath(it.next()));
             QString layoutId = fInfo.baseName();
-            if (foundlayouts.contains(fInfo.baseName()) && !fInfo.isWritable()) {
+            if (foundlayouts.contains(layoutId) && !fInfo.isWritable()) {
                 // Only overwrite if the folder is writable
-                continue;
+                auto layout = foundlayouts.value(layoutId);
+                if (layoutId.endsWith(QLatin1String("_vertical"))) {
+                    // We are processing a vertical layout, ensure we have none yet
+                    if (layout.hasVerticalData()) {
+                        continue;
+                    }
+                } else if (layout.hasHorizontalData()) {
+                    continue;
+                }
             }
             // Read layout info
             QFile loadFile(fInfo.absoluteFilePath());
@@ -156,6 +164,7 @@ void LayoutCollection::loadLayouts()
                 // Allow overriding id based on file name
                 layoutId = insideId;
             }
+            qDebug() << ":::: LOADING LAYOUT: " << layoutId << ", VERTICAL: " << isVertical;
             LayoutInfo layout;
             if (foundlayouts.contains(layoutId)) {
                 layout = foundlayouts.value(layoutId);
diff --git a/src/layouts/layoutmanagement.cpp b/src/layouts/layoutmanagement.cpp
index b9db08789a..d948ca1ab0 100644
--- a/src/layouts/layoutmanagement.cpp
+++ b/src/layouts/layoutmanagement.cpp
@@ -211,9 +211,9 @@ bool LayoutManagement::slotLoadLayoutById(const QString &layoutId)
     return slotLoadLayout(layout);
 }
 
-bool LayoutManagement::slotLoadLayout(LayoutInfo layout)
+bool LayoutManagement::slotLoadLayout(LayoutInfo layout, bool onlyIfNoPrevious)
 {
-    if (!layout.isValid()) {
+    if (!layout.isValid() || (onlyIfNoPrevious && m_firstLayoutLoaded)) {
         // Layout not found or has no data
         return false;
     }
@@ -235,6 +235,7 @@ bool LayoutManagement::slotLoadLayout(LayoutInfo layout)
         pCore->displayBinMessage(i18n("The layout %1 could not be restored, should be removed and recreated.", layout.displayName), KMessageWidget::Warning);
         return false;
     }
+    m_firstLayoutLoaded = true;
     m_layoutSwitcher->setCurrentLayout(layout.internalId);
     if (!KdenliveSettings::showtitlebars()) {
         Q_EMIT pCore->hideBars(!KdenliveSettings::showtitlebars());
@@ -254,9 +255,9 @@ void LayoutManagement::adjustLayoutToDar()
     }
 }
 
-bool LayoutManagement::slotLoadLayoutFromData(const QString &layoutData)
+bool LayoutManagement::slotLoadLayoutFromData(const QString &layoutData, bool onlyIfNoPrevious)
 {
-    if (layoutData.isEmpty()) {
+    if (layoutData.isEmpty() || (onlyIfNoPrevious && m_firstLayoutLoaded)) {
         // Layout not found or has no data
         return false;
     }
@@ -270,9 +271,10 @@ bool LayoutManagement::slotLoadLayoutFromData(const QString &layoutData)
     // Loaded a layout from Kdenlive settings or document
     m_currentLayoutId.clear();
     m_layoutSwitcher->setCurrentLayout(QString());
-    if (!KdenliveSettings::showtitlebars()) {
+    if (!KdenliveSettings::showtitlebars() && m_firstLayoutLoaded) {
         Q_EMIT pCore->hideBars(!KdenliveSettings::showtitlebars());
     }
+    m_firstLayoutLoaded = true;
     return true;
 }
 
diff --git a/src/layouts/layoutmanagement.h b/src/layouts/layoutmanagement.h
index 207d3d0201..d2b08fac71 100644
--- a/src/layouts/layoutmanagement.h
+++ b/src/layouts/layoutmanagement.h
@@ -30,10 +30,10 @@ public:
 
 public Q_SLOTS:
     /** @brief Loads a layout by LayoutInfo. */
-    bool slotLoadLayout(LayoutInfo layout);
+    bool slotLoadLayout(LayoutInfo layout, bool onlyIfNoPrevious = false);
     /** @brief Load a layout by its name. */
     bool slotLoadLayoutById(const QString &layoutId);
-    bool slotLoadLayoutFromData(const QString &layoutData);
+    bool slotLoadLayoutFromData(const QString &layoutData, bool onlyIfNoPrevious = false);
     /** @brief Load a layout by its name. */
     void adjustLayoutToDar();
 
@@ -67,4 +67,5 @@ private:
     LayoutCollection m_layoutCollection;
     KActionCategory *m_layoutCategory;
     QString m_currentLayoutId;
+    bool m_firstLayoutLoaded{false};
 };
diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp
index 5271021030..438a0d1c1d 100644
--- a/src/mainwindow.cpp
+++ b/src/mainwindow.cpp
@@ -612,7 +612,7 @@ void MainWindow::init()
     addAction(QStringLiteral("timeline_preview_button"), previewButtonAction);
 
     // Since not all widgets are added yet, don't use the Save flag now
-    setupGUI(KXmlGuiWindow::ToolBar | KXmlGuiWindow::StatusBar /*| KXmlGuiWindow::Save*/ | KXmlGuiWindow::Create);
+    setupGUI(KXmlGuiWindow::ToolBar | KXmlGuiWindow::StatusBar | KXmlGuiWindow::Create);
 
     // Only start saving config once all GUI setup is done.
     connect(pCore.get(), &Core::GUISetupDone, this, &MainWindow::finishUiSetup, Qt::DirectConnection);
@@ -854,6 +854,7 @@ void MainWindow::init()
 void MainWindow::finishUiSetup()
 {
     pCore->restoreLayout();
+    Q_EMIT pCore->closeSplash();
     setAutoSaveSettings();
     QObject::disconnect(pCore.get(), &Core::GUISetupDone, this, nullptr);
     // This should connect only after splash is done
diff --git a/src/monitor/monitormanager.cpp b/src/monitor/monitormanager.cpp
index 0fae5ae462..e32db3c00e 100644
--- a/src/monitor/monitormanager.cpp
+++ b/src/monitor/monitormanager.cpp
@@ -210,7 +210,7 @@ bool MonitorManager::activateMonitor(Kdenlive::MonitorId name, bool raiseMonitor
             if (!quickSwitch) {
                 // Set guides list to show guides
                 m_clipMonitor->updateGuidesList();
-                if (!m_clipMonitor->isVisible()) {
+                if (pCore->window()->isVisible() && !m_clipMonitor->isVisible()) {
                     pCore->displayMessage(i18n("Do you want to <a href=\"#clipmonitor\">show the clip monitor</a> to view timeline?"),
                                           MessageType::InformationMessage);
                     m_activeMonitor = m_projectMonitor;
@@ -242,7 +242,7 @@ bool MonitorManager::activateMonitor(Kdenlive::MonitorId name, bool raiseMonitor
                 m_projectMonitor->fixFocus();
             }
             if (!quickSwitch) {
-                if (!m_projectMonitor->isVisible()) {
+                if (pCore->window()->isVisible() && !m_projectMonitor->isVisible()) {
                     pCore->displayMessage(i18n("Do you want to <a href=\"#projectmonitor\">show the project monitor</a> to view timeline?"),
                                           MessageType::InformationMessage);
                     m_activeMonitor = m_clipMonitor;
diff --git a/src/project/projectmanager.cpp b/src/project/projectmanager.cpp
index 87e54013d8..db377d822b 100644
--- a/src/project/projectmanager.cpp
+++ b/src/project/projectmanager.cpp
@@ -813,7 +813,6 @@ void ProjectManager::openFile(const QUrl &url)
     if ((m_project != nullptr) && m_project->url() == url) {
         return;
     }
-
     if (!closeCurrentDocument()) {
         return;
     }
diff --git a/src/timeline2/model/timelinefunctions.cpp b/src/timeline2/model/timelinefunctions.cpp
index d62517cd3b..aec22143ee 100644
--- a/src/timeline2/model/timelinefunctions.cpp
+++ b/src/timeline2/model/timelinefunctions.cpp
@@ -2613,9 +2613,15 @@ bool TimelineFunctions::pasteTimelineClips(const std::shared_ptr<TimelineItemMod
             warp_pitch = prod.attribute(QStringLiteral("warp_pitch")).toInt();
         }
         int audioStream = prod.attribute(QStringLiteral("audioStream")).toInt();
+        PlaylistState::ClipState state = static_cast<PlaylistState::ClipState>(prod.attribute(QStringLiteral("state")).toInt());
+        if (state != PlaylistState::Disabled) {
+            PlaylistState::ClipState trackState = timeline->getTrackById_const(curTrackId)->trackType();
+            if (state != trackState) {
+                state = trackState;
+            }
+        }
         int newId;
-        bool created = timeline->requestClipCreation(originalId, newId, timeline->getTrackById_const(curTrackId)->trackType(), audioStream, speed, warp_pitch,
-                                                     timeline_undo, timeline_redo);
+        bool created = timeline->requestClipCreation(originalId, newId, state, audioStream, speed, warp_pitch, timeline_undo, timeline_redo);
         if (!created) {
             // Something is broken
             pCore->displayMessage(i18n("Could not paste items in timeline"), ErrorMessage, 500);

