homescreens/folio: Homescreen folder page snapping position bugfix

This fixes an issue where if the device is rotated in a folder, the page would not snap immediately back to the right position, but would instead animate icon position changes.

To achieve this, the following changes were made.
- changes were made to how the folder gird size is calculated to prevent an issue with the grid size changing for a brief period of time during screen rotation, causing problems with snapping to the correct page.
- icons position animations are now done by a animated index value to prevent it from animating when the device rotates
- when the device screen size changes (ex: device rotation), it now snaps to the current folder page, as before it would just stay in between the two pages.
This commit is contained in:
Micah Stanley 2024-11-09 19:04:24 +00:00 committed by Devin Lin
parent a508c8d524
commit f52bf0bd71
6 changed files with 175 additions and 144 deletions

View file

@ -694,7 +694,7 @@ void DragState::onChangeFolderPageTimerFinished()
// if we are at the left edge, go left // if we are at the left edge, go left
int page = m_state->currentFolderPage() - 1; int page = m_state->currentFolderPage() - 1;
if (page >= 0) { if (page >= 0) {
m_state->goToFolderPage(page); m_state->goToFolderPage(page, false);
} }
} else if (x >= rightPagePosition - PAGE_CHANGE_THRESHOLD) { } else if (x >= rightPagePosition - PAGE_CHANGE_THRESHOLD) {
@ -703,7 +703,7 @@ void DragState::onChangeFolderPageTimerFinished()
// go to page if it exists // go to page if it exists
if (page < folder->applications()->numTotalPages()) { if (page < folder->applications()->numTotalPages()) {
m_state->goToFolderPage(page); m_state->goToFolderPage(page, false);
} }
} }
} }

View file

@ -90,7 +90,7 @@ void FolioApplicationFolder::setApplications(QList<FolioApplication *> applicati
m_delegates.append({new FolioDelegate{app, m_homeScreen}, 0, 0}); m_delegates.append({new FolioDelegate{app, m_homeScreen}, 0, 0});
} }
m_applicationFolderModel = new ApplicationFolderModel{this}; m_applicationFolderModel = new ApplicationFolderModel{this};
m_applicationFolderModel->evaluateDelegatePositions(); m_applicationFolderModel->evaluateDelegateIndexes();
Q_EMIT applicationsChanged(); Q_EMIT applicationsChanged();
Q_EMIT applicationsReset(); Q_EMIT applicationsReset();
@ -128,28 +128,28 @@ ApplicationFolderModel::ApplicationFolderModel(FolioApplicationFolder *folder)
{ {
HomeScreenState *homeScreenState = folder->m_homeScreen->homeScreenState(); HomeScreenState *homeScreenState = folder->m_homeScreen->homeScreenState();
connect(homeScreenState, &HomeScreenState::folderPageWidthChanged, this, [this]() { connect(homeScreenState, &HomeScreenState::folderPageWidthChanged, this, [this]() {
evaluateDelegatePositions(); evaluateDelegateIndexes();
}); });
connect(homeScreenState, &HomeScreenState::folderPageHeightChanged, this, [this]() { connect(homeScreenState, &HomeScreenState::folderPageHeightChanged, this, [this]() {
evaluateDelegatePositions(); evaluateDelegateIndexes();
}); });
connect(homeScreenState, &HomeScreenState::folderPageContentWidthChanged, this, [this]() { connect(homeScreenState, &HomeScreenState::folderPageContentWidthChanged, this, [this]() {
evaluateDelegatePositions(); evaluateDelegateIndexes();
}); });
connect(homeScreenState, &HomeScreenState::folderPageContentHeightChanged, this, [this]() { connect(homeScreenState, &HomeScreenState::folderPageContentHeightChanged, this, [this]() {
evaluateDelegatePositions(); evaluateDelegateIndexes();
}); });
connect(homeScreenState, &HomeScreenState::viewWidthChanged, this, [this]() { connect(homeScreenState, &HomeScreenState::viewWidthChanged, this, [this]() {
evaluateDelegatePositions(); evaluateDelegateIndexes();
}); });
connect(homeScreenState, &HomeScreenState::viewHeightChanged, this, [this]() { connect(homeScreenState, &HomeScreenState::viewHeightChanged, this, [this]() {
evaluateDelegatePositions(); evaluateDelegateIndexes();
}); });
connect(homeScreenState, &HomeScreenState::pageCellWidthChanged, this, [this]() { connect(homeScreenState, &HomeScreenState::pageCellWidthChanged, this, [this]() {
evaluateDelegatePositions(); evaluateDelegateIndexes();
}); });
connect(homeScreenState, &HomeScreenState::pageCellHeightChanged, this, [this]() { connect(homeScreenState, &HomeScreenState::pageCellHeightChanged, this, [this]() {
evaluateDelegatePositions(); evaluateDelegateIndexes();
}); });
} }
@ -167,10 +167,12 @@ QVariant ApplicationFolderModel::data(const QModelIndex &index, int role) const
switch (role) { switch (role) {
case DelegateRole: case DelegateRole:
return QVariant::fromValue(m_folder->m_delegates.at(index.row()).delegate); return QVariant::fromValue(m_folder->m_delegates.at(index.row()).delegate);
case XPositionRole: case columnIndexRole:
return QVariant::fromValue(m_folder->m_delegates.at(index.row()).xPosition); return QVariant::fromValue(m_folder->m_delegates.at(index.row()).columnIndex);
case YPositionRole: case rowIndexRole:
return QVariant::fromValue(m_folder->m_delegates.at(index.row()).yPosition); return QVariant::fromValue(m_folder->m_delegates.at(index.row()).rowIndex);
case pageIndexRole:
return QVariant::fromValue(m_folder->m_delegates.at(index.row()).pageIndex);
} }
return QVariant(); return QVariant();
@ -178,7 +180,7 @@ QVariant ApplicationFolderModel::data(const QModelIndex &index, int role) const
QHash<int, QByteArray> ApplicationFolderModel::roleNames() const QHash<int, QByteArray> ApplicationFolderModel::roleNames() const
{ {
return {{DelegateRole, "delegate"}, {XPositionRole, "xPosition"}, {YPositionRole, "yPosition"}}; return {{DelegateRole, "delegate"}, {columnIndexRole, "columnIndex"}, {rowIndexRole, "rowIndex"}, {pageIndexRole, "pageIndex"}};
} }
FolioDelegate *ApplicationFolderModel::getDelegate(int index) FolioDelegate *ApplicationFolderModel::getDelegate(int index)
@ -209,7 +211,7 @@ void ApplicationFolderModel::moveEntry(int fromRow, int toRow)
} }
endMoveRows(); endMoveRows();
evaluateDelegatePositions(); evaluateDelegateIndexes();
Q_EMIT m_folder->applicationsChanged(); Q_EMIT m_folder->applicationsChanged();
Q_EMIT m_folder->saveRequested(); Q_EMIT m_folder->saveRequested();
@ -237,18 +239,18 @@ bool ApplicationFolderModel::addDelegate(FolioDelegate *delegate, int index)
if (index == m_folder->m_delegates.size()) { if (index == m_folder->m_delegates.size()) {
beginInsertRows(QModelIndex(), index, index); beginInsertRows(QModelIndex(), index, index);
m_folder->m_delegates.append({delegate, 0, 0}); m_folder->m_delegates.append({delegate, 0, 0});
evaluateDelegatePositions(false); evaluateDelegateIndexes(false);
endInsertRows(); endInsertRows();
} else if (m_folder->m_delegates[index].delegate->type() == FolioDelegate::None) { } else if (m_folder->m_delegates[index].delegate->type() == FolioDelegate::None) {
replaceGhostEntry(delegate); replaceGhostEntry(delegate);
} else { } else {
beginInsertRows(QModelIndex(), index, index); beginInsertRows(QModelIndex(), index, index);
m_folder->m_delegates.insert(index, {delegate, 0, 0}); m_folder->m_delegates.insert(index, {delegate, 0, 0});
evaluateDelegatePositions(false); evaluateDelegateIndexes(false);
endInsertRows(); endInsertRows();
} }
evaluateDelegatePositions(); evaluateDelegateIndexes();
Q_EMIT m_folder->applicationsChanged(); Q_EMIT m_folder->applicationsChanged();
Q_EMIT m_folder->saveRequested(); Q_EMIT m_folder->saveRequested();
@ -268,7 +270,7 @@ void ApplicationFolderModel::removeDelegate(int index)
m_folder->m_delegates.removeAt(index); m_folder->m_delegates.removeAt(index);
endRemoveRows(); endRemoveRows();
evaluateDelegatePositions(); evaluateDelegateIndexes();
Q_EMIT m_folder->applicationsChanged(); Q_EMIT m_folder->applicationsChanged();
Q_EMIT m_folder->saveRequested(); Q_EMIT m_folder->saveRequested();
@ -280,7 +282,18 @@ QPointF ApplicationFolderModel::getDelegatePosition(int index)
return {0, 0}; return {0, 0};
} }
auto delegate = m_folder->m_delegates[index]; auto delegate = m_folder->m_delegates[index];
return {delegate.xPosition, delegate.yPosition}; qreal pageContentWidth = m_folder->m_homeScreen->homeScreenState()->folderPageContentWidth();
qreal margin = horizontalPageMargin();
int cellSize = pageContentWidth / numGridLengthOnPage();
qreal cellWitdhRecenter = (cellSize - m_folder->m_homeScreen->homeScreenState()->pageCellWidth()) / 2;
qreal cellHeightRecenter = (cellSize - m_folder->m_homeScreen->homeScreenState()->pageCellHeight()) / 2;
qreal xPosition = cellWitdhRecenter + margin + delegate.columnIndex * cellSize;
qreal yPosition = cellHeightRecenter + delegate.rowIndex * cellSize;
return {xPosition, yPosition};
} }
int ApplicationFolderModel::getGhostEntryPosition() int ApplicationFolderModel::getGhostEntryPosition()
@ -344,27 +357,27 @@ void ApplicationFolderModel::deleteGhostEntry()
int ApplicationFolderModel::dropInsertPosition(int page, qreal x, qreal y) int ApplicationFolderModel::dropInsertPosition(int page, qreal x, qreal y)
{ {
qreal cellWidth = m_folder->m_homeScreen->homeScreenState()->pageCellWidth(); qreal pageContentWidth = m_folder->m_homeScreen->homeScreenState()->folderPageContentWidth();
qreal cellHeight = m_folder->m_homeScreen->homeScreenState()->pageCellHeight(); qreal cellSize = (pageContentWidth) / numGridLengthOnPage();
int row = (y - topMarginFromScreenEdge()) / cellHeight; int row = (y - topMarginFromScreenEdge()) / cellSize;
row = std::max(0, std::min(numRowsOnPage(), row)); row = std::max(0, std::min(numGridLengthOnPage(), row));
// the index that the position is over // the index that the position is over
int leftColumn = std::max(0.0, x - leftMarginFromScreenEdge()) / cellWidth; int leftColumn = std::max(0.0, x - leftMarginFromScreenEdge()) / cellSize;
leftColumn = std::min(numColumnsOnPage() - 1, leftColumn); leftColumn = std::min(numGridLengthOnPage() - 1, leftColumn);
qreal leftColumnPosition = leftColumn * cellWidth + leftMarginFromScreenEdge(); qreal leftColumnPosition = leftColumn * cellSize + leftMarginFromScreenEdge();
int column = leftColumn + 1; int column = leftColumn + 1;
// if it's the left half of this position or it's the last column on this row, return itself // if it's the left half of this position or it's the last column on this row, return itself
if ((x < leftColumnPosition + cellWidth * 0.5) || (leftColumn == numColumnsOnPage() - 1)) { if ((x < leftColumnPosition + cellSize * 0.5) || (leftColumn == numGridLengthOnPage() - 1)) {
column = leftColumn; column = leftColumn;
} }
// calculate the position based on the page, row and column it is at // calculate the position based on the page, row and column it is at
int pos = (page * numRowsOnPage() * numColumnsOnPage()) + (row * numColumnsOnPage()) + column; int pos = (page * numGridLengthOnPage() * numGridLengthOnPage()) + (row * numGridLengthOnPage()) + column;
// make sure it's in bounds // make sure it's in bounds
return std::min((int)m_folder->m_delegates.size(), std::max(0, pos)); return std::min((int)m_folder->m_delegates.size(), std::max(0, pos));
} }
@ -375,17 +388,10 @@ bool ApplicationFolderModel::isDropPositionOutside(qreal x, qreal y)
|| (y < topMarginFromScreenEdge()) || (y > m_folder->m_homeScreen->homeScreenState()->viewHeight() - topMarginFromScreenEdge()); || (y < topMarginFromScreenEdge()) || (y > m_folder->m_homeScreen->homeScreenState()->viewHeight() - topMarginFromScreenEdge());
} }
void ApplicationFolderModel::evaluateDelegatePositions(bool emitSignal) void ApplicationFolderModel::evaluateDelegateIndexes(bool emitSignal)
{ {
qreal pageWidth = m_folder->m_homeScreen->homeScreenState()->folderPageWidth(); int rows = numGridLengthOnPage();
qreal topMargin = verticalPageMargin(); int columns = numGridLengthOnPage();
qreal leftMargin = horizontalPageMargin();
qreal cellWidth = m_folder->m_homeScreen->homeScreenState()->pageCellWidth();
qreal cellHeight = m_folder->m_homeScreen->homeScreenState()->pageCellHeight();
int rows = numRowsOnPage();
int columns = numColumnsOnPage();
int numOfDelegates = m_folder->m_delegates.size(); int numOfDelegates = m_folder->m_delegates.size();
int index = 0; int index = 0;
@ -394,11 +400,12 @@ void ApplicationFolderModel::evaluateDelegatePositions(bool emitSignal)
while (index < m_folder->m_delegates.size()) { while (index < m_folder->m_delegates.size()) {
int prevIndex = index; int prevIndex = index;
// determine positions page-by-page // determine the row and column index page-by-page
for (int row = 0; row < rows && index < numOfDelegates; row++) { for (int row = 0; row < rows && index < numOfDelegates; row++) {
for (int column = 0; column < columns && index < numOfDelegates; column++) { for (int column = 0; column < columns && index < numOfDelegates; column++) {
m_folder->m_delegates[index].xPosition = qRound(page * pageWidth + leftMargin + column * cellWidth); m_folder->m_delegates[index].columnIndex = column;
m_folder->m_delegates[index].yPosition = qRound(topMargin + row * cellHeight); m_folder->m_delegates[index].rowIndex = row;
m_folder->m_delegates[index].pageIndex = page;
index++; index++;
} }
} }
@ -411,8 +418,9 @@ void ApplicationFolderModel::evaluateDelegatePositions(bool emitSignal)
} }
if (emitSignal) { if (emitSignal) {
Q_EMIT dataChanged(createIndex(0, 0), createIndex(m_folder->m_delegates.size() - 1, 0), {XPositionRole}); Q_EMIT dataChanged(createIndex(0, 0), createIndex(m_folder->m_delegates.size() - 1, 0), {columnIndexRole});
Q_EMIT dataChanged(createIndex(0, 0), createIndex(m_folder->m_delegates.size() - 1, 0), {YPositionRole}); Q_EMIT dataChanged(createIndex(0, 0), createIndex(m_folder->m_delegates.size() - 1, 0), {rowIndexRole});
Q_EMIT dataChanged(createIndex(0, 0), createIndex(m_folder->m_delegates.size() - 1, 0), {pageIndexRole});
} }
Q_EMIT numberOfPagesChanged(); Q_EMIT numberOfPagesChanged();
@ -429,26 +437,13 @@ QPointF ApplicationFolderModel::getDelegateStartPosition(int page)
int ApplicationFolderModel::numTotalPages() int ApplicationFolderModel::numTotalPages()
{ {
int numOfDelegatesOnPage = numRowsOnPage() * numColumnsOnPage(); int numOfDelegatesOnPage = numGridLengthOnPage() * numGridLengthOnPage();
return std::ceil(((qreal)m_folder->m_delegates.size()) / numOfDelegatesOnPage); return std::ceil(((qreal)m_folder->m_delegates.size()) / numOfDelegatesOnPage);
} }
int ApplicationFolderModel::numRowsOnPage() int ApplicationFolderModel::numGridLengthOnPage()
{ {
HomeScreenState *homeScreenState = m_folder->m_homeScreen->homeScreenState(); return m_folder->m_homeScreen->homeScreenState()->folderGridLength();
qreal contentHeight = homeScreenState->folderPageContentHeight();
qreal cellHeight = homeScreenState->pageCellHeight();
return std::max(0.0, contentHeight / cellHeight);
}
int ApplicationFolderModel::numColumnsOnPage()
{
HomeScreenState *homeScreenState = m_folder->m_homeScreen->homeScreenState();
qreal contentWidth = homeScreenState->folderPageContentWidth();
qreal cellWidth = homeScreenState->pageCellWidth();
return std::max(0.0, contentWidth / cellWidth);
} }
qreal ApplicationFolderModel::leftMarginFromScreenEdge() qreal ApplicationFolderModel::leftMarginFromScreenEdge()

View file

@ -74,8 +74,9 @@ private:
struct ApplicationDelegate { struct ApplicationDelegate {
FolioDelegate *delegate; FolioDelegate *delegate;
qreal xPosition; int columnIndex;
qreal yPosition; int rowIndex;
int pageIndex;
}; };
class ApplicationFolderModel : public QAbstractListModel class ApplicationFolderModel : public QAbstractListModel
@ -86,8 +87,9 @@ class ApplicationFolderModel : public QAbstractListModel
public: public:
enum Roles { enum Roles {
DelegateRole = Qt::UserRole + 1, DelegateRole = Qt::UserRole + 1,
XPositionRole, columnIndexRole,
YPositionRole, rowIndexRole,
pageIndexRole,
}; };
ApplicationFolderModel(FolioApplicationFolder *folder); ApplicationFolderModel(FolioApplicationFolder *folder);
@ -126,13 +128,12 @@ Q_SIGNALS:
void numberOfPagesChanged(); void numberOfPagesChanged();
private: private:
void evaluateDelegatePositions(bool emitSignal = true); void evaluateDelegateIndexes(bool emitSignal = true);
// get the position where delegates start being placed // get the position where delegates start being placed
QPointF getDelegateStartPosition(int page); QPointF getDelegateStartPosition(int page);
int numRowsOnPage(); int numGridLengthOnPage();
int numColumnsOnPage();
// distance between folder edge and page content // distance between folder edge and page content
qreal horizontalPageMargin(); qreal horizontalPageMargin();

View file

@ -120,13 +120,32 @@ void HomeScreenState::init()
Q_EMIT pageColumnsChanged(); Q_EMIT pageColumnsChanged();
}); });
connect(this, &HomeScreenState::pageWidthChanged, this, &HomeScreenState::calculatePageContentWidth); connect(this, &HomeScreenState::pageWidthChanged, [this]() {
connect(this, &HomeScreenState::pageHeightChanged, this, &HomeScreenState::calculatePageContentHeight); calculatePageContentWidth();
calculateFolderGridLength();
});
connect(this, &HomeScreenState::pageHeightChanged, [this]() {
calculatePageContentHeight();
calculateFolderGridLength();
});
connect(this, &HomeScreenState::pageContentWidthChanged, [this]() {
calculatePageCellWidth();
calculateFolderGridLength();
});
connect(this, &HomeScreenState::pageColumnsChanged, [this]() {
calculatePageCellWidth();
calculateFolderGridLength();
});
connect(this, &HomeScreenState::pageContentHeightChanged, [this]() {
calculatePageCellHeight();
calculateFolderGridLength();
});
connect(this, &HomeScreenState::pageRowsChanged, [this]() {
calculatePageCellHeight();
calculateFolderGridLength();
});
connect(this, &HomeScreenState::pageContentWidthChanged, this, &HomeScreenState::calculatePageCellWidth); connect(m_homeScreen->folioSettings(), &FolioSettings::delegateIconSizeChanged, this, &HomeScreenState::calculateFolderGridLength);
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]() { connect(this, &HomeScreenState::viewWidthChanged, this, [this]() {
Q_EMIT favouritesBarLocationChanged(); Q_EMIT favouritesBarLocationChanged();
@ -317,6 +336,7 @@ void HomeScreenState::setPageWidth(qreal pageWidth)
// make sure we snap // make sure we snap
goToPage(m_pageNum, true); goToPage(m_pageNum, true);
goToFolderPage(m_folderPageNum, true);
} }
} }
@ -510,6 +530,22 @@ void HomeScreenState::setCurrentFolder(FolioApplicationFolder *folder)
} }
} }
int HomeScreenState::folderGridLength() const
{
return m_folderGridLength;
}
void HomeScreenState::calculateFolderGridLength()
{
const int folderGridLength = std::max(2, qRound(std::min(m_viewWidth, m_viewHeight) * 0.6 / m_homeScreen->folioSettings()->delegateIconSize() * 0.6));
if (m_folderGridLength != folderGridLength) {
m_folderGridLength = folderGridLength;
Q_EMIT folderGridLengthChanged();
goToFolderPage(m_folderPageNum, true);
}
}
qreal HomeScreenState::settingsOpenProgress() qreal HomeScreenState::settingsOpenProgress()
{ {
return m_settingsOpenProgress; return m_settingsOpenProgress;
@ -667,13 +703,8 @@ QPointF HomeScreenState::getFolderDelegateScreenPosition(int position)
return {0, 0}; return {0, 0};
} }
auto pos = m_currentFolder->applications()->getDelegatePosition(position); auto pos = m_currentFolder->applications()->getDelegatePosition(position);
qreal x = pos.x() + (m_viewWidth - m_viewLeftPadding - m_viewRightPadding - m_folderPageWidth) / 2; qreal x = pos.x() + (m_viewWidth - m_folderPageWidth) / 2;
qreal y = pos.y() + (m_viewHeight - m_viewTopPadding - m_viewBottomPadding - m_folderPageHeight) / 2; qreal y = pos.y() + (m_viewHeight - m_folderPageHeight) / 2;
x += m_viewLeftPadding;
y += m_viewTopPadding;
// adjust for the current page
x -= currentFolderPage() * m_folderPageWidth;
return {x, y}; return {x, y};
} }
@ -735,7 +766,7 @@ void HomeScreenState::goToPage(int page, bool snap)
m_pageAnim->start(); m_pageAnim->start();
} }
void HomeScreenState::goToFolderPage(int page) void HomeScreenState::goToFolderPage(int page, bool snap)
{ {
if (!m_currentFolder) { if (!m_currentFolder) {
return; return;
@ -753,7 +784,12 @@ void HomeScreenState::goToFolderPage(int page)
m_folderPageNum = page; m_folderPageNum = page;
Q_EMIT folderPageNumChanged(); Q_EMIT folderPageNumChanged();
if (snap) {
// Skip the animation and go straight to the intended page
m_folderPageAnim->setStartValue(-page * m_folderPageWidth);
} else {
m_folderPageAnim->setStartValue(m_folderViewX); m_folderPageAnim->setStartValue(m_folderViewX);
}
m_folderPageAnim->setEndValue(-page * m_folderPageWidth); m_folderPageAnim->setEndValue(-page * m_folderPageWidth);
m_folderPageAnim->start(); m_folderPageAnim->start();
} }
@ -908,9 +944,9 @@ void HomeScreenState::swipeEnded()
// m_movingRight refers to finger movement // m_movingRight refers to finger movement
if (m_movingRight || m_folderViewX > 0) { if (m_movingRight || m_folderViewX > 0) {
goToFolderPage(page); goToFolderPage(page, false);
} else { } else {
goToFolderPage(page + 1); goToFolderPage(page + 1, false);
} }
break; break;
} }

View file

@ -61,6 +61,7 @@ class HomeScreenState : public QObject
Q_PROPERTY(qreal folderPageContentHeight READ folderPageContentHeight WRITE setFolderPageContentHeight NOTIFY folderPageContentHeightChanged) Q_PROPERTY(qreal folderPageContentHeight READ folderPageContentHeight WRITE setFolderPageContentHeight NOTIFY folderPageContentHeightChanged)
Q_PROPERTY(qreal folderOpenProgress READ folderOpenProgress WRITE setFolderOpenProgress NOTIFY folderOpenProgressChanged) Q_PROPERTY(qreal folderOpenProgress READ folderOpenProgress WRITE setFolderOpenProgress NOTIFY folderOpenProgressChanged)
Q_PROPERTY(FolioApplicationFolder *currentFolder READ currentFolder NOTIFY currentFolderChanged) Q_PROPERTY(FolioApplicationFolder *currentFolder READ currentFolder NOTIFY currentFolderChanged)
Q_PROPERTY(qreal folderGridLength READ folderGridLength NOTIFY folderGridLengthChanged)
Q_PROPERTY(qreal settingsOpenProgress READ settingsOpenProgress WRITE setSettingsOpenProgress NOTIFY settingsOpenProgressChanged) Q_PROPERTY(qreal settingsOpenProgress READ settingsOpenProgress WRITE setSettingsOpenProgress NOTIFY settingsOpenProgressChanged)
@ -204,6 +205,9 @@ public:
qreal folderOpenProgress() const; qreal folderOpenProgress() const;
void setFolderOpenProgress(qreal folderOpenProgress); void setFolderOpenProgress(qreal folderOpenProgress);
int folderGridLength() const;
void calculateFolderGridLength();
FolioApplicationFolder *currentFolder() const; FolioApplicationFolder *currentFolder() const;
void setCurrentFolder(FolioApplicationFolder *folder); void setCurrentFolder(FolioApplicationFolder *folder);
@ -286,6 +290,7 @@ Q_SIGNALS:
void folderPageContentWidthChanged(); void folderPageContentWidthChanged();
void folderPageContentHeightChanged(); void folderPageContentHeightChanged();
void folderOpenProgressChanged(); void folderOpenProgressChanged();
void folderGridLengthChanged();
void currentFolderChanged(); void currentFolderChanged();
void settingsOpenProgressChanged(); void settingsOpenProgressChanged();
void appDrawerOpenProgressChanged(); void appDrawerOpenProgressChanged();
@ -318,7 +323,7 @@ public Q_SLOTS:
void goToPage(int page, bool snap); void goToPage(int page, bool snap);
void goToFolderPage(int page); void goToFolderPage(int page, bool snap);
void openFolder(qreal delegateX, qreal delegateY, FolioApplicationFolder *folder); void openFolder(qreal delegateX, qreal delegateY, FolioApplicationFolder *folder);
void closeFolder(); void closeFolder();
@ -385,6 +390,7 @@ private:
qreal m_folderPageContentHeight{0}; qreal m_folderPageContentHeight{0};
qreal m_folderOpenProgress{0}; qreal m_folderOpenProgress{0};
FolioApplicationFolder *m_currentFolder{nullptr}; FolioApplicationFolder *m_currentFolder{nullptr};
int m_folderGridLength{0};
qreal m_settingsOpenProgress{0}; qreal m_settingsOpenProgress{0};

View file

@ -47,7 +47,7 @@ Folio.DelegateTouchArea {
width: root.width width: root.width
// have to use y instead of anchors to avoid animations // have to use y instead of anchors to avoid animations
y: Math.round((root.height / 2) - (folderBackground.height / 2) - Kirigami.Units.gridUnit - height) y: Math.round(((root.height / 2) - (folderBackground.height / 2)) * 0.9 - height)
anchors.left: parent.left anchors.left: parent.left
anchors.right: parent.right anchors.right: parent.right
@ -61,14 +61,12 @@ Folio.DelegateTouchArea {
function updateContentWidth() { function updateContentWidth() {
let margin = folderBackground.margin; let margin = folderBackground.margin;
let columns = Math.floor((folderBackground.width - margin * 2) / folio.HomeScreenState.pageCellWidth); folio.HomeScreenState.folderPageContentWidth = (folderBackground.width - margin * 2);
folio.HomeScreenState.folderPageContentWidth = columns * folio.HomeScreenState.pageCellWidth;
} }
function updateContentHeight() { function updateContentHeight() {
let margin = folderBackground.margin; let margin = folderBackground.margin;
let rows = Math.floor((folderBackground.height - margin * 2) / folio.HomeScreenState.pageCellHeight); folio.HomeScreenState.folderPageContentHeight = (folderBackground.height - margin * 2);
folio.HomeScreenState.folderPageContentHeight = rows * folio.HomeScreenState.pageCellHeight;
} }
Connections { Connections {
@ -90,28 +88,26 @@ Folio.DelegateTouchArea {
color: Qt.rgba(255, 255, 255, 0.3) color: Qt.rgba(255, 255, 255, 0.3)
radius: Kirigami.Units.gridUnit radius: Kirigami.Units.gridUnit
readonly property real margin: Kirigami.Units.largeSpacing readonly property int gridLength: folio.HomeScreenState.folderGridLength
readonly property real maxLength: Math.min(root.width * 0.9, root.height * 0.9)
width: { readonly property int margin: Kirigami.Units.largeSpacing
let perRow = 0; readonly property int maxLength: Math.min(root.width - Kirigami.Units.gridUnit * 4, root.height - Kirigami.Units.gridUnit * 2)
if (root.width < root.height) {
perRow = Math.floor((maxLength - margin * 2) / folio.HomeScreenState.pageCellWidth); readonly property int pageSize: Math.min(maxLength, (folio.FolioSettings.delegateIconSize + Kirigami.Units.gridUnit * 3) * gridLength + Kirigami.Units.gridUnit * 2)
} else {
// try to get the same number of rows as columns width: pageSize - margin * 2
perRow = Math.floor((maxLength - margin * 2) / folio.HomeScreenState.pageCellHeight); height: pageSize
}
return Math.min(root.width * 0.9, perRow * folio.HomeScreenState.pageCellWidth + margin * 2); QQC2.PageIndicator {
} visible: count > 1
height: { Kirigami.Theme.inherit: false
let perRow = 0; Kirigami.Theme.colorSet: Kirigami.Theme.Complementary
if (root.width < root.height) {
// try to get the same number of rows as columns anchors.horizontalCenter: parent.horizontalCenter
perRow = Math.floor((maxLength - margin * 2) / folio.HomeScreenState.pageCellWidth); anchors.bottom: parent.bottom
} else {
perRow = Math.floor((maxLength - margin * 2) / folio.HomeScreenState.pageCellHeight); currentIndex: folio.HomeScreenState.currentFolderPage
} count: folio.HomeScreenState.currentFolder ? folio.HomeScreenState.currentFolder.applications.numberOfPages : 0
return Math.min(root.height * 0.9, perRow * folio.HomeScreenState.pageCellHeight + margin * 2);
} }
onWidthChanged: { onWidthChanged: {
@ -173,27 +169,42 @@ Folio.DelegateTouchArea {
delegate: Item { delegate: Item {
id: delegate id: delegate
property var delegateModel: model.delegate readonly property var delegateModel: model.delegate
property int index: model.index readonly property int index: model.index
property var dragState: folio.HomeScreenState.dragState readonly property int folderCellSize: folio.HomeScreenState.folderPageContentWidth / folderBackground.gridLength
property bool isDropPositionThis: dragState.candidateDropPosition.location === Folio.DelegateDragPosition.Folder && readonly property int cellWidth: folio.HomeScreenState.pageCellWidth
readonly property int cellHeight: folio.HomeScreenState.pageCellHeight
readonly property var dragState: folio.HomeScreenState.dragState
readonly property bool isDropPositionThis: dragState.candidateDropPosition.location === Folio.DelegateDragPosition.Folder &&
dragState.candidateDropPosition.folderPosition === index dragState.candidateDropPosition.folderPosition === index
x: model.xPosition // get the index position value so we can animate them
y: model.yPosition property double columnValue: model.columnIndex
property double rowValue: model.rowIndex
Behavior on x { property double pageValue: model.pageIndex
Behavior on columnValue {
NumberAnimation { duration: 250; easing.type: Easing.InOutQuad } NumberAnimation { duration: 250; easing.type: Easing.InOutQuad }
} }
Behavior on y { Behavior on rowValue {
NumberAnimation { duration: 250; easing.type: Easing.InOutQuad }
}
Behavior on pageValue {
NumberAnimation { duration: 250; easing.type: Easing.InOutQuad } NumberAnimation { duration: 250; easing.type: Easing.InOutQuad }
} }
implicitWidth: folio.HomeScreenState.pageCellWidth // multiply the index values by the cell size to get the actual position
implicitHeight: folio.HomeScreenState.pageCellHeight readonly property int positionColumn: folderCellSize * columnValue
width: folio.HomeScreenState.pageCellWidth readonly property int positionRow: folderCellSize * rowValue
height: folio.HomeScreenState.pageCellHeight
x: (folderCellSize - cellWidth) / 2 + folderBackground.margin + pageValue * folderBackground.width + positionColumn
y: (folderCellSize - cellHeight) / 2 + folderBackground.margin + positionRow
implicitWidth: cellWidth
implicitHeight: cellHeight
width: cellWidth
height: cellHeight
Loader { Loader {
id: delegateLoader id: delegateLoader
@ -282,22 +293,4 @@ Folio.DelegateTouchArea {
} }
} }
} }
QQC2.PageIndicator {
visible: count > 1
Kirigami.Theme.inherit: false
Kirigami.Theme.colorSet: Kirigami.Theme.Complementary
// have to use y instead of anchors to avoid animations
y: Math.round((root.height / 2) + (folderBackground.height / 2) + Kirigami.Units.largeSpacing)
anchors.horizontalCenter: parent.horizontalCenter
currentIndex: folio.HomeScreenState.currentFolderPage
count: folio.HomeScreenState.currentFolder ? folio.HomeScreenState.currentFolder.applications.numberOfPages : 0
opacity: (root.opacity === 1) ? 1 : 0
Behavior on opacity {
NumberAnimation { duration: Kirigami.Units.shortDuration }
}
}
} }