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