diff --git a/YACReader/Info.plist.mac b/YACReader/Info.plist.mac new file mode 100644 index 00000000..be9dbf3d --- /dev/null +++ b/YACReader/Info.plist.mac @@ -0,0 +1,39 @@ + + + + + NSPrincipalClass + NSApplication + CFBundleIconFile + @ICON@ + CFBundlePackageType + APPL + CFBundleGetInfoString + Created by Qt/QMake + CFBundleSignature + @TYPEINFO@ + CFBundleExecutable + @EXECUTABLE@ + CFBundleIdentifier + @BUNDLEIDENTIFIER@ + NOTE + This file was generated by Qt/QMake. + + CFBundleDocumentTypes + + + CFBundleTypeName + + CFBundleTypeRole + Viewer + LSHandlerRank + Alternate + LSItemContentTypes + + public.item + + + + + + diff --git a/YACReader/YACReader.pro b/YACReader/YACReader.pro index 57a500de..8a64c8cf 100644 --- a/YACReader/YACReader.pro +++ b/YACReader/YACReader.pro @@ -212,6 +212,7 @@ RC_FILE = icon.rc macx { ICON = YACReader.icns + QMAKE_INFO_PLIST = Info.plist.mac } TRANSLATIONS = yacreader_es.ts \ diff --git a/YACReader/configuration.cpp b/YACReader/configuration.cpp index 841ce1e6..4be384d7 100644 --- a/YACReader/configuration.cpp +++ b/YACReader/configuration.cpp @@ -12,7 +12,12 @@ Configuration::Configuration() { //read configuration - //load("/YACReader.conf"); + //load("/YACReader.conf"); +} + +QSettings *Configuration::getSettings() +{ + return settings; } /*Configuration::Configuration(const Configuration & conf) @@ -50,7 +55,7 @@ void Configuration::load(QSettings * settings) if(!settings->contains(SHOW_TOOLBARS)) settings->setValue(SHOW_TOOLBARS, true); if(!settings->contains(QUICK_NAVI_MODE)) - settings->setValue(QUICK_NAVI_MODE, true); + settings->setValue(QUICK_NAVI_MODE, false); //old fit stuff /*if(!settings->contains(FIT)) settings->setValue(FIT,false); @@ -71,4 +76,4 @@ void Configuration::updateOpenRecentList (QString path) list.removeLast(); } settings->setValue("recentFiles", list); -} \ No newline at end of file +} diff --git a/YACReader/configuration.h b/YACReader/configuration.h index ec5932c9..6d27227d 100644 --- a/YACReader/configuration.h +++ b/YACReader/configuration.h @@ -51,6 +51,7 @@ using namespace YACReader; static Configuration configuration; return configuration; }; + QSettings *getSettings(); void load(QSettings * settings); QString getDefaultPath() { return settings->value(PATH).toString(); } void setDefaultPath(QString defaultPath){settings->setValue(PATH,defaultPath);} diff --git a/YACReader/goto_flow.cpp b/YACReader/goto_flow.cpp index a74acf03..091924c5 100644 --- a/YACReader/goto_flow.cpp +++ b/YACReader/goto_flow.cpp @@ -223,6 +223,12 @@ void GoToFlow::updateConfig(QSettings * settings) resize(5*imageSize.width(), toolBar->height() + imageSize.height()*1.7); updateSize(); } + +void GoToFlow::setFlowRightToLeft(bool b) +{ + flow->setFlowRightToLeft(b); +} + //----------------------------------------------------------------------------- //SlideInitializer //----------------------------------------------------------------------------- diff --git a/YACReader/goto_flow.h b/YACReader/goto_flow.h index 041fe273..be157fa7 100644 --- a/YACReader/goto_flow.h +++ b/YACReader/goto_flow.h @@ -62,6 +62,8 @@ private slots: void setImageReady(int index,const QByteArray & image); void setFlowType(FlowType flowType); void updateConfig(QSettings * settings); + void setFlowRightToLeft(bool b); + signals: void goToPage(unsigned int page); diff --git a/YACReader/goto_flow_gl.cpp b/YACReader/goto_flow_gl.cpp index 5075cbca..80dca124 100644 --- a/YACReader/goto_flow_gl.cpp +++ b/YACReader/goto_flow_gl.cpp @@ -160,3 +160,8 @@ void GoToFlowGL::resizeEvent(QResizeEvent *event) toolBar->move(0, event->size().height() - toolBar->height()); toolBar->setFixedWidth(width()); } + +void GoToFlowGL::setFlowRightToLeft(bool b) +{ + flow->setFlowRightToLeft(b); +} diff --git a/YACReader/goto_flow_gl.h b/YACReader/goto_flow_gl.h index e6d76dc1..1feca85d 100644 --- a/YACReader/goto_flow_gl.h +++ b/YACReader/goto_flow_gl.h @@ -25,6 +25,7 @@ public: void setImageReady(int index,const QByteArray & image); void updateConfig(QSettings * settings); + void setFlowRightToLeft(bool b); signals: void goToPage(unsigned int page); diff --git a/YACReader/goto_flow_toolbar.cpp b/YACReader/goto_flow_toolbar.cpp index 4fe09d79..4043f568 100644 --- a/YACReader/goto_flow_toolbar.cpp +++ b/YACReader/goto_flow_toolbar.cpp @@ -20,18 +20,19 @@ GoToFlowToolBar::GoToFlowToolBar(QWidget * parent) slider = new QSlider(Qt::Horizontal,this); slider->setStyleSheet( "QSlider::groove:horizontal {" - " border: 1px solid white;" - " border-radius: 6px;" - " background: rgba(255, 255, 255, 50);" - " margin: 2px 0;" + " border: 1px solid #22FFFFFF;" + " border-radius: 1px;" + " background: #77000000;" + " margin: 2px 0;" + " padding: 1px;" "}" "QSlider::handle:horizontal {" - " background: rgba(0, 0, 0, 200);" - " border: 1px solid white;" - " width: 24px;" - " border-radius: 6px;" + " background: #55FFFFFF;" + " width: 48px;" + " border-radius: 1px;" "}" ); + connect(slider, &QSlider::valueChanged, this, [&](int v) { emit(setCenter(v)); }); pageHint = new QLabel("" + tr("Page : ") + "",this); @@ -85,19 +86,11 @@ GoToFlowToolBar::GoToFlowToolBar(QWidget * parent) naviLayout->addWidget(slider); naviLayout->addWidget(goToButton); - switchLayout(); + updateOptions(); setFixedHeight(50); } -void GoToFlowToolBar::switchLayout() -{ - if (Configuration::getConfiguration().getQuickNaviMode()) - setCurrentIndex(1); - else - setCurrentIndex(0); -} - void GoToFlowToolBar::paintEvent(QPaintEvent *) { QPainter painter(this); @@ -130,5 +123,15 @@ void GoToFlowToolBar::goTo() void GoToFlowToolBar::centerSlide() { if(edit->text().toInt()!=0) - emit(setCenter(edit->text().toInt()-1)); + emit(setCenter(edit->text().toInt()-1)); +} + +void GoToFlowToolBar::updateOptions() +{ + if (Configuration::getConfiguration().getQuickNaviMode()) + setCurrentIndex(1); + else + setCurrentIndex(0); + + slider->setInvertedAppearance(Configuration::getConfiguration().getDoubleMangaPage()); } diff --git a/YACReader/goto_flow_toolbar.h b/YACReader/goto_flow_toolbar.h index 803026c0..417a466a 100644 --- a/YACReader/goto_flow_toolbar.h +++ b/YACReader/goto_flow_toolbar.h @@ -25,12 +25,13 @@ class GoToFlowToolBar : public QStackedWidget public: GoToFlowToolBar(QWidget * parent = 0); - void switchLayout(); + public slots: void setPage(int pageNumber); void setTop(int numPages); void goTo(); void centerSlide(); + void updateOptions(); signals: void setCenter(unsigned int); void goTo(unsigned int); diff --git a/YACReader/goto_flow_widget.cpp b/YACReader/goto_flow_widget.cpp index 6714a733..acb31468 100644 --- a/YACReader/goto_flow_widget.cpp +++ b/YACReader/goto_flow_widget.cpp @@ -54,7 +54,7 @@ void GoToFlowWidget::keyPressEvent(QKeyEvent* event) void GoToFlowWidget::updateConfig(QSettings * settings) { Q_UNUSED(settings) - toolBar->switchLayout(); + toolBar->updateOptions(); } void GoToFlowWidget::updateSize() diff --git a/YACReader/goto_flow_widget.h b/YACReader/goto_flow_widget.h index 5c194982..a981fa2c 100644 --- a/YACReader/goto_flow_widget.h +++ b/YACReader/goto_flow_widget.h @@ -29,6 +29,7 @@ public slots: virtual void setImageReady(int index,const QByteArray & image) = 0; virtual void updateSize(); virtual void updateConfig(QSettings * settings); + virtual void setFlowRightToLeft(bool b) = 0; protected: void keyPressEvent(QKeyEvent* event); diff --git a/YACReader/main.cpp b/YACReader/main.cpp index efd8d012..90c1545b 100644 --- a/YACReader/main.cpp +++ b/YACReader/main.cpp @@ -169,5 +169,13 @@ int main(int argc, char * argv[]) YACReader::exitCheck(ret); +#ifdef Q_OS_MAC + // ugly workaround to avoid crash when app exit on MacOS Sierra due to Qt's QColorDialog bug. + // cf. https://bugreports.qt.io/browse/QTBUG-56448 + QColorDialog colorDlg(0); + colorDlg.setOption(QColorDialog::NoButtons); + colorDlg.setCurrentColor(Qt::white); +#endif + return ret; } diff --git a/YACReader/main_window_viewer.cpp b/YACReader/main_window_viewer.cpp index d114108d..e3da7210 100644 --- a/YACReader/main_window_viewer.cpp +++ b/YACReader/main_window_viewer.cpp @@ -189,6 +189,10 @@ void MainWindowViewer::setupUI() // setWindowFlags(this->windowFlags() | Qt::CustomizeWindowHint | Qt::WindowStaysOnTopHint); //} + previousWindowFlags = windowFlags(); + previousPos = pos(); + previousSize = size(); + if(fullscreen) toFullScreen(); if(conf.getMaximized()) @@ -651,13 +655,68 @@ void MainWindowViewer::createToolBars() fileMenu->addAction(openFolderAction); fileMenu->addSeparator(); fileMenu->addAction(saveImageAction); + fileMenu->addSeparator(); + + QMenu * recentmenu = new QMenu(tr("Open recent")); + recentmenu->addActions(recentFilesActionList); + recentmenu->addSeparator(); + recentmenu->addAction(clearRecentFilesAction); + refreshRecentFilesActionList(); + fileMenu->addMenu(recentmenu); + + fileMenu->addSeparator(); + fileMenu->addAction(closeAction); + + QMenu * editMenu = new QMenu(tr("Edit")); + editMenu->addAction(leftRotationAction); + editMenu->addAction(rightRotationAction); + + QMenu * viewMenu = new QMenu(tr("View")); + viewMenu->addAction(adjustHeightAction); + viewMenu->addAction(adjustWidthAction); + viewMenu->addAction(fitToPageAction); + viewMenu->addAction(adjustToFullSizeAction); + viewMenu->addSeparator(); + viewMenu->addAction(increasePageZoomAction); + viewMenu->addAction(decreasePageZoomAction); + viewMenu->addAction(resetZoomAction); + viewMenu->addAction(showZoomSliderlAction); + viewMenu->addSeparator(); + viewMenu->addAction(doublePageAction); + viewMenu->addAction(doubleMangaPageAction); + viewMenu->addSeparator(); + viewMenu->addAction(showMagnifyingGlassAction); + + QMenu * goMenu = new QMenu(tr("Go")); + goMenu->addAction(prevAction); + goMenu->addAction(nextAction); + goMenu->addAction(goToPageAction); + goMenu->addSeparator(); + goMenu->addAction(setBookmarkAction); + goMenu->addAction(showBookmarksAction); + + QMenu * windowMenu = new QMenu(tr("Window")); + windowMenu->addAction(optionsAction); // this action goes to MacOS's Preference menu by Qt + windowMenu->addAction(showShorcutsAction); + windowMenu->addAction(showFlowAction); + windowMenu->addAction(showInfoAction); + windowMenu->addAction(showDictionaryAction); + + QMenu * helpMenu = new QMenu(tr("Help")); + helpMenu->addAction(helpAboutAction); + + menuBar->addMenu(fileMenu); + menuBar->addMenu(editMenu); + menuBar->addMenu(viewMenu); + menuBar->addMenu(goMenu); + menuBar->addMenu(windowMenu); + menuBar->addMenu(helpMenu); //tool bar //QMenu * toolbarMenu = new QMenu(tr("Toolbar")); //toolbarMenu->addAction(); //TODO - menuBar->addMenu(fileMenu); //menu->addMenu(toolbarMenu); //attach toolbar @@ -922,6 +981,11 @@ void MainWindowViewer::enableActions() showInfoAction->setDisabled(false); //TODO enable goTo and showInfo (or update) when numPages emited showDictionaryAction->setDisabled(false); showFlowAction->setDisabled(false); + +#ifdef Q_OS_MAC + activateWindow(); + raise(); +#endif } void MainWindowViewer::disableActions() { @@ -1000,6 +1064,57 @@ void MainWindowViewer::toggleFullScreen() Configuration::getConfiguration().setFullScreen(fullscreen = !fullscreen); } +#ifdef Q_OS_WIN //fullscreen mode in Windows for preventing this bug: QTBUG-41309 https://bugreports.qt.io/browse/QTBUG-41309 + +void MainWindowViewer::toFullScreen() +{ + fromMaximized = this->isMaximized(); + + hideToolBars(); + viewer->hide(); + viewer->fullscreen = true;//TODO, change by the right use of windowState(); + + previousWindowFlags = windowFlags(); + previousPos = pos(); + previousSize = size(); + + showNormal(); + setWindowFlags(previousWindowFlags | Qt::FramelessWindowHint); + + const QRect r = windowHandle()->screen()->geometry(); + + move(r.x(), r.y()); + resize(r.width(),r.height()+1); + show(); + + viewer->show(); + if(viewer->magnifyingGlassIsVisible()) + viewer->showMagnifyingGlass(); +} + +void MainWindowViewer::toNormal() +{ + //show all + viewer->hide(); + viewer->fullscreen = false;//TODO, change by the right use of windowState(); + //viewer->hideMagnifyingGlass(); + + setWindowFlags(previousWindowFlags); + move(previousPos); + resize(previousSize); + show(); + + if(fromMaximized) + showMaximized(); + + if(Configuration::getConfiguration().getShowToolbars()) + showToolBars(); + viewer->show(); + if(viewer->magnifyingGlassIsVisible()) + viewer->showMagnifyingGlass(); +} + +#else void MainWindowViewer::toFullScreen() { fromMaximized = this->isMaximized(); @@ -1030,6 +1145,7 @@ void MainWindowViewer::toNormal() if(viewer->magnifyingGlassIsVisible()) viewer->showMagnifyingGlass(); } +#endif void MainWindowViewer::toggleToolBars() { @@ -1218,6 +1334,22 @@ void MainWindowViewer::setUpShortcutsManagement() autoScrollBackwardAction->setData(AUTO_SCROLL_BACKWARD_ACTION_Y); autoScrollBackwardAction->setShortcut(ShortcutsManager::getShortcutsManager().getShortcut(AUTO_SCROLL_BACKWARD_ACTION_Y)); + QAction * autoScrollForwardHorizontalFirstAction = new QAction(tr("Autoscroll forward, horizontal first"),orphanActions); + autoScrollForwardHorizontalFirstAction->setData(AUTO_SCROLL_FORWARD_HORIZONTAL_FIRST_ACTION_Y); + autoScrollForwardHorizontalFirstAction->setShortcut(ShortcutsManager::getShortcutsManager().getShortcut(AUTO_SCROLL_FORWARD_HORIZONTAL_FIRST_ACTION_Y)); + + QAction * autoScrollBackwardHorizontalFirstAction = new QAction(tr("Autoscroll backward, horizontal first"),orphanActions); + autoScrollBackwardHorizontalFirstAction->setData(AUTO_SCROLL_BACKWARD_HORIZONTAL_FIRST_ACTION_Y); + autoScrollBackwardHorizontalFirstAction->setShortcut(ShortcutsManager::getShortcutsManager().getShortcut(AUTO_SCROLL_BACKWARD_HORIZONTAL_FIRST_ACTION_Y)); + + QAction * autoScrollForwardVerticalFirstAction = new QAction(tr("Autoscroll forward, vertical first"),orphanActions); + autoScrollForwardVerticalFirstAction->setData(AUTO_SCROLL_FORWARD_VERTICAL_FIRST_ACTION_Y); + autoScrollForwardVerticalFirstAction->setShortcut(ShortcutsManager::getShortcutsManager().getShortcut(AUTO_SCROLL_FORWARD_VERTICAL_FIRST_ACTION_Y)); + + QAction * autoScrollBackwardVerticalFirstAction = new QAction(tr("Autoscroll backward, vertical first"),orphanActions); + autoScrollBackwardVerticalFirstAction->setData(AUTO_SCROLL_BACKWARD_VERTICAL_FIRST_ACTION_Y); + autoScrollBackwardVerticalFirstAction->setShortcut(ShortcutsManager::getShortcutsManager().getShortcut(AUTO_SCROLL_BACKWARD_VERTICAL_FIRST_ACTION_Y)); + QAction * moveDownAction = new QAction(tr("Move down"),orphanActions); moveDownAction->setData(MOVE_DOWN_ACTION_Y); moveDownAction->setShortcut(ShortcutsManager::getShortcutsManager().getShortcut(MOVE_DOWN_ACTION_Y)); @@ -1250,6 +1382,10 @@ void MainWindowViewer::setUpShortcutsManagement() << showBookmarksAction << autoScrollForwardAction << autoScrollBackwardAction + << autoScrollForwardHorizontalFirstAction + << autoScrollBackwardHorizontalFirstAction + << autoScrollForwardVerticalFirstAction + << autoScrollBackwardVerticalFirstAction << moveDownAction << moveUpAction << moveLeftAction diff --git a/YACReader/main_window_viewer.h b/YACReader/main_window_viewer.h index beaef34e..e18aa901 100644 --- a/YACReader/main_window_viewer.h +++ b/YACReader/main_window_viewer.h @@ -167,6 +167,11 @@ class EditShortcutsDialog; bool isClient; QString startComicPath; quint64 libraryId; + + //fullscreen mode in Windows for preventing this bug: QTBUG-41309 https://bugreports.qt.io/browse/QTBUG-41309 + Qt::WindowFlags previousWindowFlags; + QPoint previousPos; + QSize previousSize; signals: void closed(); protected: diff --git a/YACReader/viewer.cpp b/YACReader/viewer.cpp index e5091243..8fb45728 100644 --- a/YACReader/viewer.cpp +++ b/YACReader/viewer.cpp @@ -117,6 +117,11 @@ Viewer::Viewer(QWidget * parent) //animations verticalScroller = new QPropertyAnimation(verticalScrollBar(), "sliderPosition"); connect(verticalScroller,SIGNAL(valueChanged (const QVariant &)),this,SIGNAL(backgroundChanges())); + horizontalScroller = new QPropertyAnimation(horizontalScrollBar(), "sliderPosition"); + connect(horizontalScroller,SIGNAL(valueChanged (const QVariant &)),this,SIGNAL(backgroundChanges())); + groupScroller = new QParallelAnimationGroup(); + groupScroller->addAnimation(verticalScroller); + groupScroller->addAnimation(horizontalScroller); notificationsLabel = new NotificationsLabelWidget(this); notificationsLabel->hide(); @@ -136,6 +141,8 @@ Viewer::~Viewer() delete hideCursorTimer; delete informationLabel; delete verticalScroller; + delete horizontalScroller; + delete groupScroller; delete bd; delete notificationsLabel; delete mglass; @@ -455,6 +462,142 @@ void Viewer::scrollUp() } } +void Viewer::scrollForwardHorizontalFirst() +{ + if (!doubleMangaPage) + { + scrollZigzag(RIGHT, DOWN, true); // right->right->lower left->right->...->next page + } + else + { + scrollZigzag(LEFT, DOWN, true); // left->left->lower right->left->...->next page + } +} + +void Viewer::scrollBackwardHorizontalFirst() +{ + if (!doubleMangaPage) + { + scrollZigzag(LEFT, UP, false); // left->left->upper right->left->...->prev page + } + else + { + scrollZigzag(RIGHT, UP, false); // right->right->upper left->right->...->prev page + } +} + +void Viewer::scrollForwardVerticalFirst() +{ + if (!doubleMangaPage) + { + scrollZigzag(DOWN, RIGHT, true); // down->down->upper right->down->...->next page + } + else + { + scrollZigzag(DOWN, LEFT, true); // down->down->upper left->down->...->next page + } +} + +void Viewer::scrollBackwardVerticalFirst() +{ + if (!doubleMangaPage) + { + scrollZigzag(UP, LEFT, false); // up->up->lower left->up->...->prev page + } + else + { + scrollZigzag(UP, RIGHT, false); // up->up->lower right->up->...->prev page + } +} + +bool Viewer::isEdge(scrollDirection d) +{ + if(d == UP) + return verticalScrollBar()->sliderPosition() == verticalScrollBar()->minimum(); + else if(d == DOWN) + return verticalScrollBar()->sliderPosition() == verticalScrollBar()->maximum(); + else if(d == LEFT) + return horizontalScrollBar()->sliderPosition() == horizontalScrollBar()->minimum(); + else // d == RIGHT + return horizontalScrollBar()->sliderPosition() == horizontalScrollBar()->maximum(); +} + +void Viewer::scrollZigzag(scrollDirection d1, scrollDirection d2, bool forward) +{ + if(!isEdge(d1)) + { + if(d1 == UP) + scrollTo(horizontalScrollBar()->sliderPosition(), + verticalScrollBar()->sliderPosition()-static_cast((height()*0.80))); + else if(d1 == DOWN) + scrollTo(horizontalScrollBar()->sliderPosition(), + verticalScrollBar()->sliderPosition()+static_cast((height()*0.80))); + else if(d1 == LEFT) + scrollTo(horizontalScrollBar()->sliderPosition()-static_cast((width()*0.80)), + verticalScrollBar()->sliderPosition()); + else // d1 == RIGHT + scrollTo(horizontalScrollBar()->sliderPosition()+static_cast((width()*0.80)), + verticalScrollBar()->sliderPosition()); + } + else if(!isEdge(d2)) + { + int x = 0; + int y = 0; + + if(d1 == UP) + y = verticalScrollBar()->maximum(); + else if(d1 == DOWN) + y = verticalScrollBar()->minimum(); + else if(d1 == LEFT) + x = horizontalScrollBar()->maximum(); + else // d1 == RIGHT + x = horizontalScrollBar()->minimum(); + + if(d2 == UP) + y = std::max(verticalScrollBar()->sliderPosition()-static_cast((height()*0.80)), verticalScrollBar()->minimum()); + else if(d2 == DOWN) + y = std::min(verticalScrollBar()->sliderPosition()+static_cast((height()*0.80)), verticalScrollBar()->maximum()); + else if(d2 == LEFT) + x = std::max(horizontalScrollBar()->sliderPosition()-static_cast((width()*0.80)), horizontalScrollBar()->minimum()); + else // d2 == RIGHT + x = std::min(horizontalScrollBar()->sliderPosition()+static_cast((width()*0.80)), horizontalScrollBar()->maximum()); + + scrollTo(x, y); + } + else + { + // next or prev page's corner + int savedPageNumber = getCurrentPageNumber(); + + if(forward) + next(); + else + prev(); + + if(savedPageNumber != getCurrentPageNumber()){ + if(d1 == LEFT || d2 == LEFT) + horizontalScrollBar()->setSliderPosition(horizontalScrollBar()->maximum()); + else + horizontalScrollBar()->setSliderPosition(horizontalScrollBar()->minimum()); + emit backgroundChanges(); + } + } +} + +void Viewer::scrollTo(int x, int y) +{ + if(groupScroller->state() == QAbstractAnimation::Running) + return; + horizontalScroller->setDuration(250); + horizontalScroller->setStartValue(horizontalScrollBar()->sliderPosition()); + horizontalScroller->setEndValue(x); + verticalScroller->setDuration(250); + verticalScroller->setStartValue(verticalScrollBar()->sliderPosition()); + verticalScroller->setEndValue(y); + groupScroller->start(); + emit backgroundChanges(); +} + void Viewer::keyPressEvent(QKeyEvent *event) { if(render->hasLoadedComic()) @@ -490,6 +633,26 @@ void Viewer::keyPressEvent(QKeyEvent *event) scrollUp(); } + else if (key == ShortcutsManager::getShortcutsManager().getShortcut(AUTO_SCROLL_FORWARD_HORIZONTAL_FIRST_ACTION_Y)) + { + scrollForwardHorizontalFirst(); + } + + else if (key == ShortcutsManager::getShortcutsManager().getShortcut(AUTO_SCROLL_BACKWARD_HORIZONTAL_FIRST_ACTION_Y)) + { + scrollBackwardHorizontalFirst(); + } + + else if (key == ShortcutsManager::getShortcutsManager().getShortcut(AUTO_SCROLL_FORWARD_VERTICAL_FIRST_ACTION_Y)) + { + scrollForwardVerticalFirst(); + } + + else if (key == ShortcutsManager::getShortcutsManager().getShortcut(AUTO_SCROLL_BACKWARD_VERTICAL_FIRST_ACTION_Y)) + { + scrollBackwardVerticalFirst(); + } + else if (key == ShortcutsManager::getShortcutsManager().getShortcut(MOVE_DOWN_ACTION_Y) || key == ShortcutsManager::getShortcutsManager().getShortcut(MOVE_UP_ACTION_Y) || key == ShortcutsManager::getShortcutsManager().getShortcut(MOVE_LEFT_ACTION_Y) || @@ -799,7 +962,10 @@ void Viewer::doubleMangaPageSwitch() { doubleMangaPage = !doubleMangaPage; render->doubleMangaPageSwitch(); - Configuration::getConfiguration().setDoubleMangaPage(doubleMangaPage); + Configuration &config = Configuration::getConfiguration(); + config.setDoubleMangaPage(doubleMangaPage); + goToFlow->setFlowRightToLeft(doubleMangaPage); + goToFlow->updateConfig(config.getSettings()); } void Viewer::resetContent() diff --git a/YACReader/viewer.h b/YACReader/viewer.h index 7c3a1b67..e22bfb93 100644 --- a/YACReader/viewer.h +++ b/YACReader/viewer.h @@ -14,6 +14,7 @@ #include #include #include +#include #include #include "scroll_management.h" @@ -55,6 +56,10 @@ class NotificationsLabelWidget; void updateOptions(); void scrollDown(); void scrollUp(); + void scrollForwardHorizontalFirst(); + void scrollBackwardHorizontalFirst(); + void scrollForwardVerticalFirst(); + void scrollBackwardVerticalFirst(); void magnifyingGlassSwitch(); void showMagnifyingGlass(); void hideMagnifyingGlass(); @@ -108,6 +113,8 @@ virtual void mouseReleaseEvent ( QMouseEvent * event ); PageLabelWidget * informationLabel; //QTimer * scroller; QPropertyAnimation * verticalScroller; + QPropertyAnimation * horizontalScroller; + QParallelAnimationGroup * groupScroller; int posByStep; int nextPos; GoToFlowWidget * goToFlow; @@ -153,6 +160,12 @@ virtual void mouseReleaseEvent ( QMouseEvent * event ); void wheelEvent(QWheelEvent * event); void mouseMoveEvent(QMouseEvent * event); + //!ZigzagScroll + enum scrollDirection{ UP, DOWN, LEFT, RIGHT }; + bool isEdge(scrollDirection d); + void scrollZigzag(scrollDirection d1, scrollDirection d2, bool forward); + void scrollTo(int x, int y); + public: Viewer(QWidget * parent = 0); ~Viewer(); diff --git a/YACReaderLibrary/library_window.cpp b/YACReaderLibrary/library_window.cpp index 9def54cf..19e3277b 100644 --- a/YACReaderLibrary/library_window.cpp +++ b/YACReaderLibrary/library_window.cpp @@ -2022,6 +2022,48 @@ void LibraryWindow::toggleFullScreen() fullscreen = !fullscreen; } +#ifdef Q_OS_WIN //fullscreen mode in Windows for preventing this bug: QTBUG-41309 https://bugreports.qt.io/browse/QTBUG-41309 +void LibraryWindow::toFullScreen() +{ + fromMaximized = this->isMaximized(); + + sideBar->hide(); + libraryToolBar->hide(); + + previousWindowFlags = windowFlags(); + previousPos = pos(); + previousSize = size(); + + showNormal(); + setWindowFlags(previousWindowFlags | Qt::FramelessWindowHint); + + const QRect r = windowHandle()->screen()->geometry(); + + move(r.x(), r.y()); + resize(r.width(),r.height()+1); + show(); + + comicsViewsManager->comicsView->toFullScreen(); +} + +void LibraryWindow::toNormal() +{ + sideBar->show(); + libraryToolBar->show(); + + setWindowFlags(previousWindowFlags); + move(previousPos); + resize(previousSize); + show(); + + if(fromMaximized) + showMaximized(); + + comicsViewsManager->comicsView->toNormal(); +} + +#else + void LibraryWindow::toFullScreen() { fromMaximized = this->isMaximized(); @@ -2057,6 +2099,8 @@ void LibraryWindow::toNormal() } +#endif + void LibraryWindow::setSearchFilter(const YACReader::SearchModifiers modifier, QString filter) { if(!filter.isEmpty()) diff --git a/YACReaderLibrary/library_window.h b/YACReaderLibrary/library_window.h index 66588c41..e4ec675a 100644 --- a/YACReaderLibrary/library_window.h +++ b/YACReaderLibrary/library_window.h @@ -375,6 +375,12 @@ public slots: void onAddComicsToLabel(); void setToolbarTitle(const QModelIndex & modelIndex); void saveSelectedCoversTo(); + +private: + //fullscreen mode in Windows for preventing this bug: QTBUG-41309 https://bugreports.qt.io/browse/QTBUG-41309 + Qt::WindowFlags previousWindowFlags; + QPoint previousPos; + QSize previousSize; }; #endif diff --git a/YACReaderLibrary/yacreader_comics_views_manager.cpp b/YACReaderLibrary/yacreader_comics_views_manager.cpp index 36991443..21c9fb26 100644 --- a/YACReaderLibrary/yacreader_comics_views_manager.cpp +++ b/YACReaderLibrary/yacreader_comics_views_manager.cpp @@ -12,6 +12,8 @@ #include "empty_reading_list_widget.h" #include "no_search_results_widget.h" +#include "yacreader_sidebar.h" + //-- #include "yacreader_search_line_edit.h" #include "options_dialog.h" @@ -71,6 +73,10 @@ QWidget * YACReaderComicsViewsManager::containerWidget() void YACReaderComicsViewsManager::showComicsView() { comicsViewStack->setCurrentWidget(comicsView); + + //BUG, ugly workaround for glitch when QOpenGLWidget (flow) is used just after any other widget in the views stack + //Somehow QOpenGLWidget is messing with the rendering of the side bar (wrong buffer swapping) + libraryWindow->sideBar->update(); } void YACReaderComicsViewsManager::showEmptyFolderView() diff --git a/common/gl/yacreader_flow_gl.cpp b/common/gl/yacreader_flow_gl.cpp index 7d9628cb..45c30820 100644 --- a/common/gl/yacreader_flow_gl.cpp +++ b/common/gl/yacreader_flow_gl.cpp @@ -200,7 +200,7 @@ struct Preset pressetYACReaderFlowDownConfig = { }; /*Constructor*/ YACReaderFlowGL::YACReaderFlowGL(QWidget *parent,struct Preset p) - :QOpenGLWidget(/*QOpenGLWidget migration QGLFormat(QGL::SampleBuffers),*/ parent),numObjects(0),lazyPopulateObjects(-1),bUseVSync(false),hasBeenInitialized(false) + :QOpenGLWidget(/*QOpenGLWidget migration QGLFormat(QGL::SampleBuffers),*/ parent),numObjects(0),lazyPopulateObjects(-1),bUseVSync(false),hasBeenInitialized(false),flowRightToLeft(false) { updateCount = 0; config = p; @@ -385,7 +385,11 @@ void YACReaderFlowGL::udpatePerspective(int width, int height) /*Private*/ void YACReaderFlowGL::calcPos(YACReader3DImage & image, int pos) { - if(pos == 0){ + if(flowRightToLeft){ + pos = pos * -1; + } + + if(pos == 0){ image.current = centerPos; }else{ if(pos > 0){ @@ -1052,6 +1056,11 @@ void YACReaderFlowGL::render() //do nothing } +void YACReaderFlowGL::setFlowRightToLeft(bool b) +{ + flowRightToLeft = b; +} + //EVENTOS void YACReaderFlowGL::wheelEvent(QWheelEvent * event) @@ -1073,7 +1082,7 @@ void YACReaderFlowGL::wheelEvent(QWheelEvent * event) void YACReaderFlowGL::keyPressEvent(QKeyEvent *event) { - if(event->key() == Qt::Key_Left) + if((event->key() == Qt::Key_Left && !flowRightToLeft) || (event->key() == Qt::Key_Right && flowRightToLeft)) { if(event->modifiers() == Qt::ControlModifier) setCurrentIndex((currentSelected-10<0)?0:currentSelected-10); @@ -1083,7 +1092,7 @@ void YACReaderFlowGL::keyPressEvent(QKeyEvent *event) return; } - if(event->key() == Qt::Key_Right) + if((event->key() == Qt::Key_Right && !flowRightToLeft) || (event->key() == Qt::Key_Left && flowRightToLeft)) { if(event->modifiers() == Qt::ControlModifier) setCurrentIndex((currentSelected+10>=numObjects)?numObjects-1:currentSelected+10); @@ -1128,7 +1137,7 @@ void YACReaderFlowGL::mousePressEvent(QMouseEvent *event) gluUnProject(winX, winY, winZ, modelview, projection, viewport, &posX, &posY, &posZ); - if(posX >= 0.5) + if((posX >= 0.5 && !flowRightToLeft) || (posX <=-0.5 && flowRightToLeft)) { //int index = currentSelected+1; //while((cfImages[index].current.x-cfImages[index].width/(2.0*config.rotation)) < posX) @@ -1136,7 +1145,7 @@ void YACReaderFlowGL::mousePressEvent(QMouseEvent *event) //setCurrentIndex(index-1); showNext(); } - else if(posX <=-0.5) + else if((posX <=-0.5 && !flowRightToLeft) || (posX >= 0.5 && flowRightToLeft) ) showPrevious(); } else QOpenGLWidget::mousePressEvent(event); diff --git a/common/gl/yacreader_flow_gl.h b/common/gl/yacreader_flow_gl.h index 2fc37d51..60cd8ce5 100644 --- a/common/gl/yacreader_flow_gl.h +++ b/common/gl/yacreader_flow_gl.h @@ -173,6 +173,9 @@ protected: //sets the updateInterval in ms static int updateInterval; + // sets flow direction right-to-left (manga mode) + bool flowRightToLeft; + void startAnimationTimer(); void stopAnimationTimer(); @@ -251,6 +254,8 @@ public: void useVSync(bool b); + void setFlowRightToLeft(bool b); + virtual void updateImageData() = 0; void reset(); diff --git a/common/pictureflow.cpp b/common/pictureflow.cpp index d92f4299..61fe2d60 100644 --- a/common/pictureflow.cpp +++ b/common/pictureflow.cpp @@ -207,6 +207,8 @@ public: QVector leftSlides; QVector rightSlides; int centerIndex; + + bool flowRightToLeft; }; class PictureFlowAnimator @@ -281,7 +283,7 @@ private: PictureFlowState::PictureFlowState(int a, float sr): backgroundColor(0), slideWidth(150), slideHeight(200), -reflectionEffect(PictureFlow::BlurredReflection), centerIndex(0) , rawAngle(a), spacingRatio(sr) +reflectionEffect(PictureFlow::BlurredReflection), centerIndex(0) , rawAngle(a), spacingRatio(sr), flowRightToLeft(false) { } @@ -327,7 +329,10 @@ void PictureFlowState::reset() si.angle = angle; si.cx = -(offsetX + spacing*(i)*PFREAL_ONE); si.cy = offsetY; - si.slideIndex = centerIndex-1-i; + if(!flowRightToLeft) + si.slideIndex = centerIndex-1-i; + else + si.slideIndex = centerIndex+1+i; si.blend = 200; if(i == (int)leftSlides.count()-2) si.blend = 128; @@ -344,7 +349,10 @@ void PictureFlowState::reset() si.angle = -angle; si.cx = offsetX + spacing*(i)*PFREAL_ONE; si.cy = offsetY; - si.slideIndex = centerIndex+1+i; + if(!flowRightToLeft) + si.slideIndex = centerIndex+1+i; + else + si.slideIndex = centerIndex-1-i; si.blend = 200; if(i == (int)rightSlides.count()-2) si.blend = 128; @@ -423,13 +431,31 @@ void PictureFlowAnimator::update() frame = index << 16; state->centerSlide.slideIndex = state->centerIndex; for(int i = 0; i < (int)state->leftSlides.count(); i++) - state->leftSlides[i].slideIndex = state->centerIndex-1-i; + { + if(!state->flowRightToLeft) + state->leftSlides[i].slideIndex = state->centerIndex-1-i; + else + state->leftSlides[i].slideIndex = state->centerIndex+1+i; + } for(int i = 0; i < (int)state->rightSlides.count(); i++) - state->rightSlides[i].slideIndex = state->centerIndex+1+i; + { + if(!state->flowRightToLeft) + state->rightSlides[i].slideIndex = state->centerIndex+1+i; + else + state->rightSlides[i].slideIndex = state->centerIndex-1-i; + } } - state->centerSlide.angle = (step * tick * state->angle) >> 16; - state->centerSlide.cx = -step * fmul(state->offsetX, ftick); + if(!state->flowRightToLeft) + { + state->centerSlide.angle = (step * tick * state->angle) >> 16; + state->centerSlide.cx = -step * fmul(state->offsetX, ftick); + } + else + { + state->centerSlide.angle = (-step * tick * state->angle) >> 16; + state->centerSlide.cx = step * fmul(state->offsetX, ftick); + } state->centerSlide.cy = fmul(state->offsetY, ftick); if(state->centerIndex == target) @@ -443,7 +469,10 @@ void PictureFlowAnimator::update() { SlideInfo& si = state->leftSlides[i]; si.angle = state->angle; - si.cx = -(state->offsetX + state->spacing*(i)*PFREAL_ONE + step*state->spacing*ftick); + if(!state->flowRightToLeft) + si.cx = -(state->offsetX + state->spacing*(i)*PFREAL_ONE + step*state->spacing*ftick); + else + si.cx = -(state->offsetX + state->spacing*(i)*PFREAL_ONE - step*state->spacing*ftick); si.cy = state->offsetY; } @@ -451,24 +480,41 @@ void PictureFlowAnimator::update() { SlideInfo& si = state->rightSlides[i]; si.angle = -state->angle; - si.cx = state->offsetX + state->spacing*(i)*PFREAL_ONE - step*state->spacing*ftick; + if(!state->flowRightToLeft) + si.cx = state->offsetX + state->spacing*(i)*PFREAL_ONE - step*state->spacing*ftick; + else + si.cx = state->offsetX + state->spacing*(i)*PFREAL_ONE + step*state->spacing*ftick; si.cy = state->offsetY; } - if(step > 0) + if(step > 0 && !state->flowRightToLeft) { PFreal ftick = (neg * PFREAL_ONE) >> 16; state->rightSlides[0].angle = -(neg * state->angle) >> 16; state->rightSlides[0].cx = fmul(state->offsetX, ftick); state->rightSlides[0].cy = fmul(state->offsetY, ftick); } - else + else if(!state->flowRightToLeft) { PFreal ftick = (pos * PFREAL_ONE) >> 16; state->leftSlides[0].angle = (pos * state->angle) >> 16; state->leftSlides[0].cx = -fmul(state->offsetX, ftick); state->leftSlides[0].cy = fmul(state->offsetY, ftick); } + else if(step < 0) + { + PFreal ftick = (pos * PFREAL_ONE) >> 16; + state->rightSlides[0].angle = -(pos * state->angle) >> 16; + state->rightSlides[0].cx = fmul(state->offsetX, ftick); + state->rightSlides[0].cy = fmul(state->offsetY, ftick); + } + else + { + PFreal ftick = (neg * PFREAL_ONE) >> 16; + state->leftSlides[0].angle = (neg * state->angle) >> 16; + state->leftSlides[0].cx = -fmul(state->offsetX, ftick); + state->leftSlides[0].cy = fmul(state->offsetY, ftick); + } // must change direction ? if(target < index) if(step > 0) @@ -1053,6 +1099,13 @@ void PictureFlow::setReflectionEffect(ReflectionEffect effect) triggerRender(); } +void PictureFlow::setFlowRightToLeft(bool b) +{ + d->state->flowRightToLeft = b; + d->state->reset(); + triggerRender(); +} + QImage PictureFlow::slide(int index) const { QImage* i = 0; @@ -1225,7 +1278,8 @@ void PictureFlow::showSlide(unsigned int index) void PictureFlow::keyPressEvent(QKeyEvent* event) { - if(event->key() == Qt::Key_Left) + if((event->key() == Qt::Key_Left && !(d->state->flowRightToLeft)) + || (event->key() == Qt::Key_Right && d->state->flowRightToLeft)) { /*if(event->modifiers() == Qt::ControlModifier) showSlide(centerIndex()-10); @@ -1235,7 +1289,8 @@ void PictureFlow::keyPressEvent(QKeyEvent* event) return; } - if(event->key() == Qt::Key_Right) + if((event->key() == Qt::Key_Right && !(d->state->flowRightToLeft)) + || (event->key() == Qt::Key_Left && d->state->flowRightToLeft)) { /*if(event->modifiers() == Qt::ControlModifier) showSlide(centerIndex()+10); @@ -1256,10 +1311,19 @@ void PictureFlow::keyPressEvent(QKeyEvent* event) void PictureFlow::mousePressEvent(QMouseEvent* event) { - if(event->x() > width()/2) + mousePressEvent(event, 0); +} + +void PictureFlow::mousePressEvent(QMouseEvent* event, int slideWidth) +{ + if((event->x() > (width() + slideWidth)/2 && !(d->state->flowRightToLeft)) + || (event->x() < (width() - slideWidth)/2 && d->state->flowRightToLeft)) showNext(); - else - showPrevious(); + else if((event->x() < (width() - slideWidth)/2 && !(d->state->flowRightToLeft)) + || (event->x() > (width() + slideWidth)/2 && d->state->flowRightToLeft)) + showPrevious(); + + //else (centered slide space) } void PictureFlow::paintEvent(QPaintEvent* event) diff --git a/common/pictureflow.h b/common/pictureflow.h index 0ac197d4..df071d2a 100644 --- a/common/pictureflow.h +++ b/common/pictureflow.h @@ -119,7 +119,12 @@ public: */ void setReflectionEffect(ReflectionEffect effect); + /*! + Sets the flow direction right-to-left (manga mode) + */ + void setFlowRightToLeft(bool b); + public slots: /*! @@ -213,6 +218,7 @@ public: void paintEvent(QPaintEvent *event); void keyPressEvent(QKeyEvent* event); void mousePressEvent(QMouseEvent* event); + void mousePressEvent(QMouseEvent* event, int slideWidth); void resizeEvent(QResizeEvent* event); private slots: diff --git a/custom_widgets/yacreader_flow.cpp b/custom_widgets/yacreader_flow.cpp index e40507d3..7da4715f 100644 --- a/custom_widgets/yacreader_flow.cpp +++ b/custom_widgets/yacreader_flow.cpp @@ -7,12 +7,7 @@ YACReaderFlow::YACReaderFlow(QWidget * parent,FlowType flowType) : PictureFlow(p void YACReaderFlow::mousePressEvent(QMouseEvent* event) { - if(event->x() > (width()+slideSize().width())/2) - showNext(); - else - if(event->x() < (width()-slideSize().width())/2) - showPrevious(); - //else (centered cover space) + PictureFlow::mousePressEvent(event, slideSize().width()); } void YACReaderFlow::mouseDoubleClickEvent(QMouseEvent* event) diff --git a/custom_widgets/yacreader_options_dialog.cpp b/custom_widgets/yacreader_options_dialog.cpp index db4d1f34..b8ec1aca 100644 --- a/custom_widgets/yacreader_options_dialog.cpp +++ b/custom_widgets/yacreader_options_dialog.cpp @@ -356,46 +356,46 @@ void YACReaderOptionsDialog::setOverlappedStripeConfigSW() #ifndef NO_OPENGL void YACReaderOptionsDialog::setClassicConfig() { - settings->setValue(FLOW_TYPE_GL,CoverFlowLike); - gl->setValues(presetYACReaderFlowClassicConfig); saveFlowParameters(); + + settings->setValue(FLOW_TYPE_GL,CoverFlowLike); } void YACReaderOptionsDialog::setStripeConfig() { - settings->setValue(FLOW_TYPE_GL,Strip); - gl->setValues(presetYACReaderFlowStripeConfig); saveFlowParameters(); + + settings->setValue(FLOW_TYPE_GL,Strip); } void YACReaderOptionsDialog::setOverlappedStripeConfig() { - settings->setValue(FLOW_TYPE_GL,StripOverlapped); - gl->setValues(presetYACReaderFlowOverlappedStripeConfig); saveFlowParameters(); + + settings->setValue(FLOW_TYPE_GL,StripOverlapped); } void YACReaderOptionsDialog::setModernConfig() { - settings->setValue(FLOW_TYPE_GL,Modern); - gl->setValues(defaultYACReaderFlowConfig); saveFlowParameters(); + + settings->setValue(FLOW_TYPE_GL,Modern); } void YACReaderOptionsDialog::setRouletteConfig() { - settings->setValue(FLOW_TYPE_GL,Roulette); - gl->setValues(pressetYACReaderFlowDownConfig); saveFlowParameters(); + + settings->setValue(FLOW_TYPE_GL,Roulette); } #endif diff --git a/shortcuts_management/shortcuts_manager.h b/shortcuts_management/shortcuts_manager.h index 24aa40ef..7997a4f2 100644 --- a/shortcuts_management/shortcuts_manager.h +++ b/shortcuts_management/shortcuts_manager.h @@ -125,6 +125,10 @@ public: //viewer #define AUTO_SCROLL_FORWARD_ACTION_Y "AUTO_SCROLL_FORWARD_ACTION_Y" #define AUTO_SCROLL_BACKWARD_ACTION_Y "AUTO_SCROLL_BACKWARD_ACTION_Y" +#define AUTO_SCROLL_FORWARD_VERTICAL_FIRST_ACTION_Y "AUTO_SCROLL_FORWARD_VERTICAL_FIRST_ACTION_Y" +#define AUTO_SCROLL_BACKWARD_VERTICAL_FIRST_ACTION_Y "AUTO_SCROLL_BACKWARD_VERTICAL_FIRST_ACTION_Y" +#define AUTO_SCROLL_FORWARD_HORIZONTAL_FIRST_ACTION_Y "AUTO_SCROLL_FORWARD_HORIZONTAL_FIRST_ACTION_Y" +#define AUTO_SCROLL_BACKWARD_HORIZONTAL_FIRST_ACTION_Y "AUTO_SCROLL_BACKWARD_HORIZONTAL_FIRST_ACTION_Y" #define MOVE_DOWN_ACTION_Y "MOVE_DOWN_ACTION_Y" #define MOVE_UP_ACTION_Y "MOVE_UP_ACTION_Y" #define MOVE_LEFT_ACTION_Y "MOVE_LEFT_ACTION_Y"