mirror of
https://invent.kde.org/marcoa/shift-shell.git
synced 2026-04-26 14:23:09 +00:00
SwipeArea requires 10px to differentiate between taps and swipes. HomeScreenState uses a further 10px to differentiate between vertical and horizontal swipes. This MR combines the swipe detection together so that we only need 10px rather than 20px for gesture detection.
1067 lines
31 KiB
C++
1067 lines
31 KiB
C++
// SPDX-FileCopyrightText: 2023 Devin Lin <devin@kde.org>
|
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
|
|
#include "homescreenstate.h"
|
|
#include "favouritesmodel.h"
|
|
#include "foliosettings.h"
|
|
#include "pagelistmodel.h"
|
|
|
|
#include <algorithm>
|
|
|
|
// TODO don't hardcode, use something more device dependent?
|
|
constexpr qreal APP_DRAWER_OPEN_DIST = 300;
|
|
constexpr qreal SEARCH_WIDGET_OPEN_DIST = 300;
|
|
|
|
// pixels to move before we determine the swipe type
|
|
constexpr qreal DETERMINE_SWIPE_THRESHOLD = 10;
|
|
|
|
constexpr qreal VERTICAL_FAVOURITES_BAR_THRESHOLD = 400;
|
|
|
|
QPropertyAnimation *HomeScreenState::setupAnimation(QByteArray property, int duration, QEasingCurve::Type curve, qreal endValue)
|
|
{
|
|
auto anim = new QPropertyAnimation{this, property, this};
|
|
anim->setDuration(duration);
|
|
anim->setEndValue(endValue);
|
|
anim->setEasingCurve(curve);
|
|
return anim;
|
|
}
|
|
|
|
HomeScreenState::HomeScreenState(HomeScreen *parent)
|
|
: QObject{parent}
|
|
, m_homeScreen{parent}
|
|
, m_dragState{new DragState{this, parent}}
|
|
, m_appDrawerY{APP_DRAWER_OPEN_DIST}
|
|
, m_searchWidgetY{SEARCH_WIDGET_OPEN_DIST}
|
|
{
|
|
}
|
|
|
|
void HomeScreenState::init()
|
|
{
|
|
const int expoDuration = 800;
|
|
const int cubicDuration = 400;
|
|
|
|
m_openAppDrawerAnim = setupAnimation("appDrawerY", expoDuration, QEasingCurve::OutExpo, 0);
|
|
|
|
connect(m_openAppDrawerAnim, &QPropertyAnimation::valueChanged, this, [this]() {
|
|
// the animation runs too long to connect to QPropertyAnimation::finished
|
|
// instead just have the end behaviour execute once we are 90% through
|
|
if (m_appDrawerOpenProgress > 0.9) {
|
|
setViewState(ViewState::AppDrawerView);
|
|
Q_EMIT appDrawerOpened();
|
|
}
|
|
});
|
|
|
|
m_closeAppDrawerAnim = setupAnimation("appDrawerY", expoDuration, QEasingCurve::OutExpo, APP_DRAWER_OPEN_DIST);
|
|
|
|
connect(m_closeAppDrawerAnim, &QPropertyAnimation::valueChanged, this, [this]() {
|
|
// the animation runs too long to connect to QPropertyAnimation::finished
|
|
// instead just have the end behaviour execute once we are 90% through
|
|
if (m_appDrawerOpenProgress < 0.1) {
|
|
setViewState(ViewState::PageView);
|
|
Q_EMIT appDrawerClosed();
|
|
}
|
|
});
|
|
|
|
m_openSearchWidgetAnim = setupAnimation("searchWidgetY", cubicDuration, QEasingCurve::OutCubic, 0);
|
|
|
|
connect(m_openSearchWidgetAnim, &QPropertyAnimation::finished, this, [this]() {
|
|
setViewState(ViewState::SearchWidgetView);
|
|
});
|
|
|
|
m_closeSearchWidgetAnim = setupAnimation("searchWidgetY", cubicDuration, QEasingCurve::OutCubic, SEARCH_WIDGET_OPEN_DIST);
|
|
|
|
connect(m_closeSearchWidgetAnim, &QPropertyAnimation::finished, this, [this]() {
|
|
setViewState(ViewState::PageView);
|
|
});
|
|
|
|
m_pageAnim = setupAnimation("pageViewX", cubicDuration, QEasingCurve::OutCubic, 0);
|
|
|
|
m_openFolderAnim = setupAnimation("folderOpenProgress", cubicDuration, QEasingCurve::OutCubic, 1.0);
|
|
|
|
connect(m_openFolderAnim, &QPropertyAnimation::finished, this, [this]() {
|
|
setViewState(ViewState::FolderView);
|
|
});
|
|
|
|
m_closeFolderAnim = setupAnimation("folderOpenProgress", cubicDuration, QEasingCurve::OutCubic, 0.0);
|
|
|
|
connect(m_closeFolderAnim, &QPropertyAnimation::finished, this, [this]() {
|
|
setViewState(ViewState::PageView);
|
|
setCurrentFolder(nullptr);
|
|
setFolderViewX(0); // reset to first page
|
|
m_folderPageNum = 0;
|
|
Q_EMIT folderPageNumChanged();
|
|
|
|
Q_EMIT leftCurrentFolder();
|
|
});
|
|
|
|
m_folderPageAnim = setupAnimation("folderViewX", cubicDuration, QEasingCurve::OutCubic, 0);
|
|
|
|
m_openSettingsAnim = setupAnimation("settingsOpenProgress", cubicDuration, QEasingCurve::OutExpo, 1.0);
|
|
|
|
connect(m_openSettingsAnim, &QPropertyAnimation::finished, this, [this]() {
|
|
setViewState(ViewState::SettingsView);
|
|
});
|
|
|
|
m_closeSettingsAnim = setupAnimation("settingsOpenProgress", cubicDuration, QEasingCurve::InOutExpo, 0.0);
|
|
|
|
connect(m_closeSettingsAnim, &QPropertyAnimation::finished, this, [this]() {
|
|
setViewState(ViewState::PageView);
|
|
});
|
|
|
|
connect(this, &HomeScreenState::viewWidthChanged, this, [this]() {
|
|
// TODO: we only support 2 orientations at the moment since we don't know what the device rotated to
|
|
setPageOrientation(m_viewWidth > m_viewHeight ? RotateCounterClockwise : RegularPosition);
|
|
});
|
|
connect(this, &HomeScreenState::viewHeightChanged, this, [this]() {
|
|
setPageOrientation(m_viewWidth > m_viewHeight ? RotateCounterClockwise : RegularPosition);
|
|
});
|
|
connect(this, &HomeScreenState::pageOrientationChanged, this, [this]() {
|
|
Q_EMIT pageRowsChanged();
|
|
Q_EMIT pageColumnsChanged();
|
|
});
|
|
|
|
connect(this, &HomeScreenState::pageWidthChanged, this, &HomeScreenState::calculatePageContentWidth);
|
|
connect(this, &HomeScreenState::pageHeightChanged, this, &HomeScreenState::calculatePageContentHeight);
|
|
|
|
connect(this, &HomeScreenState::pageContentWidthChanged, this, &HomeScreenState::calculatePageCellWidth);
|
|
connect(this, &HomeScreenState::pageColumnsChanged, this, &HomeScreenState::calculatePageCellWidth);
|
|
connect(this, &HomeScreenState::pageContentHeightChanged, this, &HomeScreenState::calculatePageCellHeight);
|
|
connect(this, &HomeScreenState::pageRowsChanged, this, &HomeScreenState::calculatePageCellHeight);
|
|
|
|
connect(this, &HomeScreenState::viewWidthChanged, this, [this]() {
|
|
Q_EMIT favouritesBarLocationChanged();
|
|
});
|
|
connect(this, &HomeScreenState::viewHeightChanged, this, [this]() {
|
|
Q_EMIT favouritesBarLocationChanged();
|
|
});
|
|
|
|
connect(m_homeScreen->folioSettings(), &FolioSettings::homeScreenRowsChanged, this, [this]() {
|
|
Q_EMIT pageRowsChanged();
|
|
Q_EMIT pageColumnsChanged();
|
|
});
|
|
connect(m_homeScreen->folioSettings(), &FolioSettings::homeScreenColumnsChanged, this, [this]() {
|
|
Q_EMIT pageRowsChanged();
|
|
Q_EMIT pageColumnsChanged();
|
|
});
|
|
}
|
|
|
|
HomeScreenState::ViewState HomeScreenState::viewState() const
|
|
{
|
|
return m_viewState;
|
|
}
|
|
|
|
void HomeScreenState::setViewState(ViewState viewState)
|
|
{
|
|
if (viewState != m_viewState) {
|
|
m_viewState = viewState;
|
|
Q_EMIT viewStateChanged();
|
|
}
|
|
}
|
|
|
|
HomeScreenState::SwipeState HomeScreenState::swipeState() const
|
|
{
|
|
return m_swipeState;
|
|
}
|
|
|
|
void HomeScreenState::setSwipeState(SwipeState swipeState)
|
|
{
|
|
if (swipeState != m_swipeState) {
|
|
m_swipeState = swipeState;
|
|
Q_EMIT swipeStateChanged();
|
|
}
|
|
}
|
|
|
|
DragState *HomeScreenState::dragState() const
|
|
{
|
|
return m_dragState;
|
|
}
|
|
|
|
qreal HomeScreenState::viewWidth() const
|
|
{
|
|
return m_viewWidth;
|
|
}
|
|
|
|
void HomeScreenState::setViewWidth(qreal viewWidth)
|
|
{
|
|
if (m_viewWidth != viewWidth) {
|
|
m_viewWidth = viewWidth;
|
|
Q_EMIT viewWidthChanged();
|
|
}
|
|
}
|
|
|
|
qreal HomeScreenState::viewHeight() const
|
|
{
|
|
return m_viewHeight;
|
|
}
|
|
|
|
void HomeScreenState::setViewHeight(qreal viewHeight)
|
|
{
|
|
if (m_viewHeight != viewHeight) {
|
|
m_viewHeight = viewHeight;
|
|
Q_EMIT viewHeightChanged();
|
|
}
|
|
}
|
|
|
|
qreal HomeScreenState::viewTopPadding() const
|
|
{
|
|
return m_viewTopPadding;
|
|
}
|
|
|
|
void HomeScreenState::setViewTopPadding(qreal viewTopPadding)
|
|
{
|
|
if (m_viewTopPadding != viewTopPadding) {
|
|
m_viewTopPadding = viewTopPadding;
|
|
Q_EMIT viewTopPaddingChanged();
|
|
}
|
|
}
|
|
|
|
qreal HomeScreenState::viewBottomPadding() const
|
|
{
|
|
return m_viewBottomPadding;
|
|
}
|
|
|
|
void HomeScreenState::setViewBottomPadding(qreal viewBottomPadding)
|
|
{
|
|
if (m_viewBottomPadding != viewBottomPadding) {
|
|
m_viewBottomPadding = viewBottomPadding;
|
|
Q_EMIT viewBottomPaddingChanged();
|
|
}
|
|
}
|
|
|
|
qreal HomeScreenState::viewLeftPadding() const
|
|
{
|
|
return m_viewLeftPadding;
|
|
}
|
|
|
|
void HomeScreenState::setViewLeftPadding(qreal viewLeftPadding)
|
|
{
|
|
if (m_viewLeftPadding != viewLeftPadding) {
|
|
m_viewLeftPadding = viewLeftPadding;
|
|
Q_EMIT viewLeftPaddingChanged();
|
|
}
|
|
}
|
|
|
|
qreal HomeScreenState::viewRightPadding() const
|
|
{
|
|
return m_viewRightPadding;
|
|
}
|
|
|
|
void HomeScreenState::setViewRightPadding(qreal viewRightPadding)
|
|
{
|
|
if (m_viewRightPadding != viewRightPadding) {
|
|
m_viewRightPadding = viewRightPadding;
|
|
Q_EMIT viewRightPaddingChanged();
|
|
}
|
|
}
|
|
|
|
HomeScreenState::PageOrientation HomeScreenState::pageOrientation() const
|
|
{
|
|
return m_pageOrientation;
|
|
}
|
|
|
|
void HomeScreenState::setPageOrientation(PageOrientation pageOrientation)
|
|
{
|
|
if (m_pageOrientation != pageOrientation) {
|
|
m_pageOrientation = pageOrientation;
|
|
Q_EMIT pageOrientationChanged();
|
|
}
|
|
}
|
|
|
|
HomeScreenState::FavouritesBarLocation HomeScreenState::favouritesBarLocation() const
|
|
{
|
|
// TODO need to determine screen rotation and bottom of screen to have Left and Right accordingly
|
|
return m_viewHeight < VERTICAL_FAVOURITES_BAR_THRESHOLD && m_viewWidth > m_viewHeight ? Right : Bottom;
|
|
}
|
|
|
|
int HomeScreenState::pageRows() const
|
|
{
|
|
if (m_pageOrientation == RegularPosition || m_pageOrientation == RotateUpsideDown) {
|
|
return m_homeScreen->folioSettings()->homeScreenRows();
|
|
} else {
|
|
return m_homeScreen->folioSettings()->homeScreenColumns();
|
|
}
|
|
}
|
|
|
|
int HomeScreenState::pageColumns() const
|
|
{
|
|
if (m_pageOrientation == RegularPosition || m_pageOrientation == RotateUpsideDown) {
|
|
return m_homeScreen->folioSettings()->homeScreenColumns();
|
|
} else {
|
|
return m_homeScreen->folioSettings()->homeScreenRows();
|
|
}
|
|
}
|
|
|
|
qreal HomeScreenState::pageViewX() const
|
|
{
|
|
return m_pageViewX;
|
|
}
|
|
|
|
void HomeScreenState::setPageViewX(qreal pageViewX)
|
|
{
|
|
if (m_pageViewX != pageViewX) {
|
|
m_pageViewX = pageViewX;
|
|
Q_EMIT pageViewXChanged();
|
|
}
|
|
}
|
|
|
|
qreal HomeScreenState::pageWidth() const
|
|
{
|
|
return m_pageWidth;
|
|
}
|
|
|
|
void HomeScreenState::setPageWidth(qreal pageWidth)
|
|
{
|
|
if (m_pageWidth != pageWidth) {
|
|
m_pageWidth = pageWidth;
|
|
Q_EMIT pageWidthChanged();
|
|
|
|
// make sure we snap
|
|
snapPage();
|
|
}
|
|
}
|
|
|
|
qreal HomeScreenState::pageHeight() const
|
|
{
|
|
return m_pageHeight;
|
|
}
|
|
|
|
void HomeScreenState::setPageHeight(qreal pageHeight)
|
|
{
|
|
if (m_pageHeight != pageHeight) {
|
|
m_pageHeight = pageHeight;
|
|
Q_EMIT pageHeightChanged();
|
|
}
|
|
}
|
|
|
|
qreal HomeScreenState::pageContentWidth() const
|
|
{
|
|
return m_pageContentWidth;
|
|
}
|
|
|
|
void HomeScreenState::calculatePageContentWidth()
|
|
{
|
|
const qreal pageContentWidth = std::round(m_pageWidth * 0.95); // 0.05 on both sides
|
|
|
|
if (m_pageContentWidth != pageContentWidth) {
|
|
m_pageContentWidth = pageContentWidth;
|
|
Q_EMIT pageContentWidthChanged();
|
|
}
|
|
}
|
|
|
|
qreal HomeScreenState::pageContentHeight() const
|
|
{
|
|
return m_pageContentHeight;
|
|
}
|
|
|
|
void HomeScreenState::calculatePageContentHeight()
|
|
{
|
|
const qreal pageContentHeight = std::round(m_pageHeight * 0.95); // 0.05 on both sides
|
|
|
|
if (m_pageContentHeight != pageContentHeight) {
|
|
m_pageContentHeight = pageContentHeight;
|
|
Q_EMIT pageContentHeightChanged();
|
|
}
|
|
}
|
|
|
|
qreal HomeScreenState::pageCellWidth() const
|
|
{
|
|
return m_pageCellWidth;
|
|
}
|
|
|
|
void HomeScreenState::calculatePageCellWidth()
|
|
{
|
|
qreal pageCellWidth = (pageColumns() == 0) ? 0 : qMax(0.0, std::round(m_pageContentWidth / pageColumns()));
|
|
|
|
if (m_pageCellWidth != pageCellWidth) {
|
|
m_pageCellWidth = pageCellWidth;
|
|
Q_EMIT pageCellWidthChanged();
|
|
}
|
|
}
|
|
|
|
qreal HomeScreenState::pageCellHeight() const
|
|
{
|
|
return m_pageCellHeight;
|
|
}
|
|
|
|
void HomeScreenState::calculatePageCellHeight()
|
|
{
|
|
qreal pageCellHeight = (pageRows() == 0) ? 0 : std::round(m_pageContentHeight / pageRows());
|
|
|
|
if (m_pageCellHeight != pageCellHeight) {
|
|
m_pageCellHeight = pageCellHeight;
|
|
Q_EMIT pageCellHeightChanged();
|
|
}
|
|
}
|
|
|
|
qreal HomeScreenState::pageDelegateLabelHeight() const
|
|
{
|
|
return m_pageDelegateLabelHeight;
|
|
}
|
|
|
|
void HomeScreenState::setPageDelegateLabelHeight(qreal pageDelegateLabelHeight)
|
|
{
|
|
if (m_pageDelegateLabelHeight != pageDelegateLabelHeight) {
|
|
m_pageDelegateLabelHeight = pageDelegateLabelHeight;
|
|
Q_EMIT pageDelegateLabelHeightChanged();
|
|
}
|
|
}
|
|
|
|
qreal HomeScreenState::pageDelegateLabelSpacing() const
|
|
{
|
|
return m_pageDelegateLabelSpacing;
|
|
}
|
|
|
|
void HomeScreenState::setPageDelegateLabelSpacing(qreal pageDelegateLabelSpacing)
|
|
{
|
|
if (m_pageDelegateLabelSpacing != pageDelegateLabelSpacing) {
|
|
m_pageDelegateLabelSpacing = pageDelegateLabelSpacing;
|
|
Q_EMIT pageDelegateLabelSpacingChanged();
|
|
}
|
|
}
|
|
|
|
qreal HomeScreenState::folderViewX() const
|
|
{
|
|
return m_folderViewX;
|
|
}
|
|
|
|
void HomeScreenState::setFolderViewX(qreal folderViewX)
|
|
{
|
|
if (m_folderViewX != folderViewX) {
|
|
m_folderViewX = folderViewX;
|
|
Q_EMIT folderViewXChanged();
|
|
}
|
|
}
|
|
|
|
qreal HomeScreenState::folderPageWidth() const
|
|
{
|
|
return m_folderPageWidth;
|
|
}
|
|
|
|
void HomeScreenState::setFolderPageWidth(qreal folderPageWidth)
|
|
{
|
|
if (m_folderPageWidth != folderPageWidth) {
|
|
m_folderPageWidth = folderPageWidth;
|
|
Q_EMIT folderPageWidthChanged();
|
|
}
|
|
}
|
|
|
|
qreal HomeScreenState::folderPageHeight() const
|
|
{
|
|
return m_folderPageHeight;
|
|
}
|
|
|
|
void HomeScreenState::setFolderPageHeight(qreal folderPageHeight)
|
|
{
|
|
if (m_folderPageHeight != folderPageHeight) {
|
|
m_folderPageHeight = folderPageHeight;
|
|
Q_EMIT folderPageHeightChanged();
|
|
}
|
|
}
|
|
|
|
qreal HomeScreenState::folderPageContentWidth() const
|
|
{
|
|
return m_folderPageContentWidth;
|
|
}
|
|
|
|
void HomeScreenState::setFolderPageContentWidth(qreal folderPageContentWidth)
|
|
{
|
|
if (m_folderPageContentWidth != folderPageContentWidth) {
|
|
m_folderPageContentWidth = folderPageContentWidth;
|
|
Q_EMIT folderPageContentWidthChanged();
|
|
}
|
|
}
|
|
|
|
qreal HomeScreenState::folderPageContentHeight() const
|
|
{
|
|
return m_folderPageContentHeight;
|
|
}
|
|
|
|
void HomeScreenState::setFolderPageContentHeight(qreal folderPageContentHeight)
|
|
{
|
|
if (m_folderPageContentHeight != folderPageContentHeight) {
|
|
m_folderPageContentHeight = folderPageContentHeight;
|
|
Q_EMIT folderPageContentHeightChanged();
|
|
}
|
|
}
|
|
|
|
qreal HomeScreenState::folderOpenProgress() const
|
|
{
|
|
return m_folderOpenProgress;
|
|
}
|
|
|
|
void HomeScreenState::setFolderOpenProgress(qreal folderOpenProgress)
|
|
{
|
|
if (m_folderOpenProgress != folderOpenProgress) {
|
|
m_folderOpenProgress = folderOpenProgress;
|
|
Q_EMIT folderOpenProgressChanged();
|
|
}
|
|
}
|
|
|
|
FolioApplicationFolder *HomeScreenState::currentFolder() const
|
|
{
|
|
return m_currentFolder;
|
|
}
|
|
|
|
void HomeScreenState::setCurrentFolder(FolioApplicationFolder *folder)
|
|
{
|
|
if (m_currentFolder != folder) {
|
|
m_currentFolder = folder;
|
|
Q_EMIT currentFolderChanged();
|
|
}
|
|
}
|
|
|
|
qreal HomeScreenState::settingsOpenProgress()
|
|
{
|
|
return m_settingsOpenProgress;
|
|
}
|
|
|
|
void HomeScreenState::setSettingsOpenProgress(qreal settingsOpenProgress)
|
|
{
|
|
if (m_settingsOpenProgress != settingsOpenProgress) {
|
|
m_settingsOpenProgress = settingsOpenProgress;
|
|
Q_EMIT settingsOpenProgressChanged();
|
|
}
|
|
}
|
|
|
|
qreal HomeScreenState::appDrawerOpenProgress()
|
|
{
|
|
return m_appDrawerOpenProgress;
|
|
}
|
|
|
|
qreal HomeScreenState::appDrawerY()
|
|
{
|
|
return m_appDrawerY;
|
|
}
|
|
|
|
void HomeScreenState::setAppDrawerY(qreal appDrawerY)
|
|
{
|
|
m_appDrawerY = appDrawerY;
|
|
m_appDrawerOpenProgress = 1 - qBound(0.0, m_appDrawerY, APP_DRAWER_OPEN_DIST) / APP_DRAWER_OPEN_DIST;
|
|
Q_EMIT appDrawerYChanged();
|
|
Q_EMIT appDrawerOpenProgressChanged();
|
|
}
|
|
|
|
qreal HomeScreenState::searchWidgetOpenProgress()
|
|
{
|
|
return m_searchWidgetOpenProgress;
|
|
}
|
|
|
|
qreal HomeScreenState::searchWidgetY()
|
|
{
|
|
return m_searchWidgetOpenProgress;
|
|
}
|
|
|
|
void HomeScreenState::setSearchWidgetY(qreal searchWidgetY)
|
|
{
|
|
m_searchWidgetY = searchWidgetY;
|
|
m_searchWidgetOpenProgress = 1 - qBound(0.0, m_searchWidgetY, SEARCH_WIDGET_OPEN_DIST) / SEARCH_WIDGET_OPEN_DIST;
|
|
Q_EMIT searchWidgetYChanged();
|
|
Q_EMIT searchWidgetOpenProgressChanged();
|
|
}
|
|
|
|
qreal HomeScreenState::delegateDragX()
|
|
{
|
|
return m_delegateDragX;
|
|
}
|
|
|
|
void HomeScreenState::setDelegateDragX(qreal delegateDragX)
|
|
{
|
|
m_delegateDragX = delegateDragX;
|
|
Q_EMIT delegateDragXChanged();
|
|
}
|
|
|
|
qreal HomeScreenState::delegateDragY()
|
|
{
|
|
return m_delegateDragY;
|
|
}
|
|
|
|
void HomeScreenState::setDelegateDragY(qreal delegateDragY)
|
|
{
|
|
m_delegateDragY = delegateDragY;
|
|
Q_EMIT delegateDragYChanged();
|
|
}
|
|
|
|
qreal HomeScreenState::delegateDragPointerOffsetX()
|
|
{
|
|
return m_delegateDragPointerOffsetX;
|
|
}
|
|
|
|
void HomeScreenState::setDelegateDragPointerOffsetX(qreal delegateDragPointerOffsetX)
|
|
{
|
|
m_delegateDragPointerOffsetX = delegateDragPointerOffsetX;
|
|
}
|
|
|
|
qreal HomeScreenState::delegateDragPointerOffsetY()
|
|
{
|
|
return m_delegateDragPointerOffsetY;
|
|
}
|
|
|
|
void HomeScreenState::setDelegateDragPointerOffsetY(qreal delegateDragPointerOffsetY)
|
|
{
|
|
m_delegateDragPointerOffsetY = delegateDragPointerOffsetY;
|
|
}
|
|
|
|
int HomeScreenState::currentPage()
|
|
{
|
|
return m_pageNum;
|
|
}
|
|
|
|
void HomeScreenState::setCurrentPage(int currentPage)
|
|
{
|
|
if (m_pageNum != currentPage) {
|
|
m_pageNum = currentPage;
|
|
Q_EMIT pageNumChanged();
|
|
}
|
|
}
|
|
|
|
int HomeScreenState::currentFolderPage()
|
|
{
|
|
return m_folderPageNum;
|
|
}
|
|
|
|
FolioDelegate *HomeScreenState::getPageDelegateAt(int page, int row, int column)
|
|
{
|
|
PageModel *pageModel = m_homeScreen->pageListModel()->getPage(page);
|
|
if (!pageModel) {
|
|
return nullptr;
|
|
}
|
|
|
|
FolioDelegate *delegate = pageModel->getDelegate(row, column);
|
|
if (!delegate) {
|
|
return nullptr;
|
|
}
|
|
|
|
return delegate;
|
|
}
|
|
|
|
FolioDelegate *HomeScreenState::getFavouritesDelegateAt(int position)
|
|
{
|
|
return m_homeScreen->favouritesModel()->getEntryAt(position);
|
|
}
|
|
|
|
FolioDelegate *HomeScreenState::getFolderDelegateAt(int position)
|
|
{
|
|
if (!m_currentFolder) {
|
|
return nullptr;
|
|
}
|
|
|
|
return m_currentFolder->applications()->getDelegate(position);
|
|
}
|
|
|
|
QPointF HomeScreenState::getPageDelegateScreenPosition(int page, int row, int column)
|
|
{
|
|
Q_UNUSED(page)
|
|
qreal x = m_viewLeftPadding + ((m_pageWidth - m_pageContentWidth) / 2) + (m_pageCellWidth * column);
|
|
qreal y = m_viewTopPadding + ((m_pageHeight - m_pageContentHeight) / 2) + (m_pageCellHeight * row);
|
|
return QPointF{x, y};
|
|
}
|
|
|
|
QPointF HomeScreenState::getFavouritesDelegateScreenPosition(int position)
|
|
{
|
|
return m_homeScreen->favouritesModel()->getDelegateScreenPosition(position);
|
|
}
|
|
|
|
QPointF HomeScreenState::getFolderDelegateScreenPosition(int position)
|
|
{
|
|
if (!m_currentFolder || position < 0 || position >= m_currentFolder->applications()->rowCount()) {
|
|
return {0, 0};
|
|
}
|
|
auto pos = m_currentFolder->applications()->getDelegatePosition(position);
|
|
qreal x = pos.x() + (m_viewWidth - m_viewLeftPadding - m_viewRightPadding - m_folderPageWidth) / 2;
|
|
qreal y = pos.y() + (m_viewHeight - m_viewTopPadding - m_viewBottomPadding - m_folderPageHeight) / 2;
|
|
x += m_viewLeftPadding;
|
|
y += m_viewTopPadding;
|
|
|
|
// adjust for the current page
|
|
x -= currentFolderPage() * m_folderPageWidth;
|
|
|
|
return {x, y};
|
|
}
|
|
|
|
void HomeScreenState::openAppDrawer()
|
|
{
|
|
cancelAppDrawerAnimations();
|
|
m_openAppDrawerAnim->setStartValue(m_appDrawerY);
|
|
m_openAppDrawerAnim->start();
|
|
}
|
|
|
|
void HomeScreenState::closeAppDrawer()
|
|
{
|
|
cancelAppDrawerAnimations();
|
|
m_closeAppDrawerAnim->setStartValue(m_appDrawerY);
|
|
m_closeAppDrawerAnim->start();
|
|
}
|
|
|
|
void HomeScreenState::openSearchWidget()
|
|
{
|
|
cancelSearchWidgetAnimations();
|
|
m_openSearchWidgetAnim->setStartValue(m_searchWidgetY);
|
|
m_openSearchWidgetAnim->start();
|
|
}
|
|
|
|
void HomeScreenState::closeSearchWidget()
|
|
{
|
|
cancelSearchWidgetAnimations();
|
|
m_closeSearchWidgetAnim->setStartValue(m_searchWidgetY);
|
|
m_closeSearchWidgetAnim->start();
|
|
}
|
|
|
|
void HomeScreenState::snapPage()
|
|
{
|
|
const int numOfPages = m_homeScreen->pageListModel()->rowCount();
|
|
|
|
const int leftPage = qBound(0.0, (m_pageViewX / m_pageWidth), numOfPages - 1.0);
|
|
const qreal leftPagePos = -leftPage * m_pageWidth;
|
|
|
|
if (leftPage == numOfPages + 1) {
|
|
// if we are past the last page
|
|
goToPage(leftPage);
|
|
} else {
|
|
const qreal rightPagePos = leftPagePos - m_pageWidth;
|
|
|
|
// go to the closer page (right or left)
|
|
if (qAbs(rightPagePos - m_pageViewX) < qAbs(leftPagePos - m_pageViewX)) {
|
|
goToPage(leftPage + 1);
|
|
} else {
|
|
goToPage(leftPage);
|
|
}
|
|
}
|
|
}
|
|
|
|
void HomeScreenState::goToPage(int page)
|
|
{
|
|
if (page < 0) {
|
|
page = 0;
|
|
}
|
|
|
|
const int numOfPages = m_homeScreen->pageListModel()->rowCount();
|
|
if (page >= numOfPages) {
|
|
page = std::max(0, numOfPages - 1);
|
|
}
|
|
|
|
setCurrentPage(page);
|
|
|
|
m_pageAnim->setStartValue(m_pageViewX);
|
|
m_pageAnim->setEndValue(-page * m_pageWidth);
|
|
m_pageAnim->start();
|
|
}
|
|
|
|
void HomeScreenState::goToFolderPage(int page)
|
|
{
|
|
if (!m_currentFolder) {
|
|
return;
|
|
}
|
|
|
|
if (page < 0) {
|
|
page = 0;
|
|
}
|
|
|
|
int numOfPages = m_currentFolder->applications()->numTotalPages();
|
|
if (page >= numOfPages) {
|
|
page = std::max(0, numOfPages - 1);
|
|
}
|
|
|
|
m_folderPageNum = page;
|
|
Q_EMIT folderPageNumChanged();
|
|
|
|
m_folderPageAnim->setStartValue(m_folderViewX);
|
|
m_folderPageAnim->setEndValue(-page * m_folderPageWidth);
|
|
m_folderPageAnim->start();
|
|
}
|
|
|
|
void HomeScreenState::openFolder(qreal delegateX, qreal delegateY, FolioApplicationFolder *folder)
|
|
{
|
|
setCurrentFolder(folder);
|
|
|
|
m_openFolderAnim->stop();
|
|
m_closeFolderAnim->stop();
|
|
m_openFolderAnim->setStartValue(m_folderOpenProgress);
|
|
m_openFolderAnim->start();
|
|
|
|
Q_EMIT folderAboutToOpen(delegateX, delegateY);
|
|
}
|
|
|
|
void HomeScreenState::closeFolder()
|
|
{
|
|
m_openFolderAnim->stop();
|
|
m_closeFolderAnim->stop();
|
|
m_closeFolderAnim->setStartValue(m_folderOpenProgress);
|
|
m_closeFolderAnim->start();
|
|
}
|
|
|
|
void HomeScreenState::openSettingsView()
|
|
{
|
|
m_closeSettingsAnim->stop();
|
|
m_openSettingsAnim->stop();
|
|
m_openSettingsAnim->setStartValue(m_settingsOpenProgress);
|
|
m_openSettingsAnim->start();
|
|
}
|
|
|
|
void HomeScreenState::closeSettingsView()
|
|
{
|
|
m_openSettingsAnim->stop();
|
|
m_closeSettingsAnim->stop();
|
|
m_closeSettingsAnim->setStartValue(m_settingsOpenProgress);
|
|
m_closeSettingsAnim->start();
|
|
}
|
|
|
|
void HomeScreenState::startDelegateDrag(qreal startX, qreal startY, qreal pointerOffsetX, qreal pointerOffsetY)
|
|
{
|
|
// start drag and drop positions
|
|
setDelegateDragX(startX);
|
|
setDelegateDragY(startY);
|
|
setDelegateDragPointerOffsetX(pointerOffsetX);
|
|
setDelegateDragPointerOffsetY(pointerOffsetY);
|
|
|
|
// end current swipe
|
|
swipeEnded();
|
|
|
|
// start the delegate drag
|
|
setSwipeState(SwipeState::AwaitingDraggingDelegate);
|
|
}
|
|
|
|
void HomeScreenState::startDelegatePageDrag(qreal startX, qreal startY, qreal pointerOffsetX, qreal pointerOffsetY, int page, int row, int column)
|
|
{
|
|
startDelegateDrag(startX, startY, pointerOffsetX, pointerOffsetY);
|
|
Q_EMIT delegateDragFromPageStarted(page, row, column);
|
|
}
|
|
|
|
void HomeScreenState::startDelegateFavouritesDrag(qreal startX, qreal startY, qreal pointerOffsetX, qreal pointerOffsetY, int position)
|
|
{
|
|
startDelegateDrag(startX, startY, pointerOffsetX, pointerOffsetY);
|
|
Q_EMIT delegateDragFromFavouritesStarted(position);
|
|
}
|
|
|
|
void HomeScreenState::startDelegateAppDrawerDrag(qreal startX, qreal startY, qreal pointerOffsetX, qreal pointerOffsetY, QString storageId)
|
|
{
|
|
startDelegateDrag(startX, startY, pointerOffsetX, pointerOffsetY);
|
|
Q_EMIT delegateDragFromAppDrawerStarted(storageId);
|
|
|
|
// we start dragging the delegate immediately from the app drawer, because we don't have a context menu to deal with!
|
|
// NOTE: this has to happen after delegateDragFromAppDrawerStarted, because slots for that expect SwipeState::AwaitingDraggingDelegate
|
|
setSwipeState(SwipeState::DraggingDelegate);
|
|
}
|
|
|
|
void HomeScreenState::startDelegateFolderDrag(qreal startX,
|
|
qreal startY,
|
|
qreal pointerOffsetX,
|
|
qreal pointerOffsetY,
|
|
FolioApplicationFolder *folder,
|
|
int position)
|
|
{
|
|
startDelegateDrag(startX, startY, pointerOffsetX, pointerOffsetY);
|
|
Q_EMIT delegateDragFromFolderStarted(folder, position);
|
|
}
|
|
|
|
void HomeScreenState::startDelegateWidgetListDrag(qreal startX, qreal startY, qreal pointerOffsetX, qreal pointerOffsetY, QString appletPluginId)
|
|
{
|
|
startDelegateDrag(startX, startY, pointerOffsetX, pointerOffsetY);
|
|
Q_EMIT delegateDragFromWidgetListStarted(appletPluginId);
|
|
|
|
// we start dragging the delegate immediately from the app drawer, because we don't have a context menu to deal with!
|
|
// NOTE: this has to happen after delegateDragFromAppDrawerStarted, because slots for that expect SwipeState::AwaitingDraggingDelegate
|
|
setSwipeState(SwipeState::DraggingDelegate);
|
|
}
|
|
|
|
void HomeScreenState::cancelDelegateDrag()
|
|
{
|
|
swipeEnded();
|
|
}
|
|
|
|
void HomeScreenState::swipeStarted(qreal deltaX, qreal deltaY)
|
|
{
|
|
if (m_swipeState != SwipeState::None) {
|
|
return;
|
|
}
|
|
|
|
setSwipeState(SwipeState::DeterminingSwipeType);
|
|
|
|
// the user interaction has already moved a bit (for swipe detection),
|
|
// so we call the move event too.
|
|
swipeMoved(deltaX, deltaY, deltaX, deltaY);
|
|
}
|
|
|
|
void HomeScreenState::swipeEnded()
|
|
{
|
|
switch (m_swipeState) {
|
|
case SwipeState::SwipingOpenAppDrawer:
|
|
case SwipeState::SwipingCloseAppDrawer:
|
|
if (m_movingUp) {
|
|
closeAppDrawer();
|
|
} else {
|
|
openAppDrawer();
|
|
}
|
|
break;
|
|
case SwipeState::SwipingAppDrawerGrid:
|
|
Q_EMIT appDrawerGridFlickRequested();
|
|
break;
|
|
case SwipeState::SwipingOpenSearchWidget:
|
|
case SwipeState::SwipingCloseSearchWidget:
|
|
if (m_movingUp) {
|
|
openSearchWidget();
|
|
} else {
|
|
closeSearchWidget();
|
|
}
|
|
break;
|
|
case SwipeState::SwipingPages: {
|
|
int page = std::max(0.0, -m_pageViewX) / m_pageWidth;
|
|
|
|
// m_movingRight refers to finger movement
|
|
if (m_movingRight || m_pageViewX > 0) {
|
|
goToPage(page);
|
|
} else {
|
|
goToPage(page + 1);
|
|
}
|
|
break;
|
|
}
|
|
case SwipeState::SwipingFolderPages: {
|
|
int page = std::max(0.0, -m_folderViewX) / m_folderPageWidth;
|
|
|
|
// m_movingRight refers to finger movement
|
|
if (m_movingRight || m_folderViewX > 0) {
|
|
goToFolderPage(page);
|
|
} else {
|
|
goToFolderPage(page + 1);
|
|
}
|
|
break;
|
|
}
|
|
case SwipeState::DraggingDelegate:
|
|
Q_EMIT delegateDragEnded();
|
|
break;
|
|
case SwipeState::AwaitingDraggingDelegate:
|
|
case SwipeState::DeterminingSwipeType:
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
setSwipeState(SwipeState::None);
|
|
}
|
|
|
|
void HomeScreenState::swipeMoved(qreal totalDeltaX, qreal totalDeltaY, qreal deltaX, qreal deltaY)
|
|
{
|
|
m_movingUp = deltaY > 0;
|
|
|
|
switch (m_swipeState) {
|
|
case SwipeState::DeterminingSwipeType:
|
|
// check if we can determine the type of swipe this is
|
|
determineSwipeTypeAfterThreshold(totalDeltaX, totalDeltaY);
|
|
break;
|
|
case SwipeState::SwipingOpenSearchWidget:
|
|
case SwipeState::SwipingCloseSearchWidget:
|
|
setSearchWidgetY(m_searchWidgetY - deltaY);
|
|
break;
|
|
case SwipeState::SwipingOpenAppDrawer:
|
|
case SwipeState::SwipingCloseAppDrawer:
|
|
setAppDrawerY(m_appDrawerY + deltaY);
|
|
break;
|
|
case SwipeState::SwipingAppDrawerGrid:
|
|
Q_EMIT appDrawerGridYChanged(deltaY);
|
|
break;
|
|
case SwipeState::SwipingPages:
|
|
m_movingRight = deltaX > 0;
|
|
setPageViewX(m_pageViewX + deltaX);
|
|
break;
|
|
case SwipeState::SwipingFolderPages:
|
|
m_movingRight = deltaX > 0;
|
|
setFolderViewX(m_folderViewX + deltaX);
|
|
break;
|
|
case SwipeState::AwaitingDraggingDelegate:
|
|
setSwipeState(SwipeState::DraggingDelegate);
|
|
break;
|
|
case SwipeState::DraggingDelegate:
|
|
setDelegateDragX(m_delegateDragX + deltaX);
|
|
setDelegateDragY(m_delegateDragY + deltaY);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
void HomeScreenState::determineSwipeTypeAfterThreshold(qreal totalDeltaX, qreal totalDeltaY)
|
|
{
|
|
// we check if the x or y movement has passed a certain threshold before determining the swipe type
|
|
|
|
if (qAbs(totalDeltaX) >= DETERMINE_SWIPE_THRESHOLD && (m_viewState == ViewState::PageView || m_viewState == ViewState::SettingsView)) {
|
|
// select horizontal swipe mode (only if in page view)
|
|
setSwipeState(SwipeState::SwipingPages);
|
|
|
|
// ensure no animations are running when starting a swipe
|
|
m_pageAnim->stop();
|
|
|
|
} else if (qAbs(totalDeltaX) >= DETERMINE_SWIPE_THRESHOLD && m_viewState == ViewState::FolderView) {
|
|
// select horizontal swipe mode (only if in page view)
|
|
setSwipeState(SwipeState::SwipingFolderPages);
|
|
|
|
// ensure no animations are running when starting a swipe
|
|
m_folderPageAnim->stop();
|
|
|
|
} else if (qAbs(totalDeltaY) >= DETERMINE_SWIPE_THRESHOLD) {
|
|
// select vertical swipe mode
|
|
|
|
if (m_movingUp) {
|
|
// moving up
|
|
switch (m_viewState) {
|
|
case ViewState::PageView:
|
|
// if the app drawer is still being opened
|
|
if (m_openAppDrawerAnim->state() == QPropertyAnimation::Running) {
|
|
setSwipeState(SwipeState::SwipingOpenAppDrawer);
|
|
cancelAppDrawerAnimations();
|
|
} else {
|
|
setSwipeState(SwipeState::SwipingOpenSearchWidget);
|
|
cancelSearchWidgetAnimations();
|
|
}
|
|
break;
|
|
case ViewState::AppDrawerView:
|
|
setSwipeState(SwipeState::SwipingCloseAppDrawer);
|
|
cancelAppDrawerAnimations();
|
|
break;
|
|
case ViewState::SearchWidgetView:
|
|
setSwipeState(SwipeState::SwipingCloseSearchWidget);
|
|
cancelSearchWidgetAnimations();
|
|
case ViewState::FolderView:
|
|
case ViewState::SettingsView:
|
|
// no vertical behaviour in folder or settings view
|
|
default:
|
|
break;
|
|
}
|
|
} else {
|
|
// moving down
|
|
switch (m_viewState) {
|
|
case ViewState::PageView:
|
|
if (m_openSearchWidgetAnim->state() == QPropertyAnimation::Running) {
|
|
setSwipeState(SwipeState::SwipingOpenSearchWidget);
|
|
cancelSearchWidgetAnimations();
|
|
} else {
|
|
setSwipeState(SwipeState::SwipingOpenAppDrawer);
|
|
cancelAppDrawerAnimations();
|
|
}
|
|
break;
|
|
case ViewState::SearchWidgetView:
|
|
setSwipeState(SwipeState::SwipingCloseSearchWidget);
|
|
cancelSearchWidgetAnimations();
|
|
break;
|
|
case ViewState::AppDrawerView:
|
|
setSwipeState(SwipeState::SwipingAppDrawerGrid);
|
|
// don't call cancelAppDrawerAnimations(), so we don't have it half open
|
|
case ViewState::FolderView:
|
|
case ViewState::SettingsView:
|
|
// no vertical behaviour in folder or settings view
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void HomeScreenState::cancelAppDrawerAnimations()
|
|
{
|
|
m_openAppDrawerAnim->stop();
|
|
m_closeAppDrawerAnim->stop();
|
|
}
|
|
|
|
void HomeScreenState::cancelSearchWidgetAnimations()
|
|
{
|
|
m_openSearchWidgetAnim->stop();
|
|
m_closeSearchWidgetAnim->stop();
|
|
}
|