1 #include "viewer.h"
2 #include "magnifying_glass.h"
3 #include "configuration.h"
4 #include "magnifying_glass.h"
5 #include "goto_flow.h"
6 #ifndef NO_OPENGL
7 #include "goto_flow_gl.h"
8 #else
9 #include <QtWidgets>
10 #endif
11 #include "bookmarks_dialog.h"
12 #include "render.h"
13 #include "goto_dialog.h"
14 #include "translator.h"
15 #include "onstart_flow_selection_dialog.h"
16 #include "page_label_widget.h"
17 #include "notifications_label_widget.h"
18 #include "comic_db.h"
19 #include "shortcuts_manager.h"
20 
21 #include "opengl_checker.h"
22 
23 #include <QFile>
24 
Viewer(QWidget * parent)25 Viewer::Viewer(QWidget *parent)
26     : QScrollArea(parent),
27       fullscreen(false),
28       information(false),
29       doublePage(false),
30       doubleMangaPage(false),
31       zoom(100),
32       currentPage(nullptr),
33       wheelStop(false),
34       direction(1),
35       drag(false),
36       numScrollSteps(22),
37       shouldOpenNext(false),
38       shouldOpenPrevious(false),
39       magnifyingGlassShowed(false),
40       restoreMagnifyingGlass(false)
41 {
42     translator = new YACReaderTranslator(this);
43     translator->hide();
44     translatorAnimation = new QPropertyAnimation(translator, "pos");
45     translatorAnimation->setDuration(150);
46     translatorXPos = -10000;
47     translator->move(-translator->width(), 10);
48     //current comic page
49     content = new QLabel(this);
50     configureContent(tr("Press 'O' to open comic."));
51     //scroll area configuration
52     setBackgroundRole(QPalette::Dark);
53     setWidget(content);
54     setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
55     setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
56     setFrameStyle(QFrame::NoFrame);
57     setAlignment(Qt::AlignCenter);
58 
59     QPalette palette;
60     palette.setColor(backgroundRole(), Configuration::getConfiguration().getBackgroundColor());
61     setPalette(palette);
62     //---------------------------------------
63     mglass = new MagnifyingGlass(Configuration::getConfiguration().getMagnifyingGlassSize(), this);
64     mglass->hide();
65     content->setMouseTracking(true);
66     setMouseTracking(true);
67 
68     showCursor();
69 
70     goToDialog = new GoToDialog(this);
71 
72     QSettings *settings = new QSettings(YACReader::getSettingsPath() + "/YACReader.ini", QSettings::IniFormat);
73 
74     //CONFIG GOTO_FLOW--------------------------------------------------------
75 #ifndef NO_OPENGL
76 
77     OpenGLChecker openGLChecker;
78     bool openGLAvailable = openGLChecker.hasCompatibleOpenGLVersion();
79 
80     if (openGLAvailable && !settings->contains(USE_OPEN_GL))
81         settings->setValue(USE_OPEN_GL, 2);
82     else if (!openGLAvailable)
83         settings->setValue(USE_OPEN_GL, 0);
84 
85     if ((settings->value(USE_OPEN_GL).toBool() == true))
86         goToFlow = new GoToFlowGL(this, Configuration::getConfiguration().getFlowType());
87     else
88         goToFlow = new GoToFlow(this, Configuration::getConfiguration().getFlowType());
89 #else
90     goToFlow = new GoToFlow(this, Configuration::getConfiguration().getFlowType());
91 #endif
92     goToFlow->setFocusPolicy(Qt::StrongFocus);
93     goToFlow->hide();
94     showGoToFlowAnimation = new QPropertyAnimation(goToFlow, "pos");
95     showGoToFlowAnimation->setDuration(150);
96 
97     bd = new BookmarksDialog(this->parentWidget());
98 
99     render = new Render();
100 
101     hideCursorTimer = new QTimer();
102     hideCursorTimer->setSingleShot(true);
103 
104     if (Configuration::getConfiguration().getDoublePage())
105         doublePageSwitch();
106 
107     if (Configuration::getConfiguration().getDoubleMangaPage())
108         doubleMangaPageSwitch();
109 
110     createConnections();
111 
112     hideCursorTimer->start(2500);
113 
114     setMouseTracking(true);
115 
116     //animations
117     verticalScroller = new QPropertyAnimation(verticalScrollBar(), "sliderPosition");
118     connect(verticalScroller, SIGNAL(valueChanged(const QVariant &)), this, SIGNAL(backgroundChanges()));
119     horizontalScroller = new QPropertyAnimation(horizontalScrollBar(), "sliderPosition");
120     connect(horizontalScroller, SIGNAL(valueChanged(const QVariant &)), this, SIGNAL(backgroundChanges()));
121     groupScroller = new QParallelAnimationGroup();
122     groupScroller->addAnimation(verticalScroller);
123     groupScroller->addAnimation(horizontalScroller);
124 
125     notificationsLabel = new NotificationsLabelWidget(this);
126     notificationsLabel->hide();
127 
128     informationLabel = new PageLabelWidget(this);
129 
130     setAcceptDrops(true);
131 }
132 
~Viewer()133 Viewer::~Viewer()
134 {
135     delete render;
136     delete goToFlow;
137     delete translator;
138     delete translatorAnimation;
139     delete content;
140     delete hideCursorTimer;
141     delete informationLabel;
142     delete verticalScroller;
143     delete horizontalScroller;
144     delete groupScroller;
145     delete bd;
146     delete notificationsLabel;
147     delete mglass;
148     if (currentPage != nullptr)
149         delete currentPage;
150 }
151 
createConnections()152 void Viewer::createConnections()
153 {
154     //magnifyingGlass (update mg after a background change
155     connect(this, SIGNAL(backgroundChanges()), mglass, SLOT(updateImage()));
156 
157     //goToDialog
158     connect(goToDialog, SIGNAL(goToPage(unsigned int)), this, SLOT(goTo(unsigned int)));
159 
160     //goToFlow goTo
161     connect(goToFlow, SIGNAL(goToPage(unsigned int)), this, SLOT(goTo(unsigned int)));
162 
163     //current time
164     auto t = new QTimer(this);
165     connect(t, SIGNAL(timeout()), this, SLOT(updateInformation()));
166     t->start(1000);
167 
168     //hide cursor
169     connect(hideCursorTimer, SIGNAL(timeout()), this, SLOT(hideCursor()));
170 
171     //bookmarks
172     connect(bd, SIGNAL(goToPage(unsigned int)), this, SLOT(goTo(unsigned int)));
173 
174     //render
175     connect(render, SIGNAL(errorOpening()), this, SLOT(resetContent()));
176     connect(render, SIGNAL(errorOpening()), this, SLOT(showMessageErrorOpening()));
177     connect(render, SIGNAL(errorOpening(QString)), this, SLOT(showMessageErrorOpening(QString)));
178     connect(render, SIGNAL(crcError(QString)), this, SLOT(processCRCError(QString)));
179     connect(render, SIGNAL(numPages(unsigned int)), goToFlow, SLOT(setNumSlides(unsigned int)));
180     connect(render, SIGNAL(numPages(unsigned int)), goToDialog, SLOT(setNumPages(unsigned int)));
181     //connect(render,SIGNAL(numPages(unsigned int)),this,SLOT(updateInformation()));
182     connect(render, SIGNAL(imageLoaded(int, QByteArray)), goToFlow, SLOT(setImageReady(int, QByteArray)));
183     connect(render, SIGNAL(currentPageReady()), this, SLOT(updatePage()));
184     connect(render, SIGNAL(processingPage()), this, SLOT(setLoadingMessage()));
185     connect(render, SIGNAL(currentPageIsBookmark(bool)), this, SIGNAL(pageIsBookmark(bool)));
186     connect(render, SIGNAL(pageChanged(int)), this, SLOT(updateInformation()));
187     //connect(render,SIGNAL(bookmarksLoaded(Bookmarks)),this,SLOT(setBookmarks(Bookmarks)));
188 
189     connect(render, SIGNAL(isLast()), this, SLOT(showIsLastMessage()));
190     connect(render, SIGNAL(isCover()), this, SLOT(showIsCoverMessage()));
191 
192     connect(render, SIGNAL(bookmarksUpdated()), this, SLOT(setBookmarks()));
193 }
194 
195 //Deprecated
prepareForOpening()196 void Viewer::prepareForOpening()
197 {
198     if (render->hasLoadedComic())
199         save();
200     //bd->setBookmarks(*bm);
201 
202     goToFlow->reset();
203 
204     //render->update();
205 
206     verticalScrollBar()->setSliderPosition(verticalScrollBar()->minimum());
207 
208     if (Configuration::getConfiguration().getShowInformation() && !information) {
209         QTimer::singleShot(0, this, &Viewer::informationSwitch);
210     }
211 
212     informationLabel->setText("...");
213 }
214 
open(QString pathFile,int atPage)215 void Viewer::open(QString pathFile, int atPage)
216 {
217     prepareForOpening();
218     render->load(pathFile, atPage);
219 }
220 
open(QString pathFile,const ComicDB & comic)221 void Viewer::open(QString pathFile, const ComicDB &comic)
222 {
223     prepareForOpening();
224     render->load(pathFile, comic);
225 }
226 
showMessageErrorOpening()227 void Viewer::showMessageErrorOpening()
228 {
229     QMessageBox::critical(this, tr("Not found"), tr("Comic not found"));
230     //resetContent(); --> not needed
231 }
232 
showMessageErrorOpening(QString message)233 void Viewer::showMessageErrorOpening(QString message)
234 {
235     QMessageBox::critical(this, tr("Error opening comic"), message);
236     resetContent();
237 }
238 
processCRCError(QString message)239 void Viewer::processCRCError(QString message)
240 {
241     QMessageBox::critical(this, tr("CRC Error"), message);
242 }
243 
next()244 void Viewer::next()
245 {
246     direction = 1;
247     if (doublePage && render->currentPageIsDoublePage()) {
248         render->nextDoublePage();
249     } else {
250         render->nextPage();
251     }
252     updateInformation();
253     shouldOpenPrevious = false;
254 }
255 
left()256 void Viewer::left()
257 {
258     if (doubleMangaPage) {
259         next();
260     } else {
261         prev();
262     }
263 }
264 
right()265 void Viewer::right()
266 {
267     if (doubleMangaPage) {
268         prev();
269     } else {
270         next();
271     }
272 }
273 
prev()274 void Viewer::prev()
275 {
276     direction = -1;
277     if (doublePage && render->previousPageIsDoublePage()) {
278         render->previousDoublePage();
279     } else {
280         render->previousPage();
281     }
282     updateInformation();
283     shouldOpenNext = false;
284 }
showGoToDialog()285 void Viewer::showGoToDialog()
286 {
287     goToDialog->open();
288 }
goTo(unsigned int page)289 void Viewer::goTo(unsigned int page)
290 {
291     direction = 1; //in "go to" direction is always fordward
292     render->goTo(page);
293 }
294 
updatePage()295 void Viewer::updatePage()
296 {
297     QPixmap *previousPage = currentPage;
298     if (doublePage) {
299         if (!doubleMangaPage)
300             currentPage = render->getCurrentDoublePage();
301         else {
302             currentPage = render->getCurrentDoubleMangaPage();
303         }
304         if (currentPage == nullptr) {
305             currentPage = render->getCurrentPage();
306         }
307     } else {
308         currentPage = render->getCurrentPage();
309     }
310     content->setPixmap(*currentPage);
311     updateContentSize();
312     updateVerticalScrollBar();
313 
314     if (goToFlow->isHidden())
315         setFocus(Qt::ShortcutFocusReason);
316     else
317         goToFlow->setFocus(Qt::OtherFocusReason);
318     delete previousPage;
319 
320     if (currentPage->isNull())
321         setPageUnavailableMessage();
322     else
323         emit(pageAvailable(true));
324 
325     emit backgroundChanges();
326 
327     if (restoreMagnifyingGlass) {
328         restoreMagnifyingGlass = false;
329         showMagnifyingGlass();
330     }
331 }
332 
updateContentSize()333 void Viewer::updateContentSize()
334 {
335     //there is an image to resize
336     if (currentPage != nullptr && !currentPage->isNull()) {
337         QSize pagefit = currentPage->size();
338         bool stretchImages = Configuration::getConfiguration().getEnlargeImages();
339         YACReader::FitMode fitmode = Configuration::getConfiguration().getFitMode();
340         switch (fitmode) {
341         case YACReader::FitMode::FullRes:
342             break;
343         case YACReader::FitMode::ToWidth:
344             if (!stretchImages && width() > pagefit.width()) {
345                 break;
346             }
347             pagefit.scale(width(), 0, Qt::KeepAspectRatioByExpanding);
348             break;
349         case YACReader::FitMode::ToHeight:
350             if (!stretchImages && height() > pagefit.height()) {
351                 break;
352             }
353             pagefit.scale(0, height(), Qt::KeepAspectRatioByExpanding);
354             break;
355             //if everything fails showing the full page is a good idea
356         case YACReader::FitMode::FullPage:
357         default:
358             pagefit.scale(size(), Qt::KeepAspectRatio);
359             break;
360         }
361 
362         if (zoom != 100) {
363             pagefit.scale(floor(pagefit.width() * zoom / 100.0f), 0, Qt::KeepAspectRatioByExpanding);
364         }
365         //apply scaling
366         content->resize(pagefit);
367 
368         //TODO: updtateContentSize should only scale the pixmap once
369         if (devicePixelRatio() > 1) //only in retina display
370         {
371             QPixmap page = currentPage->scaled(content->width() * devicePixelRatio(), content->height() * devicePixelRatio(), Qt::KeepAspectRatio, Qt::SmoothTransformation);
372             page.setDevicePixelRatio(devicePixelRatio());
373             content->setPixmap(page);
374         }
375 
376         emit backgroundChanges();
377     }
378     content->update(); //TODO, it shouldn't be neccesary
379 }
380 
increaseZoomFactor()381 void Viewer::increaseZoomFactor()
382 {
383     zoom = std::min(zoom + 10, 500);
384 
385     updateContentSize();
386     notificationsLabel->setText(QString::number(getZoomFactor()) + "%");
387     notificationsLabel->flash();
388 
389     emit zoomUpdated(zoom);
390 }
decreaseZoomFactor()391 void Viewer::decreaseZoomFactor()
392 {
393     zoom = std::max(zoom - 10, 30);
394 
395     updateContentSize();
396     notificationsLabel->setText(QString::number(getZoomFactor()) + "%");
397     notificationsLabel->flash();
398 
399     emit zoomUpdated(zoom);
400 }
401 
getZoomFactor()402 int Viewer::getZoomFactor()
403 {
404     //this function is a placeholder for future refactoring work
405     return zoom;
406 }
407 
setZoomFactor(int z)408 void Viewer::setZoomFactor(int z)
409 {
410     //this function is mostly used to reset the zoom after a fitmode switch
411     if (z > 500)
412         zoom = 500;
413     else if (z < 30)
414         zoom = 30;
415     else
416         zoom = z;
417 
418     emit zoomUpdated(zoom);
419 }
420 
updateVerticalScrollBar()421 void Viewer::updateVerticalScrollBar()
422 {
423     if (direction > 0)
424         verticalScrollBar()->setSliderPosition(verticalScrollBar()->minimum());
425     else
426         verticalScrollBar()->setSliderPosition(verticalScrollBar()->maximum());
427 }
428 
scrollDown()429 void Viewer::scrollDown()
430 {
431     if (verticalScrollBar()->sliderPosition() == verticalScrollBar()->maximum()) {
432         next();
433     } else {
434         int currentPos = verticalScrollBar()->sliderPosition();
435         verticalScroller->setDuration(250);
436         verticalScroller->setStartValue(currentPos);
437         verticalScroller->setEndValue(nextPos);
438 
439         verticalScroller->start();
440 
441         emit backgroundChanges();
442     }
443 }
444 
scrollUp()445 void Viewer::scrollUp()
446 {
447     if (verticalScrollBar()->sliderPosition() == verticalScrollBar()->minimum()) {
448         prev();
449     } else {
450         int currentPos = verticalScrollBar()->sliderPosition();
451         verticalScroller->setDuration(250);
452         verticalScroller->setStartValue(currentPos);
453         verticalScroller->setEndValue(nextPos);
454 
455         verticalScroller->start();
456 
457         emit backgroundChanges();
458     }
459 }
460 
scrollForwardHorizontalFirst()461 void Viewer::scrollForwardHorizontalFirst()
462 {
463     if (!doubleMangaPage) {
464         scrollZigzag(RIGHT, DOWN, true); // right->right->lower left->right->...->next page
465     } else {
466         scrollZigzag(LEFT, DOWN, true); // left->left->lower right->left->...->next page
467     }
468 }
469 
scrollBackwardHorizontalFirst()470 void Viewer::scrollBackwardHorizontalFirst()
471 {
472     if (!doubleMangaPage) {
473         scrollZigzag(LEFT, UP, false); // left->left->upper right->left->...->prev page
474     } else {
475         scrollZigzag(RIGHT, UP, false); // right->right->upper left->right->...->prev page
476     }
477 }
478 
scrollForwardVerticalFirst()479 void Viewer::scrollForwardVerticalFirst()
480 {
481     if (!doubleMangaPage) {
482         scrollZigzag(DOWN, RIGHT, true); // down->down->upper right->down->...->next page
483     } else {
484         scrollZigzag(DOWN, LEFT, true); // down->down->upper left->down->...->next page
485     }
486 }
487 
scrollBackwardVerticalFirst()488 void Viewer::scrollBackwardVerticalFirst()
489 {
490     if (!doubleMangaPage) {
491         scrollZigzag(UP, LEFT, false); // up->up->lower left->up->...->prev page
492     } else {
493         scrollZigzag(UP, RIGHT, false); // up->up->lower right->up->...->prev page
494     }
495 }
496 
isEdge(scrollDirection d)497 bool Viewer::isEdge(scrollDirection d)
498 {
499     if (d == UP)
500         return verticalScrollBar()->sliderPosition() == verticalScrollBar()->minimum();
501     else if (d == DOWN)
502         return verticalScrollBar()->sliderPosition() == verticalScrollBar()->maximum();
503     else if (d == LEFT)
504         return horizontalScrollBar()->sliderPosition() == horizontalScrollBar()->minimum();
505     else // d == RIGHT
506         return horizontalScrollBar()->sliderPosition() == horizontalScrollBar()->maximum();
507 }
508 
scrollZigzag(scrollDirection d1,scrollDirection d2,bool forward)509 void Viewer::scrollZigzag(scrollDirection d1, scrollDirection d2, bool forward)
510 {
511     if (!isEdge(d1)) {
512         if (d1 == UP)
513             scrollTo(horizontalScrollBar()->sliderPosition(),
514                      verticalScrollBar()->sliderPosition() - static_cast<int>((height() * 0.80)));
515         else if (d1 == DOWN)
516             scrollTo(horizontalScrollBar()->sliderPosition(),
517                      verticalScrollBar()->sliderPosition() + static_cast<int>((height() * 0.80)));
518         else if (d1 == LEFT)
519             scrollTo(horizontalScrollBar()->sliderPosition() - static_cast<int>((width() * 0.80)),
520                      verticalScrollBar()->sliderPosition());
521         else // d1 == RIGHT
522             scrollTo(horizontalScrollBar()->sliderPosition() + static_cast<int>((width() * 0.80)),
523                      verticalScrollBar()->sliderPosition());
524     } else if (!isEdge(d2)) {
525         int x = 0;
526         int y = 0;
527 
528         if (d1 == UP)
529             y = verticalScrollBar()->maximum();
530         else if (d1 == DOWN)
531             y = verticalScrollBar()->minimum();
532         else if (d1 == LEFT)
533             x = horizontalScrollBar()->maximum();
534         else // d1 == RIGHT
535             x = horizontalScrollBar()->minimum();
536 
537         if (d2 == UP)
538             y = std::max(verticalScrollBar()->sliderPosition() - static_cast<int>((height() * 0.80)), verticalScrollBar()->minimum());
539         else if (d2 == DOWN)
540             y = std::min(verticalScrollBar()->sliderPosition() + static_cast<int>((height() * 0.80)), verticalScrollBar()->maximum());
541         else if (d2 == LEFT)
542             x = std::max(horizontalScrollBar()->sliderPosition() - static_cast<int>((width() * 0.80)), horizontalScrollBar()->minimum());
543         else // d2 == RIGHT
544             x = std::min(horizontalScrollBar()->sliderPosition() + static_cast<int>((width() * 0.80)), horizontalScrollBar()->maximum());
545 
546         scrollTo(x, y);
547     } else {
548         // next or prev page's corner
549         int savedPageNumber = getCurrentPageNumber();
550 
551         if (forward)
552             next();
553         else
554             prev();
555 
556         if (savedPageNumber != getCurrentPageNumber()) {
557             if (d1 == LEFT || d2 == LEFT)
558                 horizontalScrollBar()->setSliderPosition(horizontalScrollBar()->maximum());
559             else
560                 horizontalScrollBar()->setSliderPosition(horizontalScrollBar()->minimum());
561             emit backgroundChanges();
562         }
563     }
564 }
565 
scrollTo(int x,int y)566 void Viewer::scrollTo(int x, int y)
567 {
568     if (groupScroller->state() == QAbstractAnimation::Running)
569         return;
570     horizontalScroller->setDuration(250);
571     horizontalScroller->setStartValue(horizontalScrollBar()->sliderPosition());
572     horizontalScroller->setEndValue(x);
573     verticalScroller->setDuration(250);
574     verticalScroller->setStartValue(verticalScrollBar()->sliderPosition());
575     verticalScroller->setEndValue(y);
576     groupScroller->start();
577     emit backgroundChanges();
578 }
579 
keyPressEvent(QKeyEvent * event)580 void Viewer::keyPressEvent(QKeyEvent *event)
581 {
582     if (render->hasLoadedComic()) {
583         int _key = event->key();
584         Qt::KeyboardModifiers modifiers = event->modifiers();
585 
586         if (modifiers & Qt::ShiftModifier)
587             _key |= Qt::SHIFT;
588         if (modifiers & Qt::ControlModifier)
589             _key |= Qt::CTRL;
590         if (modifiers & Qt::MetaModifier)
591             _key |= Qt::META;
592         if (modifiers & Qt::AltModifier)
593             _key |= Qt::ALT;
594 
595         QKeySequence key(_key);
596         /*if(goToFlow->isVisible() && event->key()!=Qt::Key_S)
597 			QCoreApplication::sendEvent(goToFlow,event);
598 		else*/
599 
600         if (key == ShortcutsManager::getShortcutsManager().getShortcut(AUTO_SCROLL_FORWARD_ACTION_Y)) {
601             posByStep = height() / numScrollSteps;
602             nextPos = verticalScrollBar()->sliderPosition() + static_cast<int>((height() * 0.80));
603             scrollDown();
604         }
605 
606         else if (key == ShortcutsManager::getShortcutsManager().getShortcut(AUTO_SCROLL_BACKWARD_ACTION_Y)) {
607             posByStep = height() / numScrollSteps;
608             nextPos = verticalScrollBar()->sliderPosition() - static_cast<int>((height() * 0.80));
609             scrollUp();
610         }
611 
612         else if (key == ShortcutsManager::getShortcutsManager().getShortcut(AUTO_SCROLL_FORWARD_HORIZONTAL_FIRST_ACTION_Y)) {
613             scrollForwardHorizontalFirst();
614         }
615 
616         else if (key == ShortcutsManager::getShortcutsManager().getShortcut(AUTO_SCROLL_BACKWARD_HORIZONTAL_FIRST_ACTION_Y)) {
617             scrollBackwardHorizontalFirst();
618         }
619 
620         else if (key == ShortcutsManager::getShortcutsManager().getShortcut(AUTO_SCROLL_FORWARD_VERTICAL_FIRST_ACTION_Y)) {
621             scrollForwardVerticalFirst();
622         }
623 
624         else if (key == ShortcutsManager::getShortcutsManager().getShortcut(AUTO_SCROLL_BACKWARD_VERTICAL_FIRST_ACTION_Y)) {
625             scrollBackwardVerticalFirst();
626         }
627 
628         else if (key == ShortcutsManager::getShortcutsManager().getShortcut(MOVE_DOWN_ACTION_Y) ||
629                  key == ShortcutsManager::getShortcutsManager().getShortcut(MOVE_UP_ACTION_Y) ||
630                  key == ShortcutsManager::getShortcutsManager().getShortcut(MOVE_LEFT_ACTION_Y) ||
631                  key == ShortcutsManager::getShortcutsManager().getShortcut(MOVE_RIGHT_ACTION_Y)) {
632             moveAction(key);
633             emit backgroundChanges();
634         }
635 
636         else if (key == ShortcutsManager::getShortcutsManager().getShortcut(GO_TO_FIRST_PAGE_ACTION_Y)) {
637             goTo(0);
638         }
639 
640         else if (key == ShortcutsManager::getShortcutsManager().getShortcut(GO_TO_LAST_PAGE_ACTION_Y)) {
641             goTo(this->render->numPages() - 1);
642         }
643 
644         else
645             QAbstractScrollArea::keyPressEvent(event);
646 
647         if (mglass->isVisible() && (key == ShortcutsManager::getShortcutsManager().getShortcut(SIZE_UP_MGLASS_ACTION_Y) || key == ShortcutsManager::getShortcutsManager().getShortcut(SIZE_DOWN_MGLASS_ACTION_Y) || key == ShortcutsManager::getShortcutsManager().getShortcut(ZOOM_IN_MGLASS_ACTION_Y) || key == ShortcutsManager::getShortcutsManager().getShortcut(ZOOM_OUT_MGLASS_ACTION_Y))) {
648             QCoreApplication::sendEvent(mglass, event);
649         }
650 
651     } else
652         QAbstractScrollArea::keyPressEvent(event);
653 }
654 
moveAction(const QKeySequence & key)655 void Viewer::moveAction(const QKeySequence &key)
656 {
657     int _key = 0;
658 
659     if (key == ShortcutsManager::getShortcutsManager().getShortcut(MOVE_DOWN_ACTION_Y))
660         _key = Qt::Key_Down;
661 
662     else if (key == ShortcutsManager::getShortcutsManager().getShortcut(MOVE_UP_ACTION_Y))
663         _key = Qt::Key_Up;
664 
665     else if (key == ShortcutsManager::getShortcutsManager().getShortcut(MOVE_LEFT_ACTION_Y))
666         _key = Qt::Key_Left;
667 
668     else if (key == ShortcutsManager::getShortcutsManager().getShortcut(MOVE_RIGHT_ACTION_Y))
669         _key = Qt::Key_Right;
670 
671     QKeyEvent _event = QKeyEvent(QEvent::KeyPress, _key, Qt::NoModifier);
672     QAbstractScrollArea::keyPressEvent(&_event);
673 }
674 
animateScroll(QPropertyAnimation & scroller,const QScrollBar & scrollBar,int delta)675 static void animateScroll(QPropertyAnimation &scroller, const QScrollBar &scrollBar, int delta)
676 {
677     int deltaNotFinished = 0;
678     if (scroller.state() == QAbstractAnimation::Running) {
679         deltaNotFinished = scroller.startValue().toInt() - scroller.endValue().toInt();
680         scroller.stop();
681     }
682 
683     const int currentPos = scrollBar.sliderPosition();
684     scroller.setDuration(250);
685     scroller.setStartValue(currentPos);
686     scroller.setEndValue(currentPos - delta - deltaNotFinished);
687 
688     scroller.start();
689 }
690 
wheelEvent(QWheelEvent * event)691 void Viewer::wheelEvent(QWheelEvent *event)
692 {
693     if (render->hasLoadedComic()) {
694         if (event->orientation() == Qt::Horizontal) {
695             animateScroll(*horizontalScroller, *horizontalScrollBar(), event->delta());
696             return;
697         }
698 
699         if ((event->delta() < 0) && (verticalScrollBar()->sliderPosition() == verticalScrollBar()->maximum())) {
700             if (wheelStop) {
701                 if (getMovement(event) == Forward) {
702                     next();
703                     verticalScroller->stop();
704                     event->accept();
705                     wheelStop = false;
706                 }
707                 return;
708             } else
709                 wheelStop = true;
710         } else {
711             if ((event->delta() > 0) && (verticalScrollBar()->sliderPosition() == verticalScrollBar()->minimum())) {
712                 if (wheelStop) {
713                     if (getMovement(event) == Backward) {
714                         prev();
715                         verticalScroller->stop();
716                         event->accept();
717                         wheelStop = false;
718                     }
719                     return;
720                 } else
721                     wheelStop = true;
722             }
723         }
724 
725         animateScroll(*verticalScroller, *verticalScrollBar(), event->delta());
726     }
727 }
728 
resizeEvent(QResizeEvent * event)729 void Viewer::resizeEvent(QResizeEvent *event)
730 {
731     updateContentSize();
732     goToFlow->updateSize();
733     goToFlow->move((width() - goToFlow->width()) / 2, height() - goToFlow->height());
734     informationLabel->updatePosition();
735     QScrollArea::resizeEvent(event);
736 }
737 
mouseMoveEvent(QMouseEvent * event)738 void Viewer::mouseMoveEvent(QMouseEvent *event)
739 {
740     showCursor();
741     hideCursorTimer->start(2500);
742 
743     if (magnifyingGlassShowed)
744         mglass->move(static_cast<int>(event->x() - float(mglass->width()) / 2), static_cast<int>(event->y() - float(mglass->height()) / 2));
745 
746     if (render->hasLoadedComic()) {
747         if (showGoToFlowAnimation->state() != QPropertyAnimation::Running) {
748             if (Configuration::getConfiguration().getDisableShowOnMouseOver() == false) {
749                 if (goToFlow->isVisible()) {
750                     QPoint gtfPos = goToFlow->mapFrom(this, event->pos());
751                     if (gtfPos.y() < 0 || gtfPos.x() < 0 || gtfPos.x() > goToFlow->width()) //TODO this extra check is for Mavericks (mouseMove over goToFlowGL seems to be broken)
752                         animateHideGoToFlow();
753                     //goToFlow->hide();
754                 } else {
755                     int umbral = (width() - goToFlow->width()) / 2;
756                     if ((event->y() > height() - 15) && (event->x() > umbral) && (event->x() < width() - umbral)) {
757 
758                         animateShowGoToFlow();
759                         hideCursorTimer->stop();
760                     }
761                 }
762             }
763         }
764 
765         if (drag) {
766             int currentPosY = verticalScrollBar()->sliderPosition();
767             int currentPosX = horizontalScrollBar()->sliderPosition();
768             verticalScrollBar()->setSliderPosition(currentPosY = currentPosY + (yDragOrigin - event->y()));
769             horizontalScrollBar()->setSliderPosition(currentPosX = currentPosX + (xDragOrigin - event->x()));
770             yDragOrigin = event->y();
771             xDragOrigin = event->x();
772         }
773     }
774 }
775 
pixmap()776 const QPixmap *Viewer::pixmap()
777 {
778     return content->pixmap();
779 }
780 
magnifyingGlassSwitch()781 void Viewer::magnifyingGlassSwitch()
782 {
783     magnifyingGlassShowed ? hideMagnifyingGlass() : showMagnifyingGlass();
784 }
785 
showMagnifyingGlass()786 void Viewer::showMagnifyingGlass()
787 {
788     if (render->hasLoadedComic()) {
789         QPoint p = QPoint(cursor().pos().x(), cursor().pos().y());
790         p = this->parentWidget()->mapFromGlobal(p);
791         mglass->move(static_cast<int>(p.x() - float(mglass->width()) / 2), static_cast<int>(p.y() - float(mglass->height()) / 2));
792         mglass->show();
793         mglass->updateImage(mglass->x() + mglass->width() / 2, mglass->y() + mglass->height() / 2);
794         magnifyingGlassShowed = true;
795     }
796 }
797 
hideMagnifyingGlass()798 void Viewer::hideMagnifyingGlass()
799 {
800     mglass->hide();
801     magnifyingGlassShowed = false;
802 }
803 
informationSwitch()804 void Viewer::informationSwitch()
805 {
806     information ? informationLabel->hide() : informationLabel->show();
807     //informationLabel->move(QPoint((width()-informationLabel->width())/2,0));
808     information = !information;
809     Configuration::getConfiguration().setShowInformation(information);
810     //TODO it shouldn't be neccesary
811     informationLabel->adjustSize();
812     informationLabel->update();
813 }
814 
updateInformation()815 void Viewer::updateInformation()
816 {
817     if (render->hasLoadedComic()) {
818         informationLabel->setText(render->getCurrentPagesInformation() + " - " + QTime::currentTime().toString("HH:mm"));
819         informationLabel->adjustSize();
820         informationLabel->update(); //TODO it shouldn't be neccesary
821     }
822 }
823 
goToFlowSwitch()824 void Viewer::goToFlowSwitch()
825 {
826     goToFlow->isVisible() ? animateHideGoToFlow() : showGoToFlow();
827 }
828 
translatorSwitch()829 void Viewer::translatorSwitch()
830 {
831     translator->isVisible() ? animateHideTranslator() : animateShowTranslator();
832 }
833 
showGoToFlow()834 void Viewer::showGoToFlow()
835 {
836     if (render->hasLoadedComic()) {
837         animateShowGoToFlow();
838     }
839 }
840 
animateShowGoToFlow()841 void Viewer::animateShowGoToFlow()
842 {
843     if (goToFlow->isHidden() && showGoToFlowAnimation->state() != QPropertyAnimation::Running) {
844         disconnect(showGoToFlowAnimation, SIGNAL(finished()), goToFlow, SLOT(hide()));
845         connect(showGoToFlowAnimation, SIGNAL(finished()), this, SLOT(moveCursoToGoToFlow()));
846         showGoToFlowAnimation->setStartValue(QPoint((width() - goToFlow->width()) / 2, height() - 10));
847         showGoToFlowAnimation->setEndValue(QPoint((width() - goToFlow->width()) / 2, height() - goToFlow->height()));
848         showGoToFlowAnimation->start();
849         goToFlow->centerSlide(render->getIndex());
850         goToFlow->setPageNumber(render->getIndex());
851         goToFlow->show();
852         goToFlow->setFocus(Qt::OtherFocusReason);
853     }
854 }
855 
animateHideGoToFlow()856 void Viewer::animateHideGoToFlow()
857 {
858     if (goToFlow->isVisible() && showGoToFlowAnimation->state() != QPropertyAnimation::Running) {
859         connect(showGoToFlowAnimation, SIGNAL(finished()), goToFlow, SLOT(hide()));
860         disconnect(showGoToFlowAnimation, SIGNAL(finished()), this, SLOT(moveCursoToGoToFlow()));
861         showGoToFlowAnimation->setStartValue(QPoint((width() - goToFlow->width()) / 2, height() - goToFlow->height()));
862         showGoToFlowAnimation->setEndValue(QPoint((width() - goToFlow->width()) / 2, height()));
863         showGoToFlowAnimation->start();
864         goToFlow->centerSlide(render->getIndex());
865         goToFlow->setPageNumber(render->getIndex());
866         this->setFocus(Qt::OtherFocusReason);
867     }
868 }
869 
moveCursoToGoToFlow()870 void Viewer::moveCursoToGoToFlow()
871 {
872     if (Configuration::getConfiguration().getDisableShowOnMouseOver()) {
873         return;
874     }
875 
876     //Move cursor to goToFlow widget on show (this avoid hide when mouse is moved)
877     int y = goToFlow->pos().y();
878     int x1 = goToFlow->pos().x();
879     int x2 = x1 + goToFlow->width();
880     QPoint cursorPos = mapFromGlobal(cursor().pos());
881     int cursorX = cursorPos.x();
882     int cursorY = cursorPos.y();
883 
884     if (cursorY <= y)
885         cursorY = y + 10;
886     if (cursorX <= x1)
887         cursorX = x1 + 10;
888     if (cursorX >= x2)
889         cursorX = x2 - 10;
890     cursor().setPos(mapToGlobal(QPoint(cursorX, cursorY)));
891     hideCursorTimer->stop();
892     showCursor();
893 }
894 
rotateLeft()895 void Viewer::rotateLeft()
896 {
897     render->rotateLeft();
898 }
rotateRight()899 void Viewer::rotateRight()
900 {
901     render->rotateRight();
902 }
903 
904 //TODO
setBookmark(bool set)905 void Viewer::setBookmark(bool set)
906 {
907     render->setBookmark();
908     if (set) //add bookmark
909     {
910         render->setBookmark();
911     } else //remove bookmark
912     {
913         render->removeBookmark();
914     }
915 }
916 
save()917 void Viewer::save()
918 {
919     if (render->hasLoadedComic())
920         render->save();
921 }
922 
doublePageSwitch()923 void Viewer::doublePageSwitch()
924 {
925     doublePage = !doublePage;
926     render->doublePageSwitch();
927     Configuration::getConfiguration().setDoublePage(doublePage);
928 }
929 
setMangaWithoutStoringSetting(bool manga)930 void Viewer::setMangaWithoutStoringSetting(bool manga)
931 {
932     doubleMangaPage = manga;
933     render->setManga(manga);
934     goToFlow->setFlowRightToLeft(doubleMangaPage);
935 }
936 
doubleMangaPageSwitch()937 void Viewer::doubleMangaPageSwitch()
938 {
939     doubleMangaPage = !doubleMangaPage;
940     render->doubleMangaPageSwitch();
941     Configuration &config = Configuration::getConfiguration();
942     config.setDoubleMangaPage(doubleMangaPage);
943     goToFlow->setFlowRightToLeft(doubleMangaPage);
944     goToFlow->updateConfig(config.getSettings());
945 }
946 
resetContent()947 void Viewer::resetContent()
948 {
949     configureContent(tr("Press 'O' to open comic."));
950     goToFlow->reset();
951     emit reset();
952 }
953 
setLoadingMessage()954 void Viewer::setLoadingMessage()
955 {
956     if (magnifyingGlassShowed) {
957         hideMagnifyingGlass();
958         restoreMagnifyingGlass = true;
959     }
960     emit(pageAvailable(false));
961     configureContent(tr("Loading...please wait!"));
962 }
963 
setPageUnavailableMessage()964 void Viewer::setPageUnavailableMessage()
965 {
966     if (magnifyingGlassShowed) {
967         hideMagnifyingGlass();
968         restoreMagnifyingGlass = true;
969     }
970     emit(pageAvailable(false));
971     configureContent(tr("Page not available!"));
972 }
973 
configureContent(QString msg)974 void Viewer::configureContent(QString msg)
975 {
976     content->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Ignored);
977     if (!(devicePixelRatio() > 1))
978         content->setScaledContents(true);
979     content->setAlignment(Qt::AlignTop | Qt::AlignHCenter);
980     content->setText(msg);
981     content->setFont(QFont("courier new", 12));
982     content->adjustSize();
983     setFocus(Qt::ShortcutFocusReason);
984     //emit showingText();
985 }
986 
hideCursor()987 void Viewer::hideCursor()
988 {
989 #ifdef Q_OS_MAC
990     setCursor(QCursor(QBitmap(1, 1), QBitmap(1, 1)));
991 #else
992     setCursor(Qt::BlankCursor);
993 #endif
994 }
showCursor()995 void Viewer::showCursor()
996 {
997     if (drag)
998         setCursor(Qt::ClosedHandCursor);
999     else
1000         setCursor(Qt::OpenHandCursor);
1001 }
1002 
updateOptions()1003 void Viewer::updateOptions()
1004 {
1005 
1006     goToFlow->setFlowType(Configuration::getConfiguration().getFlowType());
1007     updateBackgroundColor(Configuration::getConfiguration().getBackgroundColor());
1008     updateContentSize();
1009 }
1010 
updateBackgroundColor(const QColor & color)1011 void Viewer::updateBackgroundColor(const QColor &color)
1012 {
1013     QPalette palette;
1014     palette.setColor(backgroundRole(), color);
1015     setPalette(palette);
1016 }
1017 
animateShowTranslator()1018 void Viewer::animateShowTranslator()
1019 {
1020     if (translator->isHidden() && translatorAnimation->state() != QPropertyAnimation::Running) {
1021         disconnect(translatorAnimation, SIGNAL(finished()), translator, SLOT(hide()));
1022         if (translatorXPos == -10000)
1023             translatorXPos = (width() - translator->width()) / 2;
1024         int x = qMax(0, qMin(translatorXPos, width() - translator->width()));
1025         if (translator->pos().x() < 0) {
1026             translatorAnimation->setStartValue(QPoint(-translator->width(), translator->pos().y()));
1027         } else {
1028             translatorAnimation->setStartValue(QPoint(width() + translator->width(), translator->pos().y()));
1029         }
1030         translatorAnimation->setEndValue(QPoint(x, translator->pos().y()));
1031         translatorAnimation->start();
1032         translator->show();
1033         translator->setFocus(Qt::OtherFocusReason);
1034     }
1035 }
animateHideTranslator()1036 void Viewer::animateHideTranslator()
1037 {
1038     if (translator->isVisible() && translatorAnimation->state() != QPropertyAnimation::Running) {
1039         connect(translatorAnimation, SIGNAL(finished()), translator, SLOT(hide()));
1040         translatorAnimation->setStartValue(QPoint(translatorXPos = translator->pos().x(), translator->pos().y()));
1041         if ((translator->width() / 2) + translator->pos().x() <= width() / 2)
1042             translatorAnimation->setEndValue(QPoint(-translator->width(), translator->pos().y()));
1043         else
1044             translatorAnimation->setEndValue(QPoint(width() + translator->width(), translator->pos().y()));
1045         translatorAnimation->start();
1046         this->setFocus(Qt::OtherFocusReason);
1047     }
1048 }
1049 
mousePressEvent(QMouseEvent * event)1050 void Viewer::mousePressEvent(QMouseEvent *event)
1051 {
1052     if (event->button() == Qt::LeftButton) {
1053         drag = true;
1054         yDragOrigin = event->y();
1055         xDragOrigin = event->x();
1056         setCursor(Qt::ClosedHandCursor);
1057         event->accept();
1058     }
1059 }
1060 
mouseReleaseEvent(QMouseEvent * event)1061 void Viewer::mouseReleaseEvent(QMouseEvent *event)
1062 {
1063     drag = false;
1064     setCursor(Qt::OpenHandCursor);
1065     event->accept();
1066 }
1067 
updateZoomRatio(int ratio)1068 void Viewer::updateZoomRatio(int ratio)
1069 {
1070     zoom = ratio;
1071     updateContentSize();
1072 }
1073 
getIsMangaMode()1074 bool Viewer::getIsMangaMode()
1075 {
1076     return doubleMangaPage;
1077 }
1078 
updateConfig(QSettings * settings)1079 void Viewer::updateConfig(QSettings *settings)
1080 {
1081     goToFlow->updateConfig(settings);
1082 
1083     QPalette palette;
1084     palette.setColor(backgroundRole(), Configuration::getConfiguration().getBackgroundColor());
1085     setPalette(palette);
1086 }
1087 
1088 //deprecated
updateImageOptions()1089 void Viewer::updateImageOptions()
1090 {
1091     render->reload();
1092 }
1093 
updateFilters(int brightness,int contrast,int gamma)1094 void Viewer::updateFilters(int brightness, int contrast, int gamma)
1095 {
1096     render->updateFilters(brightness, contrast, gamma);
1097 }
1098 
setBookmarks()1099 void Viewer::setBookmarks()
1100 {
1101     bd->setBookmarks(*render->getBookmarks());
1102 }
1103 
showIsCoverMessage()1104 void Viewer::showIsCoverMessage()
1105 {
1106     if (!shouldOpenPrevious) {
1107         notificationsLabel->setText(tr("Cover!"));
1108         notificationsLabel->flash();
1109         shouldOpenPrevious = true;
1110     } else {
1111         shouldOpenPrevious = false;
1112         emit(openPreviousComic());
1113     }
1114 
1115     shouldOpenNext = false; //single page comic
1116 }
1117 
showIsLastMessage()1118 void Viewer::showIsLastMessage()
1119 {
1120     if (!shouldOpenNext) {
1121         notificationsLabel->setText(tr("Last page!"));
1122         notificationsLabel->flash();
1123         shouldOpenNext = true;
1124     } else {
1125         shouldOpenNext = false;
1126         emit(openNextComic());
1127     }
1128 
1129     shouldOpenPrevious = false; //single page comic
1130 }
1131 
getIndex()1132 unsigned int Viewer::getIndex()
1133 {
1134     return render->getIndex() + 1;
1135 }
1136 
getCurrentPageNumber()1137 int Viewer::getCurrentPageNumber()
1138 {
1139     return render->getIndex();
1140 }
1141 
updateComic(ComicDB & comic)1142 void Viewer::updateComic(ComicDB &comic)
1143 {
1144     if (render->hasLoadedComic()) {
1145         //set currentPage
1146         if (!doublePage || (doublePage && render->currentPageIsDoublePage() == false)) {
1147             comic.info.currentPage = render->getIndex() + 1;
1148         } else {
1149             if (!(render->getIndex() + 1 == comic.info.currentPage || render->getIndex() + 2 == comic.info.currentPage)) {
1150                 comic.info.currentPage = std::min(render->numPages(), render->getIndex() + 1);
1151             }
1152         }
1153         //set bookmarks
1154         Bookmarks *boomarks = render->getBookmarks();
1155         QList<int> boomarksList = boomarks->getBookmarkPages();
1156         int numBookmarks = boomarksList.size();
1157         if (numBookmarks > 0)
1158             comic.info.bookmark1 = boomarksList[0];
1159         if (numBookmarks > 1)
1160             comic.info.bookmark2 = boomarksList[1];
1161         if (numBookmarks > 2)
1162             comic.info.bookmark3 = boomarksList[2];
1163         //set filters
1164         //TODO: avoid use settings for this...
1165         QSettings settings(YACReader::getSettingsPath() + "/YACReader.ini", QSettings::IniFormat);
1166         int brightness = settings.value(BRIGHTNESS, 0).toInt();
1167         int contrast = settings.value(CONTRAST, 100).toInt();
1168         int gamma = settings.value(GAMMA, 100).toInt();
1169 
1170         if (brightness != 0 || comic.info.brightness != -1)
1171             comic.info.brightness = brightness;
1172         if (contrast != 100 || comic.info.contrast != -1)
1173             comic.info.contrast = contrast;
1174         if (gamma != 100 || comic.info.gamma != -1)
1175             comic.info.gamma = gamma;
1176     }
1177 }
1178