[app] Corrected page stack behaviour
It couldn't push the same position that was just popped. Also, some countChanged signals were not being deferred - it was probably not intentional, at least I couldn't remember why it was done like that. Let all countChanged signals be deferred.
This commit is contained in:
parent
7a7067869d
commit
feffa61273
1 changed files with 75 additions and 56 deletions
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (C) 2016-2017 Jolla Ltd.
|
* Copyright (C) 2016-2018 Jolla Ltd.
|
||||||
* Contact: Slava Monich <slava.monich@jolla.com>
|
* Contact: Slava Monich <slava.monich@jolla.com>
|
||||||
*
|
*
|
||||||
* You may use this file under the terms of the BSD license as follows:
|
* You may use this file under the terms of the BSD license as follows:
|
||||||
|
@ -89,12 +89,12 @@ public:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
BooksPos::List iPageMarks;
|
BooksPos::List iPageMarks;
|
||||||
BooksPageStack* iModel;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Private(BooksPageStack* aModel);
|
Private(BooksPageStack* aModel);
|
||||||
|
|
||||||
BooksPos::Stack getStack() const;
|
BooksPos::Stack getStack() const;
|
||||||
|
bool atEnd() const;
|
||||||
bool isValidIndex(int aIndex) const;
|
bool isValidIndex(int aIndex) const;
|
||||||
void setCurrentIndex(int aIndex);
|
void setCurrentIndex(int aIndex);
|
||||||
int currentPage() const;
|
int currentPage() const;
|
||||||
|
@ -103,7 +103,6 @@ public:
|
||||||
void setPageAt(int aIndex, int aPage);
|
void setPageAt(int aIndex, int aPage);
|
||||||
void setStack(BooksPos::List aStack, int aCurrentPos);
|
void setStack(BooksPos::List aStack, int aCurrentPos);
|
||||||
void setPageMarks(BooksPos::List aPageMarks);
|
void setPageMarks(BooksPos::List aPageMarks);
|
||||||
void push(BooksPos aPos, int aPage);
|
|
||||||
void push(BooksPos);
|
void push(BooksPos);
|
||||||
void push(int aPage);
|
void push(int aPage);
|
||||||
void pop();
|
void pop();
|
||||||
|
@ -114,6 +113,8 @@ private Q_SLOTS:
|
||||||
void onModelChanged();
|
void onModelChanged();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
BooksPageStack* parentModel() const;
|
||||||
|
void push(BooksPos aPos, int aPage);
|
||||||
BooksPos getPosAt(int aIndex) const;
|
BooksPos getPosAt(int aIndex) const;
|
||||||
int findPage(BooksPos aPos) const;
|
int findPage(BooksPos aPos) const;
|
||||||
int makeIndexValid(int aIndex) const;
|
int makeIndexValid(int aIndex) const;
|
||||||
|
@ -128,8 +129,7 @@ private:
|
||||||
BooksPageStack::Private::Private(BooksPageStack* aModel) :
|
BooksPageStack::Private::Private(BooksPageStack* aModel) :
|
||||||
QObject(aModel),
|
QObject(aModel),
|
||||||
iCurrentIndex(0),
|
iCurrentIndex(0),
|
||||||
iQueuedSignals(0),
|
iQueuedSignals(0)
|
||||||
iModel(aModel)
|
|
||||||
{
|
{
|
||||||
iEntries.append(Entry());
|
iEntries.append(Entry());
|
||||||
connect(aModel,
|
connect(aModel,
|
||||||
|
@ -146,6 +146,11 @@ BooksPageStack::Private::Private(BooksPageStack* aModel) :
|
||||||
SLOT(onModelChanged()));
|
SLOT(onModelChanged()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline BooksPageStack* BooksPageStack::Private::parentModel() const
|
||||||
|
{
|
||||||
|
return qobject_cast<BooksPageStack*>(parent());
|
||||||
|
}
|
||||||
|
|
||||||
void BooksPageStack::Private::emitQueuedSignals()
|
void BooksPageStack::Private::emitQueuedSignals()
|
||||||
{
|
{
|
||||||
static const struct SignalInfo {
|
static const struct SignalInfo {
|
||||||
|
@ -158,10 +163,13 @@ void BooksPageStack::Private::emitQueuedSignals()
|
||||||
{ SignalCurrentPageChanged, &BooksPageStack::currentPageChanged}
|
{ SignalCurrentPageChanged, &BooksPageStack::currentPageChanged}
|
||||||
};
|
};
|
||||||
const uint n = sizeof(signalInfo)/sizeof(signalInfo[0]);
|
const uint n = sizeof(signalInfo)/sizeof(signalInfo[0]);
|
||||||
for (uint i=0; i<n && iQueuedSignals; i++) {
|
if (iQueuedSignals) {
|
||||||
if (iQueuedSignals & signalInfo[i].signal) {
|
BooksPageStack* model = parentModel();
|
||||||
iQueuedSignals &= ~signalInfo[i].signal;
|
for (uint i=0; i<n && iQueuedSignals; i++) {
|
||||||
Q_EMIT (iModel->*(signalInfo[i].fn))();
|
if (iQueuedSignals & signalInfo[i].signal) {
|
||||||
|
iQueuedSignals &= ~signalInfo[i].signal;
|
||||||
|
Q_EMIT (model->*(signalInfo[i].fn))();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -191,6 +199,11 @@ inline bool BooksPageStack::Private::isValidIndex(int aIndex) const
|
||||||
return aIndex >= 0 && aIndex < iEntries.count();
|
return aIndex >= 0 && aIndex < iEntries.count();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline bool BooksPageStack::Private::atEnd() const
|
||||||
|
{
|
||||||
|
return (iCurrentIndex + 1) >= iEntries.count();
|
||||||
|
}
|
||||||
|
|
||||||
inline void BooksPageStack::Private::checkCurrentIndex(int aLastIndex)
|
inline void BooksPageStack::Private::checkCurrentIndex(int aLastIndex)
|
||||||
{
|
{
|
||||||
if (validateCurrentIndex() != aLastIndex) {
|
if (validateCurrentIndex() != aLastIndex) {
|
||||||
|
@ -274,8 +287,9 @@ void BooksPageStack::Private::pageChanged(int aIndex)
|
||||||
{
|
{
|
||||||
QVector<int> roles;
|
QVector<int> roles;
|
||||||
roles.append(PageRole);
|
roles.append(PageRole);
|
||||||
QModelIndex modelIndex(iModel->createIndex(aIndex, 0));
|
BooksPageStack* model = parentModel();
|
||||||
Q_EMIT iModel->dataChanged(modelIndex, modelIndex, roles);
|
QModelIndex modelIndex(model->createIndex(aIndex, 0));
|
||||||
|
Q_EMIT model->dataChanged(modelIndex, modelIndex, roles);
|
||||||
}
|
}
|
||||||
|
|
||||||
void BooksPageStack::Private::setStack(BooksPos::List aStack, int aStackPos)
|
void BooksPageStack::Private::setStack(BooksPos::List aStack, int aStackPos)
|
||||||
|
@ -313,12 +327,13 @@ void BooksPageStack::Private::setStack(BooksPos::List aStack, int aStackPos)
|
||||||
|
|
||||||
if (entryIndex < oldEntryCount) {
|
if (entryIndex < oldEntryCount) {
|
||||||
// We have run out of stack entries, remove remainig rows
|
// We have run out of stack entries, remove remainig rows
|
||||||
iModel->beginRemoveRows(QModelIndex(), entryIndex, oldEntryCount-1);
|
BooksPageStack* model = parentModel();
|
||||||
|
model->beginRemoveRows(QModelIndex(), entryIndex, oldEntryCount-1);
|
||||||
while (iEntries.count() > entryIndex) {
|
while (iEntries.count() > entryIndex) {
|
||||||
iEntries.removeLast();
|
iEntries.removeLast();
|
||||||
}
|
}
|
||||||
iModel->endRemoveRows();
|
model->endRemoveRows();
|
||||||
Q_EMIT iModel->countChanged();
|
queueSignals(SignalCountChanged);
|
||||||
} else {
|
} else {
|
||||||
// Add new entries if necessary
|
// Add new entries if necessary
|
||||||
while (stackIndex < aStack.count()) {
|
while (stackIndex < aStack.count()) {
|
||||||
|
@ -332,9 +347,10 @@ void BooksPageStack::Private::setStack(BooksPos::List aStack, int aStackPos)
|
||||||
const int n = iEntries.count();
|
const int n = iEntries.count();
|
||||||
if (n > oldEntryCount) {
|
if (n > oldEntryCount) {
|
||||||
// We have added some entries, update the model
|
// We have added some entries, update the model
|
||||||
iModel->beginInsertRows(QModelIndex(), oldEntryCount, n-1);
|
BooksPageStack* model = parentModel();
|
||||||
iModel->endInsertRows();
|
model->beginInsertRows(QModelIndex(), oldEntryCount, n-1);
|
||||||
Q_EMIT iModel->countChanged();
|
model->endInsertRows();
|
||||||
|
queueSignals(SignalCountChanged);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -395,55 +411,56 @@ BooksPos BooksPageStack::Private::getPosAt(int aIndex) const
|
||||||
void BooksPageStack::Private::push(BooksPos aPos, int aPage)
|
void BooksPageStack::Private::push(BooksPos aPos, int aPage)
|
||||||
{
|
{
|
||||||
Entry last = iEntries.last();
|
Entry last = iEntries.last();
|
||||||
if (last.iPos != aPos || last.iPage != aPage) {
|
const int n = iEntries.count();
|
||||||
const int n = iEntries.count();
|
// The caller makes sure that the operation makes sense
|
||||||
if (n >= iCurrentIndex+2) {
|
HASSERT(!atEnd() || last.iPos != aPos || last.iPage != aPage);
|
||||||
// Push on top of the current position.
|
if (n >= iCurrentIndex+2) {
|
||||||
if (n > iCurrentIndex+2) {
|
// Push on top of the current position.
|
||||||
// Drop unnecessary entries
|
if (n > iCurrentIndex+2) {
|
||||||
iModel->beginRemoveRows(QModelIndex(), iCurrentIndex+2, n-1);
|
// Drop unnecessary entries
|
||||||
while (iEntries.count() > iCurrentIndex+2) {
|
BooksPageStack* model = parentModel();
|
||||||
iEntries.removeLast();
|
model->beginRemoveRows(QModelIndex(), iCurrentIndex+2, n-1);
|
||||||
}
|
while (iEntries.count() > iCurrentIndex+2) {
|
||||||
iModel->endRemoveRows();
|
iEntries.removeLast();
|
||||||
Q_EMIT iModel->countChanged();
|
|
||||||
queueSignals(SignalCountChanged);
|
|
||||||
}
|
}
|
||||||
// And replace the next one
|
model->endRemoveRows();
|
||||||
setPageAt(iCurrentIndex+1, aPage);
|
|
||||||
setCurrentIndex(iCurrentIndex+1);
|
|
||||||
} else if (n >= MAX_DEPTH) {
|
|
||||||
// We have reached the depth limit, push the entire stack down
|
|
||||||
const int oldCurrentPage = currentPage();
|
|
||||||
for (int i=1; i<n; i++) {
|
|
||||||
iEntries[i-1] = iEntries[i];
|
|
||||||
pageChanged(i-1);
|
|
||||||
}
|
|
||||||
iEntries[n-1] = Entry(aPos, aPage);
|
|
||||||
pageChanged(n-1);
|
|
||||||
checkCurrentPage(oldCurrentPage);
|
|
||||||
} else {
|
|
||||||
// Just push the new one
|
|
||||||
const int i = iCurrentIndex+1;
|
|
||||||
iModel->beginInsertRows(QModelIndex(), i, i);
|
|
||||||
iEntries.append(Entry(aPos, aPage));
|
|
||||||
iModel->endInsertRows();
|
|
||||||
queueSignals(SignalCountChanged);
|
queueSignals(SignalCountChanged);
|
||||||
setCurrentIndex(i);
|
|
||||||
}
|
}
|
||||||
|
// And replace the next one
|
||||||
|
setPageAt(iCurrentIndex+1, aPage);
|
||||||
|
setCurrentIndex(iCurrentIndex+1);
|
||||||
|
} else if (n >= MAX_DEPTH) {
|
||||||
|
// We have reached the depth limit, push the entire stack down
|
||||||
|
const int oldCurrentPage = currentPage();
|
||||||
|
for (int i=1; i<n; i++) {
|
||||||
|
iEntries[i-1] = iEntries[i];
|
||||||
|
pageChanged(i-1);
|
||||||
|
}
|
||||||
|
iEntries[n-1] = Entry(aPos, aPage);
|
||||||
|
pageChanged(n-1);
|
||||||
|
checkCurrentPage(oldCurrentPage);
|
||||||
|
} else {
|
||||||
|
// Just push the new one
|
||||||
|
const int i = iCurrentIndex+1;
|
||||||
|
BooksPageStack* model = parentModel();
|
||||||
|
model->beginInsertRows(QModelIndex(), i, i);
|
||||||
|
iEntries.append(Entry(aPos, aPage));
|
||||||
|
model->endInsertRows();
|
||||||
|
queueSignals(SignalCountChanged);
|
||||||
|
setCurrentIndex(i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void BooksPageStack::Private::push(BooksPos aPos)
|
void BooksPageStack::Private::push(BooksPos aPos)
|
||||||
{
|
{
|
||||||
if (iEntries.last().iPos != aPos) {
|
if (!atEnd() || iEntries.last().iPos != aPos) {
|
||||||
push(aPos, findPage(aPos));
|
push(aPos, findPage(aPos));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void BooksPageStack::Private::push(int aPage)
|
void BooksPageStack::Private::push(int aPage)
|
||||||
{
|
{
|
||||||
if (iEntries.last().iPage != aPage) {
|
if (!atEnd() || iEntries.last().iPage != aPage) {
|
||||||
push(getPosAt(aPage), aPage);
|
push(getPosAt(aPage), aPage);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -452,10 +469,11 @@ void BooksPageStack::Private::pop()
|
||||||
{
|
{
|
||||||
const int n = iEntries.count();
|
const int n = iEntries.count();
|
||||||
if (n > 1) {
|
if (n > 1) {
|
||||||
iModel->beginRemoveRows(QModelIndex(), n-1, n-1);
|
BooksPageStack* model = parentModel();
|
||||||
|
model->beginRemoveRows(QModelIndex(), n-1, n-1);
|
||||||
iEntries.removeLast();
|
iEntries.removeLast();
|
||||||
validateCurrentIndex();
|
validateCurrentIndex();
|
||||||
iModel->endRemoveRows();
|
model->endRemoveRows();
|
||||||
queueSignals(SignalCountChanged);
|
queueSignals(SignalCountChanged);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -464,13 +482,14 @@ void BooksPageStack::Private::clear()
|
||||||
{
|
{
|
||||||
const int n = iEntries.count();
|
const int n = iEntries.count();
|
||||||
if (n > 1) {
|
if (n > 1) {
|
||||||
|
BooksPageStack* model = parentModel();
|
||||||
Entry currentEntry = iEntries.at(iCurrentIndex);
|
Entry currentEntry = iEntries.at(iCurrentIndex);
|
||||||
iModel->beginRemoveRows(QModelIndex(), 1, n-1);
|
model->beginRemoveRows(QModelIndex(), 1, n-1);
|
||||||
while (iEntries.count() > 1) {
|
while (iEntries.count() > 1) {
|
||||||
iEntries.removeLast();
|
iEntries.removeLast();
|
||||||
}
|
}
|
||||||
validateCurrentIndex();
|
validateCurrentIndex();
|
||||||
iModel->endRemoveRows();
|
model->endRemoveRows();
|
||||||
if (iEntries.at(0) != currentEntry) {
|
if (iEntries.at(0) != currentEntry) {
|
||||||
iEntries[0] = currentEntry;
|
iEntries[0] = currentEntry;
|
||||||
pageChanged(0);
|
pageChanged(0);
|
||||||
|
|
Loading…
Reference in a new issue