┌   ┐
54
└   ┘

summaryrefslogtreecommitdiff
path: root/src/dolphintabpage.cpp
diff options
context:
space:
mode:
authorFelix Ernst <[email protected]>2021-01-02 17:48:52 +0000
committerElvis Angelaccio <[email protected]>2021-01-02 17:48:52 +0000
commitf01a61b76c8588a4df2054ab70e9a746a74f7817 (patch)
tree1bc359df5c5f2e203652f1e59e1c08544383488e /src/dolphintabpage.cpp
parentd3c5bb6e9b99c6ff43bd8160df58d35a725a0894 (diff)
Animate split view mode toggling
Have the secondary ViewContainer slide into/out of view when split view mode is switched on or off by the user. This should help users understand what split view mode is about. Without the animation it might seem like the only thing the button does is creating a weird vertical line in the middle of the view or something. With the animation it should be clear that the second view is a separate entity that was added. The closing animation will help users understand which of the ViewContainers was just closed.
Diffstat (limited to 'src/dolphintabpage.cpp')
-rw-r--r--src/dolphintabpage.cpp144
1 files changed, 137 insertions, 7 deletions
diff --git a/src/dolphintabpage.cpp b/src/dolphintabpage.cpp
index 138822cfd..a90e8e7f0 100644
--- a/src/dolphintabpage.cpp
+++ b/src/dolphintabpage.cpp
@@ -1,5 +1,6 @@
/*
* SPDX-FileCopyrightText: 2014 Emmanuel Pescosta <[email protected]>
+ * SPDX-FileCopyrightText: 2020 Felix Ernst <[email protected]>
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
@@ -8,13 +9,17 @@
#include "dolphin_generalsettings.h"
#include "dolphinviewcontainer.h"
+#include "global.h"
+#include <QVariantAnimation>
#include <QSplitter>
#include <QGridLayout>
#include <QWidgetAction>
+#include <QStyle>
DolphinTabPage::DolphinTabPage(const QUrl &primaryUrl, const QUrl &secondaryUrl, QWidget* parent) :
QWidget(parent),
+ m_expandingContainer{nullptr},
m_primaryViewActive(true),
m_splitViewEnabled(false),
m_active(true)
@@ -65,12 +70,24 @@ bool DolphinTabPage::splitViewEnabled() const
return m_splitViewEnabled;
}
-void DolphinTabPage::setSplitViewEnabled(bool enabled, const QUrl &secondaryUrl)
+void DolphinTabPage::setSplitViewEnabled(bool enabled, Animated animated, const QUrl &secondaryUrl)
{
if (m_splitViewEnabled != enabled) {
m_splitViewEnabled = enabled;
+ if (animated == WithAnimation && (
+ style()->styleHint(QStyle::SH_Widget_Animation_Duration, nullptr, this) < 1 ||
+ GlobalConfig::animationDurationFactor() <= 0.0)) {
+ animated = WithoutAnimation;
+ }
+ if (m_expandViewAnimation) {
+ m_expandViewAnimation->stop(); // deletes because of QAbstractAnimation::DeleteWhenStopped.
+ if (animated == WithoutAnimation) {
+ slotAnimationFinished();
+ }
+ }
if (enabled) {
+ QList<int> splitterSizes = m_splitter->sizes();
const QUrl& url = (secondaryUrl.isEmpty()) ? m_primaryViewContainer->url() : secondaryUrl;
m_secondaryViewContainer = createViewContainer(url);
@@ -84,8 +101,15 @@ void DolphinTabPage::setSplitViewEnabled(bool enabled, const QUrl &secondaryUrl)
m_splitter->addWidget(m_secondaryViewContainer);
m_secondaryViewContainer->installEventFilter(this);
- m_secondaryViewContainer->show();
m_secondaryViewContainer->setActive(true);
+
+ if (animated == WithAnimation) {
+ m_secondaryViewContainer->setMinimumWidth(1);
+ splitterSizes.append(1);
+ m_splitter->setSizes(splitterSizes);
+ startExpandViewAnimation(m_secondaryViewContainer);
+ }
+ m_secondaryViewContainer->show();
} else {
m_navigatorsWidget->setSecondaryNavigatorVisible(false);
m_secondaryViewContainer->disconnectUrlNavigator();
@@ -117,8 +141,18 @@ void DolphinTabPage::setSplitViewEnabled(bool enabled, const QUrl &secondaryUrl)
}
}
m_primaryViewContainer->setActive(true);
- view->close();
- view->deleteLater();
+
+ if (animated == WithoutAnimation) {
+ view->close();
+ view->deleteLater();
+ } else {
+ // Kill it but keep it as a zombie for the closing animation.
+ m_secondaryViewContainer = nullptr;
+ view->blockSignals(true);
+ view->view()->blockSignals(true);
+ view->setDisabled(true);
+ startExpandViewAnimation(m_primaryViewContainer);
+ }
}
}
}
@@ -204,7 +238,7 @@ void DolphinTabPage::insertNavigatorsWidget(DolphinNavigatorsWidgetAction* navig
void DolphinTabPage::resizeNavigators() const
{
- if (!m_splitViewEnabled) {
+ if (!m_secondaryViewContainer) {
m_navigatorsWidget->followViewContainerGeometry(
m_primaryViewContainer->mapToGlobal(QPoint(0,0)).x(),
m_primaryViewContainer->width());
@@ -285,7 +319,7 @@ void DolphinTabPage::restoreState(const QByteArray& state)
bool isSplitViewEnabled = false;
stream >> isSplitViewEnabled;
- setSplitViewEnabled(isSplitViewEnabled);
+ setSplitViewEnabled(isSplitViewEnabled, WithoutAnimation);
QUrl primaryUrl;
stream >> primaryUrl;
@@ -329,7 +363,7 @@ void DolphinTabPage::restoreStateV1(const QByteArray& state)
bool isSplitViewEnabled = false;
stream >> isSplitViewEnabled;
- setSplitViewEnabled(isSplitViewEnabled);
+ setSplitViewEnabled(isSplitViewEnabled, WithoutAnimation);
QUrl primaryUrl;
stream >> primaryUrl;
@@ -372,6 +406,72 @@ void DolphinTabPage::setActive(bool active)
activeViewContainer()->setActive(active);
}
+void DolphinTabPage::slotAnimationFinished()
+{
+ for (int i = 0; i < m_splitter->count(); ++i) {
+ QWidget *viewContainer = m_splitter->widget(i);
+ if (viewContainer != m_primaryViewContainer &&
+ viewContainer != m_secondaryViewContainer) {
+ viewContainer->close();
+ viewContainer->deleteLater();
+ }
+ }
+ for (int i = 0; i < m_splitter->count(); ++i) {
+ QWidget *viewContainer = m_splitter->widget(i);
+ viewContainer->setMinimumWidth(viewContainer->minimumSizeHint().width());
+ }
+ m_expandingContainer = nullptr;
+}
+
+void DolphinTabPage::slotAnimationValueChanged(const QVariant& value)
+{
+ Q_CHECK_PTR(m_expandingContainer);
+ const int indexOfExpandingContainer = m_splitter->indexOf(m_expandingContainer);
+ int indexOfNonExpandingContainer = -1;
+ if (m_expandingContainer == m_primaryViewContainer) {
+ indexOfNonExpandingContainer = m_splitter->indexOf(m_secondaryViewContainer);
+ } else {
+ indexOfNonExpandingContainer = m_splitter->indexOf(m_primaryViewContainer);
+ }
+ std::vector<QWidget *> widgetsToRemove;
+ const QList<int> oldSplitterSizes = m_splitter->sizes();
+ QList<int> newSplitterSizes{oldSplitterSizes};
+ int expansionWidthNeeded = value.toInt() - oldSplitterSizes.at(indexOfExpandingContainer);
+
+ // Reduce the size of the other widgets to make space for the expandingContainer.
+ for (int i = m_splitter->count() - 1; i >= 0; --i) {
+ if (m_splitter->widget(i) == m_primaryViewContainer ||
+ m_splitter->widget(i) == m_secondaryViewContainer) {
+ continue;
+ }
+ newSplitterSizes[i] = oldSplitterSizes.at(i) - expansionWidthNeeded;
+ expansionWidthNeeded = 0;
+ if (indexOfNonExpandingContainer != -1) {
+ // Make sure every zombie container is at least slightly reduced in size
+ // so it doesn't seem like they are here to stay.
+ newSplitterSizes[i]--;
+ newSplitterSizes[indexOfNonExpandingContainer]++;
+ }
+ if (newSplitterSizes.at(i) <= 0) {
+ expansionWidthNeeded -= newSplitterSizes.at(i);
+ newSplitterSizes[i] = 0;
+ widgetsToRemove.emplace_back(m_splitter->widget(i));
+ }
+ }
+ if (expansionWidthNeeded > 1 && indexOfNonExpandingContainer != -1) {
+ Q_ASSERT(m_splitViewEnabled);
+ newSplitterSizes[indexOfNonExpandingContainer] -= expansionWidthNeeded;
+ }
+ newSplitterSizes[indexOfExpandingContainer] = value.toInt();
+ m_splitter->setSizes(newSplitterSizes);
+ while (!widgetsToRemove.empty()) {
+ widgetsToRemove.back()->close();
+ widgetsToRemove.back()->deleteLater();
+ widgetsToRemove.pop_back();
+ }
+}
+
+
void DolphinTabPage::slotViewActivated()
{
const DolphinView* oldActiveView = activeViewContainer()->view();
@@ -441,3 +541,33 @@ DolphinViewContainer* DolphinTabPage::createViewContainer(const QUrl& url) const
return container;
}
+
+void DolphinTabPage::startExpandViewAnimation(DolphinViewContainer *expandingContainer)
+{
+ Q_CHECK_PTR(expandingContainer);
+ Q_ASSERT(expandingContainer == m_primaryViewContainer ||
+ expandingContainer == m_secondaryViewContainer);
+ m_expandingContainer = expandingContainer;
+
+ m_expandViewAnimation = new QVariantAnimation(m_splitter);
+ m_expandViewAnimation->setDuration(2 *
+ style()->styleHint(QStyle::SH_Widget_Animation_Duration, nullptr, this) *
+ GlobalConfig::animationDurationFactor());
+ for (int i = 0; i < m_splitter->count(); ++i) {
+ m_splitter->widget(i)->setMinimumWidth(1);
+ }
+ connect(m_expandViewAnimation, &QAbstractAnimation::finished,
+ this, &DolphinTabPage::slotAnimationFinished);
+ connect(m_expandViewAnimation, &QVariantAnimation::valueChanged,
+ this, &DolphinTabPage::slotAnimationValueChanged);
+
+ m_expandViewAnimation->setStartValue(expandingContainer->width());
+ if (m_splitViewEnabled) { // A new viewContainer is being opened.
+ m_expandViewAnimation->setEndValue(m_splitter->width() / 2);
+ m_expandViewAnimation->setEasingCurve(QEasingCurve::OutCubic);
+ } else { // A viewContainer is being closed.
+ m_expandViewAnimation->setEndValue(m_splitter->width());
+ m_expandViewAnimation->setEasingCurve(QEasingCurve::InCubic);
+ }
+ m_expandViewAnimation->start(QAbstractAnimation::DeleteWhenStopped);
+}