Skip to content

Commit

Permalink
Interruptiong necessary page update if new request for updating all p…
Browse files Browse the repository at this point in the history
…age buffers comes in
  • Loading branch information
AlexD97 committed May 1, 2018
1 parent 65cc586 commit bcf1282
Show file tree
Hide file tree
Showing 2 changed files with 109 additions and 34 deletions.
113 changes: 81 additions & 32 deletions widget.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,12 @@ Widget::Widget(QWidget *parent)

void Widget::updateAllPageBuffers()
{
if(updateThread->isRunning()){
qDebug() << "isRunning";
updateThread->requestInterruption();
}
if(prevZoom != zoom || pageBufferPtr.size() != currentDocument.pages.size() || pageBufferPtr.isEmpty()){
QMutexLocker locker1(&overallBufferMutex);

QVector<QFuture<void>> future;
pageBufferPtr.clear();
Expand All @@ -120,7 +125,6 @@ void Widget::updateAllPageBuffers()
pageBufferPtr.append(std::make_shared<std::shared_ptr<QPixmap>>(std::make_shared<QPixmap>()));
}

int currentPageNum = getCurrentPage();
QSet<int> allPages;
for(int i = 0; i < currentDocument.pages.size(); ++i){
allPages.insert(i);
Expand All @@ -141,8 +145,14 @@ void Widget::updateAllPageBuffers()
prevZoom = zoom;
}
else{
QtConcurrent::run(this, &Widget::updateNecessaryPagesBuffer);
UpdateWorker* worker = new UpdateWorker(this);
worker->moveToThread(updateThread);
connect(worker, &UpdateWorker::finished, updateThread, &QThread::quit);
connect(updateThread, &QThread::started, worker, &UpdateWorker::process);
updateThread->start();
//QtConcurrent::run(this, &Widget::updateNecessaryPagesBuffer);
}
//scrollingBecauseOfZooming = false;
}

void Widget::updateNecessaryPagesBuffer(){
Expand All @@ -160,12 +170,25 @@ void Widget::updateNecessaryPagesBuffer(){
// future[buffNum].waitForFinished();
// }

// if(scrollingBecauseOfZooming){
// scrollingBecauseOfZooming = false;
// return;
// }
QMutexLocker locker1(&overallBufferMutex);
QVector<QFuture<void>> future;

int startingPage = std::max(0, getCurrentPage()-6);
int endPage = std::min(currentDocument.pages.size(), getCurrentPage()+6);

for(int buffNum = startingPage; buffNum < endPage; ++buffNum){
if(QThread::currentThread()->isInterruptionRequested()){
qDebug() << "interrupt requested";
for(int i = 0; i < future.size(); ++i){
future[i].waitForFinished();
}
locker1.unlock();
return;
}
const MrDoc::Page& buffPage = currentDocument.pages[buffNum];
int pageWidth = zoom * buffPage.width() * devicePixelRatio();
int pageHight = zoom * buffPage.height() * devicePixelRatio();
Expand Down Expand Up @@ -479,27 +502,43 @@ QRect Widget::getWidgetGeometry()
if(currentView == view::VERTICAL){
int width = 0;
int height = 0;
for (int i = 0; i < pageBufferPtr.size(); ++i)
{
height += (*pageBufferPtr[i])->height()/devicePixelRatio() + PAGE_GAP;
if ((*pageBufferPtr[i])->width()/devicePixelRatio() > width)
width = (*pageBufferPtr[i])->width()/devicePixelRatio();
// for (int i = 0; i < pageBufferPtr.size(); ++i)
// {
// height += (*pageBufferPtr[i])->height()/devicePixelRatio() + PAGE_GAP;
// if ((*pageBufferPtr[i])->width()/devicePixelRatio() > width)
// width = (*pageBufferPtr[i])->width()/devicePixelRatio();
// }
// height -= PAGE_GAP;
// return QRect(0, 0, width, height);

for (int i = 0; i < currentDocument.pages.size(); ++i){
height += currentDocument.pages[i].height()*zoom + PAGE_GAP;
if (currentDocument.pages[i].width()*zoom > width)
width = currentDocument.pages[i].width()*zoom;
}
height -= PAGE_GAP;
return QRect(0, 0, width, height);
return QRect(0,0,width,height);
}
else{ //view::HORIZONTAL
int width = 0;
int height = 0;

for (int i = 0; i < pageBufferPtr.size(); ++i)
{
width += (*(pageBufferPtr[i]))->width()/devicePixelRatio() + PAGE_GAP;
if ((*(pageBufferPtr[i]))->height()/devicePixelRatio() > height)
height = (*pageBufferPtr[i])->height()/devicePixelRatio();
// for (int i = 0; i < pageBufferPtr.size(); ++i)
// {
// width += (*(pageBufferPtr[i]))->width()/devicePixelRatio() + PAGE_GAP;
// if ((*(pageBufferPtr[i]))->height()/devicePixelRatio() > height)
// height = (*pageBufferPtr[i])->height()/devicePixelRatio();
// }
// width -= PAGE_GAP;
// return QRect(0, 0, width, height);

for (int i = 0; i < currentDocument.pages.size(); ++i){
width += currentDocument.pages[i].width()*zoom + PAGE_GAP;
if(currentDocument.pages[i].height()*zoom > height)
height = currentDocument.pages[i].height()*zoom;
}
width -= PAGE_GAP;
return QRect(0, 0, width, height);
return QRect(0,0,width,height);
}
}

Expand Down Expand Up @@ -1859,21 +1898,25 @@ int Widget::getCurrentPage()
QSet<int> Widget::getVisiblePages(){
QSet<int> visiblePages;
if(currentView == view::VERTICAL){
QPoint globalMousePosTop = parentWidget()->mapToGlobal(QPoint(parentWidget()->size().width()/2, 0));
QPoint posTop = this->mapFromGlobal(globalMousePosTop);
QPoint globalMousePosBottom = parentWidget()->mapToGlobal(QPoint(parentWidget()->size().width()/2, parentWidget()->size().height()));
QPoint globalMousePosTop = parentWidget()->mapToGlobal(QPoint(0,0)) + QPoint(parentWidget()->size().width()/2, parentWidget()->size().height()/2);
QPoint posTop = this->mapFromGlobal(QPoint(globalMousePosTop));
posTop -= QPoint(0,parentWidget()->size().height()/2);
QPoint globalMousePosBottom = parentWidget()->mapToGlobal(QPoint(0,0)) + QPoint(parentWidget()->size().width()/2, parentWidget()->size().height()/2);
QPoint posBottom = this->mapFromGlobal(globalMousePosBottom);
posBottom += QPoint(0,parentWidget()->size().height()/2);
int beginPage = getPageFromMousePos(posTop);
int endPage = getPageFromMousePos(posBottom);
for(int i = beginPage; i <= endPage; ++i){
visiblePages.insert(i);
}
}
else{
QPoint globalMousePosLeft = parentWidget()->mapToGlobal(QPoint(0, parentWidget()->size().height()/2));
QPoint globalMousePosLeft = parentWidget()->mapToGlobal(QPoint(0, 0)) + QPoint(parentWidget()->size().width()/2, parentWidget()->size().height()/2);
QPoint posLeft = this->mapFromGlobal(globalMousePosLeft);
QPoint globalMousePosRight = parentWidget()->mapToGlobal(QPoint(parentWidget()->size().width(), parentWidget()->size().height()/2));
posLeft -= QPoint(parentWidget()->size().width()/2,0);
QPoint globalMousePosRight = parentWidget()->mapToGlobal(QPoint(0,0)) + QPoint(parentWidget()->size().width()/2, parentWidget()->size().height()/2);
QPoint posRight = this->mapFromGlobal(globalMousePosRight);
posRight += QPoint(parentWidget()->size().width()/2,0);
int beginPage = getPageFromMousePos(posLeft);
int endPage = getPageFromMousePos(posRight);
for(int i = beginPage; i <= endPage; ++i){
Expand Down Expand Up @@ -1994,9 +2037,10 @@ void Widget::zoomTo(qreal newZoom)
int prevH = scrollArea->horizontalScrollBar()->value();
int prevV = scrollArea->verticalScrollBar()->value();

updateAllPageBuffers();
currentSelection.updateBuffer(zoom);
setGeometry(getWidgetGeometry());
//updateAllPageBuffers();
currentSelection.updateBuffer(zoom);
//setGeometry(getWidgetGeometry());

int newHMax = scrollArea->horizontalScrollBar()->maximum();
int newVMax = scrollArea->verticalScrollBar()->maximum();
Expand Down Expand Up @@ -2029,6 +2073,8 @@ void Widget::zoomTo(qreal newZoom)
scrollArea->horizontalScrollBar()->setValue(newH);
scrollArea->verticalScrollBar()->setValue(newV);

updateAllPageBuffers();

//scrollArea->verticalScrollBar()->setTracking(false);
connect(scrollArea->verticalScrollBar(), &QScrollBar::valueChanged, this, &Widget::updatePageAfterScrolling, Qt::UniqueConnection);
connect(scrollArea->horizontalScrollBar(), &QScrollBar::valueChanged, this, &Widget::updatePageAfterScrolling, Qt::UniqueConnection);
Expand Down Expand Up @@ -2177,29 +2223,23 @@ void Widget::scrollDocumentToPageNum(int pageNum)

// qreal x = currentCOSPos.x();

//I don't know why these calculations are better than simply taking the ratio of pageNum / pages.size() * scrollBar()->maximum()
if(currentView == view::VERTICAL){
qreal y = 0.0;
for (int i = 0; i < pageNum; ++i)
{
y += (currentDocument.pages[i].height()) * zoom + PAGE_GAP;
}
y -= 2*PAGE_GAP;
y -= PAGE_GAP;

y += static_cast<qreal>(pageNum) / static_cast<qreal>(currentDocument.pages.size()) * scrollArea->verticalScrollBar()->maximum();
y /= 2;
scrollArea->verticalScrollBar()->setValue(y);
}
else{
qreal x = 0.0;
for(int i = 0; i < pageNum; ++i){
x += (currentDocument.pages[i].width() * zoom + PAGE_GAP);
}
x += 2*PAGE_GAP;
x *= 3;
x -= PAGE_GAP;

x += static_cast<qreal>(pageNum) / static_cast<qreal>(currentDocument.pages.size()) * scrollArea->horizontalScrollBar()->maximum();
x /= 4;
scrollArea->horizontalScrollBar()->setValue(x);
}

Expand Down Expand Up @@ -2374,13 +2414,14 @@ Widget::state Widget::getCurrentState()
}

void Widget::setCurrentView(view newView){
int currentPage = getCurrentPage();
currentView = newView;
//prevZoom = -2;
//updateAllPageBuffers();

qreal oldZoom = zoom;
zoom = 0.0;
zoomTo(oldZoom);
//update();
scrollDocumentToPageNum(currentPage);

}

Widget::view Widget::getCurrentView(){
Expand Down Expand Up @@ -2582,3 +2623,11 @@ void Widget::pageHistoryBackward(){
scrollDocumentToPageNum(pageHistory.at(pageHistoryPosition));
}
}

UpdateWorker::UpdateWorker(Widget* widget)
: widgetPtr{widget} {}

void UpdateWorker::process(){
widgetPtr->updateNecessaryPagesBuffer();
emit finished();
}
30 changes: 28 additions & 2 deletions widget.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
#include <QSizeGrip>
#include <QGridLayout>
#include <QSet>
#include <QThread>
#include <QtConcurrent>
#include <QMutex>
#include <QMutexLocker>
Expand Down Expand Up @@ -41,6 +42,8 @@ struct BasicPageSize;
struct BasicPageSizeHash;
struct BasicPageSizeEqual;

class UpdateWorker;

class Widget : public QWidget
// class Widget : public QOpenGLWidget
{
Expand Down Expand Up @@ -136,7 +139,7 @@ class Widget : public QWidget
int getCurrentPage();
/**
* @brief getVisiblePages
* @return the number of visible pages
* @return the indices of the visible pages
*/
QSet<int> getVisiblePages();

Expand Down Expand Up @@ -179,7 +182,8 @@ class Widget : public QWidget
MrDoc::Document currentDocument;

QVector<std::shared_ptr<std::shared_ptr<QPixmap>>> pageBufferPtr; /**< buffer for page pixmaps */
QMutex pageBufferPtrMutex; /**< Mutex for @ref pageBufferPtr */
QMutex pageBufferPtrMutex; /**< Mutex for @ref pageBufferPtr It locks only single buffer operations like replace, but not clear.*/
QMutex overallBufferMutex; /**< Mutex for @ref pageBufferPtr. */

QColor currentColor;
qreal currentPenWidth;
Expand Down Expand Up @@ -219,12 +223,15 @@ class Widget : public QWidget
};
std::unordered_map<BasicPageSize, std::shared_ptr<std::shared_ptr<QPixmap>>, BasicPageSizeHash, BasicPageSizeEqual> basePixmapMap; /**< Stores the pointers to the blank placeholders for certain page sizes */
QMutex basePixmapMutex;

int previousVerticalValueRendered = 0; /**< Stores the vertical slider value where the last call of updateAllPageBuffers happened */
int previousVerticalValueMaybeRendered = 0; /**< Stores the vertical slider value where the last @ref scrollTimer start happened */
int previousHorizontalValueRendered = 0;
int previousHorizontalValueMaybeRendered = 0;
QTimer* scrollTimer;

QThread* updateThread = new QThread();

QTime timer;

QTimer *updateTimer;
Expand Down Expand Up @@ -401,4 +408,23 @@ public slots:
void pageHistoryBackward();
};

/**
* @brief The UpdateWorker class calls updateNecessaryPages. It is necessary to work with QThread instead of QtConcurrent.
*/
class UpdateWorker : public QObject {
Q_OBJECT

public:
UpdateWorker(Widget* widget);

public slots:
void process();

signals:
void finished();

private:
Widget* widgetPtr;
};

#endif // WIDGET_H

0 comments on commit bcf1282

Please sign in to comment.