Fixes. About dialog. Books properly removed from library when file is deleted.
[mebook:mebook.git] / ui / bookview.cpp
1 #include "bookview.h"
2
3 #include <QDebug>
4 #include <QAction>
5 #include <QWebElement>
6 #include <QWebFrame>
7 #include <QMouseEvent>
8 #include <QWebSettings>
9 #include <QApplication>
10 #include <QDesktopWidget>
11 #include <QAbstractKineticScroller>
12 #include <QFontMetrics>
13 #include <QFontDatabase>
14 #include <math.h>
15 #include <QTime>
16 #include <QMenu>
17 #include <QMessageBox>
18 #include <QGraphicsProxyWidget>
19
20 #include "addbookmarkdialog.h"
21 #include "addannotationdialog.h"
22
23 #include "libosso.h"
24
25 //Q_DECLARE_METATYPE(RenderTile)
26
27 BookView::BookView(QWidget *parent) : QGraphicsView(parent), 
28         autoScrollStep(1), 
29         autoScrollBy(0), 
30         isTap(false), 
31         tapMove(0)
32 {
33     setMouseTracking(false); 
34
35     currentPosition.section.number = 0;
36     currentPosition.page = 0;
37     currentPosition.multiplier = 0.00;
38
39     scene = new QGraphicsScene(this);
40     setScene(scene);
41
42     pageWidgetCurrent = NULL;
43     pageWidgetNext = NULL;
44     scrollablePage = NULL;
45     
46
47     setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
48     setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
49     
50     renderer = new Renderer(this);
51
52     //int type = qRegisterMetaType<RenderTile>("RenderTile");
53
54     connect(renderer, SIGNAL(tileRendered(RenderTile*)), this, SLOT(addTile(RenderTile*)));
55     connect(this, SIGNAL(requestRender(QString, int)), renderer, SLOT(addToQueue(QString, int)));
56
57     renderer->setRenderSettings(&renderSettings);
58
59   
60     //Set PageMode as default.
61     setViewMode(PageMode, Qt::WA_Maemo5PortraitOrientation);
62
63     //Autoscroll every 200ms
64     autoScrollTimer.setInterval(200);
65     connect(&autoScrollTimer, SIGNAL(timeout()), this, SLOT(handleAutoScroll()));
66
67     setContextMenuPolicy(Qt::CustomContextMenu);
68     connect(this, SIGNAL(customContextMenuRequested(const QPoint&)), this, SLOT(openContextMenu(const QPoint&)));
69
70
71     
72 }
73
74 BookView::~BookView()
75 {
76     deleteTiles();
77 }
78
79 void BookView::setBook(Book *openBook)
80 {
81     if(openBook){
82         book = openBook;
83         
84
85         if(!book->isLoaded())
86             book->load();
87
88         renderer->setAnnotations(book->getAnnotations());
89         renderer->setResourceManager(book->getResourceManager());
90
91         progressSlider->setRange(0, book->getBookLength());
92
93         if(book->getProgress().isValid()){
94             currentPosition.multiplier = book->getProgress().getPercentage();
95             currentPosition.section.number = book->getProgress().getSection();
96         }else{ 
97             currentPosition.multiplier = 0;
98             currentPosition.section.number = 0;
99         }  
100
101         goToSection(currentPosition.section.number, currentPosition.multiplier);
102
103     }
104 }
105
106 void BookView::deleteTiles()
107 {
108     for(QHash< int, QHash<int, RenderTile*> >::iterator iter = tiles.begin(); iter != tiles.end(); ++iter)
109     {
110         qDeleteAll(*iter);
111         (*iter).clear();
112     }
113
114     tiles.clear();
115 }
116
117 void BookView::goToSection(int section, float multiplier)
118
119     history.push_back(currentPosition);
120     if(viewMode == PageMode){
121         if(tiles.contains(section)){
122             currentPosition.section.number = section;
123             currentPosition.multiplier = multiplier;
124             currentPosition.page = ((float)currentPosition.section.numPages) * ((float)currentPosition.multiplier);
125             pageWidgetCurrent->setPixmap(getCurrentPagePixmap());
126         }else{
127             QString content = book->getSection(section);
128             currentPosition.section.number = section;
129             currentPosition.multiplier = multiplier;
130             currentPosition.page = -1;
131             pageWidgetCurrent->setPixmap(loadingPixmap());
132             deleteTiles();
133             if(multiplier == 0)
134                 progressSlider->setValue(book->getSectionStart(currentPosition.section.number));
135             emit requestRender(content, currentPosition.section.number);
136         }
137     }else{
138         QString content = book->getSection(section);
139         currentPosition.section.number = section;
140         currentPosition.multiplier = multiplier;
141         emit requestRender(content, currentPosition.section.number);
142     }
143 }
144
145 void BookView::goToTOCIndex(int index)
146 {
147     goToSection(book->getSectionNumberOfTOCIndex(index), 0);
148 }
149
150 void BookView::goToBookmark(int id)
151 {
152     QList<Bookmark> bookmarks = book->getBookmarks();
153     if(id < bookmarks.count() && id >= 0){
154         Bookmark bm = bookmarks.at(id);
155         goToSection(bm.getSection(), bm.getMultiplier());
156     }else{
157         qDebug() << "Can't find bookmark!";
158     }
159 }
160
161 void BookView::goToAnnotation(int id)
162 {
163     QList<Annotation> annotations = book->getAnnotations();
164     if(id < annotations.count() && id >= 0){
165         Annotation annotation = annotations[id];
166         goToSection(annotation.getSection(), annotation.getPercentage());
167
168     }
169 }
170
171 void BookView::backInHistory()
172 {
173     PositionInBook last = history.last();
174     goToSection(last.section.number, last.multiplier);
175     history.removeLast();
176 }
177
178 void BookView::nextSection()
179 {
180     if(currentPosition.section.number < (book->getNumberOfSections() - 1)){
181         goToSection(currentPosition.section.number + 1, 0);
182     } else{
183         goToSection(0, 0);
184     }
185 }
186
187 void BookView::previousSection()
188 {
189     if(currentPosition.section.number > 0){
190         goToSection(currentPosition.section.number - 1, 0);
191     }
192 }
193
194 void BookView::setFont(const QString &family, int size)
195 {
196     renderSettings.setFont(QFont(family, size));    
197 }
198
199 void BookView::setNightMode(bool toggle)
200 {
201     if(toggle){
202         renderSettings.setTextColor(QColor(Qt::white));
203         renderSettings.setBackgroundColor(QColor(Qt::black));
204         scene->setBackgroundBrush(QBrush(Qt::black));
205     }
206     else{
207         renderSettings.setTextColor(QColor(Qt::black));
208         renderSettings.setBackgroundColor(QColor(Qt::lightGray));
209         scene->setBackgroundBrush(QBrush(Qt::lightGray));
210     }
211     
212 }
213
214 void BookView::setViewMode(BookViewMode mode, Qt::WidgetAttribute orientation)
215 {
216
217     viewMode = mode;    
218
219     int pageWidth = 0;
220     int pageHeight = 0;
221     int screenWidth = 0;
222     int screenHeight = 0;
223     if(orientation == Qt::WA_Maemo5PortraitOrientation){
224         pageWidth = 480;
225         pageHeight = 730;
226
227         screenWidth = 480;
228         screenHeight = 800;
229     }
230     else{
231         pageWidth = 800;
232         pageHeight = 410;
233
234         screenWidth = 800;
235         screenHeight = 480;
236     }
237
238     const int topMargin = 20;
239
240     if(viewMode == PageMode){
241
242         scene->clear();
243
244         pageWidgetCurrent = new QGraphicsPixmapItem();
245         pageWidgetNext = new QGraphicsPixmapItem();
246
247         scene->addItem(pageWidgetCurrent);
248         scene->addItem(pageWidgetNext);
249         connect(renderer, SIGNAL(contentHeight(int)), this, SLOT(contentHeight(int)));
250         connect(renderer, SIGNAL(numberOfPages(int)), this, SLOT(numberOfPages(int)));
251         scene->setSceneRect(QRectF(0, 0, screenWidth, screenHeight));
252
253         deleteTiles();
254
255         pageWidgetCurrent->setPos(0, 0);
256         pageWidgetNext->setPos(pageWidth, 0);
257
258         pageWidgetCurrent->setOffset(0, topMargin);
259         pageWidgetNext->setOffset(0, topMargin);
260
261         pageWidgetCurrent->setPixmap(loadingPixmap());
262
263         renderer->enablePagination(true);
264         renderer->enablePixmapRendering(true);
265
266         
267
268     } else{
269         scene->clear();
270
271         scrollablePage = new ScrollablePage();
272         scene->addItem(scrollablePage);
273         connect(renderer, SIGNAL(webPageLoaded(QWebPage*)), this, SLOT(webPageLoaded(QWebPage*)));
274         connect(scrollablePage, SIGNAL(positionChanged(int)), this, SLOT(sectionScrolled(int)));
275         scrollablePage->setGeometry(0, 0, pageWidth, pageHeight);
276         scene->setSceneRect(0, 0, screenWidth, screenHeight);
277         renderer->enablePagination(false);
278         renderer->enablePixmapRendering(false);
279
280     }
281
282     const int sliderHeight = 32;
283     const int leftMargin = 5;
284
285     progressSlider = new BookProgressSlider();
286     progressSlider->setMinimumWidth(pageWidth - 10);
287     progressSlider->setMaximum(100);
288     progressSlider->setColors(renderSettings.getTextColor(), renderSettings.getBackgroundColor());
289
290     connect(progressSlider, SIGNAL(sliderReleased()), this, SLOT(sliderMoved()));
291     sliderProxy = scene->addWidget(progressSlider);
292     sliderProxy->setPos(leftMargin, screenHeight - (sliderHeight + leftMargin));
293
294     pageSize = QSizeF(pageWidth, pageHeight); 
295     renderer->setPageSize(pageSize);
296     renderSettings.setMaxImageSize(pageWidth-(2*leftMargin), pageHeight-(2*topMargin));
297
298 }
299
300 void BookView::addBookmark(QString name, QColor color)
301 {
302     //TODO:Fix pagemode multiplier..
303     float multiplier = currentPosition.multiplier;
304     if(viewMode == PageMode) 
305         multiplier = ((float)currentPosition.page / ((float)currentPosition.section.numPages));
306     Bookmark bookmark(name, color, currentPosition.section.number, multiplier);
307     book->addBookmark(bookmark);
308 }
309
310 void BookView::mousePressEvent(QMouseEvent *event)
311 {
312     if(viewMode == PageMode && event->pos().y() < sliderProxy->pos().y())
313         swipeStart = event->pos();    
314
315     isTap = true;
316     tapMove = 0;
317
318     QGraphicsView::mousePressEvent(event);  
319 }
320
321 void BookView::mouseMoveEvent(QMouseEvent *event)
322 {
323    if(viewMode == PageMode){
324        if(!swipeStart.isNull() && event->pos().x() > 0){
325             float moveX = event->pos().x() - swipeStart.x();
326             swipeStart = event->pos();
327             pageWidgetCurrent->moveBy(moveX, 0);
328
329             //If moved enough user is not tapping
330             tapMove += moveX;
331             if((tapMove > 10 || tapMove < -10) && isTap){
332                 isTap = false;
333                 tapMove = 0;
334             }
335
336             int pageWidth = pageWidgetNext->boundingRect().width();
337             //Calculate new position of pageWidgetNext.
338             //It is either on the left or right side of pageWidgetCurrent
339             float nextX = (pageWidgetCurrent->pos().x() >= 0) ? pageWidgetCurrent->pos().x() - pageWidth : pageWidgetCurrent->pos().x() + pageWidth;
340             pageWidgetNext->setPos(nextX, pageWidgetNext->pos().y());
341
342             if(nextX > 0){
343                 pageWidgetNext->setPixmap(getNextPagePixmap());
344             }else{
345                 pageWidgetNext->setPixmap(getPreviousPagePixmap());
346             }
347        }
348    }
349     QGraphicsView::mouseMoveEvent(event);  
350 }
351
352 void BookView::mouseReleaseEvent(QMouseEvent *event)
353 {
354     if(viewMode == PageMode){
355         int pageWidth = pageSize.width();
356         if(pageWidgetCurrent->x() < -(pageWidth/2)){
357             pageWidgetCurrent->setPos(-pageWidth, pageWidgetCurrent->pos().y());
358             pageWidgetNext->setPos(0, pageWidgetNext->pos().y());
359             //Switch pointers of current and next page widget
360             QGraphicsPixmapItem *temp = pageWidgetCurrent;
361             pageWidgetCurrent = pageWidgetNext;
362             pageWidgetNext = temp;
363             //Handle changing page logic.
364             nextPage();
365             pageWidgetCurrent->setPixmap(getCurrentPagePixmap());
366         }else if(pageWidgetCurrent->x() > (pageWidth/2) && (currentPosition.section.number != 0 || currentPosition.page != 0)){
367             pageWidgetCurrent->setPos(pageWidth, pageWidgetCurrent->pos().y());
368             pageWidgetNext->setPos(0, pageWidgetNext->pos().y());
369             //Switch pointers of current and next page widget
370             QGraphicsPixmapItem *temp = pageWidgetCurrent;
371             pageWidgetCurrent = pageWidgetNext;
372             pageWidgetNext = temp;
373             //Handle changing page logic.
374             previousPage(); 
375             pageWidgetCurrent->setPixmap(getCurrentPagePixmap());
376             
377         }else{
378             //If user didn't drag far enought snap current page back to position.
379             pageWidgetCurrent->setPos(0, pageWidgetCurrent->pos().y());
380             pageWidgetNext->setPos(pageWidth, pageWidgetNext->pos().y());
381         }
382         swipeStart = QPoint();
383     }
384
385
386     //Test if the user tapped a annotation
387     if(isTap){
388         QString annotationHit;
389         bool hit = false;
390         if(viewMode == PageMode){
391             hit = renderer->hitAnnotation(event->pos() - QPoint(0, 20), annotationHit, tiles[currentPosition.section.number][currentPosition.page]);
392         } else{
393             QPoint t = QPoint(event->pos().x(), scrollablePage->getPosition() + event->pos().y());
394             hit = renderer->hitAnnotation(t, annotationHit);
395         }
396
397         if(hit){
398             Annotation *a = book->getAnnotation(annotationHit);
399             if(a){
400                 QMessageBox annotationBox(this);
401                 annotationBox.setText(a->getAnnotation());
402                 annotationBox.setWindowTitle(tr("Annotation"));
403                 annotationBox.setStandardButtons(QMessageBox::Close);
404                 annotationBox.exec();
405             }
406         }
407     }
408
409
410     QGraphicsView::mouseReleaseEvent(event);
411 }
412
413 void BookView::resizeEvent(QResizeEvent *event)
414 {
415     //Make sure pageWidget stays fully visible when returning to application from app switcher
416 /*    QPointF viewPos = mapToScene(pos());
417     if(viewPos != QPointF(0, 0)){
418         QPointF move = QPointF(0, 0) - viewPos;
419         translate(viewPos.x(), viewPos.y());
420     }
421     ensureVisible(QRectF(0, 0, pageSize.width(), pageSize.height()));*/
422     QGraphicsView::resizeEvent(event);
423 }
424
425
426 QPixmap BookView::loadingPixmap()
427 {
428     //TODO: Replace with a more useful loading picture.
429 /*    QPixmap tile(20, 20);
430     QPainter painter;
431     painter.begin(&tile);
432     painter.setPen(Qt::NoPen);
433     painter.setBrush(Qt::lightGray);
434     painter.drawRect(0, 0, 20, 20);
435     painter.setBrush(Qt::white);
436     painter.drawRect(0, 0, 10, 10);
437     painter.drawRect(10, 10, 10, 10);
438     painter.end();*/
439     QPixmap pixmap(pageSize.toSize());
440     pixmap.fill(renderSettings.getBackgroundColor());
441 /*    painter.begin(&pixmap);
442     painter.drawTiledPixmap(0, 0, pageSize.width(), pageSize.height(), tile);
443     painter.end();*/
444     return pixmap;
445 }
446
447 void BookView::nextPage()
448 {
449     if(tiles.keys().contains(currentPosition.section.number)){
450         QHash<int, RenderTile*> pages = tiles[currentPosition.section.number];
451         history.push_back(currentPosition);
452         if((currentPosition.page + 1) < currentPosition.section.numPages){
453             currentPosition.page++;
454             currentPosition.multiplier = (((float)currentPosition.page) / ((float)currentPosition.section.numPages));
455             int value = ((float)book->getSectionLength(currentPosition.section.number) * ((float)currentPosition.multiplier)) + book->getSectionStart(currentPosition.section.number);
456             progressSlider->setValue(value);
457         }else{
458             goToSection(currentPosition.section.number + 1, 0);
459         }
460     }
461
462
463 }
464
465 void BookView::previousPage()
466 {
467     if(tiles.keys().contains(currentPosition.section.number)){
468         QHash<int, RenderTile*> pages = tiles[currentPosition.section.number];
469         history.push_back(currentPosition);
470         if(0 < currentPosition.page){
471             currentPosition.page--;
472             currentPosition.multiplier = (((float)currentPosition.page) / ((float)currentPosition.section.numPages));
473             int value = ((float)book->getSectionLength(currentPosition.section.number) * ((float)currentPosition.multiplier)) + book->getSectionStart(currentPosition.section.number);
474
475             progressSlider->setValue(value);
476
477         }else{
478             goToSection(currentPosition.section.number - 1, 1.0);
479         }
480     }
481
482     if(currentPosition.section.number < 0)
483         currentPosition.section.number = 0;
484
485 }
486
487 QPixmap BookView::getCurrentPagePixmap()
488 {
489     if(tiles.contains(currentPosition.section.number)){
490         QHash<int, RenderTile*> pages = tiles[currentPosition.section.number];
491         if(pages.contains(currentPosition.page))
492             return QPixmap::fromImage(pages[currentPosition.page]->getPixmap());
493     }    
494     
495     return loadingPixmap();
496 }
497
498 QPixmap BookView::getNextPagePixmap()
499 {
500     if(tiles.keys().contains(currentPosition.section.number)){
501         QHash<int, RenderTile*> pages = tiles[currentPosition.section.number];
502         if(pages.contains(currentPosition.page+1)){
503             return QPixmap::fromImage(pages[currentPosition.page+1]->getPixmap());
504         }else if(tiles.keys().contains(currentPosition.section.number+1)){
505             pages = tiles[currentPosition.section.number+1];
506             return QPixmap::fromImage(pages[0]->getPixmap());
507         }
508     }
509     return loadingPixmap();
510 }
511
512 QPixmap BookView::getPreviousPagePixmap()
513 {
514     if(tiles.keys().contains(currentPosition.section.number)){
515         QHash<int, RenderTile*> pages = tiles[currentPosition.section.number];
516         if(pages.contains(currentPosition.page-1)){
517             return QPixmap::fromImage(pages[currentPosition.page-1]->getPixmap());
518         }
519     }
520     return loadingPixmap();
521 }
522
523 void BookView::volumeUpPressed(){
524    if(viewMode == PageMode){
525         nextPage();
526         pageWidgetCurrent->setPixmap(getCurrentPagePixmap());
527    }else{
528         autoScrollBy += autoScrollStep; 
529         autoScrollTimer.start();
530    }
531 }
532
533 void BookView::volumeDownPressed()
534 {
535    if(viewMode == PageMode){
536         previousPage();
537         pageWidgetCurrent->setPixmap(getCurrentPagePixmap());
538    }else{
539         autoScrollBy -= autoScrollStep; 
540         autoScrollTimer.start();
541    }
542 }
543
544
545 void BookView::saveProgress()
546 {
547     if(viewMode == PageMode){
548         int section = currentPosition.section.number;
549         float multiplier = ((float)currentPosition.page / ((float)currentPosition.section.numPages));
550
551         BookProgress progress;
552         progress.setProgress(section, multiplier);
553         book->setProgress(progress);
554     }else{
555         int scrollPosition = scrollablePage->getPosition();
556         int section = currentPosition.section.number; 
557         float multiplier = ((float)scrollPosition / (float)currentPosition.section.contentHeight);
558
559         BookProgress progress;
560         progress.setProgress(section, multiplier);
561         book->setProgress(progress);
562     }
563
564 }
565
566 void BookView::addTile(RenderTile *tile)
567 {
568     if(tiles.keys().contains(tile->getSection()))
569         tiles[tile->getSection()].insert(tile->getID(), tile);
570     else{
571         QHash<int, RenderTile*> pages;
572         pages.insert(tile->getID(), tile);
573         tiles.insert(tile->getSection(), pages);
574     }
575
576     if(tile->getID() == currentPosition.page && tile->getSection() == currentPosition.section.number){
577         pageWidgetCurrent->setPixmap(QPixmap::fromImage(tile->getPixmap()));
578     }
579     
580     //Set first page as cover if no cover image found.
581     if(tile->getSection() == 0 && tile->getID() == 0 && book->getCoverImage().isNull()){
582         book->addCoverImage(QPixmap::fromImage(tile->getPixmap()));
583     }
584 }
585
586 void BookView::contentHeight(int height)
587 {
588     if(viewMode == PageMode){
589         if(currentPosition.page == -1){
590             currentPosition.page = ((float)height / pageSize.height()) * ((float)currentPosition.multiplier);
591             currentPosition.section.contentHeight = height;
592             currentPosition.section.numPages = (float)height / (float)pageSize.height();
593         }
594         
595     }else{
596         currentPosition.section.contentHeight = height;
597         int scrollPosition = (float)height * ((float)currentPosition.multiplier);
598         scrollablePage->setPosition(scrollPosition);
599     }
600         
601 }
602
603 void BookView::numberOfPages(int n)
604 {
605     currentPosition.section.numPages = n;
606     currentPosition.page = ((float)currentPosition.section.numPages) * ((float)currentPosition.multiplier);
607     if(currentPosition.page >= currentPosition.section.numPages)
608         currentPosition.page = currentPosition.section.numPages - 1;
609     pageWidgetCurrent->setPixmap(getCurrentPagePixmap());
610 }
611
612
613 void BookView::webPageLoaded(QWebPage *page){
614     scrollablePage->setPage(page);
615 }
616
617 void BookView::handleAutoScroll()
618 {
619     //Only scroll if MainWindow is active.
620     if(parentWidget()->isActiveWindow()){
621         if(autoScrollBy != 0)
622             scrollablePage->scrollBy(autoScrollBy);
623         else
624             autoScrollTimer.stop();
625     }
626 }
627
628 void BookView::openContextMenu(const QPoint &pos)
629 {
630     QMenu *menu = new QMenu();
631     menu->addAction(tr("Add bookmark"), this, SLOT(addBookmark()));
632     menu->addAction(tr("Add annotation"), this, SLOT(addAnnotation()));
633
634     QString temp;
635     if(viewMode == PageMode){
636         temp = renderer->getParagraphAt(pos - QPoint(0, 20), tiles[currentPosition.section.number][currentPosition.page]);
637     } else{
638         QPoint t = QPoint(pos.x(), scrollablePage->getPosition() + pos.y());
639         temp = renderer->getParagraphAt(t);
640     }
641
642     if(temp.isEmpty()) temp = "Couldn't get paragraph!";
643
644     annotationParagraph = temp;
645
646     menu->exec(mapToGlobal(pos));
647 }
648
649 void BookView::addBookmark()
650 {
651     AddBookmarkDialog dialog;
652     if(dialog.exec() == QDialog::Accepted){
653         addBookmark(dialog.getName(), dialog.getColor());        
654     }
655 }
656
657 void BookView::addAnnotation()
658 {
659     AddAnnotationDialog dialog;
660     dialog.setParagraph(annotationParagraph);
661     if(dialog.exec() == QDialog::Accepted){
662         float multiplier = currentPosition.multiplier;
663         if(viewMode == PageMode) 
664             multiplier = ((float)currentPosition.page / ((float)currentPosition.section.numPages));
665         Annotation annotation(currentPosition.section.number, multiplier, annotationParagraph, dialog.getSelectedText(), dialog.getAnnotation(), dialog.getColor());
666
667         book->addAnnotation(annotation);
668         renderer->setAnnotations(book->getAnnotations());
669         if(viewMode == PageMode){
670             renderer->renderTile(tiles[currentPosition.section.number][currentPosition.page]);
671             pageWidgetCurrent->setPixmap(getCurrentPagePixmap());
672         }
673     }
674 }
675
676 void BookView::sectionScrolled(int pos)
677 {
678     currentPosition.multiplier = ((float)pos / (float)currentPosition.section.contentHeight);
679     int value = ((float)book->getSectionLength(currentPosition.section.number) * ((float)currentPosition.multiplier)) + book->getSectionStart(currentPosition.section.number);
680     progressSlider->setValue(value);
681 }
682
683 void BookView::sliderMoved()
684 {
685     int sliderPosition = progressSlider->sliderPosition();
686     int section = book->getSectionAtPosition(sliderPosition);
687
688     if(section != -1){
689         currentPosition.multiplier = (((float)sliderPosition - (float)book->getSectionStart(section)) / (float)book->getSectionLength(section));
690         goToSection(section, currentPosition.multiplier);
691     }
692
693 }