[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:
Slava Monich 2018-01-20 13:35:35 +02:00
parent 7a7067869d
commit feffa61273

View file

@ -1,5 +1,5 @@
/*
* Copyright (C) 2016-2017 Jolla Ltd.
* Copyright (C) 2016-2018 Jolla Ltd.
* Contact: Slava Monich <slava.monich@jolla.com>
*
* You may use this file under the terms of the BSD license as follows:
@ -89,12 +89,12 @@ public:
private:
BooksPos::List iPageMarks;
BooksPageStack* iModel;
public:
Private(BooksPageStack* aModel);
BooksPos::Stack getStack() const;
bool atEnd() const;
bool isValidIndex(int aIndex) const;
void setCurrentIndex(int aIndex);
int currentPage() const;
@ -103,7 +103,6 @@ public:
void setPageAt(int aIndex, int aPage);
void setStack(BooksPos::List aStack, int aCurrentPos);
void setPageMarks(BooksPos::List aPageMarks);
void push(BooksPos aPos, int aPage);
void push(BooksPos);
void push(int aPage);
void pop();
@ -114,6 +113,8 @@ private Q_SLOTS:
void onModelChanged();
private:
BooksPageStack* parentModel() const;
void push(BooksPos aPos, int aPage);
BooksPos getPosAt(int aIndex) const;
int findPage(BooksPos aPos) const;
int makeIndexValid(int aIndex) const;
@ -128,8 +129,7 @@ private:
BooksPageStack::Private::Private(BooksPageStack* aModel) :
QObject(aModel),
iCurrentIndex(0),
iQueuedSignals(0),
iModel(aModel)
iQueuedSignals(0)
{
iEntries.append(Entry());
connect(aModel,
@ -146,6 +146,11 @@ BooksPageStack::Private::Private(BooksPageStack* aModel) :
SLOT(onModelChanged()));
}
inline BooksPageStack* BooksPageStack::Private::parentModel() const
{
return qobject_cast<BooksPageStack*>(parent());
}
void BooksPageStack::Private::emitQueuedSignals()
{
static const struct SignalInfo {
@ -158,10 +163,13 @@ void BooksPageStack::Private::emitQueuedSignals()
{ SignalCurrentPageChanged, &BooksPageStack::currentPageChanged}
};
const uint n = sizeof(signalInfo)/sizeof(signalInfo[0]);
for (uint i=0; i<n && iQueuedSignals; i++) {
if (iQueuedSignals & signalInfo[i].signal) {
iQueuedSignals &= ~signalInfo[i].signal;
Q_EMIT (iModel->*(signalInfo[i].fn))();
if (iQueuedSignals) {
BooksPageStack* model = parentModel();
for (uint i=0; i<n && iQueuedSignals; i++) {
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();
}
inline bool BooksPageStack::Private::atEnd() const
{
return (iCurrentIndex + 1) >= iEntries.count();
}
inline void BooksPageStack::Private::checkCurrentIndex(int aLastIndex)
{
if (validateCurrentIndex() != aLastIndex) {
@ -274,8 +287,9 @@ void BooksPageStack::Private::pageChanged(int aIndex)
{
QVector<int> roles;
roles.append(PageRole);
QModelIndex modelIndex(iModel->createIndex(aIndex, 0));
Q_EMIT iModel->dataChanged(modelIndex, modelIndex, roles);
BooksPageStack* model = parentModel();
QModelIndex modelIndex(model->createIndex(aIndex, 0));
Q_EMIT model->dataChanged(modelIndex, modelIndex, roles);
}
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) {
// 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) {
iEntries.removeLast();
}
iModel->endRemoveRows();
Q_EMIT iModel->countChanged();
model->endRemoveRows();
queueSignals(SignalCountChanged);
} else {
// Add new entries if necessary
while (stackIndex < aStack.count()) {
@ -332,9 +347,10 @@ void BooksPageStack::Private::setStack(BooksPos::List aStack, int aStackPos)
const int n = iEntries.count();
if (n > oldEntryCount) {
// We have added some entries, update the model
iModel->beginInsertRows(QModelIndex(), oldEntryCount, n-1);
iModel->endInsertRows();
Q_EMIT iModel->countChanged();
BooksPageStack* model = parentModel();
model->beginInsertRows(QModelIndex(), oldEntryCount, n-1);
model->endInsertRows();
queueSignals(SignalCountChanged);
}
}
@ -395,55 +411,56 @@ BooksPos BooksPageStack::Private::getPosAt(int aIndex) const
void BooksPageStack::Private::push(BooksPos aPos, int aPage)
{
Entry last = iEntries.last();
if (last.iPos != aPos || last.iPage != aPage) {
const int n = iEntries.count();
if (n >= iCurrentIndex+2) {
// Push on top of the current position.
if (n > iCurrentIndex+2) {
// Drop unnecessary entries
iModel->beginRemoveRows(QModelIndex(), iCurrentIndex+2, n-1);
while (iEntries.count() > iCurrentIndex+2) {
iEntries.removeLast();
}
iModel->endRemoveRows();
Q_EMIT iModel->countChanged();
queueSignals(SignalCountChanged);
const int n = iEntries.count();
// The caller makes sure that the operation makes sense
HASSERT(!atEnd() || last.iPos != aPos || last.iPage != aPage);
if (n >= iCurrentIndex+2) {
// Push on top of the current position.
if (n > iCurrentIndex+2) {
// Drop unnecessary entries
BooksPageStack* model = parentModel();
model->beginRemoveRows(QModelIndex(), iCurrentIndex+2, n-1);
while (iEntries.count() > iCurrentIndex+2) {
iEntries.removeLast();
}
// 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;
iModel->beginInsertRows(QModelIndex(), i, i);
iEntries.append(Entry(aPos, aPage));
iModel->endInsertRows();
model->endRemoveRows();
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)
{
if (iEntries.last().iPos != aPos) {
if (!atEnd() || iEntries.last().iPos != aPos) {
push(aPos, findPage(aPos));
}
}
void BooksPageStack::Private::push(int aPage)
{
if (iEntries.last().iPage != aPage) {
if (!atEnd() || iEntries.last().iPage != aPage) {
push(getPosAt(aPage), aPage);
}
}
@ -452,10 +469,11 @@ void BooksPageStack::Private::pop()
{
const int n = iEntries.count();
if (n > 1) {
iModel->beginRemoveRows(QModelIndex(), n-1, n-1);
BooksPageStack* model = parentModel();
model->beginRemoveRows(QModelIndex(), n-1, n-1);
iEntries.removeLast();
validateCurrentIndex();
iModel->endRemoveRows();
model->endRemoveRows();
queueSignals(SignalCountChanged);
}
}
@ -464,13 +482,14 @@ void BooksPageStack::Private::clear()
{
const int n = iEntries.count();
if (n > 1) {
BooksPageStack* model = parentModel();
Entry currentEntry = iEntries.at(iCurrentIndex);
iModel->beginRemoveRows(QModelIndex(), 1, n-1);
model->beginRemoveRows(QModelIndex(), 1, n-1);
while (iEntries.count() > 1) {
iEntries.removeLast();
}
validateCurrentIndex();
iModel->endRemoveRows();
model->endRemoveRows();
if (iEntries.at(0) != currentEntry) {
iEntries[0] = currentEntry;
pageChanged(0);