Merge pull request #346 from YACReader/develop

9.10 release
This commit is contained in:
Luis Ángel San Martín 2022-10-30 08:43:40 +01:00 committed by GitHub
commit 6cc92a260c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
438 changed files with 18305 additions and 3681 deletions

1
.gitignore vendored
View File

@ -45,6 +45,7 @@ Makefile*
*.xcworkspace*
*xcshareddata*
*.swp
*.qm
# Qt unit tests
target_wrapper.*

View File

@ -2,6 +2,28 @@
Version counting is based on semantic versioning (Major.Feature.Patch)
## 9.10
### YACReader
* Fixed color selection dialog appearing as a subwindow in macos.
* Better support for HDPI screens (SVG icons).
### YACReaderLibrary
* Update QtWebApp webserver to v1.8.6
* New folder content view that replaces the old `subfolders in this folder` view shown when folders don't have direct comics.
* Fixed going forward in history navigation.
* Continue Reading view that it is shown for the root folder.
* UI gets updated when YACReaderLibrary gets updates from YACReader or YACReader for iOS.
* Linux: Add fallback for dynamically loading libqrencode on distros that don't provide unversioned library symlinks
* Fixed selected folder restoration after folder updates.
* Better support for HDPI screens (SVG icons).
* Add option to delete metadata from comics.
* Importing ComicInfo.XML is now optional and disabled by default, you can change the behavior in Settings -> General.
* Add option to scan XML metadata from all the comics in a folder.
### Server
* Add webui status page (reachable by navigating to server::port/webui)
## 9.9.2
### General

View File

@ -21,6 +21,8 @@ This software has been developed by Luis Ángel San Martín Rodríguez
### Official releases:
[https://github.com/YACReader/yacreader/releases](https://github.com/YACReader/yacreader/releases)
[<img src="https://flathub.org/assets/badges/flathub-badge-en.png" width="100"/>](https://flathub.org/apps/details/com.yacreader.YACReader)
### As a package:
[![Packaging status](https://repology.org/badge/vertical-allrepos/yacreader.svg)](https://repology.org/metapackage/yacreader)
@ -47,20 +49,20 @@ If you need help or have any suggestion, please, send me an e-mail.
## Contributing
If you are interested in contributing to the project the first step should be to contact me so we can plan together the best approach, you can send an e-mail or just open an issue in this repo. For small bug fixes it is usually ok to open a PR directly.
Contributions are not restricted to code, you can help the project by bringing new UI/UX ideas, designing new assets, writing manuals or tutorials, translating the apps, etc. If you are interested in DevOps, YACReader uses Azure Pipelines for CI/CD, any improvements in that area are welcome. Testing pre-releases is also really appreciated.
Contributions are not restricted to coding; you can help the project by bringing new UI/UX ideas, designing new assets, writing manuals or tutorials, translating the apps, etc. If you are interested in DevOps, YACReader uses Azure Pipelines for CI/CD, any improvements in that area are welcome. Testing pre-releases is also really appreciated.
#### Dev Setup
YACReader is developed in *c++/Qt*, so the first thing you need to do is to install a *C++* compiler or environment that supports at least *C++17* and *Qt*. In *Windows* I use *Visual Studio Community Edition 2019* as build system and in *macos* I use Xcode, but I do all the coding using *QtCreator*. The project is adding support to *Qt6* and it alreaady compiles under it but it is not ready to ship, so you need to make sure that everything works in both *Qt5* and *Qt6*, you only need to install *Qt5* for now and *CI* will check that everything builds with *Qt6*.
YACReader is developed in *c++/Qt*, so the first thing you need to do is to install a *C++* compiler or environment that supports at least *C++17* and *Qt*. In *Windows* I use *Visual Studio Community Edition 2019* as build system and in *macos* I use Xcode, but I do all the coding using *QtCreator*. The project is adding support to *Qt6* and it already compiles under it but it is not ready to ship, so you need to make sure that everything works in both *Qt5* and *Qt6*, you only need to install *Qt5* for now and *CI* will check that everything builds with *Qt6*.
The repo includes binaries for the dependencies needed for *Windows* (MSVC compiler) and *macos* (clang) but you need to configure *7zip/p7zip* dependency manually, please take a look at *compressed_archive/README_7zip.txt*.
##### Running and debuging
YACReader needs to find its dependencies at runtime, make sure that *Qt* binaries are in your *PATH* and the third party binaries are next to the executable. The best way to make sure you have all the thirdparty binaries in place is to check YACReader installation and copying the binaries in your output folder.
##### Running and debugging
YACReader needs to find its dependencies at runtime, make sure that *Qt* binaries are in your *PATH* and the third-party binaries are next to the executable. The best way to make sure you have all the third-party binaries in place is to check YACReader installation and copy the binaries in your output folder.
If you have the time and the energy, please open a PR with a script that automatizes any of these manual proceses.
If you have the time and the energy, please open a PR with a script that automatizes any of these manual processes.
#### Code Format
YACReader uses `clang-format` to ensure a common style and avoid deviances from it. CI checks this and will fail if the correct format is not used. `clang-format` needs to be called recursively in all the folders because some of them have the own `.clang-format` file, mainly to exclude changing the format in third-party libraries which are included in the source code. I recommend to configure your development tools to use `clang-format`, you can try to use it manually, but please, do it always before committing changes. I recommend using QtCreator configured properly, you can find a tutorial [here]( https://www.vikingsoftware.com/using-clang-format-with-qtcreator/).
YACReader uses `clang-format` to ensure a common style and avoid deviances from it. CI checks this and will fail if the correct format is not used. `clang-format` needs to be called recursively in all the folders because some of them have their own `.clang-format` file, mainly to exclude changing the format in third-party libraries which are included in the source code. I recommend configuring your development tools to use `clang-format`, you can try to use it manually, but please, do it always before committing changes. I recommend using QtCreator configured properly, you can find a tutorial [here]( https://www.vikingsoftware.com/using-clang-format-with-qtcreator/).
#### CI/CD
Any PR will be validated through CI, and it will not be merged if CI fails.
@ -70,3 +72,6 @@ The base and target branch for any PR should always be `develop`.
## Donations
YACReader is free but it needs money to keep being alive, so please, if you like YACReader, visit the home page and make a donation.
## Hacktoberfest
If you are interested in YACReader, please contact me so we can discuss your next steps.

View File

@ -173,10 +173,6 @@ include(../shortcuts_management/shortcuts_management.pri)
RESOURCES += yacreader_images.qrc \
yacreader_files.qrc
win32:RESOURCES += yacreader_images_win.qrc
unix:!macx:RESOURCES += yacreader_images_win.qrc
macx:RESOURCES += yacreader_images_osx.qrc
include(../third_party/QsLog/QsLog.pri)
RC_FILE = icon.rc
@ -197,7 +193,28 @@ TRANSLATIONS = yacreader_es.ts \
yacreader_zh_TW.ts \
yacreader_zh_HK.ts \
yacreader_it.ts \
yacreader_source.ts
yacreader_en.ts
CONFIG += lrelease
win32 {
CONFIG(release, debug|release) {
SOURCE_QM_DIR = $$OUT_PWD/release/*.qm
}
CONFIG(debug, debug|release) {
SOURCE_QM_DIR = $$OUT_PWD/debug/*.qm
}
DEPLOYMENT_OUT_QM_DIR = ../release/languages/
OUT_QM_DIR = $${DESTDIR}/languages/
QMAKE_POST_LINK += $(MKDIR) $$shell_path($${OUT_QM_DIR}) 2> NULL & \
$(COPY) $$shell_path($${SOURCE_QM_DIR}) $$shell_path($${OUT_QM_DIR}) & \
$(MKDIR) $$shell_path($${DEPLOYMENT_OUT_QM_DIR}) 2> NULL & \
$(COPY) $$shell_path($${SOURCE_QM_DIR}) $$shell_path($${DEPLOYMENT_OUT_QM_DIR})
} else {
LRELEASE_DIR = ../release/languages/
}
unix:!macx {
# set install prefix if it's empty

View File

@ -173,11 +173,10 @@ int main(int argc, char *argv[])
logger.addDestination(std::move(fileDestination));
QTranslator translator;
QString sufix = QLocale::system().name();
#if defined Q_OS_UNIX && !defined Q_OS_MAC
translator.load(QString(DATADIR) + "/yacreader/languages/yacreader_" + sufix);
translator.load(QLocale(), "yacreader", "_", QString(DATADIR) + "/yacreader/languages");
#else
translator.load(QCoreApplication::applicationDirPath() + "/languages/yacreader_" + sufix);
translator.load(QLocale(), "yacreader", "_", "languages");
#endif
app.installTranslator(&translator);
auto mwv = new MainWindowViewer();

View File

@ -36,41 +36,6 @@
#include <QDate>
#include <QMenuBar>
/* TODO remove, no longer used
#ifdef Q_OS_MAC
class MacToolBarSeparator : public QWidget
{
public:
MacToolBarSeparator(QWidget * parent =0)
:QWidget(parent)
{
setFixedWidth(2);
}
void paintEvent(QPaintEvent *event)
{
Q_UNUSED(event);
QPainter painter(this);
QLinearGradient lG(0,0,0,height());
lG.setColorAt(0,QColor(128,128,128,0));
lG.setColorAt(0.5,QColor(128,128,128,255));
lG.setColorAt(1,QColor(128,128,128,0));
painter.fillRect(0,0,1,height(),lG);
QLinearGradient lG2(1,0,1,height());
lG2.setColorAt(0,QColor(220,220,220,0));
lG2.setColorAt(0.5,QColor(220,220,220,255));
lG2.setColorAt(1,QColor(220,220,220,0));
painter.fillRect(1,0,1,height(),lG2);
}
};
#endif*/
MainWindowViewer::MainWindowViewer()
: QMainWindow(), fullscreen(false), toolbars(true), currentDirectory("."), currentDirectoryImgDest("."), isClient(false)
{
@ -217,7 +182,7 @@ void MainWindowViewer::setupUI()
void MainWindowViewer::createActions()
{
openAction = new QAction(tr("&Open"), this);
openAction->setIcon(QIcon(":/images/viewer_toolbar/open.png"));
openAction->setIcon(QIcon(addExtensionToIconPath(":/images/viewer_toolbar/open")));
openAction->setToolTip(tr("Open a comic"));
openAction->setData(OPEN_ACTION_Y);
openAction->setShortcut(ShortcutsManager::getShortcutsManager().getShortcut(OPEN_ACTION_Y));
@ -244,7 +209,7 @@ void MainWindowViewer::createActions()
#endif
openFolderAction = new QAction(tr("Open Folder"), this);
openFolderAction->setIcon(QIcon(":/images/viewer_toolbar/openFolder.png"));
openFolderAction->setIcon(QIcon(addExtensionToIconPath(":/images/viewer_toolbar/openFolder")));
openFolderAction->setToolTip(tr("Open image folder"));
openFolderAction->setData(OPEN_FOLDER_ACTION_Y);
openFolderAction->setShortcut(ShortcutsManager::getShortcutsManager().getShortcut(OPEN_FOLDER_ACTION_Y));
@ -268,28 +233,28 @@ void MainWindowViewer::createActions()
connect(clearRecentFilesAction, &QAction::triggered, this, &MainWindowViewer::clearRecentFiles);
saveImageAction = new QAction(tr("Save"), this);
saveImageAction->setIcon(QIcon(":/images/viewer_toolbar/save.png"));
saveImageAction->setIcon(QIcon(addExtensionToIconPath(":/images/viewer_toolbar/save")));
saveImageAction->setToolTip(tr("Save current page"));
saveImageAction->setData(SAVE_IMAGE_ACTION_Y);
saveImageAction->setShortcut(ShortcutsManager::getShortcutsManager().getShortcut(SAVE_IMAGE_ACTION_Y));
connect(saveImageAction, &QAction::triggered, this, &MainWindowViewer::saveImage);
openComicOnTheLeftAction = new QAction(tr("Previous Comic"), this);
openComicOnTheLeftAction->setIcon(QIcon(":/images/viewer_toolbar/openPrevious.png"));
openComicOnTheLeftAction->setIcon(QIcon(addExtensionToIconPath(":/images/viewer_toolbar/openPrevious")));
openComicOnTheLeftAction->setToolTip(tr("Open previous comic"));
openComicOnTheLeftAction->setData(OPEN_PREVIOUS_COMIC_ACTION_Y);
openComicOnTheLeftAction->setShortcut(ShortcutsManager::getShortcutsManager().getShortcut(OPEN_PREVIOUS_COMIC_ACTION_Y));
connect(openComicOnTheLeftAction, &QAction::triggered, this, &MainWindowViewer::openLeftComic);
openComicOnTheRightAction = new QAction(tr("Next Comic"), this);
openComicOnTheRightAction->setIcon(QIcon(":/images/viewer_toolbar/openNext.png"));
openComicOnTheRightAction->setIcon(QIcon(addExtensionToIconPath(":/images/viewer_toolbar/openNext")));
openComicOnTheRightAction->setToolTip(tr("Open next comic"));
openComicOnTheRightAction->setData(OPEN_NEXT_COMIC_ACTION_Y);
openComicOnTheRightAction->setShortcut(ShortcutsManager::getShortcutsManager().getShortcut(OPEN_NEXT_COMIC_ACTION_Y));
connect(openComicOnTheRightAction, &QAction::triggered, this, &MainWindowViewer::openRightComic);
goToPageOnTheLeftAction = new QAction(tr("&Previous"), this);
goToPageOnTheLeftAction->setIcon(QIcon(":/images/viewer_toolbar/previous.png"));
goToPageOnTheLeftAction->setIcon(QIcon(addExtensionToIconPath(":/images/viewer_toolbar/previous")));
goToPageOnTheLeftAction->setShortcutContext(Qt::WidgetShortcut);
goToPageOnTheLeftAction->setToolTip(tr("Go to previous page"));
goToPageOnTheLeftAction->setData(PREV_ACTION_Y);
@ -297,7 +262,7 @@ void MainWindowViewer::createActions()
connect(goToPageOnTheLeftAction, &QAction::triggered, viewer, &Viewer::left);
goToPageOnTheRightAction = new QAction(tr("&Next"), this);
goToPageOnTheRightAction->setIcon(QIcon(":/images/viewer_toolbar/next.png"));
goToPageOnTheRightAction->setIcon(QIcon(addExtensionToIconPath(":/images/viewer_toolbar/next")));
goToPageOnTheRightAction->setShortcutContext(Qt::WidgetShortcut);
goToPageOnTheRightAction->setToolTip(tr("Go to next page"));
goToPageOnTheRightAction->setData(NEXT_ACTION_Y);
@ -305,27 +270,27 @@ void MainWindowViewer::createActions()
connect(goToPageOnTheRightAction, &QAction::triggered, viewer, &Viewer::right);
adjustHeightAction = new QAction(tr("Fit Height"), this);
adjustHeightAction->setIcon(QIcon(":/images/viewer_toolbar/toHeight.png"));
adjustHeightAction->setIcon(QIcon(addExtensionToIconPath(":/images/viewer_toolbar/toHeight")));
// adjustWidth->setCheckable(true);
adjustHeightAction->setToolTip(tr("Fit image to height"));
// adjustWidth->setIcon(QIcon(":/images/fitWidth.png"));
// adjustWidth->setIcon(QIcon(":/images/fitWidth.svg"));
adjustHeightAction->setData(ADJUST_HEIGHT_ACTION_Y);
adjustHeightAction->setShortcut(ShortcutsManager::getShortcutsManager().getShortcut(ADJUST_HEIGHT_ACTION_Y));
adjustHeightAction->setCheckable(true);
connect(adjustHeightAction, &QAction::triggered, this, &MainWindowViewer::fitToHeight);
adjustWidthAction = new QAction(tr("Fit Width"), this);
adjustWidthAction->setIcon(QIcon(":/images/viewer_toolbar/toWidth.png"));
adjustWidthAction->setIcon(QIcon(addExtensionToIconPath(":/images/viewer_toolbar/toWidth")));
// adjustWidth->setCheckable(true);
adjustWidthAction->setToolTip(tr("Fit image to width"));
// adjustWidth->setIcon(QIcon(":/images/fitWidth.png"));
// adjustWidth->setIcon(QIcon(":/images/fitWidth.svg"));
adjustWidthAction->setData(ADJUST_WIDTH_ACTION_Y);
adjustWidthAction->setShortcut(ShortcutsManager::getShortcutsManager().getShortcut(ADJUST_WIDTH_ACTION_Y));
adjustWidthAction->setCheckable(true);
connect(adjustWidthAction, &QAction::triggered, this, &MainWindowViewer::fitToWidth);
adjustToFullSizeAction = new QAction(tr("Show full size"), this);
adjustToFullSizeAction->setIcon(QIcon(":/images/viewer_toolbar/full.png"));
adjustToFullSizeAction->setIcon(QIcon(addExtensionToIconPath(":/images/viewer_toolbar/full")));
adjustToFullSizeAction->setCheckable(false);
adjustToFullSizeAction->setData(ADJUST_TO_FULL_SIZE_ACTION_Y);
adjustToFullSizeAction->setShortcut(ShortcutsManager::getShortcutsManager().getShortcut(ADJUST_TO_FULL_SIZE_ACTION_Y));
@ -333,7 +298,7 @@ void MainWindowViewer::createActions()
connect(adjustToFullSizeAction, &QAction::triggered, this, &MainWindowViewer::adjustToFullSizeSwitch);
fitToPageAction = new QAction(tr("Fit to page"), this);
fitToPageAction->setIcon(QIcon(":/images/viewer_toolbar/fitToPage.png"));
fitToPageAction->setIcon(QIcon(addExtensionToIconPath(":/images/viewer_toolbar/fitToPage")));
fitToPageAction->setData(FIT_TO_PAGE_ACTION_Y);
fitToPageAction->setShortcut(ShortcutsManager::getShortcutsManager().getShortcut(FIT_TO_PAGE_ACTION_Y));
fitToPageAction->setCheckable(true);
@ -369,7 +334,7 @@ void MainWindowViewer::createActions()
connect(resetZoomAction, &QAction::triggered, this, &MainWindowViewer::resetZoomLevel);
showZoomSliderlAction = new QAction(tr("Show zoom slider"), this);
showZoomSliderlAction->setIcon(QIcon(":/images/viewer_toolbar/zoom.png"));
showZoomSliderlAction->setIcon(QIcon(addExtensionToIconPath(":/images/viewer_toolbar/zoom")));
increasePageZoomAction = new QAction(tr("Zoom+"), this);
increasePageZoomAction->setData(ZOOM_PLUS_ACTION_Y);
@ -382,20 +347,20 @@ void MainWindowViewer::createActions()
connect(decreasePageZoomAction, &QAction::triggered, this, &MainWindowViewer::decreasePageZoomLevel);
leftRotationAction = new QAction(tr("Rotate image to the left"), this);
leftRotationAction->setIcon(QIcon(":/images/viewer_toolbar/rotateL.png"));
leftRotationAction->setIcon(QIcon(addExtensionToIconPath(":/images/viewer_toolbar/rotateL")));
leftRotationAction->setData(LEFT_ROTATION_ACTION_Y);
leftRotationAction->setShortcut(ShortcutsManager::getShortcutsManager().getShortcut(LEFT_ROTATION_ACTION_Y));
connect(leftRotationAction, &QAction::triggered, viewer, &Viewer::rotateLeft);
rightRotationAction = new QAction(tr("Rotate image to the right"), this);
rightRotationAction->setIcon(QIcon(":/images/viewer_toolbar/rotateR.png"));
rightRotationAction->setIcon(QIcon(addExtensionToIconPath(":/images/viewer_toolbar/rotateR")));
rightRotationAction->setData(RIGHT_ROTATION_ACTION_Y);
rightRotationAction->setShortcut(ShortcutsManager::getShortcutsManager().getShortcut(RIGHT_ROTATION_ACTION_Y));
connect(rightRotationAction, &QAction::triggered, viewer, &Viewer::rotateRight);
doublePageAction = new QAction(tr("Double page mode"), this);
doublePageAction->setToolTip(tr("Switch to double page mode"));
doublePageAction->setIcon(QIcon(":/images/viewer_toolbar/doublePage.png"));
doublePageAction->setIcon(QIcon(addExtensionToIconPath(":/images/viewer_toolbar/doublePage")));
doublePageAction->setCheckable(true);
doublePageAction->setChecked(Configuration::getConfiguration().getDoublePage());
doublePageAction->setData(DOUBLE_PAGE_ACTION_Y);
@ -405,7 +370,7 @@ void MainWindowViewer::createActions()
// inversed pictures mode
doubleMangaPageAction = new QAction(tr("Double page manga mode"), this);
doubleMangaPageAction->setToolTip(tr("Reverse reading order in double page mode"));
doubleMangaPageAction->setIcon(QIcon(":/images/viewer_toolbar/doubleMangaPage.png"));
doubleMangaPageAction->setIcon(QIcon(addExtensionToIconPath(":/images/viewer_toolbar/doubleMangaPage")));
doubleMangaPageAction->setCheckable(true);
doubleMangaPageAction->setChecked(Configuration::getConfiguration().getDoubleMangaPage());
doubleMangaPageAction->setData(DOUBLE_MANGA_PAGE_ACTION_Y);
@ -414,7 +379,7 @@ void MainWindowViewer::createActions()
connect(doubleMangaPageAction, &QAction::triggered, this, &MainWindowViewer::doubleMangaPageSwitch);
goToPageAction = new QAction(tr("Go To"), this);
goToPageAction->setIcon(QIcon(":/images/viewer_toolbar/goto.png"));
goToPageAction->setIcon(QIcon(addExtensionToIconPath(":/images/viewer_toolbar/goto")));
goToPageAction->setToolTip(tr("Go to page ..."));
goToPageAction->setData(GO_TO_PAGE_ACTION_Y);
goToPageAction->setShortcut(ShortcutsManager::getShortcutsManager().getShortcut(GO_TO_PAGE_ACTION_Y));
@ -424,20 +389,20 @@ void MainWindowViewer::createActions()
optionsAction->setToolTip(tr("YACReader options"));
optionsAction->setData(OPTIONS_ACTION_Y);
optionsAction->setShortcut(ShortcutsManager::getShortcutsManager().getShortcut(OPTIONS_ACTION_Y));
optionsAction->setIcon(QIcon(":/images/viewer_toolbar/options.png"));
optionsAction->setIcon(QIcon(addExtensionToIconPath(":/images/viewer_toolbar/options")));
connect(optionsAction, &QAction::triggered, optionsDialog, &OptionsDialog::show);
helpAboutAction = new QAction(tr("Help"), this);
helpAboutAction->setToolTip(tr("Help, About YACReader"));
helpAboutAction->setIcon(QIcon(":/images/viewer_toolbar/help.png"));
helpAboutAction->setIcon(QIcon(addExtensionToIconPath(":/images/viewer_toolbar/help")));
helpAboutAction->setData(HELP_ABOUT_ACTION_Y);
helpAboutAction->setShortcut(ShortcutsManager::getShortcutsManager().getShortcut(HELP_ABOUT_ACTION_Y));
connect(helpAboutAction, &QAction::triggered, had, &QWidget::show);
showMagnifyingGlassAction = new QAction(tr("Magnifying glass"), this);
showMagnifyingGlassAction->setToolTip(tr("Switch Magnifying glass"));
showMagnifyingGlassAction->setIcon(QIcon(":/images/viewer_toolbar/magnifyingGlass.png"));
showMagnifyingGlassAction->setIcon(QIcon(addExtensionToIconPath(":/images/viewer_toolbar/magnifyingGlass")));
showMagnifyingGlassAction->setCheckable(true);
showMagnifyingGlassAction->setData(SHOW_MAGNIFYING_GLASS_ACTION_Y);
showMagnifyingGlassAction->setShortcut(ShortcutsManager::getShortcutsManager().getShortcut(SHOW_MAGNIFYING_GLASS_ACTION_Y));
@ -445,7 +410,7 @@ void MainWindowViewer::createActions()
setBookmarkAction = new QAction(tr("Set bookmark"), this);
setBookmarkAction->setToolTip(tr("Set a bookmark on the current page"));
setBookmarkAction->setIcon(QIcon(":/images/viewer_toolbar/bookmark.png"));
setBookmarkAction->setIcon(QIcon(addExtensionToIconPath(":/images/viewer_toolbar/bookmark")));
setBookmarkAction->setCheckable(true);
setBookmarkAction->setData(SET_BOOKMARK_ACTION_Y);
setBookmarkAction->setShortcut(ShortcutsManager::getShortcutsManager().getShortcut(SET_BOOKMARK_ACTION_Y));
@ -455,39 +420,38 @@ void MainWindowViewer::createActions()
showBookmarksAction = new QAction(tr("Show bookmarks"), this);
showBookmarksAction->setToolTip(tr("Show the bookmarks of the current comic"));
showBookmarksAction->setIcon(QIcon(":/images/viewer_toolbar/showBookmarks.png"));
showBookmarksAction->setIcon(QIcon(addExtensionToIconPath(":/images/viewer_toolbar/showBookmarks")));
showBookmarksAction->setData(SHOW_BOOKMARKS_ACTION_Y);
showBookmarksAction->setShortcut(ShortcutsManager::getShortcutsManager().getShortcut(SHOW_BOOKMARKS_ACTION_Y));
connect(showBookmarksAction, &QAction::triggered, viewer->getBookmarksDialog(), &QWidget::show);
showShorcutsAction = new QAction(tr("Show keyboard shortcuts"), this);
showShorcutsAction->setIcon(QIcon(":/images/viewer_toolbar/shortcuts.png"));
showShorcutsAction->setIcon(QIcon(addExtensionToIconPath(":/images/viewer_toolbar/shortcuts")));
showShorcutsAction->setData(SHOW_SHORCUTS_ACTION_Y);
showShorcutsAction->setShortcut(ShortcutsManager::getShortcutsManager().getShortcut(SHOW_SHORCUTS_ACTION_Y));
// connect(showShorcutsAction, SIGNAL(triggered()),shortcutsDialog,SLOT(show()));
connect(showShorcutsAction, &QAction::triggered, editShortcutsDialog, &QWidget::show);
showInfoAction = new QAction(tr("Show Info"), this);
showInfoAction->setIcon(QIcon(":/images/viewer_toolbar/info.png"));
showInfoAction->setIcon(QIcon(addExtensionToIconPath(":/images/viewer_toolbar/info")));
showInfoAction->setData(SHOW_INFO_ACTION_Y);
showInfoAction->setShortcut(ShortcutsManager::getShortcutsManager().getShortcut(SHOW_INFO_ACTION_Y));
connect(showInfoAction, &QAction::triggered, viewer, &Viewer::informationSwitch);
closeAction = new QAction(tr("Close"), this);
closeAction->setIcon(QIcon(":/images/viewer_toolbar/close.png"));
closeAction->setIcon(QIcon(addExtensionToIconPath(":/images/viewer_toolbar/close")));
closeAction->setData(CLOSE_ACTION_Y);
closeAction->setShortcut(ShortcutsManager::getShortcutsManager().getShortcut(CLOSE_ACTION_Y));
connect(closeAction, &QAction::triggered, this, &QWidget::close);
showDictionaryAction = new QAction(tr("Show Dictionary"), this);
showDictionaryAction->setIcon(QIcon(":/images/viewer_toolbar/translator.png"));
showDictionaryAction->setIcon(QIcon(addExtensionToIconPath(":/images/viewer_toolbar/translator")));
// showDictionaryAction->setCheckable(true);
showDictionaryAction->setData(SHOW_DICTIONARY_ACTION_Y);
showDictionaryAction->setShortcut(ShortcutsManager::getShortcutsManager().getShortcut(SHOW_DICTIONARY_ACTION_Y));
connect(showDictionaryAction, &QAction::triggered, viewer, &Viewer::translatorSwitch);
showFlowAction = new QAction(tr("Show go to flow"), this);
showFlowAction->setIcon(QIcon(":/images/viewer_toolbar/flow.png"));
showFlowAction->setIcon(QIcon(addExtensionToIconPath(":/images/viewer_toolbar/flow")));
showFlowAction->setData(SHOW_FLOW_ACTION_Y);
showFlowAction->setShortcut(ShortcutsManager::getShortcutsManager().getShortcut(SHOW_FLOW_ACTION_Y));
connect(showFlowAction, &QAction::triggered, viewer, &Viewer::goToFlowSwitch);
@ -511,20 +475,21 @@ void MainWindowViewer::createToolBars()
{
#ifdef Q_OS_MAC
comicToolBar = new YACReaderMacOSXToolbar(this);
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
comicToolBar->setIconSize(QSize(18, 18));
#endif
#else
comicToolBar = addToolBar(tr("&File"));
#endif
#ifdef Q_OS_MAC
// comicToolBar->setIconSize(QSize(16,16));
#else
comicToolBar->setIconSize(QSize(18, 18));
#ifndef Q_OS_MAC
comicToolBar->setStyleSheet("QToolBar{border:none;}");
comicToolBar->setIconSize(QSize(18, 18));
#endif
#ifdef Q_OS_MAC
comicToolBar->addAction(openAction);
comicToolBar->addAction(openFolderAction);
comicToolBar->addAction(actionWithCustomIcon(QIcon(addExtensionToIconPathInToolbar(":/images/viewer_toolbar/open")), openAction));
comicToolBar->addAction(actionWithCustomIcon(QIcon(addExtensionToIconPathInToolbar(":/images/viewer_toolbar/openFolder")), openFolderAction));
#else
auto recentmenu = new QMenu(tr("Open recent"));
recentmenu->addActions(recentFilesActionList);
@ -533,61 +498,72 @@ void MainWindowViewer::createToolBars()
refreshRecentFilesActionList();
auto tb = new QToolButton();
tb->addAction(openAction);
tb->addAction(openLatestComicAction);
tb->addAction(openFolderAction);
auto open = actionWithCustomIcon(QIcon(addExtensionToIconPathInToolbar(":/images/viewer_toolbar/open")), openAction);
tb->addAction(open);
tb->addAction(actionWithCustomIcon(QIcon(), openLatestComicAction));
tb->addAction(actionWithCustomIcon(QIcon(addExtensionToIconPathInToolbar(":/images/viewer_toolbar/openFolder")), openFolderAction));
tb->addAction(recentmenu->menuAction());
tb->setPopupMode(QToolButton::MenuButtonPopup);
tb->setDefaultAction(openAction);
tb->setDefaultAction(open);
comicToolBar->addWidget(tb);
#endif
comicToolBar->addAction(saveImageAction);
comicToolBar->addAction(openComicOnTheLeftAction);
comicToolBar->addAction(openComicOnTheRightAction);
comicToolBar->addAction(actionWithCustomIcon(QIcon(addExtensionToIconPathInToolbar(":/images/viewer_toolbar/save")), saveImageAction));
comicToolBar->addAction(actionWithCustomIcon(QIcon(addExtensionToIconPathInToolbar(":/images/viewer_toolbar/openPrevious")), openComicOnTheLeftAction));
comicToolBar->addAction(actionWithCustomIcon(QIcon(addExtensionToIconPathInToolbar(":/images/viewer_toolbar/openNext")), openComicOnTheRightAction));
comicToolBar->addSeparator();
comicToolBar->addAction(goToPageOnTheLeftAction);
comicToolBar->addAction(goToPageOnTheRightAction);
comicToolBar->addAction(goToPageAction);
comicToolBar->addAction(actionWithCustomIcon(QIcon(addExtensionToIconPathInToolbar(":/images/viewer_toolbar/previous")), goToPageOnTheLeftAction));
comicToolBar->addAction(actionWithCustomIcon(QIcon(addExtensionToIconPathInToolbar(":/images/viewer_toolbar/next")), goToPageOnTheRightAction));
comicToolBar->addAction(actionWithCustomIcon(QIcon(addExtensionToIconPathInToolbar(":/images/viewer_toolbar/goto")), goToPageAction));
comicToolBar->addSeparator();
comicToolBar->addAction(adjustWidthAction);
comicToolBar->addAction(adjustHeightAction);
auto adjustToWidthTBAction = actionWithCustomIcon(QIcon(addExtensionToIconPathInToolbar(":/images/viewer_toolbar/toWidth")), adjustWidthAction);
comicToolBar->addAction(adjustToWidthTBAction);
auto adjustToHeightTBAction = actionWithCustomIcon(QIcon(addExtensionToIconPathInToolbar(":/images/viewer_toolbar/toHeight")), adjustHeightAction);
comicToolBar->addAction(adjustToHeightTBAction);
auto adjustToFullSizeTBAction = actionWithCustomIcon(QIcon(addExtensionToIconPathInToolbar(":/images/viewer_toolbar/full")), adjustToFullSizeAction);
comicToolBar->addAction(adjustToFullSizeAction);
comicToolBar->addAction(fitToPageAction);
auto fitToPageTBAction = actionWithCustomIcon(QIcon(addExtensionToIconPathInToolbar(":/images/viewer_toolbar/fitToPage")), fitToPageAction);
comicToolBar->addAction(fitToPageTBAction);
auto fitModes = new QActionGroup(this);
fitModes->addAction(adjustToWidthTBAction);
fitModes->addAction(adjustToHeightTBAction);
fitModes->addAction(adjustToFullSizeTBAction);
fitModes->addAction(fitToPageTBAction);
zoomSliderAction = new YACReaderSlider(this);
zoomSliderAction->hide();
comicToolBar->addAction(showZoomSliderlAction);
comicToolBar->addAction(actionWithCustomIcon(QIcon(addExtensionToIconPathInToolbar(":/images/viewer_toolbar/zoom")), showZoomSliderlAction));
connect(showZoomSliderlAction, &QAction::triggered, this, &MainWindowViewer::toggleFitToWidthSlider);
connect(zoomSliderAction, &YACReaderSlider::zoomRatioChanged, viewer, &Viewer::updateZoomRatio);
connect(viewer, &Viewer::zoomUpdated, zoomSliderAction, &YACReaderSlider::updateZoomRatio);
comicToolBar->addAction(leftRotationAction);
comicToolBar->addAction(rightRotationAction);
comicToolBar->addAction(doublePageAction);
comicToolBar->addAction(doubleMangaPageAction);
comicToolBar->addAction(actionWithCustomIcon(QIcon(addExtensionToIconPathInToolbar(":/images/viewer_toolbar/rotateL")), leftRotationAction));
comicToolBar->addAction(actionWithCustomIcon(QIcon(addExtensionToIconPathInToolbar(":/images/viewer_toolbar/rotateR")), rightRotationAction));
comicToolBar->addAction(actionWithCustomIcon(QIcon(addExtensionToIconPathInToolbar(":/images/viewer_toolbar/doublePage")), doublePageAction));
comicToolBar->addAction(actionWithCustomIcon(QIcon(addExtensionToIconPathInToolbar(":/images/viewer_toolbar/doubleMangaPage")), doubleMangaPageAction));
comicToolBar->addSeparator();
comicToolBar->addAction(showMagnifyingGlassAction);
comicToolBar->addAction(actionWithCustomIcon(QIcon(addExtensionToIconPathInToolbar(":/images/viewer_toolbar/magnifyingGlass")), showMagnifyingGlassAction));
comicToolBar->addSeparator();
comicToolBar->addAction(setBookmarkAction);
comicToolBar->addAction(showBookmarksAction);
comicToolBar->addAction(actionWithCustomIcon(QIcon(addExtensionToIconPathInToolbar(":/images/viewer_toolbar/bookmark")), setBookmarkAction));
comicToolBar->addAction(actionWithCustomIcon(QIcon(addExtensionToIconPathInToolbar(":/images/viewer_toolbar/showBookmarks")), showBookmarksAction));
comicToolBar->addSeparator();
comicToolBar->addAction(showDictionaryAction);
comicToolBar->addAction(showFlowAction);
comicToolBar->addAction(showInfoAction);
comicToolBar->addAction(actionWithCustomIcon(QIcon(addExtensionToIconPathInToolbar(":/images/viewer_toolbar/translator")), showDictionaryAction));
comicToolBar->addAction(actionWithCustomIcon(QIcon(addExtensionToIconPathInToolbar(":/images/viewer_toolbar/flow")), showFlowAction));
comicToolBar->addAction(actionWithCustomIcon(QIcon(addExtensionToIconPathInToolbar(":/images/viewer_toolbar/info")), showInfoAction));
#ifdef Q_OS_MAC
comicToolBar->addStretch();
@ -595,10 +571,9 @@ void MainWindowViewer::createToolBars()
comicToolBar->addWidget(new YACReaderToolBarStretch());
#endif
comicToolBar->addAction(showShorcutsAction);
comicToolBar->addAction(optionsAction);
comicToolBar->addAction(helpAboutAction);
// comicToolBar->addAction(closeAction);
comicToolBar->addAction(actionWithCustomIcon(QIcon(addExtensionToIconPathInToolbar(":/images/viewer_toolbar/shortcuts")), showShorcutsAction));
comicToolBar->addAction(actionWithCustomIcon(QIcon(addExtensionToIconPathInToolbar(":/images/viewer_toolbar/options")), optionsAction));
comicToolBar->addAction(actionWithCustomIcon(QIcon(addExtensionToIconPathInToolbar(":/images/viewer_toolbar/help")), helpAboutAction));
#ifndef Q_OS_MAC
comicToolBar->setMovable(false);
@ -1156,7 +1131,7 @@ void MainWindowViewer::setUpShortcutsManagement()
QList<QAction *> allActions;
QList<QAction *> tmpList;
editShortcutsDialog->addActionsGroup(tr("Comics"), QIcon(":/images/shortcuts_group_comics.png"),
editShortcutsDialog->addActionsGroup(tr("Comics"), QIcon(":/images/shortcuts_group_comics.svg"),
tmpList = { openAction,
openLatestComicAction,
openFolderAction,
@ -1172,7 +1147,7 @@ void MainWindowViewer::setUpShortcutsManagement()
auto *const toggleToolbarsAction = addActionWithShortcut(tr("Hide/show toolbar"), TOGGLE_TOOL_BARS_ACTION_Y);
connect(toggleToolbarsAction, &QAction::triggered, this, &MainWindowViewer::toggleToolBars);
editShortcutsDialog->addActionsGroup(tr("General"), QIcon(":/images/shortcuts_group_general.png"),
editShortcutsDialog->addActionsGroup(tr("General"), QIcon(":/images/shortcuts_group_general.svg"),
tmpList = QList<QAction *>()
<< optionsAction
<< helpAboutAction
@ -1206,7 +1181,7 @@ void MainWindowViewer::setUpShortcutsManagement()
mglassActions = { sizeUpMglassAction, sizeDownMglassAction,
zoomInMglassAction, zoomOutMglassAction };
editShortcutsDialog->addActionsGroup(tr("Magnifiying glass"), QIcon(":/images/shortcuts_group_mglass.png"),
editShortcutsDialog->addActionsGroup(tr("Magnifiying glass"), QIcon(":/images/shortcuts_group_mglass.svg"),
tmpList = QList<QAction *>()
<< showMagnifyingGlassAction
<< mglassActions);
@ -1217,7 +1192,7 @@ void MainWindowViewer::setUpShortcutsManagement()
CHANGE_FIT_ACTION_Y);
connect(toggleFitToScreenAction, &QAction::triggered, this, &MainWindowViewer::toggleWidthHeight);
editShortcutsDialog->addActionsGroup(tr("Page adjustement"), QIcon(":/images/shortcuts_group_page.png"),
editShortcutsDialog->addActionsGroup(tr("Page adjustement"), QIcon(":/images/shortcuts_group_page.svg"),
tmpList = QList<QAction *>()
<< adjustHeightAction
<< adjustWidthAction
@ -1287,7 +1262,7 @@ void MainWindowViewer::setUpShortcutsManagement()
goToFirstPageAction,
goToLastPageAction };
editShortcutsDialog->addActionsGroup(tr("Reading"), QIcon(":/images/shortcuts_group_reading.png"),
editShortcutsDialog->addActionsGroup(tr("Reading"), QIcon(":/images/shortcuts_group_reading.svg"),
tmpList = QList<QAction *>()
<< goToPageOnTheRightAction
<< goToPageOnTheLeftAction

View File

@ -58,9 +58,6 @@ OptionsDialog::OptionsDialog(QWidget *parent)
backgroundColor->setPalette(pal);
backgroundColor->setAutoFillBackground(true);
colorDialog = new QColorDialog(Qt::red, this);
connect(colorDialog, &QColorDialog::colorSelected, this, &OptionsDialog::updateColor);
QGroupBox *colorBox = new QGroupBox(tr("Background color"));
// backgroundColor->setMinimumWidth(100);
colorSelection->addWidget(backgroundColor);
@ -68,7 +65,7 @@ OptionsDialog::OptionsDialog(QWidget *parent)
colorSelection->setStretchFactor(backgroundColor, 1);
colorSelection->setStretchFactor(selectBackgroundColorButton, 0);
// colorSelection->addStretch();
connect(selectBackgroundColorButton, &QAbstractButton::clicked, colorDialog, &QWidget::show);
connect(selectBackgroundColorButton, &QAbstractButton::clicked, this, &OptionsDialog::showColorDialog);
colorBox->setLayout(colorSelection);
auto scrollBox = new QGroupBox(tr("Scroll behaviour"));
@ -219,6 +216,12 @@ void OptionsDialog::findFolder()
}
}
void OptionsDialog::showColorDialog()
{
auto color = QColorDialog::getColor(currentColor, this);
updateColor(color);
}
void OptionsDialog::saveOptions()
{
settings->setValue(GO_TO_FLOW_SIZE, QSize(static_cast<int>(slideSize->sliderPosition() / SLIDE_ASPECT_RATIO), slideSize->sliderPosition()));
@ -232,7 +235,7 @@ void OptionsDialog::saveOptions()
settings->setValue(PATH, pathEdit->text());
settings->setValue(BACKGROUND_COLOR, colorDialog->currentColor());
settings->setValue(BACKGROUND_COLOR, currentColor);
// settings->setValue(FIT_TO_WIDTH_RATIO,fitToWidthRatioS->sliderPosition()/100.0);
settings->setValue(QUICK_NAVI_MODE, quickNavi->isChecked());
settings->setValue(DISABLE_MOUSE_OVER_GOTO_FLOW, disableShowOnMouseOver->isChecked());
@ -288,7 +291,7 @@ void OptionsDialog::updateColor(const QColor &color)
pal.setColor(backgroundColor->backgroundRole(), color);
backgroundColor->setPalette(pal);
backgroundColor->setAutoFillBackground(true);
colorDialog->setCurrentColor(color);
currentColor = color;
settings->setValue(BACKGROUND_COLOR, color);

View File

@ -10,7 +10,6 @@ class QPushButton;
class QSlider;
class QPushButton;
class QRadioButton;
class QColorDialog;
class YACReaderSpinSliderWidget;
class OptionsDialog : public YACReaderOptionsDialog
@ -44,18 +43,18 @@ private:
QCheckBox *doNotTurnPageOnScroll;
QCheckBox *useSingleScrollStepToTurnPage;
QColorDialog *colorDialog;
YACReaderSpinSliderWidget *brightnessS;
YACReaderSpinSliderWidget *contrastS;
YACReaderSpinSliderWidget *gammaS;
QColor currentColor;
public slots:
void saveOptions() override;
void restoreOptions(QSettings *settings) override;
void findFolder();
void showColorDialog();
void updateColor(const QColor &color);
// void fitToWidthRatio(int value);
void brightnessChanged(int value);

View File

@ -57,7 +57,7 @@ YACReaderTranslator::YACReaderTranslator(Viewer *parent)
// TITLE BAR
auto titleBar = new QHBoxLayout();
auto close = new QPushButton(QIcon(QPixmap(":/images/close.png")), "");
auto close = new QPushButton(QIcon(":/images/close.svg"), "");
close->setFlat(true);
auto title = new QLabel(tr("YACReader translator"));
title->setStyleSheet("QLabel {font-size:18px; font-family:Arial; color:white;}");

File diff suppressed because it is too large Load Diff

1174
YACReader/yacreader_en.ts Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -9,7 +9,7 @@
<file>../images/flow4.png</file>
<file>../images/flow5.png</file>
<file>../images/notCover.png</file>
<file>../images/close.png</file>
<file>../images/close.svg</file>
<file>../images/up.png</file>
<file>../images/down.png</file>
<file>../images/imgCenterSlide.png</file>
@ -21,17 +21,71 @@
<file>../images/dropDownArrow.png</file>
<file>../images/translatorSearch.png</file>
<file>../images/speaker.png</file>
<file>../images/clear_shortcut.png</file>
<file>../images/accept_shortcut.png</file>
<file>../images/shortcuts_group_comics.png</file>
<file>../images/shortcuts_group_folders.png</file>
<file>../images/shortcuts_group_general.png</file>
<file>../images/shortcuts_group_libraries.png</file>
<file>../images/shortcuts_group_mglass.png</file>
<file>../images/shortcuts_group_page.png</file>
<file>../images/shortcuts_group_reading.png</file>
<file>../images/shortcuts_group_visualization.png</file>
<file>../images/clear_shortcut.svg</file>
<file>../images/accept_shortcut.svg</file>
<file>../images/shortcuts_group_comics.svg</file>
<file>../images/shortcuts_group_folders.svg</file>
<file>../images/shortcuts_group_general.svg</file>
<file>../images/shortcuts_group_libraries.svg</file>
<file>../images/shortcuts_group_mglass.svg</file>
<file>../images/shortcuts_group_page.svg</file>
<file>../images/shortcuts_group_reading.svg</file>
<file>../images/shortcuts_group_visualization.svg</file>
<file>../images/custom_dialog/custom_close_button.svg</file>
<file>../images/whats_new/whatsnew_header.svg</file>
<file>../images/viewer_toolbar/bookmark.svg</file>
<file>../images/viewer_toolbar/close.svg</file>
<file>../images/viewer_toolbar/doublePage.svg</file>
<file>../images/viewer_toolbar/doubleMangaPage.svg</file>
<file>../images/viewer_toolbar/fitToPage.svg</file>
<file>../images/viewer_toolbar/flow.svg</file>
<file>../images/viewer_toolbar/full.svg</file>
<file>../images/viewer_toolbar/goto.svg</file>
<file>../images/viewer_toolbar/help.svg</file>
<file>../images/viewer_toolbar/info.svg</file>
<file>../images/viewer_toolbar/magnifyingGlass.svg</file>
<file>../images/viewer_toolbar/next.svg</file>
<file>../images/viewer_toolbar/open.svg</file>
<file>../images/viewer_toolbar/openFolder.svg</file>
<file>../images/viewer_toolbar/openNext.svg</file>
<file>../images/viewer_toolbar/openPrevious.svg</file>
<file>../images/viewer_toolbar/options.svg</file>
<file>../images/viewer_toolbar/previous.svg</file>
<file>../images/viewer_toolbar/rotateL.svg</file>
<file>../images/viewer_toolbar/rotateR.svg</file>
<file>../images/viewer_toolbar/save.svg</file>
<file>../images/viewer_toolbar/shortcuts.svg</file>
<file>../images/viewer_toolbar/showBookmarks.svg</file>
<file>../images/viewer_toolbar/toHeight.svg</file>
<file>../images/viewer_toolbar/toWidth.svg</file>
<file>../images/viewer_toolbar/translator.svg</file>
<file>../images/viewer_toolbar/zoom.svg</file>
<file>../images/viewer_toolbar/bookmark_18x18.svg</file>
<file>../images/viewer_toolbar/close_18x18.svg</file>
<file>../images/viewer_toolbar/doublePage_18x18.svg</file>
<file>../images/viewer_toolbar/doubleMangaPage_18x18.svg</file>
<file>../images/viewer_toolbar/fitToPage_18x18.svg</file>
<file>../images/viewer_toolbar/flow_18x18.svg</file>
<file>../images/viewer_toolbar/full_18x18.svg</file>
<file>../images/viewer_toolbar/goto_18x18.svg</file>
<file>../images/viewer_toolbar/help_18x18.svg</file>
<file>../images/viewer_toolbar/info_18x18.svg</file>
<file>../images/viewer_toolbar/magnifyingGlass_18x18.svg</file>
<file>../images/viewer_toolbar/next_18x18.svg</file>
<file>../images/viewer_toolbar/open_18x18.svg</file>
<file>../images/viewer_toolbar/openFolder_18x18.svg</file>
<file>../images/viewer_toolbar/openNext_18x18.svg</file>
<file>../images/viewer_toolbar/openPrevious_18x18.svg</file>
<file>../images/viewer_toolbar/options_18x18.svg</file>
<file>../images/viewer_toolbar/previous_18x18.svg</file>
<file>../images/viewer_toolbar/rotateL_18x18.svg</file>
<file>../images/viewer_toolbar/rotateR_18x18.svg</file>
<file>../images/viewer_toolbar/save_18x18.svg</file>
<file>../images/viewer_toolbar/shortcuts_18x18.svg</file>
<file>../images/viewer_toolbar/showBookmarks_18x18.svg</file>
<file>../images/viewer_toolbar/toHeight_18x18.svg</file>
<file>../images/viewer_toolbar/toWidth_18x18.svg</file>
<file>../images/viewer_toolbar/translator_18x18.svg</file>
<file>../images/viewer_toolbar/zoom_18x18.svg</file>
</qresource>
</RCC>

View File

@ -1,61 +0,0 @@
<RCC>
<qresource prefix="/" >
<file alias="images/viewer_toolbar/bookmark.png">../images/viewer_toolbar/bookmark_osx.png</file>
<file alias="images/viewer_toolbar/bookmark@2x.png">../images/viewer_toolbar/bookmark_osx@2x.png</file>
<file alias="images/viewer_toolbar/close.png">../images/viewer_toolbar/close_osx.png</file>
<file alias="images/viewer_toolbar/close@2x.png">../images/viewer_toolbar/close_osx@2x.png</file>
<file alias="images/viewer_toolbar/doubleMangaPage.png">../images/viewer_toolbar/doubleMangaPage_osx.png</file>
<file alias="images/viewer_toolbar/doubleMangaPage@2x.png">../images/viewer_toolbar/doubleMangaPage_osx@2x.png</file>
<file alias="images/viewer_toolbar/doublePage.png">../images/viewer_toolbar/doublePage_osx.png</file>
<file alias="images/viewer_toolbar/doublePage@2x.png">../images/viewer_toolbar/doublePage_osx@2x.png</file>
<file alias="images/viewer_toolbar/fitToPage.png">../images/viewer_toolbar/fitToPage_osx.png</file>
<file alias="images/viewer_toolbar/fitToPage@2x.png">../images/viewer_toolbar/fitToPage_osx@2x.png</file>
<file alias="images/viewer_toolbar/flow.png">../images/viewer_toolbar/flow_osx.png</file>
<file alias="images/viewer_toolbar/flow@2x.png">../images/viewer_toolbar/flow_osx@2x.png</file>
<file alias="images/viewer_toolbar/full.png">../images/viewer_toolbar/full_osx.png</file>
<file alias="images/viewer_toolbar/full@2x.png">../images/viewer_toolbar/full_osx@2x.png</file>
<file alias="images/viewer_toolbar/goto.png">../images/viewer_toolbar/goto_osx.png</file>
<file alias="images/viewer_toolbar/goto@2x.png">../images/viewer_toolbar/goto_osx@2x.png</file>
<file alias="images/viewer_toolbar/help.png">../images/viewer_toolbar/help_osx.png</file>
<file alias="images/viewer_toolbar/help@2x.png">../images/viewer_toolbar/help_osx@2x.png</file>
<file alias="images/viewer_toolbar/info.png">../images/viewer_toolbar/info_osx.png</file>
<file alias="images/viewer_toolbar/info@2x.png">../images/viewer_toolbar/info_osx@2x.png</file>
<file alias="images/viewer_toolbar/magnifyingGlass.png">../images/viewer_toolbar/magnifyingGlass_osx.png</file>
<file alias="images/viewer_toolbar/magnifyingGlass@2x.png">../images/viewer_toolbar/magnifyingGlass_osx@2x.png</file>
<file alias="images/viewer_toolbar/next.png">../images/viewer_toolbar/next_osx.png</file>
<file alias="images/viewer_toolbar/next@2x.png">../images/viewer_toolbar/next_osx@2x.png</file>
<file alias="images/viewer_toolbar/open.png">../images/viewer_toolbar/open_osx.png</file>
<file alias="images/viewer_toolbar/open@2x.png">../images/viewer_toolbar/open_osx@2x.png</file>
<file alias="images/viewer_toolbar/openFolder.png">../images/viewer_toolbar/openFolder_osx.png</file>
<file alias="images/viewer_toolbar/openFolder@2x.png">../images/viewer_toolbar/openFolder_osx@2x.png</file>
<file alias="images/viewer_toolbar/openNext.png">../images/viewer_toolbar/openNext_osx.png</file>
<file alias="images/viewer_toolbar/openNext@2x.png">../images/viewer_toolbar/openNext_osx@2x.png</file>
<file alias="images/viewer_toolbar/openPrevious.png">../images/viewer_toolbar/openPrevious_osx.png</file>
<file alias="images/viewer_toolbar/openPrevious@2x.png">../images/viewer_toolbar/openPrevious_osx@2x.png</file>
<file alias="images/viewer_toolbar/options.png">../images/viewer_toolbar/options_osx.png</file>
<file alias="images/viewer_toolbar/options@2x.png">../images/viewer_toolbar/options_osx@2x.png</file>
<file alias="images/viewer_toolbar/previous.png">../images/viewer_toolbar/previous_osx.png</file>
<file alias="images/viewer_toolbar/previous@2x.png">../images/viewer_toolbar/previous_osx@2x.png</file>
<file alias="images/viewer_toolbar/rotateL.png">../images/viewer_toolbar/rotateL_osx.png</file>
<file alias="images/viewer_toolbar/rotateL@2x.png">../images/viewer_toolbar/rotateL_osx@2x.png</file>
<file alias="images/viewer_toolbar/rotateR.png">../images/viewer_toolbar/rotateR_osx.png</file>
<file alias="images/viewer_toolbar/rotateR@2x.png">../images/viewer_toolbar/rotateR_osx@2x.png</file>
<file alias="images/viewer_toolbar/save.png">../images/viewer_toolbar/save_osx.png</file>
<file alias="images/viewer_toolbar/save@2x.png">../images/viewer_toolbar/save_osx@2x.png</file>
<file alias="images/viewer_toolbar/shortcuts.png">../images/viewer_toolbar/shortcuts_osx.png</file>
<file alias="images/viewer_toolbar/shortcuts@2x.png">../images/viewer_toolbar/shortcuts_osx@2x.png</file>
<file alias="images/viewer_toolbar/showBookmarks.png">../images/viewer_toolbar/showBookmarks_osx.png</file>
<file alias="images/viewer_toolbar/showBookmarks@2x.png">../images/viewer_toolbar/showBookmarks_osx@2x.png</file>
<file alias="images/viewer_toolbar/toHeight.png">../images/viewer_toolbar/toHeight_osx.png</file>
<file alias="images/viewer_toolbar/toHeight@2x.png">../images/viewer_toolbar/toHeight_osx@2x.png</file>
<file alias="images/viewer_toolbar/toWidth.png">../images/viewer_toolbar/toWidth_osx.png</file>
<file alias="images/viewer_toolbar/toWidth@2x.png">../images/viewer_toolbar/toWidth_osx@2x.png</file>
<file alias="images/viewer_toolbar/toWidthSlider.png">../images/viewer_toolbar/toWidthSlider_osx.png</file>
<file alias="images/viewer_toolbar/toWidthSlider@2x.png">../images/viewer_toolbar/toWidthSlider_osx@2x.png</file>
<file alias="images/viewer_toolbar/translator.png">../images/viewer_toolbar/translator_osx.png</file>
<file alias="images/viewer_toolbar/translator@2x.png">../images/viewer_toolbar/translator_osx@2x.png</file>
<file alias="images/viewer_toolbar/zoom.png">../images/viewer_toolbar/zoom_osx.png</file>
<file alias="images/viewer_toolbar/zoom@2x.png">../images/viewer_toolbar/zoom_osx@2x.png</file>
</qresource>
</RCC>

View File

@ -1,31 +0,0 @@
<RCC>
<qresource prefix="/" >
<file>../images/viewer_toolbar/bookmark.png</file>
<file>../images/viewer_toolbar/close.png</file>
<file>../images/viewer_toolbar/doublePage.png</file>
<file>../images/viewer_toolbar/doubleMangaPage.png</file>
<file>../images/viewer_toolbar/fitToPage.png</file>
<file>../images/viewer_toolbar/flow.png</file>
<file>../images/viewer_toolbar/full.png</file>
<file>../images/viewer_toolbar/goto.png</file>
<file>../images/viewer_toolbar/help.png</file>
<file>../images/viewer_toolbar/info.png</file>
<file>../images/viewer_toolbar/magnifyingGlass.png</file>
<file>../images/viewer_toolbar/next.png</file>
<file>../images/viewer_toolbar/open.png</file>
<file>../images/viewer_toolbar/openFolder.png</file>
<file>../images/viewer_toolbar/openNext.png</file>
<file>../images/viewer_toolbar/openPrevious.png</file>
<file>../images/viewer_toolbar/options.png</file>
<file>../images/viewer_toolbar/previous.png</file>
<file>../images/viewer_toolbar/rotateL.png</file>
<file>../images/viewer_toolbar/rotateR.png</file>
<file>../images/viewer_toolbar/save.png</file>
<file>../images/viewer_toolbar/shortcuts.png</file>
<file>../images/viewer_toolbar/showBookmarks.png</file>
<file>../images/viewer_toolbar/toHeight.png</file>
<file>../images/viewer_toolbar/toWidth.png</file>
<file>../images/viewer_toolbar/translator.png</file>
<file>../images/viewer_toolbar/zoom.png</file>
</qresource>
</RCC>

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -124,17 +124,17 @@
<context>
<name>HelpAboutDialog</name>
<message>
<location filename="../custom_widgets/help_about_dialog.cpp" line="25"/>
<location filename="../custom_widgets/help_about_dialog.cpp" line="27"/>
<source>About</source>
<translation></translation>
</message>
<message>
<location filename="../custom_widgets/help_about_dialog.cpp" line="28"/>
<location filename="../custom_widgets/help_about_dialog.cpp" line="30"/>
<source>Help</source>
<translation></translation>
</message>
<message>
<location filename="../custom_widgets/help_about_dialog.cpp" line="31"/>
<location filename="../custom_widgets/help_about_dialog.cpp" line="33"/>
<source>System info</source>
<translation></translation>
</message>
@ -190,112 +190,112 @@
<translation></translation>
</message>
<message>
<location filename="options_dialog.cpp" line="64"/>
<location filename="options_dialog.cpp" line="61"/>
<source>Background color</source>
<translation></translation>
</message>
<message>
<location filename="options_dialog.cpp" line="67"/>
<location filename="options_dialog.cpp" line="64"/>
<source>Choose</source>
<translation></translation>
</message>
<message>
<location filename="options_dialog.cpp" line="100"/>
<location filename="options_dialog.cpp" line="97"/>
<source>Quick Navigation Mode</source>
<translation></translation>
</message>
<message>
<location filename="options_dialog.cpp" line="101"/>
<location filename="options_dialog.cpp" line="98"/>
<source>Disable mouse over activation</source>
<translation></translation>
</message>
<message>
<location filename="options_dialog.cpp" line="200"/>
<location filename="options_dialog.cpp" line="197"/>
<source>Restart is needed</source>
<translation></translation>
</message>
<message>
<location filename="options_dialog.cpp" line="144"/>
<location filename="options_dialog.cpp" line="141"/>
<source>Brightness</source>
<translation></translation>
</message>
<message>
<location filename="options_dialog.cpp" line="74"/>
<location filename="options_dialog.cpp" line="71"/>
<source>Scroll behaviour</source>
<translation></translation>
</message>
<message>
<location filename="options_dialog.cpp" line="77"/>
<location filename="options_dialog.cpp" line="74"/>
<source>Do not turn page using scroll</source>
<translation></translation>
</message>
<message>
<location filename="options_dialog.cpp" line="78"/>
<location filename="options_dialog.cpp" line="75"/>
<source>Use single scroll step to turn page</source>
<translation>使</translation>
</message>
<message>
<location filename="options_dialog.cpp" line="145"/>
<location filename="options_dialog.cpp" line="142"/>
<source>Contrast</source>
<translation></translation>
</message>
<message>
<location filename="options_dialog.cpp" line="146"/>
<location filename="options_dialog.cpp" line="143"/>
<source>Gamma</source>
<translation>Gamma值</translation>
</message>
<message>
<location filename="options_dialog.cpp" line="150"/>
<location filename="options_dialog.cpp" line="147"/>
<source>Reset</source>
<translation></translation>
</message>
<message>
<location filename="options_dialog.cpp" line="155"/>
<location filename="options_dialog.cpp" line="152"/>
<source>Image options</source>
<translation></translation>
</message>
<message>
<location filename="options_dialog.cpp" line="159"/>
<location filename="options_dialog.cpp" line="156"/>
<source>Fit options</source>
<translation></translation>
</message>
<message>
<location filename="options_dialog.cpp" line="161"/>
<location filename="options_dialog.cpp" line="158"/>
<source>Enlarge images to fit width/height</source>
<translation>/</translation>
</message>
<message>
<location filename="options_dialog.cpp" line="172"/>
<location filename="options_dialog.cpp" line="169"/>
<source>Double Page options</source>
<translation></translation>
</message>
<message>
<location filename="options_dialog.cpp" line="174"/>
<location filename="options_dialog.cpp" line="171"/>
<source>Show covers as single page</source>
<translation></translation>
</message>
<message>
<location filename="options_dialog.cpp" line="192"/>
<location filename="options_dialog.cpp" line="189"/>
<source>General</source>
<translation></translation>
</message>
<message>
<location filename="options_dialog.cpp" line="193"/>
<location filename="options_dialog.cpp" line="190"/>
<source>Page Flow</source>
<translation></translation>
</message>
<message>
<location filename="options_dialog.cpp" line="194"/>
<location filename="options_dialog.cpp" line="191"/>
<source>Image adjustment</source>
<translation></translation>
</message>
<message>
<location filename="options_dialog.cpp" line="209"/>
<location filename="options_dialog.cpp" line="206"/>
<source>Options</source>
<translation></translation>
</message>
<message>
<location filename="options_dialog.cpp" line="216"/>
<location filename="options_dialog.cpp" line="213"/>
<source>Comics directory</source>
<translation></translation>
</message>
@ -935,7 +935,7 @@
<context>
<name>YACReader::WhatsNewDialog</name>
<message>
<location filename="../custom_widgets/whats_new_dialog.cpp" line="104"/>
<location filename="../custom_widgets/whats_new_dialog.cpp" line="95"/>
<source>Close</source>
<translation></translation>
</message>

View File

@ -124,17 +124,17 @@
<context>
<name>HelpAboutDialog</name>
<message>
<location filename="../custom_widgets/help_about_dialog.cpp" line="25"/>
<location filename="../custom_widgets/help_about_dialog.cpp" line="27"/>
<source>About</source>
<translation></translation>
</message>
<message>
<location filename="../custom_widgets/help_about_dialog.cpp" line="28"/>
<location filename="../custom_widgets/help_about_dialog.cpp" line="30"/>
<source>Help</source>
<translation></translation>
</message>
<message>
<location filename="../custom_widgets/help_about_dialog.cpp" line="31"/>
<location filename="../custom_widgets/help_about_dialog.cpp" line="33"/>
<source>System info</source>
<translation></translation>
</message>
@ -190,112 +190,112 @@
<translation></translation>
</message>
<message>
<location filename="options_dialog.cpp" line="64"/>
<location filename="options_dialog.cpp" line="61"/>
<source>Background color</source>
<translation></translation>
</message>
<message>
<location filename="options_dialog.cpp" line="67"/>
<location filename="options_dialog.cpp" line="64"/>
<source>Choose</source>
<translation></translation>
</message>
<message>
<location filename="options_dialog.cpp" line="100"/>
<location filename="options_dialog.cpp" line="97"/>
<source>Quick Navigation Mode</source>
<translation></translation>
</message>
<message>
<location filename="options_dialog.cpp" line="101"/>
<location filename="options_dialog.cpp" line="98"/>
<source>Disable mouse over activation</source>
<translation></translation>
</message>
<message>
<location filename="options_dialog.cpp" line="200"/>
<location filename="options_dialog.cpp" line="197"/>
<source>Restart is needed</source>
<translation></translation>
</message>
<message>
<location filename="options_dialog.cpp" line="144"/>
<location filename="options_dialog.cpp" line="141"/>
<source>Brightness</source>
<translation></translation>
</message>
<message>
<location filename="options_dialog.cpp" line="74"/>
<location filename="options_dialog.cpp" line="71"/>
<source>Scroll behaviour</source>
<translation></translation>
</message>
<message>
<location filename="options_dialog.cpp" line="77"/>
<location filename="options_dialog.cpp" line="74"/>
<source>Do not turn page using scroll</source>
<translation></translation>
</message>
<message>
<location filename="options_dialog.cpp" line="78"/>
<location filename="options_dialog.cpp" line="75"/>
<source>Use single scroll step to turn page</source>
<translation>使</translation>
</message>
<message>
<location filename="options_dialog.cpp" line="145"/>
<location filename="options_dialog.cpp" line="142"/>
<source>Contrast</source>
<translation></translation>
</message>
<message>
<location filename="options_dialog.cpp" line="146"/>
<location filename="options_dialog.cpp" line="143"/>
<source>Gamma</source>
<translation>Gamma值</translation>
</message>
<message>
<location filename="options_dialog.cpp" line="150"/>
<location filename="options_dialog.cpp" line="147"/>
<source>Reset</source>
<translation></translation>
</message>
<message>
<location filename="options_dialog.cpp" line="155"/>
<location filename="options_dialog.cpp" line="152"/>
<source>Image options</source>
<translation></translation>
</message>
<message>
<location filename="options_dialog.cpp" line="159"/>
<location filename="options_dialog.cpp" line="156"/>
<source>Fit options</source>
<translation></translation>
</message>
<message>
<location filename="options_dialog.cpp" line="161"/>
<location filename="options_dialog.cpp" line="158"/>
<source>Enlarge images to fit width/height</source>
<translation>/</translation>
</message>
<message>
<location filename="options_dialog.cpp" line="172"/>
<location filename="options_dialog.cpp" line="169"/>
<source>Double Page options</source>
<translation></translation>
</message>
<message>
<location filename="options_dialog.cpp" line="174"/>
<location filename="options_dialog.cpp" line="171"/>
<source>Show covers as single page</source>
<translation></translation>
</message>
<message>
<location filename="options_dialog.cpp" line="192"/>
<location filename="options_dialog.cpp" line="189"/>
<source>General</source>
<translation></translation>
</message>
<message>
<location filename="options_dialog.cpp" line="193"/>
<location filename="options_dialog.cpp" line="190"/>
<source>Page Flow</source>
<translation></translation>
</message>
<message>
<location filename="options_dialog.cpp" line="194"/>
<location filename="options_dialog.cpp" line="191"/>
<source>Image adjustment</source>
<translation>調</translation>
</message>
<message>
<location filename="options_dialog.cpp" line="209"/>
<location filename="options_dialog.cpp" line="206"/>
<source>Options</source>
<translation></translation>
</message>
<message>
<location filename="options_dialog.cpp" line="216"/>
<location filename="options_dialog.cpp" line="213"/>
<source>Comics directory</source>
<translation></translation>
</message>
@ -935,7 +935,7 @@
<context>
<name>YACReader::WhatsNewDialog</name>
<message>
<location filename="../custom_widgets/whats_new_dialog.cpp" line="104"/>
<location filename="../custom_widgets/whats_new_dialog.cpp" line="95"/>
<source>Close</source>
<translation></translation>
</message>

View File

@ -124,17 +124,17 @@
<context>
<name>HelpAboutDialog</name>
<message>
<location filename="../custom_widgets/help_about_dialog.cpp" line="25"/>
<location filename="../custom_widgets/help_about_dialog.cpp" line="27"/>
<source>About</source>
<translation></translation>
</message>
<message>
<location filename="../custom_widgets/help_about_dialog.cpp" line="28"/>
<location filename="../custom_widgets/help_about_dialog.cpp" line="30"/>
<source>Help</source>
<translation></translation>
</message>
<message>
<location filename="../custom_widgets/help_about_dialog.cpp" line="31"/>
<location filename="../custom_widgets/help_about_dialog.cpp" line="33"/>
<source>System info</source>
<translation></translation>
</message>
@ -190,112 +190,112 @@
<translation></translation>
</message>
<message>
<location filename="options_dialog.cpp" line="64"/>
<location filename="options_dialog.cpp" line="61"/>
<source>Background color</source>
<translation></translation>
</message>
<message>
<location filename="options_dialog.cpp" line="67"/>
<location filename="options_dialog.cpp" line="64"/>
<source>Choose</source>
<translation></translation>
</message>
<message>
<location filename="options_dialog.cpp" line="100"/>
<location filename="options_dialog.cpp" line="97"/>
<source>Quick Navigation Mode</source>
<translation></translation>
</message>
<message>
<location filename="options_dialog.cpp" line="101"/>
<location filename="options_dialog.cpp" line="98"/>
<source>Disable mouse over activation</source>
<translation></translation>
</message>
<message>
<location filename="options_dialog.cpp" line="200"/>
<location filename="options_dialog.cpp" line="197"/>
<source>Restart is needed</source>
<translation></translation>
</message>
<message>
<location filename="options_dialog.cpp" line="144"/>
<location filename="options_dialog.cpp" line="141"/>
<source>Brightness</source>
<translation></translation>
</message>
<message>
<location filename="options_dialog.cpp" line="74"/>
<location filename="options_dialog.cpp" line="71"/>
<source>Scroll behaviour</source>
<translation></translation>
</message>
<message>
<location filename="options_dialog.cpp" line="77"/>
<location filename="options_dialog.cpp" line="74"/>
<source>Do not turn page using scroll</source>
<translation></translation>
</message>
<message>
<location filename="options_dialog.cpp" line="78"/>
<location filename="options_dialog.cpp" line="75"/>
<source>Use single scroll step to turn page</source>
<translation>使</translation>
</message>
<message>
<location filename="options_dialog.cpp" line="145"/>
<location filename="options_dialog.cpp" line="142"/>
<source>Contrast</source>
<translation></translation>
</message>
<message>
<location filename="options_dialog.cpp" line="146"/>
<location filename="options_dialog.cpp" line="143"/>
<source>Gamma</source>
<translation>Gamma值</translation>
</message>
<message>
<location filename="options_dialog.cpp" line="150"/>
<location filename="options_dialog.cpp" line="147"/>
<source>Reset</source>
<translation></translation>
</message>
<message>
<location filename="options_dialog.cpp" line="155"/>
<location filename="options_dialog.cpp" line="152"/>
<source>Image options</source>
<translation></translation>
</message>
<message>
<location filename="options_dialog.cpp" line="159"/>
<location filename="options_dialog.cpp" line="156"/>
<source>Fit options</source>
<translation></translation>
</message>
<message>
<location filename="options_dialog.cpp" line="161"/>
<location filename="options_dialog.cpp" line="158"/>
<source>Enlarge images to fit width/height</source>
<translation>/</translation>
</message>
<message>
<location filename="options_dialog.cpp" line="172"/>
<location filename="options_dialog.cpp" line="169"/>
<source>Double Page options</source>
<translation></translation>
</message>
<message>
<location filename="options_dialog.cpp" line="174"/>
<location filename="options_dialog.cpp" line="171"/>
<source>Show covers as single page</source>
<translation></translation>
</message>
<message>
<location filename="options_dialog.cpp" line="192"/>
<location filename="options_dialog.cpp" line="189"/>
<source>General</source>
<translation></translation>
</message>
<message>
<location filename="options_dialog.cpp" line="193"/>
<location filename="options_dialog.cpp" line="190"/>
<source>Page Flow</source>
<translation></translation>
</message>
<message>
<location filename="options_dialog.cpp" line="194"/>
<location filename="options_dialog.cpp" line="191"/>
<source>Image adjustment</source>
<translation>調</translation>
</message>
<message>
<location filename="options_dialog.cpp" line="209"/>
<location filename="options_dialog.cpp" line="206"/>
<source>Options</source>
<translation></translation>
</message>
<message>
<location filename="options_dialog.cpp" line="216"/>
<location filename="options_dialog.cpp" line="213"/>
<source>Comics directory</source>
<translation></translation>
</message>
@ -935,7 +935,7 @@
<context>
<name>YACReader::WhatsNewDialog</name>
<message>
<location filename="../custom_widgets/whats_new_dialog.cpp" line="104"/>
<location filename="../custom_widgets/whats_new_dialog.cpp" line="95"/>
<source>Close</source>
<translation></translation>
</message>

View File

@ -83,6 +83,7 @@ HEADERS += comic_flow.h \
db/comic_query_result_processor.h \
db/folder_query_result_processor.h \
db/query_lexer.h \
folder_content_view.h \
initial_comic_info_extractor.h \
library_comic_opener.h \
library_creator.h \
@ -123,6 +124,7 @@ HEADERS += comic_flow.h \
trayicon_controller.h \
xml_info_library_scanner.h \
xml_info_parser.h \
yacreader_content_views_manager.h \
yacreader_local_server.h \
yacreader_main_toolbar.h \
comics_remover.h \
@ -147,7 +149,6 @@ HEADERS += comic_flow.h \
empty_reading_list_widget.h \
../common/scroll_management.h \
../common/opengl_checker.h \
yacreader_comics_views_manager.h \
info_comics_view.h \
yacreader_comics_selection_helper.h \
yacreader_comic_info_helper.h \
@ -165,6 +166,7 @@ SOURCES += comic_flow.cpp \
db/comic_query_result_processor.cpp \
db/folder_query_result_processor.cpp \
db/query_lexer.cpp \
folder_content_view.cpp \
initial_comic_info_extractor.cpp \
library_comic_opener.cpp \
library_creator.cpp \
@ -201,6 +203,7 @@ SOURCES += comic_flow.cpp \
trayicon_controller.cpp \
xml_info_library_scanner.cpp \
xml_info_parser.cpp \
yacreader_content_views_manager.cpp \
yacreader_local_server.cpp \
yacreader_main_toolbar.cpp \
comics_remover.cpp \
@ -227,7 +230,6 @@ SOURCES += comic_flow.cpp \
empty_reading_list_widget.cpp \
../common/scroll_management.cpp \
../common/opengl_checker.cpp \
yacreader_comics_views_manager.cpp \
info_comics_view.cpp \
yacreader_comics_selection_helper.cpp \
yacreader_comic_info_helper.cpp\
@ -284,7 +286,28 @@ TRANSLATIONS = yacreaderlibrary_es.ts \
yacreaderlibrary_zh_TW.ts \
yacreaderlibrary_zh_HK.ts \
yacreaderlibrary_it.ts \
yacreaderlibrary_source.ts
yacreaderlibrary_en.ts
CONFIG += lrelease
win32 {
CONFIG(release, debug|release) {
SOURCE_QM_DIR = $$OUT_PWD/release/*.qm
}
CONFIG(debug, debug|release) {
SOURCE_QM_DIR = $$OUT_PWD/debug/*.qm
}
DEPLOYMENT_OUT_QM_DIR = ../release/languages/
OUT_QM_DIR = $${DESTDIR}/languages/
QMAKE_POST_LINK += $(MKDIR) $$shell_path($${OUT_QM_DIR}) 2> NULL & \
$(COPY) $$shell_path($${SOURCE_QM_DIR}) $$shell_path($${OUT_QM_DIR}) & \
$(MKDIR) $$shell_path($${DEPLOYMENT_OUT_QM_DIR}) 2> NULL & \
$(COPY) $$shell_path($${SOURCE_QM_DIR}) $$shell_path($${DEPLOYMENT_OUT_QM_DIR})
} else {
LRELEASE_DIR = ../release/languages/
}
#QML/GridView
QT += quick qml quickwidgets

View File

@ -11,18 +11,18 @@ AddLabelDialog::AddLabelDialog(QWidget *parent)
layout->addWidget(new QLabel(tr("Choose a color:")));
layout->addWidget(list = new QListWidget());
list->addItem(new QListWidgetItem(QIcon(":/images/lists/label_red.png"), tr("red")));
list->addItem(new QListWidgetItem(QIcon(":/images/lists/label_orange.png"), tr("orange")));
list->addItem(new QListWidgetItem(QIcon(":/images/lists/label_yellow.png"), tr("yellow")));
list->addItem(new QListWidgetItem(QIcon(":/images/lists/label_green.png"), tr("green")));
list->addItem(new QListWidgetItem(QIcon(":/images/lists/label_cyan.png"), tr("cyan")));
list->addItem(new QListWidgetItem(QIcon(":/images/lists/label_blue.png"), tr("blue")));
list->addItem(new QListWidgetItem(QIcon(":/images/lists/label_violet.png"), tr("violet")));
list->addItem(new QListWidgetItem(QIcon(":/images/lists/label_purple.png"), tr("purple")));
list->addItem(new QListWidgetItem(QIcon(":/images/lists/label_pink.png"), tr("pink")));
list->addItem(new QListWidgetItem(QIcon(":/images/lists/label_white.png"), tr("white")));
list->addItem(new QListWidgetItem(QIcon(":/images/lists/label_light.png"), tr("light")));
list->addItem(new QListWidgetItem(QIcon(":/images/lists/label_dark.png"), tr("dark")));
list->addItem(new QListWidgetItem(QIcon(":/images/lists/label_red.svg"), tr("red")));
list->addItem(new QListWidgetItem(QIcon(":/images/lists/label_orange.svg"), tr("orange")));
list->addItem(new QListWidgetItem(QIcon(":/images/lists/label_yellow.svg"), tr("yellow")));
list->addItem(new QListWidgetItem(QIcon(":/images/lists/label_green.svg"), tr("green")));
list->addItem(new QListWidgetItem(QIcon(":/images/lists/label_cyan.svg"), tr("cyan")));
list->addItem(new QListWidgetItem(QIcon(":/images/lists/label_blue.svg"), tr("blue")));
list->addItem(new QListWidgetItem(QIcon(":/images/lists/label_violet.svg"), tr("violet")));
list->addItem(new QListWidgetItem(QIcon(":/images/lists/label_purple.svg"), tr("purple")));
list->addItem(new QListWidgetItem(QIcon(":/images/lists/label_pink.svg"), tr("pink")));
list->addItem(new QListWidgetItem(QIcon(":/images/lists/label_white.svg"), tr("white")));
list->addItem(new QListWidgetItem(QIcon(":/images/lists/label_light.svg"), tr("light")));
list->addItem(new QListWidgetItem(QIcon(":/images/lists/label_dark.svg"), tr("dark")));
QColor backgroundColor = this->palette().window().color();
list->setStyleSheet(QString("QListWidget {border : none; background-color: rgb(%1,%2,%3);}").arg(backgroundColor.red()).arg(backgroundColor.green()).arg(backgroundColor.blue()));

View File

@ -466,18 +466,8 @@ void ComicVineDialog::getComicsInfo(QList<QPair<ComicDB, QString>> matchingInfo,
setLoadingMessage(tr("Retrieving tags for : %1").arg(p.first.getFileName()));
}
QString connectionName = "";
{
QSqlDatabase db = DataBaseManagement::loadDatabase(databasePath);
db.open();
db.transaction();
foreach (ComicDB comic, comics) {
DBHelper::update(&(comic.info), db);
}
db.commit();
connectionName = db.connectionName();
}
QSqlDatabase::removeDatabase(connectionName);
DBHelper::updateComicsInfo(comics, databasePath);
emit accepted();
}

View File

@ -1,6 +1,7 @@
#include <QtGui>
#include <QtDebug>
#include <QStringBuilder>
#include <limits>
#include "comic_item.h"
@ -237,6 +238,7 @@ QHash<int, QByteArray> ComicModel::roleNames() const
roles[HasBeenOpenedRole] = "has_been_opened";
roles[CoverPathRole] = "cover_path";
roles[PublicationDate] = "date";
roles[ReadableTitle] = "readable_title";
return roles;
}
@ -275,7 +277,13 @@ QVariant ComicModel::data(const QModelIndex &index, int role) const
return item->data(Number);
else if (role == TitleRole)
return item->data(Title).isNull() ? item->data(FileName) : item->data(Title);
else if (role == FileNameRole)
else if (role == ReadableTitle) {
QString title;
if (!item->data(Number).isNull()) {
title = title % "#" % item->data(Number).toString() % " ";
}
return QVariant(title % (item->data(Title).isNull() ? item->data(FileName).toString() : item->data(Title).toString()));
} else if (role == FileNameRole)
return item->data(FileName);
else if (role == RatingRole)
return item->data(Rating);
@ -672,7 +680,8 @@ ComicDB ComicModel::getComic(const QModelIndex &mi)
QString connectionName = "";
{
QSqlDatabase db = DataBaseManagement::loadDatabase(_databasePath);
c = DBHelper::loadComic(_data.at(mi.row())->data(ComicModel::Id).toULongLong(), db);
bool found;
c = DBHelper::loadComic(_data.at(mi.row())->data(ComicModel::Id).toULongLong(), db, found);
connectionName = db.connectionName();
}
QSqlDatabase::removeDatabase(connectionName);
@ -686,7 +695,8 @@ ComicDB ComicModel::_getComic(const QModelIndex &mi)
QString connectionName = "";
{
QSqlDatabase db = DataBaseManagement::loadDatabase(_databasePath);
c = DBHelper::loadComic(_data.at(mi.row())->data(ComicModel::Id).toULongLong(), db);
bool found;
c = DBHelper::loadComic(_data.at(mi.row())->data(ComicModel::Id).toULongLong(), db, found);
connectionName = db.connectionName();
}
QSqlDatabase::removeDatabase(connectionName);
@ -726,7 +736,8 @@ QList<ComicDB> ComicModel::getAllComics()
int numComics = _data.count();
for (int i = 0; i < numComics; i++) {
comics.append(DBHelper::loadComic(_data.value(i)->data(ComicModel::Id).toULongLong(), db));
bool found;
comics.append(DBHelper::loadComic(_data.value(i)->data(ComicModel::Id).toULongLong(), db, found));
}
db.commit();
@ -755,7 +766,8 @@ QVector<YACReaderComicReadStatus> ComicModel::setComicsRead(QList<QModelIndex> l
foreach (QModelIndex mi, list) {
if (read == YACReader::Read) {
_data.value(mi.row())->setData(ComicModel::ReadColumn, QVariant(true));
ComicDB c = DBHelper::loadComic(_data.value(mi.row())->data(ComicModel::Id).toULongLong(), db);
bool found;
ComicDB c = DBHelper::loadComic(_data.value(mi.row())->data(ComicModel::Id).toULongLong(), db, found);
c.info.read = true;
DBHelper::update(&(c.info), db);
}
@ -763,7 +775,8 @@ QVector<YACReaderComicReadStatus> ComicModel::setComicsRead(QList<QModelIndex> l
_data.value(mi.row())->setData(ComicModel::ReadColumn, QVariant(false));
_data.value(mi.row())->setData(ComicModel::CurrentPage, QVariant(1));
_data.value(mi.row())->setData(ComicModel::HasBeenOpened, QVariant(false));
ComicDB c = DBHelper::loadComic(_data.value(mi.row())->data(ComicModel::Id).toULongLong(), db);
bool found;
ComicDB c = DBHelper::loadComic(_data.value(mi.row())->data(ComicModel::Id).toULongLong(), db, found);
c.info.read = false;
c.info.currentPage = 1;
c.info.hasBeenOpened = false;
@ -788,7 +801,8 @@ void ComicModel::setComicsManga(QList<QModelIndex> list, bool isManga)
QSqlDatabase db = DataBaseManagement::loadDatabase(_databasePath);
db.transaction();
foreach (QModelIndex mi, list) {
ComicDB c = DBHelper::loadComic(_data.value(mi.row())->data(ComicModel::Id).toULongLong(), db);
bool found;
ComicDB c = DBHelper::loadComic(_data.value(mi.row())->data(ComicModel::Id).toULongLong(), db, found);
c.info.manga = isManga;
DBHelper::update(&(c.info), db);
}
@ -808,7 +822,8 @@ qint64 ComicModel::asignNumbers(QList<QModelIndex> list, int startingNumber)
idFirst = _data.value(list[0].row())->data(ComicModel::Id).toULongLong();
int i = 0;
foreach (QModelIndex mi, list) {
ComicDB c = DBHelper::loadComic(_data.value(mi.row())->data(ComicModel::Id).toULongLong(), db);
bool found;
ComicDB c = DBHelper::loadComic(_data.value(mi.row())->data(ComicModel::Id).toULongLong(), db, found);
c.info.number = startingNumber + i;
c.info.edited = true;
DBHelper::update(&(c.info), db);
@ -864,7 +879,8 @@ void ComicModel::finishTransaction()
void ComicModel::removeInTransaction(int row)
{
auto dbTransaction = QSqlDatabase::database(_databaseConnection);
ComicDB c = DBHelper::loadComic(_data.at(row)->data(ComicModel::Id).toULongLong(), dbTransaction);
bool found;
ComicDB c = DBHelper::loadComic(_data.at(row)->data(ComicModel::Id).toULongLong(), dbTransaction, found);
DBHelper::removeFromDB(&c, dbTransaction);
beginRemoveRows(QModelIndex(), row, row);
@ -875,6 +891,32 @@ void ComicModel::removeInTransaction(int row)
endRemoveRows();
}
void ComicModel::reloadContinueReading()
{
setupReadingModelData(_databasePath);
}
void ComicModel::reload()
{
switch (mode) {
case Folder:
setupFolderModelData(sourceId, _databasePath);
break;
case Favorites:
setupFavoritesModelData(_databasePath);
break;
case Reading:
setupReadingModelData(_databasePath);
break;
case Label:
setupLabelModelData(sourceId, _databasePath);
break;
case ReadingList:
setupReadingListModelData(sourceId, _databasePath);
break;
}
}
void ComicModel::remove(int row)
{
removeInTransaction(row);

View File

@ -54,6 +54,7 @@ public:
HasBeenOpenedRole,
CoverPathRole,
PublicationDateRole,
ReadableTitle,
};
enum Mode {
@ -110,6 +111,8 @@ public:
qint64 asignNumbers(QList<QModelIndex> list, int startingNumber);
// void remove(ComicDB * comic, int row);
void removeInTransaction(int row);
void reloadContinueReading();
void reload();
void reload(const ComicDB &comic);
void resetComicRating(const QModelIndex &mi);

View File

@ -54,26 +54,26 @@ void drawMacOSXFinishedFolderIcon()
#define ROOT 1
FolderModel::FolderModel(QObject *parent)
: QAbstractItemModel(parent), rootItem(0)
: QAbstractItemModel(parent), isSubfolder(false), rootItem(nullptr), folderIcon(YACReader::noHighlightedIcon(":/images/sidebar/folder.svg")), folderFinishedIcon(YACReader::noHighlightedIcon(":/images/sidebar/folder_finished.svg"))
{
}
FolderModel::FolderModel(QSqlQuery &sqlquery, QObject *parent)
: QAbstractItemModel(parent), rootItem(0)
: QAbstractItemModel(parent), isSubfolder(false), rootItem(nullptr)
{
// lo m<>s probable es que el nodo ra<72>z no necesite tener informaci<63>n
QList<QVariant> rootData;
rootData << "root"; // id 0, padre 0, title "root" (el id, y el id del padre van a ir en la clase TreeItem)
rootItem = new FolderItem(rootData);
rootItem->id = ROOT;
rootItem->parentItem = 0;
rootItem->parentItem = nullptr;
setupModelData(sqlquery, rootItem);
// sqlquery.finish();
}
FolderModel::~FolderModel()
{
if (rootItem != 0)
if (rootItem != nullptr)
delete rootItem;
}
@ -81,8 +81,37 @@ int FolderModel::columnCount(const QModelIndex &parent) const
{
if (parent.isValid())
return static_cast<FolderItem *>(parent.internalPointer())->columnCount();
else
else {
if (rootItem == nullptr) {
return 0;
}
return rootItem->columnCount();
}
}
QHash<int, QByteArray> FolderModel::roleNames() const
{
QHash<int, QByteArray> roles;
roles[FinishedRole] = "is_finished";
roles[CompletedRole] = "is_completed";
roles[IdRole] = "id";
roles[MangaRole] = "is_manga";
roles[CoverPathRole] = "cover_path";
roles[FolderName] = "name";
return roles;
}
void FolderModel::reload()
{
setupModelData(_databasePath);
}
void FolderModel::reload(const QModelIndex &index)
{
// TODO: reload just the content under index for better efficiency
setupModelData(_databasePath);
}
QVariant FolderModel::data(const QModelIndex &index, int role) const
@ -115,12 +144,16 @@ QVariant FolderModel::data(const QModelIndex &index, int role) const
}
#else
if (item->data(FolderModel::Finished).toBool())
return QVariant(YACReader::noHighlightedIcon(":/images/sidebar/folder_finished.png"));
return QVariant(folderFinishedIcon);
else
return QVariant(YACReader::noHighlightedIcon(":/images/sidebar/folder.png"));
return QVariant(folderIcon);
#endif
}
if (role == FolderModel::FolderName) {
return item->data(FolderModel::Name);
}
if (role == FolderModel::CompletedRole)
return item->data(FolderModel::Completed);
@ -133,6 +166,9 @@ QVariant FolderModel::data(const QModelIndex &index, int role) const
if (role == FolderModel::IdRole)
return item->id;
if (role == FolderModel::CoverPathRole)
return getCoverUrlPathForComicHash(item->data(FirstChildHash).toString());
if (role != Qt::DisplayRole)
return QVariant();
@ -150,6 +186,10 @@ Qt::ItemFlags FolderModel::flags(const QModelIndex &index) const
QVariant FolderModel::headerData(int section, Qt::Orientation orientation,
int role) const
{
if (rootItem == nullptr) {
return QVariant();
}
if (orientation == Qt::Horizontal && role == Qt::DisplayRole)
return rootItem->data(section);
@ -176,6 +216,26 @@ QModelIndex FolderModel::index(int row, int column, const QModelIndex &parent)
return QModelIndex();
}
QModelIndex FolderModel::index(qulonglong folderId) const
{
QModelIndex index;
YACReader::iterate(QModelIndex(), this, [&](const QModelIndex &idx) {
if (index.isValid()) {
return false;
}
auto item = static_cast<FolderItem *>(idx.internalPointer());
if (item->id == folderId) {
index = idx;
return false;
}
return true;
});
return index;
}
QModelIndex FolderModel::parent(const QModelIndex &index) const
{
if (!index.isValid())
@ -196,10 +256,14 @@ int FolderModel::rowCount(const QModelIndex &parent) const
if (parent.column() > 0)
return 0;
if (!parent.isValid())
if (!parent.isValid()) {
if (rootItem == nullptr) {
return 0;
}
parentItem = rootItem;
else
} else {
parentItem = static_cast<FolderItem *>(parent.internalPointer());
}
return parentItem->childCount();
}
@ -207,17 +271,17 @@ int FolderModel::rowCount(const QModelIndex &parent) const
void FolderModel::setupModelData(QString path)
{
beginResetModel();
if (rootItem != 0)
if (rootItem != nullptr)
delete rootItem; // TODO comprobar que se libera bien la memoria
rootItem = 0;
rootItem = nullptr;
// inicializar el nodo ra<72>z
QList<QVariant> rootData;
rootData << "root"; // id 0, padre 0, title "root" (el id, y el id del padre van a ir en la clase TreeItem)
rootItem = new FolderItem(rootData);
rootItem->id = ROOT;
rootItem->parentItem = 0;
rootItem->parentItem = nullptr;
// cargar la base de datos
_databasePath = path;
@ -235,6 +299,13 @@ void FolderModel::setupModelData(QString path)
endResetModel();
}
void FolderModel::fullSetup(QSqlQuery &sqlquery, FolderItem *parent)
{
rootItem = parent;
setupModelData(sqlquery, parent);
}
void FolderModel::setupModelData(QSqlQuery &sqlquery, FolderItem *parent)
{
// 64 bits para la primary key, es decir la misma precisi<73>n que soporta sqlit 2^64
@ -252,6 +323,7 @@ void FolderModel::setupModelData(QSqlQuery &sqlquery, FolderItem *parent)
int manga = record.indexOf("manga");
int id = record.indexOf("id");
int parentId = record.indexOf("parentId");
int firstChildHash = record.indexOf("firstChildHash");
while (sqlquery.next()) {
QList<QVariant> data;
@ -261,6 +333,7 @@ void FolderModel::setupModelData(QSqlQuery &sqlquery, FolderItem *parent)
data << sqlquery.value(finished).toBool();
data << sqlquery.value(completed).toBool();
data << sqlquery.value(manga).toBool();
data << sqlquery.value(firstChildHash).toString();
auto item = new FolderItem(data);
item->id = sqlquery.value(id).toULongLong();
@ -286,6 +359,7 @@ void FolderModel::updateFolderModelData(QSqlQuery &sqlquery, FolderItem *parent)
int manga = record.indexOf("manga");
int id = record.indexOf("id");
int parentId = record.indexOf("parentId");
int firstChildHash = record.indexOf("firstChildHash");
while (sqlquery.next()) {
QList<QVariant> data;
@ -295,6 +369,7 @@ void FolderModel::updateFolderModelData(QSqlQuery &sqlquery, FolderItem *parent)
data << sqlquery.value(finished).toBool();
data << sqlquery.value(completed).toBool();
data << sqlquery.value(manga).toBool();
data << sqlquery.value(firstChildHash).toString();
auto item = new FolderItem(data);
item->id = sqlquery.value(id).toULongLong();
@ -329,16 +404,18 @@ void FolderModel::updateFolderCompletedStatus(const QModelIndexList &list, bool
auto item = static_cast<FolderItem *>(mi.internalPointer());
item->setData(FolderModel::Completed, status);
if (!isSubfolder) {
Folder f = DBHelper::loadFolder(item->id, db);
f.setCompleted(status);
DBHelper::update(f, db);
}
}
db.commit();
connectionName = db.connectionName();
}
QSqlDatabase::removeDatabase(connectionName);
emit dataChanged(index(list.first().row(), FolderModel::Name), index(list.last().row(), FolderModel::Completed));
emit dataChanged(index(list.first().row(), FolderModel::Name), index(list.last().row(), FolderModel::FirstChildHash));
}
void FolderModel::updateFolderFinishedStatus(const QModelIndexList &list, bool status)
@ -351,16 +428,18 @@ void FolderModel::updateFolderFinishedStatus(const QModelIndexList &list, bool s
auto item = static_cast<FolderItem *>(mi.internalPointer());
item->setData(FolderModel::Finished, status);
if (!isSubfolder) {
Folder f = DBHelper::loadFolder(item->id, db);
f.setFinished(status);
DBHelper::update(f, db);
}
}
db.commit();
connectionName = db.connectionName();
}
QSqlDatabase::removeDatabase(connectionName);
emit dataChanged(index(list.first().row(), FolderModel::Name), index(list.last().row(), FolderModel::Completed));
emit dataChanged(index(list.first().row(), FolderModel::Name), index(list.last().row(), FolderModel::FirstChildHash));
}
void FolderModel::updateFolderManga(const QModelIndexList &list, bool manga)
@ -383,14 +462,16 @@ void FolderModel::updateFolderManga(const QModelIndexList &list, bool manga)
setManga(item, manga);
if (!isSubfolder) {
DBHelper::updateFolderTreeManga(item->id, db, manga);
}
}
db.commit();
connectionName = db.connectionName();
}
QSqlDatabase::removeDatabase(connectionName);
emit dataChanged(index(list.first().row(), FolderModel::Name), index(list.last().row(), FolderModel::Manga));
emit dataChanged(index(list.first().row(), FolderModel::Name), index(list.last().row(), FolderModel::FirstChildHash));
}
QStringList FolderModel::getSubfoldersNames(const QModelIndex &mi)
@ -417,6 +498,97 @@ QStringList FolderModel::getSubfoldersNames(const QModelIndex &mi)
return result;
}
FolderModel *FolderModel::getSubfoldersModel(const QModelIndex &mi)
{
qulonglong id = 1;
FolderItem *parent = nullptr;
if (mi.isValid()) {
auto item = static_cast<FolderItem *>(mi.internalPointer());
parent = new FolderItem(item->getData(), item->parent());
id = parent->id = item->id;
}
if (id == 1) {
if (parent != nullptr) {
delete parent;
}
return this;
}
auto model = new FolderModel();
QString connectionName = "";
{
QSqlDatabase db = DataBaseManagement::loadDatabase(_databasePath);
QSqlQuery selectQuery(db); // TODO check
selectQuery.prepare("SELECT * FROM folder WHERE parentId = :parentId and id <> 1");
selectQuery.bindValue(":parentId", id);
selectQuery.exec();
if (parent != nullptr) {
model->fullSetup(selectQuery, parent);
}
connectionName = db.connectionName();
}
QSqlDatabase::removeDatabase(connectionName);
model->_databasePath = _databasePath;
model->isSubfolder = true;
return model;
}
Folder FolderModel::getFolder(const QModelIndex &mi)
{
auto folderItem = static_cast<FolderItem *>(mi.internalPointer());
auto name = folderItem->data(FolderModel::Name).toString();
auto parentItem = folderItem->parent();
auto folder = Folder(folderItem->id,
parentItem->id,
name,
folderItem->parent()->data(Columns::Path).toString() + "/" + name,
folderItem->data(Columns::Completed).toBool(),
folderItem->data(Columns::Finished).toBool(),
folderItem->data(Columns::Manga).toBool());
return folder;
}
QModelIndex FolderModel::getIndexFromFolder(const Folder &folder, const QModelIndex &parent)
{
if (rootItem == nullptr) {
return QModelIndex();
}
auto numRows = rowCount(parent);
for (auto i = 0; i < numRows; i++) {
auto modelIndex = index(i, 0, parent);
if (modelIndex.isValid()) {
auto folderItem = static_cast<FolderItem *>(modelIndex.internalPointer());
if (folderItem->id == folder.id) {
return modelIndex;
}
auto childModelIndex = getIndexFromFolder(folder, modelIndex);
if (childModelIndex.isValid()) {
auto folderItem = static_cast<FolderItem *>(childModelIndex.internalPointer());
if (folderItem->id == folder.id) {
return childModelIndex;
}
}
}
}
return QModelIndex();
}
void FolderModel::fetchMoreFromDB(const QModelIndex &parent)
{
FolderItem *item;
@ -531,6 +703,11 @@ QModelIndex FolderModel::addFolderAtParent(const QString &folderName, const QMod
return index(destRow, 0, parent);
}
QUrl FolderModel::getCoverUrlPathForComicHash(const QString &hash) const
{
return QUrl("file:" + _databasePath + "/covers/" + hash + ".jpg");
}
void FolderModel::deleteFolder(const QModelIndex &mi)
{
beginRemoveRows(mi.parent(), mi.row(), mi.row());

View File

@ -7,9 +7,12 @@
#include <QVariant>
#include <QSqlQuery>
#include <QSqlDatabase>
#include <QUrl>
#include <QIcon>
#include "yacreader_global.h"
#include "folder.h"
#include "folder_query_result_processor.h"
#include "yacreader_global.h"
class FolderItem;
@ -51,11 +54,15 @@ public:
int role = Qt::DisplayRole) const override;
QModelIndex index(int row, int column,
const QModelIndex &parent = QModelIndex()) const override;
QModelIndex index(qulonglong folderId) const;
QModelIndex parent(const QModelIndex &index) const override;
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
int columnCount(const QModelIndex &parent = QModelIndex()) const override;
QHash<int, QByteArray> roleNames() const override;
// Convenience methods
void reload();
void reload(const QModelIndex &index);
void setupModelData(QString path);
QString getDatabase();
QString getFolderPath(const QModelIndex &folder);
@ -68,31 +75,44 @@ public:
void updateFolderManga(const QModelIndexList &list, bool manga);
QStringList getSubfoldersNames(const QModelIndex &mi);
FolderModel *getSubfoldersModel(const QModelIndex &mi);
Folder getFolder(const QModelIndex &mi);
QModelIndex getIndexFromFolder(const Folder &folder, const QModelIndex &parent = QModelIndex());
void fetchMoreFromDB(const QModelIndex &parent);
QModelIndex addFolderAtParent(const QString &folderName, const QModelIndex &parent);
Q_INVOKABLE QUrl getCoverUrlPathForComicHash(const QString &hash) const;
enum Columns {
Name = 0,
Path = 1,
Finished = 2,
Completed = 3,
Manga = 4
Manga = 4,
FirstChildHash = 5
}; // id INTEGER PRIMARY KEY, parentId INTEGER NOT NULL, name TEXT NOT NULL, path TEXT NOT NULL
enum Roles {
FinishedRole = Qt::UserRole + 1,
CompletedRole,
IdRole,
MangaRole
MangaRole,
CoverPathRole,
FolderName,
};
bool isSubfolder;
public slots:
void deleteFolder(const QModelIndex &mi);
void updateFolderChildrenInfo(qulonglong folderId);
private:
void fullSetup(QSqlQuery &sqlquery, FolderItem *parent);
void setupModelData(QSqlQuery &sqlquery, FolderItem *parent);
void updateFolderModelData(QSqlQuery &sqlquery, FolderItem *parent);
@ -100,6 +120,9 @@ private:
QMap<unsigned long long int, FolderItem *> items; // relación entre folders
QString _databasePath;
QIcon folderIcon;
QIcon folderFinishedIcon;
};
#endif

View File

@ -36,7 +36,7 @@ QIcon SpecialListItem::getIcon() const
{
if (itemData.count() > Id) {
QString id = itemData.at(Id).toString();
return YACReader::noHighlightedIcon(QString(":/images/lists/default_%1.png").arg(id));
return YACReader::noHighlightedIcon(QString(":/images/lists/default_%1.svg").arg(id));
}
QLOG_WARN() << "Icon for SpecialListItem not available";
@ -76,7 +76,7 @@ QIcon LabelItem::getIcon() const
{
if (itemData.count() > Color) {
QString color = itemData.at(Color).toString();
return YACReader::noHighlightedIcon(QString(":/images/lists/label_%1.png").arg(color).toLower());
return YACReader::noHighlightedIcon(QString(":/images/lists/label_%1.svg").arg(color).toLower());
}
QLOG_WARN() << "Icon for label item not available";
@ -127,19 +127,19 @@ qulonglong LabelItem::getId() const
//------------------------------------------------------
ReadingListItem::ReadingListItem(const QList<QVariant> &data, ReadingListItem *p)
: ListItem(data), parent(p)
: ListItem(data), parent(p), list(YACReader::noHighlightedIcon(":/images/lists/list.svg")), folder(YACReader::noHighlightedIcon(":/images/sidebar/folder.svg"))
{
}
QIcon ReadingListItem::getIcon() const
{
if (parent->getId() == 0)
return YACReader::noHighlightedIcon(":/images/lists/list.png"); // top level list
return list; // top level list
else
#ifdef Q_OS_MAC
return QFileIconProvider().icon(QFileIconProvider::Folder);
#else
return YACReader::noHighlightedIcon(":/images/sidebar/folder.png"); // sublist
return folder; // sublist
#endif
}

View File

@ -82,6 +82,9 @@ public:
private:
QList<ReadingListItem *> childItems;
QIcon list;
QIcon folder;
enum DataIndexes {
Name,
Id,

View File

@ -143,7 +143,8 @@ ComicDB DBHelper::getComicInfo(qulonglong libraryId, qulonglong id)
{
QSqlDatabase db = DataBaseManagement::loadDatabase(libraryPath + "/.yacreaderlibrary");
comic = DBHelper::loadComic(id, db);
bool found;
comic = DBHelper::loadComic(id, db, found);
connectionName = db.connectionName();
}
QSqlDatabase::removeDatabase(connectionName);
@ -745,33 +746,27 @@ void DBHelper::propagateFolderUpdatesToParent(const Folder &folder, QSqlDatabase
Folder DBHelper::updateChildrenInfo(qulonglong folderId, QSqlDatabase &db)
{
auto folder = loadFolder(folderId, db);
QList<LibraryItem *> subitems;
QList<LibraryItem *> subfolders = DBHelper::getFoldersFromParent(folderId, db, false);
QList<LibraryItem *> comics = DBHelper::getComicsFromParent(folderId, db, false);
QList<LibraryItem *> subfolders = DBHelper::getFoldersFromParent(folderId, db, true);
QList<LibraryItem *> comics = DBHelper::getComicsFromParent(folderId, db, true);
QList<LibraryItem *> updatedSubfolders;
for (auto sf : subfolders) {
updatedSubfolders.append(new Folder(updateChildrenInfo(static_cast<Folder *>(sf)->id, db)));
}
subitems.append(updatedSubfolders);
subitems.append(comics);
std::sort(subitems.begin(), subitems.end(), naturalSortLessThanCILibraryItem);
QString coverHash = "";
for (auto item : subitems) {
if (item->isDir()) {
if (!comics.isEmpty()) {
auto c = static_cast<ComicDB *>(comics[0]);
coverHash = c->info.hash;
} else {
for (auto item : updatedSubfolders) {
auto f = static_cast<Folder *>(item);
auto firstChildHash = f->getFirstChildHash();
if (!firstChildHash.isEmpty()) {
coverHash = firstChildHash;
break;
}
} else {
auto c = static_cast<ComicDB *>(item);
coverHash = c->info.hash;
break;
}
}
@ -798,7 +793,7 @@ Folder DBHelper::updateChildrenInfo(qulonglong folderId, QSqlDatabase &db)
void DBHelper::updateChildrenInfo(QSqlDatabase &db)
{
QSqlQuery selectQuery(db); // TODO check
selectQuery.prepare("SELECT id FROM folder f WHERE f.parentId = 1");
selectQuery.prepare("SELECT id FROM folder f WHERE f.parentId = 1 AND f.id <> 1");
selectQuery.exec();
while (selectQuery.next()) {
@ -813,7 +808,8 @@ void DBHelper::updateProgress(qulonglong libraryId, const ComicInfo &comicInfo)
{
QSqlDatabase db = DataBaseManagement::loadDatabase(libraryPath + "/.yacreaderlibrary");
ComicDB comic = DBHelper::loadComic(comicInfo.id, db);
bool found;
ComicDB comic = DBHelper::loadComic(comicInfo.id, db, found);
comic.info.currentPage = comicInfo.currentPage;
comic.info.hasBeenOpened = comicInfo.currentPage > 0 || comic.info.hasBeenOpened;
comic.info.read = comic.info.read || comic.info.currentPage == comic.info.numPages;
@ -833,7 +829,8 @@ void DBHelper::setComicAsReading(qulonglong libraryId, const ComicInfo &comicInf
{
QSqlDatabase db = DataBaseManagement::loadDatabase(libraryPath + "/.yacreaderlibrary");
ComicDB comic = DBHelper::loadComic(comicInfo.id, db);
bool found;
ComicDB comic = DBHelper::loadComic(comicInfo.id, db, found);
comic.info.hasBeenOpened = true;
comic.info.read = comic.info.read || comic.info.currentPage == comic.info.numPages;
@ -872,7 +869,8 @@ void DBHelper::updateFromRemoteClient(qulonglong libraryId, const ComicInfo &com
{
QSqlDatabase db = DataBaseManagement::loadDatabase(libraryPath + "/.yacreaderlibrary");
ComicDB comic = DBHelper::loadComic(comicInfo.id, db);
bool found;
ComicDB comic = DBHelper::loadComic(comicInfo.id, db, found);
if (comic.info.hash == comicInfo.hash) {
if (comicInfo.currentPage > 0) {
@ -962,7 +960,8 @@ QMap<qulonglong, QList<ComicDB>> DBHelper::updateFromRemoteClient(const QMap<qul
" WHERE id = :id ");
foreach (ComicInfo comicInfo, comics[libraryId]) {
ComicDB comic = DBHelper::loadComic(comicInfo.id, db);
bool found;
ComicDB comic = DBHelper::loadComic(comicInfo.id, db, found);
if (comic.info.hash == comicInfo.hash) {
bool isMoreRecent = false;
@ -1176,6 +1175,22 @@ void DBHelper::reasignOrderToComicsInReadingList(qulonglong readingListId, QList
db.commit();
}
void DBHelper::updateComicsInfo(QList<ComicDB> &comics, const QString &databasePath)
{
QString connectionName = "";
{
QSqlDatabase db = DataBaseManagement::loadDatabase(databasePath);
db.open();
db.transaction();
foreach (ComicDB comic, comics) {
DBHelper::update(&(comic.info), db);
}
db.commit();
connectionName = db.connectionName();
}
QSqlDatabase::removeDatabase(connectionName);
}
// inserts
qulonglong DBHelper::insert(Folder *folder, QSqlDatabase &db)
{
@ -1632,7 +1647,7 @@ Folder DBHelper::loadFolder(const QString &folderName, qulonglong parentId, QSql
return folder;
}
ComicDB DBHelper::loadComic(qulonglong id, QSqlDatabase &db)
ComicDB DBHelper::loadComic(qulonglong id, QSqlDatabase &db, bool &found)
{
ComicDB comic;
@ -1654,6 +1669,9 @@ ComicDB DBHelper::loadComic(qulonglong id, QSqlDatabase &db)
comic.name = selectQuery.value(name).toString();
comic.path = selectQuery.value(path).toString();
comic.info = DBHelper::loadComicInfo(selectQuery.value(hash).toString(), db);
found = true;
} else {
found = false;
}
return comic;

View File

@ -82,6 +82,7 @@ public:
static void reasignOrderToComicsInFavorites(QList<qulonglong> comicIds, QSqlDatabase &db);
static void reasignOrderToComicsInLabel(qulonglong labelId, QList<qulonglong> comicIds, QSqlDatabase &db);
static void reasignOrderToComicsInReadingList(qulonglong readingListId, QList<qulonglong> comicIds, QSqlDatabase &db);
static void updateComicsInfo(QList<ComicDB> &comics, const QString &databasePath);
static QList<LibraryItem *> getFoldersFromParent(qulonglong parentId, QSqlDatabase &db, bool sort = true);
static QList<ComicDB> getSortedComicsFromParent(qulonglong parentId, QSqlDatabase &db);
@ -93,7 +94,7 @@ public:
// load
static Folder loadFolder(qulonglong id, QSqlDatabase &db);
static Folder loadFolder(const QString &folderName, qulonglong parentId, QSqlDatabase &db);
static ComicDB loadComic(qulonglong id, QSqlDatabase &db);
static ComicDB loadComic(qulonglong id, QSqlDatabase &db, bool &found);
static ComicDB loadComic(QString cname, QString cpath, QString chash, QSqlDatabase &database);
static ComicInfo loadComicInfo(QString hash, QSqlDatabase &db);
static ComicInfo getComicInfoFromQuery(QSqlQuery &query, const QString &idKey = "id");

View File

@ -0,0 +1,278 @@
#include "folder_content_view.h"
#include "folder_model.h"
#include "grid_comics_view.h"
#include "yacreader_global_gui.h"
#include "yacreader_tool_bar_stretch.h"
#include "QsLog.h"
#include <QQmlContext>
#include <QQuickItem>
#include <QQuickWidget>
using namespace YACReader;
FolderContentView::FolderContentView(QWidget *parent)
: QWidget { parent }, parent(QModelIndex()), comicModel(new ComicModel()), folderModel(new FolderModel())
{
qmlRegisterType<FolderModel>("com.yacreader.FolderModel", 1, 0, "FolderModel");
settings = new QSettings(YACReader::getSettingsPath() + "/YACReaderLibrary.ini", QSettings::IniFormat, this);
settings->beginGroup("libraryConfig");
view = new QQuickWidget();
// QQuickWidget requires rendering into OpenGL framebuffer objects
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
view->quickWindow()->setGraphicsApi(QSGRendererInterface::OpenGL);
#endif
view->setResizeMode(QQuickWidget::SizeRootObjectToView);
connect(
view, &QQuickWidget::statusChanged,
[=](QQuickWidget::Status status) {
if (status == QQuickWidget::Error) {
QLOG_ERROR() << view->errors();
}
});
coverSizeSliderWidget = new QWidget(this);
coverSizeSliderWidget->setFixedWidth(200);
coverSizeSlider = new QSlider(coverSizeSliderWidget);
coverSizeSlider->setOrientation(Qt::Horizontal);
coverSizeSlider->setRange(YACREADER_MIN_GRID_ZOOM_WIDTH, YACREADER_MAX_GRID_ZOOM_WIDTH);
auto horizontalLayout = new QHBoxLayout();
QLabel *smallLabel = new QLabel();
smallLabel->setPixmap(hdpiPixmap(":/images/comics_view_toolbar/small_size_grid_zoom.svg", QSize(18, 18)));
horizontalLayout->addWidget(smallLabel);
horizontalLayout->addWidget(coverSizeSlider, 0, Qt::AlignVCenter);
QLabel *bigLabel = new QLabel();
bigLabel->setPixmap(hdpiPixmap(":/images/comics_view_toolbar/big_size_grid_zoom.svg", QSize(18, 18)));
horizontalLayout->addWidget(bigLabel);
horizontalLayout->addSpacing(10);
horizontalLayout->setContentsMargins(0, 0, 0, 0);
coverSizeSliderWidget->setLayout(horizontalLayout);
connect(coverSizeSlider, &QAbstractSlider::valueChanged, this, &FolderContentView::setCoversSize);
toolbar = new QToolBar();
toolbar->addWidget(new YACReaderToolBarStretch);
toolbar->addWidget(coverSizeSliderWidget);
auto l = new QVBoxLayout;
setContentsMargins(0, 0, 0, 0);
l->setContentsMargins(0, 0, 0, 0);
l->setSpacing(0);
l->addWidget(view);
l->addWidget(toolbar);
this->setLayout(l);
QQmlContext *ctxt = view->rootContext();
LibraryUITheme theme;
#ifdef Q_OS_MAC
theme = Light;
#else
theme = Dark;
#endif
if (theme == Light) {
ctxt->setContextProperty("continueReadingBackgroundColor", "#E8E8E8");
ctxt->setContextProperty("continueReadingColor", "#000000");
ctxt->setContextProperty("backgroundColor", "#F6F6F6");
ctxt->setContextProperty("cellColor", "#FFFFFF");
ctxt->setContextProperty("selectedColor", "#FFFFFF");
ctxt->setContextProperty("selectedBorderColor", "#007AFF");
ctxt->setContextProperty("borderColor", "#DBDBDB");
ctxt->setContextProperty("titleColor", "#121212");
ctxt->setContextProperty("textColor", "#636363");
// fonts settings
ctxt->setContextProperty("fontSize", 11);
ctxt->setContextProperty("fontFamily", QApplication::font().family());
ctxt->setContextProperty("fontSpacing", 0.5);
// info - copy/pasted from info_comics_view TODO create helpers for setting the UI config
ctxt->setContextProperty("infoBackgroundColor", "#FFFFFF");
ctxt->setContextProperty("topShadow", QUrl());
ctxt->setContextProperty("infoShadow", "info-shadow-light.png");
ctxt->setContextProperty("infoIndicator", "info-indicator-light.png");
ctxt->setContextProperty("infoTextColor", "#404040");
ctxt->setContextProperty("infoTitleColor", "#2E2E2E");
ctxt->setContextProperty("ratingUnselectedColor", "#DEDEDE");
ctxt->setContextProperty("ratingSelectedColor", "#2B2B2B");
ctxt->setContextProperty("favUncheckedColor", "#DEDEDE");
ctxt->setContextProperty("favCheckedColor", "#E84852");
ctxt->setContextProperty("readTickUncheckedColor", "#DEDEDE");
ctxt->setContextProperty("readTickCheckedColor", "#E84852");
} else {
ctxt->setContextProperty("continueReadingBackgroundColor", "#88000000");
ctxt->setContextProperty("continueReadingColor", "#FFFFFF");
ctxt->setContextProperty("backgroundColor", "#2A2A2A");
ctxt->setContextProperty("cellColor", "#212121");
ctxt->setContextProperty("selectedColor", "#121212");
ctxt->setContextProperty("selectedBorderColor", "#121212");
ctxt->setContextProperty("borderColor", "#121212");
ctxt->setContextProperty("titleColor", "#FFFFFF");
ctxt->setContextProperty("textColor", "#A8A8A8");
ctxt->setContextProperty("dropShadow", QVariant(false));
// fonts settings
int fontSize = QApplication::font().pointSize();
if (fontSize == -1)
fontSize = QApplication::font().pixelSize();
ctxt->setContextProperty("fontSize", fontSize);
ctxt->setContextProperty("fontFamily", QApplication::font().family());
ctxt->setContextProperty("fontSpacing", 0.5);
// info - copy/pasted from info_comics_view TODO create helpers for setting the UI config
ctxt->setContextProperty("infoBackgroundColor", "#2E2E2E");
ctxt->setContextProperty("topShadow", "info-top-shadow.png");
ctxt->setContextProperty("infoShadow", "info-shadow.png");
ctxt->setContextProperty("infoIndicator", "info-indicator.png");
ctxt->setContextProperty("infoTextColor", "#B0B0B0");
ctxt->setContextProperty("infoTitleColor", "#FFFFFF");
ctxt->setContextProperty("ratingUnselectedColor", "#1C1C1C");
ctxt->setContextProperty("ratingSelectedColor", "#FFFFFF");
ctxt->setContextProperty("favUncheckedColor", "#1C1C1C");
ctxt->setContextProperty("favCheckedColor", "#E84852");
ctxt->setContextProperty("readTickUncheckedColor", "#1C1C1C");
ctxt->setContextProperty("readTickCheckedColor", "#E84852");
}
updateCoversSizeInContext(YACREADER_MIN_COVER_WIDTH, ctxt);
ctxt->setContextProperty("comicsList", comicModel.get());
ctxt->setContextProperty("foldersList", folderModel);
ctxt->setContextProperty("showCurrentComic", QVariant(false));
ctxt->setContextProperty("openHelper", this);
ctxt->setContextProperty("contextMenuHelper", this);
view->setSource(QUrl("qrc:/qml/FolderContentView.qml"));
}
void FolderContentView::setModel(const QModelIndex &parent, FolderModel *model)
{
this->parent = parent;
QQmlContext *ctxt = view->rootContext();
ctxt->setContextProperty("foldersList", model);
// when the root folder is set, FolderModel just returns itself in `getSubfoldersModel`, I need to measure the performance of create a deep copy...
if (folderModel->isSubfolder) {
delete folderModel;
}
folderModel = model;
auto grid = view->rootObject()->findChild<QQuickItem *>(QStringLiteral("grid"));
if (grid != nullptr) {
grid->setProperty("currentIndex", 0);
}
}
void FolderContentView::setContinueReadingModel(ComicModel *model)
{
QQmlContext *ctxt = view->rootContext();
ctxt->setContextProperty("comicsList", model);
this->comicModel.reset(model);
auto list = view->rootObject()->findChild<QQuickItem *>(QStringLiteral("list"));
if (list != nullptr) {
list->setProperty("currentIndex", 0);
}
}
void FolderContentView::reloadContinueReadingModel()
{
if (!folderModel->isSubfolder) {
comicModel->reloadContinueReading();
}
}
void FolderContentView::openFolder(int index)
{
emit subfolderSelected(this->parent, index);
}
void FolderContentView::openComicFromContinueReadingList(int index)
{
auto comic = comicModel->getComic(comicModel->index(index, 0));
emit openComic(comic, ComicModel::Folder);
}
void FolderContentView::requestedFolderContextMenu(QPoint point, int index)
{
auto folder = folderModel->getFolder(folderModel->index(index, 0));
emit openFolderContextMenu(point, folder);
}
void FolderContentView::requestedContinueReadingComicContextMenu(QPoint point, int index)
{
auto comic = comicModel->getComic(comicModel->index(index, 0));
emit openContinueReadingComicContextMenu(point, comic);
}
void FolderContentView::updateCoversSizeInContext(int width, QQmlContext *ctxt)
{
int cellBottomMarging = 8 * (1 + 2 * (1 - (float(YACREADER_MAX_GRID_ZOOM_WIDTH - width) / (YACREADER_MAX_GRID_ZOOM_WIDTH - YACREADER_MIN_GRID_ZOOM_WIDTH))));
ctxt->setContextProperty("cellCustomHeight", ((width * YACREADER_MAX_COVER_HEIGHT) / YACREADER_MIN_COVER_WIDTH) + 51 + cellBottomMarging);
ctxt->setContextProperty("cellCustomWidth", (width * YACREADER_MIN_CELL_CUSTOM_WIDTH) / YACREADER_MIN_COVER_WIDTH);
ctxt->setContextProperty("itemWidth", width);
ctxt->setContextProperty("itemHeight", ((width * YACREADER_MAX_COVER_HEIGHT) / YACREADER_MIN_COVER_WIDTH) + 51);
ctxt->setContextProperty("coverWidth", width);
ctxt->setContextProperty("coverHeight", (width * YACREADER_MAX_COVER_HEIGHT) / YACREADER_MIN_COVER_WIDTH);
}
void FolderContentView::setCoversSize(int width)
{
QQmlContext *ctxt = view->rootContext();
auto grid = view->rootObject()->findChild<QQuickItem *>(QStringLiteral("grid"));
if (grid != 0) {
QVariant cellCustomWidth = (width * YACREADER_MIN_CELL_CUSTOM_WIDTH) / YACREADER_MIN_GRID_ZOOM_WIDTH;
QMetaObject::invokeMethod(grid, "calculateCellWidths",
Q_ARG(QVariant, cellCustomWidth));
}
updateCoversSizeInContext(width, ctxt);
settings->setValue(COMICS_GRID_COVER_SIZES, coverSizeSlider->value());
}
void FolderContentView::showEvent(QShowEvent *event)
{
QWidget::showEvent(event);
int coverSize = settings->value(COMICS_GRID_COVER_SIZES, YACREADER_MIN_COVER_WIDTH).toInt();
coverSizeSlider->setValue(coverSize);
setCoversSize(coverSize);
}
void FolderContentView::dragEnterEvent(QDragEnterEvent *event)
{
}
void FolderContentView::dropEvent(QDropEvent *event)
{
}

View File

@ -0,0 +1,72 @@
#ifndef FOLDERCONTENTVIEW_H
#define FOLDERCONTENTVIEW_H
#include <QtWidgets>
#include "comic_model.h"
#include "folder.h"
#include "comic_db.h"
class FolderModel;
class ComicModel;
class YACReaderToolBarStretch;
class QQuickWidget;
class QQmlContext;
class FolderContentView : public QWidget
{
Q_OBJECT
public:
explicit FolderContentView(QWidget *parent = nullptr);
void setModel(const QModelIndex &parent, FolderModel *model);
void setContinueReadingModel(ComicModel *model);
void reloadContinueReadingModel();
FolderModel *currentFolderModel() { return folderModel; }
signals:
void subfolderSelected(QModelIndex, int);
void openComic(const ComicDB &comic, const ComicModel::Mode mode);
// Drops
void copyComicsToCurrentFolder(QList<QPair<QString, QString>>);
void moveComicsToCurrentFolder(QList<QPair<QString, QString>>);
void openFolderContextMenu(QPoint point, Folder folder);
void openContinueReadingComicContextMenu(QPoint point, ComicDB comic);
protected slots:
// void onItemClicked(const QModelIndex &mi);
void updateCoversSizeInContext(int width, QQmlContext *ctxt);
void setCoversSize(int width);
virtual void showEvent(QShowEvent *event) override;
void openFolder(int index);
void openComicFromContinueReadingList(int index);
void requestedFolderContextMenu(QPoint point, int index);
void requestedContinueReadingComicContextMenu(QPoint point, int index);
protected:
QQuickWidget *view;
QModelIndex parent;
std::unique_ptr<ComicModel> comicModel;
FolderModel *folderModel;
// Drop to import
void dragEnterEvent(QDragEnterEvent *event) override;
void dropEvent(QDropEvent *event) override;
private:
QSettings *settings;
QToolBar *toolbar;
YACReaderToolBarStretch *toolBarStretch;
QAction *toolBarStretchAction;
QWidget *coverSizeSliderWidget;
QSlider *coverSizeSlider;
QAction *coverSizeSliderAction;
QAction *showInfoAction;
QAction *showInfoSeparatorAction;
};
#endif // FOLDERCONTENTVIEW_H

View File

@ -14,22 +14,6 @@
#include "yacreader_comic_info_helper.h"
#include "current_comic_view_helper.h"
// values relative to visible cells
const unsigned int YACREADER_MIN_GRID_ZOOM_WIDTH = 156;
const unsigned int YACREADER_MAX_GRID_ZOOM_WIDTH = 312;
// GridView cells
const unsigned int YACREADER_MIN_CELL_CUSTOM_HEIGHT = 295;
const unsigned int YACREADER_MIN_CELL_CUSTOM_WIDTH = 185;
// Covers
const unsigned int YACREADER_MAX_COVER_HEIGHT = 236;
const unsigned int YACREADER_MIN_COVER_WIDTH = YACREADER_MIN_GRID_ZOOM_WIDTH;
// visible cells (realCell in qml), grid cells size is used to create faux inner margings
const unsigned int YACREADER_MIN_ITEM_HEIGHT = YACREADER_MAX_COVER_HEIGHT + 51; // 51 is the height of the bottom rectangle used for title and other info
const unsigned int YACREADER_MIN_ITEM_WIDTH = YACREADER_MIN_COVER_WIDTH;
GridComicsView::GridComicsView(QWidget *parent)
: ComicsView(parent), filterEnabled(false)
{
@ -161,7 +145,7 @@ GridComicsView::GridComicsView(QWidget *parent)
QQmlProperty(infoContainer, "width").write(settings->value(COMICS_GRID_INFO_WIDTH, 350));
showInfoAction = new QAction(tr("Show info"), this);
showInfoAction->setIcon(QIcon(":/images/comics_view_toolbar/show_comic_info.png"));
showInfoAction->setIcon(QIcon(":/images/comics_view_toolbar/show_comic_info.svg"));
showInfoAction->setCheckable(true);
showInfoAction->setChecked(showInfo);
connect(showInfoAction, &QAction::toggled, this, &GridComicsView::showInfo);
@ -195,11 +179,11 @@ void GridComicsView::createCoverSizeSliderWidget()
auto horizontalLayout = new QHBoxLayout();
QLabel *smallLabel = new QLabel();
smallLabel->setPixmap(QPixmap(":/images/comics_view_toolbar/small_size_grid_zoom.png"));
smallLabel->setPixmap(hdpiPixmap(":/images/comics_view_toolbar/small_size_grid_zoom.svg", QSize(18, 18)));
horizontalLayout->addWidget(smallLabel);
horizontalLayout->addWidget(coverSizeSlider, 0, Qt::AlignVCenter);
QLabel *bigLabel = new QLabel();
bigLabel->setPixmap(QPixmap(":/images/comics_view_toolbar/big_size_grid_zoom.png"));
bigLabel->setPixmap(hdpiPixmap(":/images/comics_view_toolbar/big_size_grid_zoom.svg", QSize(18, 18)));
horizontalLayout->addWidget(bigLabel);
horizontalLayout->addSpacing(10);
horizontalLayout->setContentsMargins(0, 0, 0, 0);
@ -422,6 +406,8 @@ void GridComicsView::setCoversSize(int width)
}
updateCoversSizeInContext(width, ctxt);
settings->setValue(COMICS_GRID_COVER_SIZES, coverSizeSlider->value());
}
void GridComicsView::updateCoversSizeInContext(int width, QQmlContext *ctxt)
@ -478,6 +464,15 @@ void GridComicsView::resetScroll()
QMetaObject::invokeMethod(scrollView, "scrollToOrigin");
}
void GridComicsView::showEvent(QShowEvent *event)
{
ComicsView::showEvent(event);
int coverSize = settings->value(COMICS_GRID_COVER_SIZES, YACREADER_MIN_COVER_WIDTH).toInt();
coverSizeSlider->setValue(coverSize);
setCoversSize(coverSize);
}
QByteArray GridComicsView::getMimeDataFromSelection()
{
QByteArray data;
@ -504,7 +499,7 @@ void GridComicsView::startDrag()
{
auto drag = new QDrag(this);
drag->setMimeData(model->mimeData(selectionHelper->selectedRows()));
drag->setPixmap(QPixmap(":/images/comics_view_toolbar/openInYACReader.png")); // TODO add better image
drag->setPixmap(hdpiPixmap(":/images/comics_view_toolbar/openInYACReader.svg", QSize(18, 18))); // TODO add better image
/*Qt::DropAction dropAction =*/drag->exec(Qt::CopyAction | Qt::MoveAction, Qt::CopyAction);
}

View File

@ -16,6 +16,22 @@ class YACReaderToolBarStretch;
class YACReaderComicsSelectionHelper;
class YACReaderComicInfoHelper;
// values relative to visible cells
const unsigned int YACREADER_MIN_GRID_ZOOM_WIDTH = 156;
const unsigned int YACREADER_MAX_GRID_ZOOM_WIDTH = 312;
// GridView cells
const unsigned int YACREADER_MIN_CELL_CUSTOM_HEIGHT = 295;
const unsigned int YACREADER_MIN_CELL_CUSTOM_WIDTH = 185;
// Covers
const unsigned int YACREADER_MAX_COVER_HEIGHT = 236;
const unsigned int YACREADER_MIN_COVER_WIDTH = YACREADER_MIN_GRID_ZOOM_WIDTH;
// visible cells (realCell in qml), grid cells size is used to create faux inner margings
const unsigned int YACREADER_MIN_ITEM_HEIGHT = YACREADER_MAX_COVER_HEIGHT + 51; // 51 is the height of the bottom rectangle used for title and other info
const unsigned int YACREADER_MIN_ITEM_WIDTH = YACREADER_MIN_COVER_WIDTH;
class GridComicsView : public ComicsView
{
Q_OBJECT
@ -73,6 +89,8 @@ protected slots:
void resetScroll();
virtual void showEvent(QShowEvent *event) override;
signals:
void onScrollToOrigin();

View File

@ -1,7 +1,7 @@
<RCC>
<qresource prefix="/">
<file>../images/accept_shortcut.png</file>
<file>../images/clear_shortcut.png</file>
<file>../images/accept_shortcut.svg</file>
<file>../images/clear_shortcut.svg</file>
<file>../images/comic_vine/downArrow.png</file>
<file>../images/comic_vine/nextPage.png</file>
<file>../images/comic_vine/previousPage.png</file>
@ -10,36 +10,21 @@
<file>../images/comic_vine/rowDown.png</file>
<file>../images/comic_vine/rowUp.png</file>
<file>../images/comic_vine/upArrow.png</file>
<file>../images/comics_view_toolbar/asignNumber.png</file>
<file>../images/comics_view_toolbar/asignNumber@2x.png</file>
<file>../images/comics_view_toolbar/big_size_grid_zoom.png</file>
<file>../images/comics_view_toolbar/big_size_grid_zoom@2x.png</file>
<file>../images/comics_view_toolbar/editComic.png</file>
<file>../images/comics_view_toolbar/editComic@2x.png</file>
<file>../images/comics_view_toolbar/getInfo.png</file>
<file>../images/comics_view_toolbar/getInfo@2x.png</file>
<file>../images/comics_view_toolbar/hideComicFlow.png</file>
<file>../images/comics_view_toolbar/hideComicFlow@2x.png</file>
<file>../images/comics_view_toolbar/openInYACReader.png</file>
<file>../images/comics_view_toolbar/openInYACReader@2x.png</file>
<file>../images/comics_view_toolbar/selectAll.png</file>
<file>../images/comics_view_toolbar/selectAll@2x.png</file>
<file>../images/comics_view_toolbar/setReadButton.png</file>
<file>../images/comics_view_toolbar/setReadButton@2x.png</file>
<file>../images/comics_view_toolbar/setUnread.png</file>
<file>../images/comics_view_toolbar/setUnread@2x.png</file>
<file>../images/comics_view_toolbar/showMarks.png</file>
<file>../images/comics_view_toolbar/showMarks@2x.png</file>
<file>../images/comics_view_toolbar/small_size_grid_zoom.png</file>
<file>../images/comics_view_toolbar/small_size_grid_zoom@2x.png</file>
<file>../images/comics_view_toolbar/trash.png</file>
<file>../images/comics_view_toolbar/trash@2x.png</file>
<file>../images/comics_view_toolbar/show_comic_info.png</file>
<file>../images/comics_view_toolbar/show_comic_info@2x.png</file>
<file>../images/comics_view_toolbar/setManga.png</file>
<file>../images/comics_view_toolbar/setManga@2x.png</file>
<file>../images/comics_view_toolbar/setNormal.png</file>
<file>../images/comics_view_toolbar/setNormal@2x.png</file>
<file>../images/comics_view_toolbar/asignNumber.svg</file>
<file>../images/comics_view_toolbar/big_size_grid_zoom.svg</file>
<file>../images/comics_view_toolbar/editComic.svg</file>
<file>../images/comics_view_toolbar/getInfo.svg</file>
<file>../images/comics_view_toolbar/hideComicFlow.svg</file>
<file>../images/comics_view_toolbar/openInYACReader.svg</file>
<file>../images/comics_view_toolbar/selectAll.svg</file>
<file>../images/comics_view_toolbar/setReadButton.svg</file>
<file>../images/comics_view_toolbar/setUnread.svg</file>
<file>../images/comics_view_toolbar/showMarks.svg</file>
<file>../images/comics_view_toolbar/small_size_grid_zoom.svg</file>
<file>../images/comics_view_toolbar/trash.svg</file>
<file>../images/comics_view_toolbar/show_comic_info.svg</file>
<file>../images/comics_view_toolbar/setManga.svg</file>
<file>../images/comics_view_toolbar/setNormal.svg</file>
<file>../images/defaultCover.png</file>
<file>../images/edit.png</file>
<file>../images/empty_current_readings.png</file>
@ -64,23 +49,16 @@
<file>../images/importingIcon.png</file>
<file>../images/importLibrary.png</file>
<file>../images/importTopCoversDecoration.png</file>
<file>../images/main_toolbar/divider.png</file>
<file>../images/menus_icons/editIcon.png</file>
<file>../images/menus_icons/editIcon@2x.png</file>
<file>../images/menus_icons/exportComicsInfoIcon.png</file>
<file>../images/menus_icons/exportComicsInfoIcon@2x.png</file>
<file>../images/menus_icons/exportLibraryIcon.png</file>
<file>../images/menus_icons/exportLibraryIcon@2x.png</file>
<file>../images/menus_icons/importComicsInfoIcon.png</file>
<file>../images/menus_icons/importComicsInfoIcon@2x.png</file>
<file>../images/menus_icons/importLibraryIcon.png</file>
<file>../images/menus_icons/importLibraryIcon@2x.png</file>
<file>../images/menus_icons/open.png</file>
<file>../images/menus_icons/open@2x.png</file>
<file>../images/menus_icons/removeLibraryIcon.png</file>
<file>../images/menus_icons/removeLibraryIcon@2x.png</file>
<file>../images/menus_icons/updateLibraryIcon.png</file>
<file>../images/menus_icons/updateLibraryIcon@2x.png</file>
<file>../images/main_toolbar/divider.svg</file>
<file>../images/menus_icons/editIcon.svg</file>
<file>../images/menus_icons/exportComicsInfoIcon.svg</file>
<file>../images/menus_icons/exportLibraryIcon.svg</file>
<file>../images/menus_icons/importComicsInfoIcon.svg</file>
<file>../images/menus_icons/importLibraryIcon.svg</file>
<file>../images/menus_icons/removeLibraryIcon.svg</file>
<file>../images/menus_icons/updateLibraryIcon.svg</file>
<file>../images/menus_icons/open_containing_folder.svg</file>
<file>../images/menus_icons/update_current_folder.svg</file>
<file>../images/new.png</file>
<file>../images/nextCoverPage.png</file>
<file>../images/noLibrariesIcon.png</file>
@ -92,28 +70,43 @@
<file>../images/readRibbon.png</file>
<file>../images/searching_icon.png</file>
<file>../images/serverConfigBackground.png</file>
<file>../images/shortcuts_group_comics.png</file>
<file>../images/shortcuts_group_folders.png</file>
<file>../images/shortcuts_group_general.png</file>
<file>../images/shortcuts_group_libraries.png</file>
<file>../images/shortcuts_group_mglass.png</file>
<file>../images/shortcuts_group_page.png</file>
<file>../images/shortcuts_group_reading.png</file>
<file>../images/shortcuts_group_visualization.png</file>
<file>../images/shortcuts_group_comics.svg</file>
<file>../images/shortcuts_group_folders.svg</file>
<file>../images/shortcuts_group_general.svg</file>
<file>../images/shortcuts_group_libraries.svg</file>
<file>../images/shortcuts_group_mglass.svg</file>
<file>../images/shortcuts_group_page.svg</file>
<file>../images/shortcuts_group_reading.svg</file>
<file>../images/shortcuts_group_visualization.svg</file>
<file>../images/shownCovers.png</file>
<file>../images/sidebar/branch-closed.png</file>
<file>../images/sidebar/branch-open.png</file>
<file>../images/sidebar/branch-closed.svg</file>
<file>../images/sidebar/branch-open.svg</file>
<file>../images/sidebar/collapsed_branch_osx.png</file>
<file>../images/sidebar/collapsed_branch_selected.png</file>
<file>../images/sidebar/expanded_branch_osx.png</file>
<file>../images/sidebar/expanded_branch_selected.png</file>
<file>../images/sidebar/folder.png</file>
<file>../images/sidebar/folder_finished.png</file>
<file>../images/sidebar/libraryIconSelected.png</file>
<file>../images/sidebar/libraryOptions.png</file>
<file>../images/sidebar/libraryOptions@2x.png</file>
<file>../images/sidebar/folder.svg</file>
<file>../images/sidebar/folder_finished.svg</file>
<file>../images/sidebar/libraryIconSelected.svg</file>
<file>../images/sidebar/libraryOptions.svg</file>
<file>../images/updatingIcon.png</file>
<file>../images/custom_dialog/custom_close_button.svg</file>
<file>../images/whats_new/whatsnew_header.svg</file>
<file>../images/lists/default_0.svg</file>
<file>../images/lists/default_1.svg</file>
<file>../images/lists/label_blue.svg</file>
<file>../images/lists/label_cyan.svg</file>
<file>../images/lists/label_dark.svg</file>
<file>../images/lists/label_green.svg</file>
<file>../images/lists/label_light.svg</file>
<file>../images/lists/label_orange.svg</file>
<file>../images/lists/label_pink.svg</file>
<file>../images/lists/label_purple.svg</file>
<file>../images/lists/label_red.svg</file>
<file>../images/lists/label_violet.svg</file>
<file>../images/lists/label_white.svg</file>
<file>../images/lists/label_yellow.svg</file>
<file>../images/lists/list.svg</file>
</qresource>
</RCC>

View File

@ -23,37 +23,7 @@
<file>../images/iconSearch@2x.png</file>
<file>../images/clearSearch.png</file>
<file>../images/clearSearch@2x.png</file>
<file alias="images/lists/default_0.png">../images/lists/default_0_osx.png</file>
<file alias="images/lists/default_1.png">../images/lists/default_1_osx.png</file>
<file alias="images/lists/label_blue.png">../images/lists/label_blue_osx.png</file>
<file alias="images/lists/label_cyan.png">../images/lists/label_cyan_osx.png</file>
<file alias="images/lists/label_dark.png">../images/lists/label_dark_osx.png</file>
<file alias="images/lists/label_green.png">../images/lists/label_green_osx.png</file>
<file alias="images/lists/label_light.png">../images/lists/label_light_osx.png</file>
<file alias="images/lists/label_orange.png">../images/lists/label_orange_osx.png</file>
<file alias="images/lists/label_pink.png">../images/lists/label_pink_osx.png</file>
<file alias="images/lists/label_purple.png">../images/lists/label_purple_osx.png</file>
<file alias="images/lists/label_red.png">../images/lists/label_red_osx.png</file>
<file alias="images/lists/label_violet.png">../images/lists/label_violet_osx.png</file>
<file alias="images/lists/label_white.png">../images/lists/label_white_osx.png</file>
<file alias="images/lists/label_yellow.png">../images/lists/label_yellow_osx.png</file>
<file alias="images/lists/list.png">../images/lists/list_osx.png</file>
<file alias="images/empty_reading_list.png">../images/empty_reading_list_osx.png</file>
<file alias="images/lists/default_0@2x.png">../images/lists/default_0_osx@2x.png</file>
<file alias="images/lists/default_1@2x.png">../images/lists/default_1_osx@2x.png</file>
<file alias="images/lists/label_blue@2x.png">../images/lists/label_blue_osx@2x.png</file>
<file alias="images/lists/label_cyan@2x.png">../images/lists/label_cyan_osx@2x.png</file>
<file alias="images/lists/label_dark@2x.png">../images/lists/label_dark_osx@2x.png</file>
<file alias="images/lists/label_green@2x.png">../images/lists/label_green_osx@2x.png</file>
<file alias="images/lists/label_light@2x.png">../images/lists/label_light_osx@2x.png</file>
<file alias="images/lists/label_orange@2x.png">../images/lists/label_orange_osx@2x.png</file>
<file alias="images/lists/label_pink@2x.png">../images/lists/label_pink_osx@2x.png</file>
<file alias="images/lists/label_purple@2x.png">../images/lists/label_purple_osx@2x.png</file>
<file alias="images/lists/label_red@2x.png">../images/lists/label_red_osx@2x.png</file>
<file alias="images/lists/label_violet@2x.png">../images/lists/label_violet_osx@2x.png</file>
<file alias="images/lists/label_white@2x.png">../images/lists/label_white_osx@2x.png</file>
<file alias="images/lists/label_yellow@2x.png">../images/lists/label_yellow_osx@2x.png</file>
<file alias="images/lists/list@2x.png">../images/lists/list_osx@2x.png</file>
<file alias="images/sidebar/libraryIcon.png">../images/sidebar/libraryIcon_osx.png</file>
<file alias="images/sidebar/setRoot.png">../images/sidebar/setRoot_osx.png</file>
<file alias="images/sidebar/expand.png">../images/sidebar/expand_osx.png</file>

View File

@ -1,47 +1,32 @@
<RCC>
<qresource prefix="/">
<file>../images/main_toolbar/back.png</file>
<file>../images/main_toolbar/back.svg</file>
<file>../images/main_toolbar/back_disabled.png</file>
<file>../images/main_toolbar/forward.png</file>
<file>../images/main_toolbar/forward.svg</file>
<file>../images/main_toolbar/forward_disabled.png</file>
<file>../images/main_toolbar/settings.png</file>
<file>../images/main_toolbar/server.png</file>
<file>../images/main_toolbar/help.png</file>
<file>../images/main_toolbar/fullscreen.png</file>
<file>../images/sidebar/libraryIcon.png</file>
<file>../images/sidebar/setRoot.png</file>
<file>../images/sidebar/expand.png</file>
<file>../images/sidebar/colapse.png</file>
<file>../images/sidebar/newLibraryIcon.png</file>
<file>../images/sidebar/openLibraryIcon.png</file>
<file>../images/main_toolbar/flow.png</file>
<file>../images/main_toolbar/grid.png</file>
<file>../images/main_toolbar/info.png</file>
<file>../images/main_toolbar/settings.svg</file>
<file>../images/main_toolbar/server.svg</file>
<file>../images/main_toolbar/help.svg</file>
<file>../images/main_toolbar/fullscreen.svg</file>
<file>../images/main_toolbar/flow.svg</file>
<file>../images/main_toolbar/grid.svg</file>
<file>../images/main_toolbar/info.svg</file>
<file>../images/sidebar/libraryIcon.svg</file>
<file>../images/sidebar/setRoot.svg</file>
<file>../images/sidebar/expand.svg</file>
<file>../images/sidebar/colapse.svg</file>
<file>../images/sidebar/newLibraryIcon.svg</file>
<file>../images/sidebar/openLibraryIcon.svg</file>
<file>../images/sidebar/addNew_sidebar.svg</file>
<file>../images/sidebar/delete_sidebar.svg</file>
<file>../images/sidebar/addLabelIcon.svg</file>
<file>../images/sidebar/renameListIcon.svg</file>
<file>../images/empty_folder.png</file>
<file>../images/empty_search.png</file>
<file>../images/sidebar/addNew_sidebar.png</file>
<file>../images/sidebar/delete_sidebar.png</file>
<file alias="images/iconSearch.png">../images/iconSearchNew.png</file>
<file alias="images/clearSearch.png">../images/clearSearchNew.png</file>
<file>../images/sidebar/addLabelIcon.png</file>
<file>../images/sidebar/renameListIcon.png</file>
<file>../images/lists/default_0.png</file>
<file>../images/lists/default_1.png</file>
<file>../images/lists/label_blue.png</file>
<file>../images/lists/label_cyan.png</file>
<file>../images/lists/label_dark.png</file>
<file>../images/lists/label_green.png</file>
<file>../images/lists/label_light.png</file>
<file>../images/lists/label_orange.png</file>
<file>../images/lists/label_pink.png</file>
<file>../images/lists/label_purple.png</file>
<file>../images/lists/label_red.png</file>
<file>../images/lists/label_violet.png</file>
<file>../images/lists/label_white.png</file>
<file>../images/lists/label_yellow.png</file>
<file>../images/lists/list.png</file>
<file alias="images/iconSearch.svg">../images/iconSearchNew.svg</file>
<file alias="images/clearSearch.svg">../images/clearSearchNew.svg</file>
<file>../images/empty_reading_list.png</file>
<file>../images/viewer_toolbar/close.png</file>
<file>../images/viewer_toolbar/close.svg</file>
<file>icon.ico</file>
</qresource>
</RCC>

View File

@ -10,8 +10,8 @@ using namespace YACReader;
bool InitialComicInfoExtractor::crash = false;
InitialComicInfoExtractor::InitialComicInfoExtractor(QString fileSource, QString target, int coverPage)
: _fileSource(fileSource), _target(target), _numPages(0), _coverPage(coverPage), _xmlInfoData()
InitialComicInfoExtractor::InitialComicInfoExtractor(QString fileSource, QString target, int coverPage, bool getXMLMetadata)
: _fileSource(fileSource), _target(target), _numPages(0), _coverPage(coverPage), getXMLMetadata(getXMLMetadata), _xmlInfoData()
{
}
@ -101,8 +101,8 @@ void InitialComicInfoExtractor::extract()
QList<QString> order = archive.getFileNames();
if (getXMLMetadata) {
// Try to find embeded XML info (ComicRack or ComicTagger)
auto infoIndex = 0;
for (auto &fileName : order) {
if (fileName.endsWith(".xml", Qt::CaseInsensitive)) {
@ -112,6 +112,7 @@ void InitialComicInfoExtractor::extract()
infoIndex++;
}
}
//--------------------------

View File

@ -9,7 +9,7 @@ class InitialComicInfoExtractor : public QObject
Q_OBJECT
public:
InitialComicInfoExtractor(QString fileSource, QString target = "", int coverPage = 1);
InitialComicInfoExtractor(QString fileSource, QString target = "", int coverPage = 1, bool getXMLMetadata = false);
private:
QString _fileSource;
@ -19,6 +19,7 @@ private:
QPair<int, int> _coverSize;
QImage _cover;
int _coverPage;
int getXMLMetadata;
static bool crash;
QByteArray _xmlInfoData;
void saveCover(const QString &path, const QImage &cover);

View File

@ -26,8 +26,8 @@ using namespace std;
using namespace YACReader;
//--------------------------------------------------------------------------------
LibraryCreator::LibraryCreator()
: creation(false), partialUpdate(false)
LibraryCreator::LibraryCreator(QSettings *settings)
: creation(false), partialUpdate(false), settings(settings)
{
_nameFilter << Comic::comicExtensions;
}
@ -301,7 +301,7 @@ void LibraryCreator::insertComic(const QString &relativePath, const QFileInfo &f
QPair<int, int> originalCoverSize = { 0, 0 };
bool exists = checkCover(hash);
YACReader::InitialComicInfoExtractor ie(QDir::cleanPath(fileInfo.absoluteFilePath()), _target + "/covers/" + hash + ".jpg", comic.info.coverPage.toInt());
YACReader::InitialComicInfoExtractor ie(QDir::cleanPath(fileInfo.absoluteFilePath()), _target + "/covers/" + hash + ".jpg", comic.info.coverPage.toInt(), settings->value(IMPORT_COMIC_INFO_XML_METADATA, false).toBool());
if (!(comic.hasCover() && exists)) {
ie.extract();

View File

@ -22,7 +22,7 @@ class LibraryCreator : public QThread
{
Q_OBJECT
public:
LibraryCreator();
LibraryCreator(QSettings *settings);
void createLibrary(const QString &source, const QString &target);
void updateLibrary(const QString &source, const QString &target);
void updateFolder(const QString &source, const QString &target, const QString &folder, const QModelIndex &dest);
@ -54,6 +54,7 @@ private:
bool creation;
bool partialUpdate;
QModelIndex folderDestinationModelIndex;
QSettings *settings;
signals:
void finished();

File diff suppressed because it is too large Load Diff

View File

@ -14,6 +14,8 @@
#include "folder_query_result_processor.h"
#include "comic_model.h"
#include "comic_db.h"
#include "folder.h"
#include <future>
#include <memory>
@ -131,7 +133,7 @@ public:
//-------------
YACReaderNavigationController *navigationController;
YACReaderComicsViewsManager *comicsViewsManager;
YACReaderContentViewsManager *contentViewsManager;
YACReaderFoldersView *foldersView;
YACReaderReadingListsView *listsView;
@ -217,6 +219,7 @@ public:
QAction *asignOrderAction;
QAction *forceCoverExtractedAction;
QAction *deleteComicsAction;
QAction *deleteMetadataAction;
QAction *focusSearchLineAction;
QAction *focusComicsViewAction;
@ -227,6 +230,7 @@ public:
QAction *updateFolderAction;
QAction *updateCurrentFolderAction;
QAction *rescanXMLFromCurrentFolderAction;
// reading lists actions
QAction *addReadingListAction;
@ -343,6 +347,8 @@ public slots:
void removeLibrary();
void renameLibrary();
void rescanLibraryForXMLInfo();
void rescanCurrentFolderForXMLInfo();
void rescanFolderForXMLInfo(QModelIndex modelIndex);
void rename(QString newName);
void cancelCreating();
void stopLibraryCreator();
@ -374,14 +380,19 @@ public slots:
void manageUpdatingError(const QString &error);
void manageOpeningLibraryError(const QString &error);
QModelIndexList getSelectedComics();
void deleteMetadataFromSelectedComics();
void deleteComics();
void deleteComicsFromDisk();
void deleteComicsFromList();
// void showSocial();
void showFoldersContextMenu(const QPoint &point);
void showGridFoldersContextMenu(QPoint point, Folder folder);
void showContinueReadingContextMenu(QPoint point, ComicDB comic);
void libraryAlreadyExists(const QString &name);
void importLibraryPackage();
void updateComicsView(quint64 libraryId, const ComicDB &comic);
void updateViewsOnClientSync();
void updateViewsOnComicUpdateWithId(quint64 libraryId, quint64 comicId);
void updateViewsOnComicUpdate(quint64 libraryId, const ComicDB &comic);
void showComicVineScraper();
void setRemoveError();
void checkRemoveError();

View File

@ -13,7 +13,7 @@
#include <QCommandLineParser>
#include "yacreader_global.h"
#include "startup.h"
#include "yacreader_http_server.h"
#include "yacreader_local_server.h"
#include "comic_db.h"
#include "db_helper.h"
@ -30,7 +30,7 @@
#define PICTUREFLOW_QT4 1
// Server interface
Startup *s;
YACReaderHttpServer *httpServer;
using namespace QsLogging;
@ -164,21 +164,20 @@ int main(int argc, char **argv)
logger.addDestination(std::move(fileDestination));
QTranslator translator;
QString sufix = QLocale::system().name();
#if defined Q_OS_UNIX && !defined Q_OS_MAC
translator.load(QString(DATADIR) + "/yacreader/languages/yacreaderlibrary_" + sufix);
translator.load(QLocale(), "yacreaderlibrary", "_", QString(DATADIR) + "/yacreader/languages");
#else
translator.load(QCoreApplication::applicationDirPath() + "/languages/yacreaderlibrary_" + sufix);
translator.load(QLocale(), "yacreaderlibrary", "_", "languages");
#endif
app.installTranslator(&translator);
QTranslator viewerTranslator;
#if defined Q_OS_UNIX && !defined Q_OS_MAC
/*QTranslator viewerTranslator;
#if defined Q_OS_UNIX && !defined Q_OS_MAC
viewerTranslator.load(QString(DATADIR) + "/yacreader/languages/yacreader_" + sufix);
#else
#else
viewerTranslator.load(QCoreApplication::applicationDirPath() + "/languages/yacreader_" + sufix);
#endif
app.installTranslator(&viewerTranslator);
#endif
app.installTranslator(&viewerTranslator);*/
qRegisterMetaType<ComicDB>("ComicDB");
@ -244,10 +243,10 @@ int main(int argc, char **argv)
QSettings *settings = new QSettings(YACReader::getSettingsPath() + "/YACReaderLibrary.ini", QSettings::IniFormat);
settings->beginGroup("libraryConfig");
s = new Startup();
httpServer = new YACReaderHttpServer();
if (settings->value(SERVER_ON, true).toBool()) {
s->start();
httpServer->start();
}
#endif
@ -255,8 +254,9 @@ int main(int argc, char **argv)
auto mw = new LibraryWindow();
mw->connect(localServer, &YACReaderLocalServer::comicUpdated, mw, &LibraryWindow::updateComicsView, Qt::QueuedConnection);
mw->connect(localServer, &YACReaderLocalServer::comicUpdated, mw, &LibraryWindow::updateViewsOnComicUpdate, Qt::QueuedConnection);
mw->connect(httpServer, &YACReaderHttpServer::comicUpdated, mw, &LibraryWindow::updateViewsOnComicUpdateWithId, Qt::QueuedConnection);
mw->connect(httpServer, &YACReaderHttpServer::clientSync, mw, &LibraryWindow::updateViewsOnClientSync, Qt::QueuedConnection);
// connections to localServer
// start as tray
@ -276,8 +276,8 @@ int main(int argc, char **argv)
YACReader::exitCheck(ret);
// shutdown
s->stop();
delete s;
httpServer->stop();
delete httpServer;
localServer->close();
delete localServer;
delete mw;

View File

@ -50,13 +50,13 @@ OptionsDialog::OptionsDialog(QWidget *parent)
trayIconCheckbox = new QCheckBox(tr("Close to tray"));
startToTrayCheckbox = new QCheckBox(tr("Start into the system tray"));
connect(trayIconCheckbox, &QCheckBox::clicked,
connect(trayIconCheckbox, &QCheckBox::clicked, this,
[=](bool checked) {
settings->setValue(CLOSE_TO_TRAY, checked);
startToTrayCheckbox->setEnabled(checked);
emit optionsChanged();
});
connect(startToTrayCheckbox, &QCheckBox::clicked,
connect(startToTrayCheckbox, &QCheckBox::clicked, this,
[=](bool checked) {
settings->setValue(START_TO_TRAY, checked);
});
@ -74,6 +74,18 @@ OptionsDialog::OptionsDialog(QWidget *parent)
connect(apiKeyButton, &QAbstractButton::clicked, this, &OptionsDialog::editApiKey);
auto comicInfoXMLBox = new QGroupBox(tr("ComicInfo.xml legacy support"));
comicInfoXMLCheckbox = new QCheckBox(tr("Import metada from ComicInfo.xml when adding new comics"));
connect(comicInfoXMLCheckbox, &QCheckBox::clicked, this,
[=](bool checked) {
settings->setValue(IMPORT_COMIC_INFO_XML_METADATA, checked);
});
auto comicInfoXMLBoxLayout = new QVBoxLayout();
comicInfoXMLBoxLayout->addWidget(comicInfoXMLCheckbox);
comicInfoXMLBox->setLayout(comicInfoXMLBoxLayout);
// grid view background config
useBackgroundImageCheck = new QCheckBox(tr("Enable background image"));
@ -139,13 +151,14 @@ OptionsDialog::OptionsDialog(QWidget *parent)
generalLayout->addWidget(trayIconBox);
generalLayout->addWidget(shortcutsBox);
generalLayout->addWidget(apiKeyBox);
generalLayout->addWidget(comicInfoXMLBox);
generalLayout->addStretch();
tabWidget->addTab(generalW, tr("General"));
tabWidget->addTab(comicFlowW, tr("Comic Flow"));
#ifndef NO_OPENGL
tabWidget->addTab(gridViewW, tr("Grid view"));
#endif
tabWidget->addTab(generalW, tr("General"));
layout->addWidget(tabWidget);
layout->addLayout(buttons);
@ -172,6 +185,8 @@ void OptionsDialog::restoreOptions(QSettings *settings)
startToTrayCheckbox->setChecked(settings->value(START_TO_TRAY, false).toBool());
startToTrayCheckbox->setEnabled(trayIconCheckbox->isChecked());
comicInfoXMLCheckbox->setChecked(settings->value(IMPORT_COMIC_INFO_XML_METADATA, false).toBool());
bool useBackgroundImage = settings->value(USE_BACKGROUND_IMAGE_IN_GRID_VIEW, true).toBool();
useBackgroundImageCheck->setChecked(useBackgroundImage);

View File

@ -37,6 +37,7 @@ private:
QCheckBox *displayContinueReadingBannerCheck;
QCheckBox *trayIconCheckbox;
QCheckBox *startToTrayCheckbox;
QCheckBox *comicInfoXMLCheckbox;
};
#endif

View File

@ -1,6 +1,7 @@
<RCC>
<qresource prefix="/">
<file>qml/GridComicsView.qml</file>
<file>qml/FolderContentView.qml</file>
<file>qml/tick.png</file>
<file>qml/reading.png</file>
<file>qml/star_menu.png</file>

View File

@ -0,0 +1,457 @@
import QtQuick 2.15
import QtQuick.Controls 2.15
import QtQuick.Layouts 1.12
import QtGraphicalEffects 1.0
import com.yacreader.ComicModel 1.0
import com.yacreader.ComicInfo 1.0
import com.yacreader.ComicDB 1.0
Rectangle {
id: main
property int continuReadingHeight: 430;
property int topContentMargin: 20;
color: backgroundColor
anchors.margins: 0
Component {
id: appDelegate
Rectangle
{
id: cell
width: grid.cellWidth
height: grid.cellHeight
color: "#00000000"
scale: mouseArea.containsMouse ? 1.025 : 1
Behavior on scale {
NumberAnimation { duration: 90 }
}
Rectangle {
id: realCell
property int position : 0
width: itemWidth
height: itemHeight
color: "transparent"
anchors.horizontalCenter: parent.horizontalCenter
MouseArea {
id: mouseArea
anchors.fill: parent
acceptedButtons: Qt.LeftButton | Qt.RightButton
hoverEnabled: true
onDoubleClicked: {
openHelper.openFolder(index);
}
onPressed: mouse => {
var ci = grid.currentIndex; //save current index
mouse.accepted = true;
if(mouse.button === Qt.RightButton) // context menu is requested
{
var coordinates = main.mapFromItem(realCell,mouseX,mouseY)
contextMenuHelper.requestedFolderContextMenu(Qt.point(coordinates.x,coordinates.y), index);
mouse.accepted = false;
}
}
}
}
/**/
Rectangle {
transform: Rotation { origin.x: coverWidth / 2; origin.y: coverHeight / 2; angle: -4}
width: coverElement.width
height: coverElement.height
radius: 10
anchors {horizontalCenter: parent.horizontalCenter; top: realCell.top; topMargin: 0}
color: "#20000000"
border {
color: "#20FFFFFF"
width: 1
}
}
Rectangle {
transform: Rotation { origin.x: coverWidth / 2; origin.y: coverHeight / 2; angle: 3}
width: coverElement.width
height: coverElement.height
radius: 10
anchors {horizontalCenter: parent.horizontalCenter; top: realCell.top; topMargin: 0}
color: "#88000000"
border {
color: "#20FFFFFF"
width: 1
}
}
Item {
width: coverWidth
height: coverHeight
anchors {horizontalCenter: parent.horizontalCenter; top: realCell.top; topMargin: 0}
id: coverElement
Image {
id: coverImage
anchors.fill: parent
source: cover_path
fillMode: Image.PreserveAspectCrop
smooth: true
mipmap: true
asynchronous : true
cache: true
layer.enabled: true
layer.effect: OpacityMask {
anchors.fill: parent
cached: true
maskSource: Rectangle {
width: coverElement.width
height: coverElement.height
radius: 10
}
}
}
}
//border
Rectangle {
width: coverElement.width
height: coverElement.height
radius: 10
anchors {horizontalCenter: parent.horizontalCenter; top: realCell.top; topMargin: 0}
color: "transparent"
border {
color: "#20FFFFFF"
width: 1
}
}
//folder name
Text {
id : titleText
anchors { top: coverElement.bottom; left: realCell.left; leftMargin: 4; rightMargin: 4; topMargin: 10; }
width: itemWidth - 8
maximumLineCount: 2
wrapMode: Text.WordWrap
text: name
elide: Text.ElideRight
color: titleColor
font.letterSpacing: fontSpacing
font.pointSize: fontSize
font.family: fontFamily
}
}
}
Rectangle {
id: scrollView
objectName: "topScrollView"
anchors.fill: parent
anchors.margins: 0
children: grid
color: "transparent"
function scrollToOrigin() {
grid.contentY = grid.originY
grid.contentX = grid.originX
}
DropArea {
anchors.fill: parent
onEntered: {
if(drag.hasUrls)
{
if(dropManager.canDropUrls(drag.urls, drag.action))
{
drag.accepted = true;
}else
drag.accepted = false;
}
else if (dropManager.canDropFormats(drag.formats)) {
drag.accepted = true;
} else
drag.accepted = false;
}
onDropped: {
if(drop.hasUrls && dropManager.canDropUrls(drop.urls, drop.action))
{
dropManager.droppedFiles(drop.urls, drop.action);
}
else{
if (dropManager.canDropFormats(drop.formats))
{
var destItem = grid.itemAt(drop.x,drop.y + grid.contentY);
var destLocalX = grid.mapToItem(destItem,drop.x,drop.y + grid.contentY).x
var realIndex = grid.indexAt(drop.x,drop.y + grid.contentY);
if(realIndex === -1)
realIndex = grid.count - 1;
var destIndex = destLocalX < (grid.cellWidth / 2) ? realIndex : realIndex + 1;
dropManager.droppedComicsForResortingAt(drop.getDataAsString(), destIndex);
}
}
}
}
property Component continueReadingView: Component {
id: continueReadingView
Rectangle {
id: continueReadingTopView
color: "#00000000"
height: list.count > 0 ? main.continuReadingHeight : main.topContentMargin
Rectangle {
color: continueReadingBackgroundColor
id: continueReadingBackground
width: main.width
height: main.continuReadingHeight - main.topContentMargin
visible: list.count > 0
Text {
id: continueReadingText
text: qsTr("Continue Reading...")
color: continueReadingColor
anchors.left: parent.left
anchors.top: parent.top
anchors.topMargin: 15
anchors.bottomMargin: 20
anchors.leftMargin: 25
anchors.rightMargin: 0
font.pointSize: 18
font.weight: Font.DemiBold
}
ListView {
id: list
objectName: "list"
anchors { top: continueReadingText.bottom; left: parent.left; right: parent.right; bottom: parent.bottom; }
property int previousIndex;
property int verticalPadding: 20
orientation: Qt.Horizontal
pixelAligned: true
model: comicsList
spacing: 20
anchors.topMargin: 15
anchors.bottomMargin: 20
anchors.leftMargin: 25
anchors.rightMargin: 20
WheelHandler {
onWheel: event => {
if (list.contentWidth <= list.width) {
return;
}
var newValue = Math.min(list.contentWidth - list.width - anchors.leftMargin, (Math.max(list.originX , list.contentX - event.angleDelta.y)));
list.contentX = newValue
}
}
delegate: Component {
//cover
Rectangle {
width: Math.floor((list.height - (list.verticalPadding * 2)) * 0.65);
height: list.height - (list.verticalPadding * 2);
color:"transparent"
scale: mouseArea.containsMouse ? 1.025 : 1
Behavior on scale {
NumberAnimation { duration: 90 }
}
Image {
id: coverElement
anchors.fill: parent
source: cover_path
fillMode: Image.PreserveAspectCrop
smooth: true
mipmap: true
asynchronous : true
cache: true
}
//title
Text {
id : comicTitleText
anchors { top: coverElement.bottom; left: coverElement.left; right: coverElement.right; leftMargin: 4; rightMargin: 4; topMargin: 4; }
width: itemWidth - 8
maximumLineCount: 2
wrapMode: Text.WordWrap
text: readable_title
elide: Text.ElideRight
color: titleColor
font.letterSpacing: fontSpacing
font.pointSize: fontSize
font.family: fontFamily
}
//border
Rectangle {
width: coverElement.width
height: coverElement.height
anchors.centerIn: coverElement
color: "transparent"
border {
color: "#30FFFFFF"
width: 1
}
}
MouseArea {
id: mouseArea
anchors.fill: parent
acceptedButtons: Qt.LeftButton | Qt.RightButton
hoverEnabled: true
onDoubleClicked: {
list.currentIndex = index;
openHelper.openComicFromContinueReadingList(index);
}
onReleased: mouse => {
list.currentIndex = index;
if(mouse.button === Qt.RightButton) // context menu is requested
{
var coordinates = main.mapFromItem(coverElement,mouseX,mouseY)
contextMenuHelper.requestedContinueReadingComicContextMenu(Qt.point(coordinates.x,coordinates.y), index);
}
mouse.accepted = true;
}
}
}
}
focus: true
}
}
}
}
GridView {
id:grid
objectName: "grid"
anchors.fill: parent
cellHeight: cellCustomHeight
header: continueReadingView
focus: true
model: foldersList
delegate: appDelegate
anchors.topMargin: 0
anchors.bottomMargin: 10
anchors.leftMargin: 0
anchors.rightMargin: 0
pixelAligned: true
highlightFollowsCurrentItem: true
currentIndex: 0
cacheBuffer: 0
interactive: true
move: Transition {
NumberAnimation { properties: "x,y"; duration: 250 }
}
moveDisplaced: Transition {
NumberAnimation { properties: "x,y"; duration: 250 }
}
remove: Transition {
ParallelAnimation {
NumberAnimation { property: "opacity"; to: 0; duration: 250 }
}
}
removeDisplaced: Transition {
NumberAnimation { properties: "x,y"; duration: 250 }
}
displaced: Transition {
NumberAnimation { properties: "x,y"; duration: 250 }
}
function numCellsPerRow() {
return Math.floor(width / cellCustomWidth);
}
onWidthChanged: {
calculateCellWidths(cellCustomWidth);
}
function calculateCellWidths(cWidth) {
var wholeCells = Math.floor(width / cWidth);
var rest = width - (cWidth * wholeCells)
grid.cellWidth = cWidth + Math.floor(rest / wholeCells);
}
WheelHandler {
onWheel: event => {
if (grid.contentHeight <= grid.height) {
return;
}
var newValue = Math.min((grid.contentHeight - grid.height - (true ? main.continuReadingHeight : main.topContentMargin)), (Math.max(grid.originY , grid.contentY - event.angleDelta.y)));
grid.contentY = newValue;
}
}
ScrollBar.vertical: ScrollBar {
visible: grid.contentHeight > grid.height
contentItem: Item {
implicitWidth: 12
implicitHeight: 26
Rectangle {
color: "#88424242"
anchors.fill: parent
anchors.topMargin: 6
anchors.leftMargin: 3
anchors.rightMargin: 2
anchors.bottomMargin: 6
border.color: "#AA313131"
border.width: 1
radius: 3.5
}
}
}
}
}
}

View File

@ -0,0 +1,459 @@
import QtQuick 2.15
import QtQuick.Controls 2.15
import QtQuick.Layouts 1.12
import Qt5Compat.GraphicalEffects
import com.yacreader.ComicModel 1.0
import com.yacreader.ComicInfo 1.0
import com.yacreader.ComicDB 1.0
import QtQuick.Controls.Basic
Rectangle {
id: main
property int continuReadingHeight: 430;
property int topContentMargin: 20;
color: backgroundColor
anchors.margins: 0
Component {
id: appDelegate
Rectangle
{
id: cell
width: grid.cellWidth
height: grid.cellHeight
color: "#00000000"
scale: mouseArea.containsMouse ? 1.025 : 1
Behavior on scale {
NumberAnimation { duration: 90 }
}
Rectangle {
id: realCell
property int position : 0
width: itemWidth
height: itemHeight
color: "transparent"
anchors.horizontalCenter: parent.horizontalCenter
MouseArea {
id: mouseArea
anchors.fill: parent
acceptedButtons: Qt.LeftButton | Qt.RightButton
hoverEnabled: true
onDoubleClicked: {
openHelper.openFolder(index);
}
onPressed: mouse => {
var ci = grid.currentIndex; //save current index
mouse.accepted = true;
if(mouse.button === Qt.RightButton) // context menu is requested
{
var coordinates = main.mapFromItem(realCell,mouseX,mouseY)
contextMenuHelper.requestedFolderContextMenu(Qt.point(coordinates.x,coordinates.y), index);
mouse.accepted = false;
}
}
}
}
/**/
Rectangle {
transform: Rotation { origin.x: coverWidth / 2; origin.y: coverHeight / 2; angle: -4}
width: coverElement.width
height: coverElement.height
radius: 10
anchors {horizontalCenter: parent.horizontalCenter; top: realCell.top; topMargin: 0}
color: "#20000000"
border {
color: "#20FFFFFF"
width: 1
}
}
Rectangle {
transform: Rotation { origin.x: coverWidth / 2; origin.y: coverHeight / 2; angle: 3}
width: coverElement.width
height: coverElement.height
radius: 10
anchors {horizontalCenter: parent.horizontalCenter; top: realCell.top; topMargin: 0}
color: "#88000000"
border {
color: "#20FFFFFF"
width: 1
}
}
Item {
width: coverWidth
height: coverHeight
anchors {horizontalCenter: parent.horizontalCenter; top: realCell.top; topMargin: 0}
id: coverElement
Image {
id: coverImage
anchors.fill: parent
source: cover_path
fillMode: Image.PreserveAspectCrop
smooth: true
mipmap: true
asynchronous : true
cache: true
layer.enabled: true
layer.effect: OpacityMask {
anchors.fill: parent
cached: true
maskSource: Rectangle {
width: coverElement.width
height: coverElement.height
radius: 10
}
}
}
}
//border
Rectangle {
width: coverElement.width
height: coverElement.height
radius: 10
anchors {horizontalCenter: parent.horizontalCenter; top: realCell.top; topMargin: 0}
color: "transparent"
border {
color: "#20FFFFFF"
width: 1
}
}
//folder name
Text {
id : titleText
anchors { top: coverElement.bottom; left: realCell.left; leftMargin: 4; rightMargin: 4; topMargin: 10; }
width: itemWidth - 8
maximumLineCount: 2
wrapMode: Text.WordWrap
text: name
elide: Text.ElideRight
color: titleColor
font.letterSpacing: fontSpacing
font.pointSize: fontSize
font.family: fontFamily
}
}
}
Rectangle {
id: scrollView
objectName: "topScrollView"
anchors.fill: parent
anchors.margins: 0
children: grid
color: "transparent"
function scrollToOrigin() {
grid.contentY = grid.originY
grid.contentX = grid.originX
}
DropArea {
anchors.fill: parent
onEntered: {
if(drag.hasUrls)
{
if(dropManager.canDropUrls(drag.urls, drag.action))
{
drag.accepted = true;
}else
drag.accepted = false;
}
else if (dropManager.canDropFormats(drag.formats)) {
drag.accepted = true;
} else
drag.accepted = false;
}
onDropped: {
if(drop.hasUrls && dropManager.canDropUrls(drop.urls, drop.action))
{
dropManager.droppedFiles(drop.urls, drop.action);
}
else{
if (dropManager.canDropFormats(drop.formats))
{
var destItem = grid.itemAt(drop.x,drop.y + grid.contentY);
var destLocalX = grid.mapToItem(destItem,drop.x,drop.y + grid.contentY).x
var realIndex = grid.indexAt(drop.x,drop.y + grid.contentY);
if(realIndex === -1)
realIndex = grid.count - 1;
var destIndex = destLocalX < (grid.cellWidth / 2) ? realIndex : realIndex + 1;
dropManager.droppedComicsForResortingAt(drop.getDataAsString(), destIndex);
}
}
}
}
property Component continueReadingView: Component {
id: continueReadingView
Rectangle {
id: continueReadingTopView
color: "#00000000"
height: list.count > 0 ? main.continuReadingHeight : main.topContentMargin
Rectangle {
color: continueReadingBackgroundColor
id: continueReadingBackground
width: main.width
height: main.continuReadingHeight - main.topContentMargin
visible: list.count > 0
Text {
id: continueReadingText
text: qsTr("Continue Reading...")
color: continueReadingColor
anchors.left: parent.left
anchors.top: parent.top
anchors.topMargin: 15
anchors.bottomMargin: 20
anchors.leftMargin: 25
anchors.rightMargin: 0
font.pointSize: 18
font.weight: Font.DemiBold
}
ListView {
id: list
objectName: "list"
anchors { top: continueReadingText.bottom; left: parent.left; right: parent.right; bottom: parent.bottom; }
property int previousIndex;
property int verticalPadding: 20
orientation: Qt.Horizontal
pixelAligned: true
model: comicsList
spacing: 20
anchors.topMargin: 15
anchors.bottomMargin: 20
anchors.leftMargin: 25
anchors.rightMargin: 20
WheelHandler {
onWheel: event => {
if (list.contentWidth <= list.width) {
return;
}
var newValue = Math.min(list.contentWidth - list.width - anchors.leftMargin, (Math.max(list.originX , list.contentX - event.angleDelta.y)));
list.contentX = newValue
}
}
delegate: Component {
//cover
Rectangle {
width: Math.floor((list.height - (list.verticalPadding * 2)) * 0.65);
height: list.height - (list.verticalPadding * 2);
color:"transparent"
scale: mouseArea.containsMouse ? 1.025 : 1
Behavior on scale {
NumberAnimation { duration: 90 }
}
Image {
id: coverElement
anchors.fill: parent
source: cover_path
fillMode: Image.PreserveAspectCrop
smooth: true
mipmap: true
asynchronous : true
cache: true
}
//title
Text {
id : comicTitleText
anchors { top: coverElement.bottom; left: coverElement.left; right: coverElement.right; leftMargin: 4; rightMargin: 4; topMargin: 4; }
width: itemWidth - 8
maximumLineCount: 2
wrapMode: Text.WordWrap
text: readable_title
elide: Text.ElideRight
color: titleColor
font.letterSpacing: fontSpacing
font.pointSize: fontSize
font.family: fontFamily
}
//border
Rectangle {
width: coverElement.width
height: coverElement.height
anchors.centerIn: coverElement
color: "transparent"
border {
color: "#30FFFFFF"
width: 1
}
}
MouseArea {
id: mouseArea
anchors.fill: parent
acceptedButtons: Qt.LeftButton | Qt.RightButton
hoverEnabled: true
onDoubleClicked: {
list.currentIndex = index;
openHelper.openComicFromContinueReadingList(index);
}
onReleased: mouse => {
list.currentIndex = index;
if(mouse.button === Qt.RightButton) // context menu is requested
{
var coordinates = main.mapFromItem(coverElement,mouseX,mouseY)
contextMenuHelper.requestedContinueReadingComicContextMenu(Qt.point(coordinates.x,coordinates.y), index);
}
mouse.accepted = true;
}
}
}
}
focus: true
}
}
}
}
GridView {
id:grid
objectName: "grid"
anchors.fill: parent
cellHeight: cellCustomHeight
header: continueReadingView
focus: true
model: foldersList
delegate: appDelegate
anchors.topMargin: 0
anchors.bottomMargin: 10
anchors.leftMargin: 0
anchors.rightMargin: 0
pixelAligned: true
highlightFollowsCurrentItem: true
currentIndex: 0
cacheBuffer: 0
interactive: true
move: Transition {
NumberAnimation { properties: "x,y"; duration: 250 }
}
moveDisplaced: Transition {
NumberAnimation { properties: "x,y"; duration: 250 }
}
remove: Transition {
ParallelAnimation {
NumberAnimation { property: "opacity"; to: 0; duration: 250 }
}
}
removeDisplaced: Transition {
NumberAnimation { properties: "x,y"; duration: 250 }
}
displaced: Transition {
NumberAnimation { properties: "x,y"; duration: 250 }
}
function numCellsPerRow() {
return Math.floor(width / cellCustomWidth);
}
onWidthChanged: {
calculateCellWidths(cellCustomWidth);
}
function calculateCellWidths(cWidth) {
var wholeCells = Math.floor(width / cWidth);
var rest = width - (cWidth * wholeCells)
grid.cellWidth = cWidth + Math.floor(rest / wholeCells);
}
WheelHandler {
onWheel: event => {
if (grid.contentHeight <= grid.height) {
return;
}
var newValue = Math.min((grid.contentHeight - grid.height - (true ? main.continuReadingHeight : main.topContentMargin)), (Math.max(grid.originY , grid.contentY - event.angleDelta.y)));
grid.contentY = newValue;
}
}
ScrollBar.vertical: ScrollBar {
visible: grid.contentHeight > grid.height
contentItem: Item {
implicitWidth: 12
implicitHeight: 26
Rectangle {
color: "#88424242"
anchors.fill: parent
anchors.topMargin: 6
anchors.leftMargin: 3
anchors.rightMargin: 2
anchors.bottomMargin: 6
border.color: "#AA313131"
border.width: 1
radius: 3.5
}
}
}
}
}
}

View File

@ -756,6 +756,17 @@ Rectangle {
grid.cellWidth = cWidth + Math.floor(rest / wholeCells);
}
WheelHandler {
onWheel: {
if (grid.contentHeight <= grid.height) {
return;
}
var newValue = Math.min((grid.contentHeight - grid.height - (showCurrentComic ? 270 : 20)), (Math.max(grid.originY , grid.contentY - event.angleDelta.y)));
grid.contentY = newValue;
}
}
ScrollBar.vertical: ScrollBar {
visible: grid.contentHeight > grid.height

View File

@ -1,6 +1,7 @@
<RCC>
<qresource prefix="/">
<file alias="qml/GridComicsView.qml">qml/GridComicsView6.qml</file>
<file alias="qml/FolderContentView.qml">qml/FolderContentView6.qml</file>
<file alias="qml/FlowView.qml">qml/FlowView6.qml</file>
<file alias="qml/InfoTick.qml">qml/InfoTick6.qml</file>
<file alias="qml/InfoFavorites.qml">qml/InfoFavorites6.qml</file>

View File

@ -44,7 +44,12 @@ void UpdateComicControllerV2::service(HttpRequest &request, HttpResponse &respon
DBHelper::setComicAsReading(libraryId, info);
}
}
error = false;
updatedLibraryId = libraryId;
updatedComicId = comicId;
} else {
error = true;
response.setStatus(412, "No comic info received");
response.write("", true);
return;

View File

@ -15,6 +15,10 @@ public:
/** Generates the response */
void service(stefanfrings::HttpRequest &request, stefanfrings::HttpResponse &response) override;
bool error;
qulonglong updatedLibraryId;
qulonglong updatedComicId;
};
#endif // UPDATECOMICCONTROLLER_H

View File

@ -0,0 +1,82 @@
#include "statuspagecontroller.h"
#include "template.h"
#include "yacreader_global.h"
#include "db_helper.h"
#include "yacreader_libraries.h"
#include "QsLog.h"
#include <QSysInfo>
using stefanfrings::HttpRequest;
using stefanfrings::HttpResponse;
// using stefanfrings::HttpSession;
using stefanfrings::Template;
StatusPageController::StatusPageController() { }
void StatusPageController::service(HttpRequest &request, HttpResponse &response)
{
response.setHeader("Content-Type", "text/html; charset=utf-8");
response.setHeader("Connection", "close");
Template StatusPage = Template(
QStringLiteral(
"<!DOCTYPE html>\n"
"<html>\n"
"<head>\n"
"<title>YACReaderLibrary Server</title>\n"
"</head>\n"
"<body>\n\n"
"<center>\n"
"<img src='/images/webui/YACLibraryServer.svg' width=15%>\n"
"<h1>YACReaderLibraryServer is up and running.</h1>\n"
"<p>YACReader {yr.version}<p>\n"
"<p>Server {server.version}<p>\n"
"<p>OS:\t{os.name} {os.version}</p>\n"
"<p>Port:\t{os.port}</p>\n"
"<table>\n"
"<thead>\n"
"<tr>\n"
"<th>Library</th>\n"
"<th>Path</th>\n"
"</tr>\n"
"</thead>\n"
"{loop Library}"
"<tr>\n"
"<td>{Library.Name}</td>\n"
"<td>{Library.Path}</td>\n"
"<tr>\n"
"{end Library}"
"</p>\n"
"</center>\n"
"</body>\n"
"</html>\n"),
"StatusPage");
StatusPage.enableWarnings();
// Set template variables
StatusPage.setVariable("os.name", QSysInfo::prettyProductName());
StatusPage.setVariable("os.version", QSysInfo::productVersion());
// Getting the port from the request is basically a hack, but should do the trick
StatusPage.setVariable("os.port", QString(request.getHeader("host")).split(":")[1]);
StatusPage.setVariable("server.version", SERVER_VERSION_NUMBER);
StatusPage.setVariable("yr.version", VERSION);
// Get library info
YACReaderLibraries libraries = DBHelper::getLibraries();
QList<QString> library_names = libraries.getNames();
size_t num_libs = libraries.getNames().size();
// Fill template
StatusPage.loop("Library", num_libs);
for (size_t i = 0; i < num_libs; i++) {
StatusPage.setVariable(QString("Library%1.Name").arg(i), library_names.at(i));
StatusPage.setVariable(QString("Library%1.Path").arg(i), libraries.getPath(library_names.at(i)));
}
response.write(StatusPage.toUtf8(), true);
}

View File

@ -0,0 +1,19 @@
#ifndef STATUSPAGE_CONTROLLER
#define STATUSPAGE_CONTROLLER
#include "httprequest.h"
#include "httpresponse.h"
#include "httprequesthandler.h"
class StatusPageController : public stefanfrings::HttpRequestHandler
{
Q_OBJECT
Q_DISABLE_COPY(StatusPageController);
public:
StatusPageController();
void service(stefanfrings::HttpRequest &request, stefanfrings::HttpResponse &response) override;
};
#endif // STATUSPAGE_CONTROLLER

View File

@ -41,6 +41,8 @@
#include "controllers/v2/comicfullinfocontroller_v2.h"
#include "controllers/v2/comiccontrollerinreadinglist_v2.h"
#include "controllers/webui/statuspagecontroller.h"
#include "db_helper.h"
#include "yacreader_libraries.h"
@ -159,11 +161,18 @@ void RequestMapper::service(HttpRequest &request, HttpResponse &response)
if (path.startsWith("/v2")) {
serviceV2(request, response);
} else if (path.startsWith("/webui")) {
serviceWebUI(request, response);
} else {
serviceV1(request, response);
}
}
void RequestMapper::serviceWebUI(HttpRequest &request, HttpResponse &response)
{
StatusPageController().service(request, response);
}
void RequestMapper::serviceV1(HttpRequest &request, HttpResponse &response)
{
QByteArray path = request.getPath();
@ -273,6 +282,7 @@ void RequestMapper::serviceV2(HttpRequest &request, HttpResponse &response)
VersionController().service(request, response);
} else if (sync.exactMatch(path)) {
SyncControllerV2().service(request, response);
emit clientSync();
} else {
if (library.indexIn(path) != -1 && DBHelper::getLibraries().contains(library.cap(1).toInt())) {
if (folderInfo.exactMatch(path)) {
@ -290,7 +300,12 @@ void RequestMapper::serviceV2(HttpRequest &request, HttpResponse &response)
} else if (comicPage.exactMatch(path) || comicPageRemote.exactMatch(path)) {
PageControllerV2().service(request, response);
} else if (comicUpdate.exactMatch(path)) {
UpdateComicControllerV2().service(request, response);
auto updateController = UpdateComicControllerV2();
updateController.service(request, response);
if (!updateController.error) {
emit comicUpdated(updateController.updatedLibraryId, updateController.updatedComicId);
}
} else if (folderContent.exactMatch(path)) {
FolderContentControllerV2().service(request, response);
} else if (tags.exactMatch(path)) {

View File

@ -20,9 +20,14 @@ public:
void loadSessionV1(stefanfrings::HttpRequest &request, stefanfrings::HttpResponse &response);
void loadSessionV2(stefanfrings::HttpRequest &request, stefanfrings::HttpResponse &response);
signals:
void clientSync();
void comicUpdated(qulonglong libraryId, qulonglong comicId);
private:
void serviceV1(stefanfrings::HttpRequest &request, stefanfrings::HttpResponse &response);
void serviceV2(stefanfrings::HttpRequest &request, stefanfrings::HttpResponse &response);
void serviceWebUI(stefanfrings::HttpRequest &request, stefanfrings::HttpResponse &response);
static QMutex mutex;
};

View File

@ -10,8 +10,8 @@ DEPENDPATH += $$PWD/controllers/v2
HEADERS += \
$$PWD/static.h \
$$PWD/startup.h \
$$PWD/requestmapper.h \
$$PWD/yacreader_http_server.h \
$$PWD/yacreader_http_session.h \
$$PWD/yacreader_http_session_store.h \
$$PWD/yacreader_server_data_helper.h \
@ -47,13 +47,15 @@ HEADERS += \
$$PWD/controllers/v2/comicfullinfocontroller_v2.h \
$$PWD/controllers/v2/readinglistinfocontroller_v2.h \
$$PWD/controllers/v2/taginfocontroller_v2.h \
$$PWD/controllers/v2/comiccontrollerinreadinglist_v2.h
$$PWD/controllers/v2/comiccontrollerinreadinglist_v2.h\
#Browser
$$PWD/controllers/webui/statuspagecontroller.h
SOURCES += \
$$PWD/static.cpp \
$$PWD/startup.cpp \
$$PWD/requestmapper.cpp \
$$PWD/yacreader_http_server.cpp \
$$PWD/yacreader_http_session.cpp \
$$PWD/yacreader_http_session_store.cpp \
$$PWD/yacreader_server_data_helper.cpp \
@ -89,7 +91,9 @@ SOURCES += \
$$PWD/controllers/v2/comicfullinfocontroller_v2.cpp \
$$PWD/controllers/v2/readinglistinfocontroller_v2.cpp \
$$PWD/controllers/v2/taginfocontroller_v2.cpp \
$$PWD/controllers/v2/comiccontrollerinreadinglist_v2.cpp
$$PWD/controllers/v2/comiccontrollerinreadinglist_v2.cpp \
#WebUI
$$PWD/controllers/webui/statuspagecontroller.cpp
include(../../third_party/QtWebApp/httpserver/httpserver.pri)
include(../../third_party/QtWebApp/templateengine/templateengine.pri)

View File

@ -1,38 +0,0 @@
/**
@file
@author Stefan Frings
*/
#ifndef STARTUP_H
#define STARTUP_H
#include <QString>
namespace stefanfrings {
class HttpListener;
}
/**
Helper class to install and run the application as a windows
service.
*/
class Startup
{
private:
// QTcpServer
stefanfrings::HttpListener *listener;
public:
/** Constructor */
Startup();
/** Start the server */
void start(quint16 port = 0);
/** Stop the server */
void stop();
QString getPort();
protected:
};
#endif // STARTUP_H

View File

@ -4,7 +4,7 @@
*/
#include "static.h"
#include "startup.h"
#include "yacreader_http_server.h"
//#include "dualfilelogger.h"
#include "httplistener.h"
#include "requestmapper.h"
@ -32,7 +32,7 @@ using stefanfrings::HttpSessionStore;
using stefanfrings::StaticFileController;
using stefanfrings::TemplateCache;
void Startup::start(quint16 port)
void YACReaderHttpServer::start(quint16 port)
{
// Initialize the core application
QCoreApplication *app = QCoreApplication::instance();
@ -53,7 +53,7 @@ void Startup::start(quint16 port)
#else
templatePath = QFileInfo(QCoreApplication::applicationDirPath(), baseTemplatePath).absoluteFilePath();
#endif
if (!templateSettings->contains("path"))
templateSettings->setValue("path", templatePath);
Static::templateLoader = new TemplateCache(templateSettings, app);
@ -84,6 +84,7 @@ void Startup::start(quint16 port)
docroot = QFileInfo(QCoreApplication::applicationDirPath(), basedocroot).absoluteFilePath();
#endif
if (!fileSettings->contains("path"))
fileSettings->setValue("path", docroot);
Static::staticFileController = new StaticFileController(fileSettings, app);
@ -137,7 +138,11 @@ void Startup::start(quint16 port)
testServer.close();
}
listener = new HttpListener(listenerSettings, new RequestMapper(app), app);
auto requestMapper = new RequestMapper(app);
listener = new HttpListener(listenerSettings, requestMapper, app);
connect(requestMapper, &RequestMapper::comicUpdated, this, &YACReaderHttpServer::comicUpdated);
connect(requestMapper, &RequestMapper::clientSync, this, &YACReaderHttpServer::clientSync);
if (listener->isListening()) {
qDebug("ServiceHelper: Service has started");
@ -146,7 +151,7 @@ void Startup::start(quint16 port)
}
}
void Startup::stop()
void YACReaderHttpServer::stop()
{
qDebug("ServiceHelper: Service has been stopped");
// QCoreApplication destroys all objects that have been created in start().
@ -157,12 +162,12 @@ void Startup::stop()
}
}
Startup::Startup()
: listener(nullptr)
YACReaderHttpServer::YACReaderHttpServer()
: QObject(nullptr), listener(nullptr)
{
}
QString Startup::getPort()
QString YACReaderHttpServer::getPort()
{
return QString("%1").arg(listener->serverPort());
}

View File

@ -0,0 +1,30 @@
#ifndef YACREADER_HTTP_SERVER_H
#define YACREADER_HTTP_SERVER_H
#include <QObject>
#include <QString>
namespace stefanfrings {
class HttpListener;
}
class YACReaderHttpServer : public QObject
{
Q_OBJECT
public:
YACReaderHttpServer();
void start(quint16 port = 0);
void stop();
QString getPort();
signals:
void clientSync();
void comicUpdated(qulonglong libraryId, qulonglong comicId);
private:
stefanfrings::HttpListener *listener;
};
#endif // YACREADER_HTTP_SERVER_H

View File

@ -11,7 +11,7 @@
#include <QBitmap>
#include <QPainter>
#include "startup.h"
#include "yacreader_http_server.h"
#include "yacreader_global_gui.h"
#include "qnaturalsorting.h"
@ -78,7 +78,7 @@ QList<QString> addresses()
#endif
extern Startup *s;
extern YACReaderHttpServer *httpServer;
ServerConfigDialog::ServerConfigDialog(QWidget *parent)
: QDialog(parent)
@ -184,11 +184,11 @@ void ServerConfigDialog::enableServer(int status)
settings->beginGroup("libraryConfig");
if (status == Qt::Checked) {
s->start();
httpServer->start();
this->generateQR();
settings->setValue(SERVER_ON, true);
} else {
s->stop();
httpServer->stop();
qrCode->setPixmap(QPixmap());
ip->clear();
port->setText("");
@ -247,14 +247,14 @@ void ServerConfigDialog::generateQR()
if (otherAddresses.length() > 0 || !dir.isEmpty()) {
if (!dir.isEmpty()) {
generateQR(dir + ":" + s->getPort());
generateQR(dir + ":" + httpServer->getPort());
ip->addItem(dir);
} else {
generateQR(otherAddresses.first() + ":" + s->getPort());
generateQR(otherAddresses.first() + ":" + httpServer->getPort());
}
ip->addItems(otherAddresses);
port->setText(s->getPort());
port->setText(httpServer->getPort());
}
}
@ -280,7 +280,7 @@ void ServerConfigDialog::generateQR(const QString &serverAddress)
void ServerConfigDialog::regenerateQR(const QString &ip)
{
generateQR(ip + ":" + s->getPort());
generateQR(ip + ":" + httpServer->getPort());
}
void ServerConfigDialog::updatePort()
@ -291,8 +291,8 @@ void ServerConfigDialog::updatePort()
settings->setValue("port", port->text().toInt());
settings->endGroup();
s->stop();
s->start();
httpServer->stop();
httpServer->start();
generateQR(ip->currentText() + ":" + port->text());
}
@ -303,6 +303,13 @@ QrEncoder::QrEncoder()
QLibrary encoder(QCoreApplication::applicationDirPath() + "/utils/libqrencode.dylib");
#else
QLibrary encoder("qrencode");
#ifdef Q_OS_UNIX
encoder.load();
// Fallback - this loads libqrencode.4.x.x.so when libqrencode.so is not available
if (!encoder.isLoaded()) {
encoder.setFileNameAndVersion("qrencode", 4);
}
#endif
#endif
QRcode_encodeString8bit = (_QRcode_encodeString8bit)encoder.resolve("QRcode_encodeString8bit");
QRcode_free = (_QRcode_free)encoder.resolve("QRcode_free");

View File

@ -6,6 +6,7 @@
#include "initial_comic_info_extractor.h"
#include "xml_info_parser.h"
#include "yacreader_global.h"
#include "folder_item.h"
#include "QsLog.h"
@ -23,6 +24,21 @@ void XMLInfoLibraryScanner::scanLibrary(const QString &source, const QString &ta
this->stopRunning = false;
partialUpdate = false;
start();
}
void XMLInfoLibraryScanner::scanFolder(const QString &source, const QString &target, const QString &folder, const QModelIndex &dest)
{
this->source = source;
this->target = target;
this->stopRunning = false;
partialUpdate = true;
folderDestinationModelIndex = dest;
start();
}
@ -52,36 +68,29 @@ void XMLInfoLibraryScanner::run()
database.transaction();
if (!partialUpdate) {
QSqlQuery comicsInfo("SELECT * FROM comic c INNER JOIN comic_info ci ON (c.comicInfoId = ci.id)", database);
comicsInfo.exec();
QSqlRecord record = comicsInfo.record();
int id = record.indexOf("id");
// int parentIdIndex = record.indexOf("parentId");
int fileNameIndex = record.indexOf("fileName");
int pathIndex = record.indexOf("path");
while (comicsInfo.next()) {
if (this->stopRunning) {
break;
updateFromSQLQuery(database, comicsInfo);
} else {
if (folderDestinationModelIndex.isValid()) {
YACReader::iterate(folderDestinationModelIndex, folderDestinationModelIndex.model(), [&](const QModelIndex &idx) {
if (stopRunning) {
return false;
}
/* currentItem.id = selectQuery.value(id).toULongLong();
currentItem.parentId = parentId; //selectQuery.value(parentId).toULongLong();
currentItem.name = selectQuery.value(fileName).toString(); */
auto fileName = comicsInfo.value(fileNameIndex).toString();
auto path = comicsInfo.value(pathIndex).toString();
emit comicScanned(path, fileName);
auto item = static_cast<FolderItem *>(idx.internalPointer());
auto info = DBHelper::getComicInfoFromQuery(comicsInfo, "comicInfoId");
QSqlQuery comicsInfo(database);
comicsInfo.prepare("SELECT * FROM comic c INNER JOIN comic_info ci ON (c.comicInfoId = ci.id) WHERE c.parentId = :parentId");
comicsInfo.bindValue(":parentId", item->id);
comicsInfo.exec();
InitialComicInfoExtractor ie(QDir::cleanPath(this->source + path), "None");
updateFromSQLQuery(database, comicsInfo);
ie.extract();
if (parseXMLIntoInfo(ie.getXMLInfoRawData(), info)) {
DBHelper::update(&info, database);
return true;
});
}
}
@ -96,3 +105,33 @@ void XMLInfoLibraryScanner::stop()
{
stopRunning = true;
}
void XMLInfoLibraryScanner::updateFromSQLQuery(QSqlDatabase &db, QSqlQuery &query)
{
QSqlRecord record = query.record();
int id = record.indexOf("id");
// int parentIdIndex = record.indexOf("parentId");
int fileNameIndex = record.indexOf("fileName");
int pathIndex = record.indexOf("path");
while (query.next()) {
if (this->stopRunning) {
break;
}
auto fileName = query.value(fileNameIndex).toString();
auto path = query.value(pathIndex).toString();
emit comicScanned(path, fileName);
auto info = DBHelper::getComicInfoFromQuery(query, "comicInfoId");
InitialComicInfoExtractor ie(QDir::cleanPath(this->source + path), "None", info.coverPage.toInt(), true);
ie.extract();
if (parseXMLIntoInfo(ie.getXMLInfoRawData(), info)) {
DBHelper::update(&info, db);
}
}
}

View File

@ -2,6 +2,7 @@
#define XMLINFOLIBRARYSCANNER_H
#include <QtCore>
#include <QSqlQuery>
namespace YACReader {
@ -11,6 +12,7 @@ class XMLInfoLibraryScanner : public QThread
public:
XMLInfoLibraryScanner();
void scanLibrary(const QString &source, const QString &target);
void scanFolder(const QString &source, const QString &target, const QString &folder, const QModelIndex &dest);
protected:
void run() override;
@ -25,6 +27,10 @@ private:
QString source;
QString target;
bool stopRunning;
bool partialUpdate;
QModelIndex folderDestinationModelIndex;
void updateFromSQLQuery(QSqlDatabase &db, QSqlQuery &query);
};
}

View File

@ -1,4 +1,4 @@
#include "yacreader_comics_views_manager.h"
#include "yacreader_content_views_manager.h"
#include "library_window.h"
@ -6,7 +6,7 @@
#include "grid_comics_view.h"
#include "info_comics_view.h"
#include "comics_view_transition.h"
#include "empty_folder_widget.h"
#include "folder_content_view.h"
#include "empty_label_widget.h"
#include "empty_special_list.h"
#include "empty_reading_list_widget.h"
@ -18,7 +18,7 @@
#include "yacreader_search_line_edit.h"
#include "options_dialog.h"
YACReaderComicsViewsManager::YACReaderComicsViewsManager(QSettings *settings, LibraryWindow *parent)
YACReaderContentViewsManager::YACReaderContentViewsManager(QSettings *settings, LibraryWindow *parent)
: QObject(parent), libraryWindow(parent), classicComicsView(nullptr), gridComicsView(nullptr), infoComicsView(nullptr)
{
comicsViewStack = new QStackedWidget();
@ -29,26 +29,23 @@ YACReaderComicsViewsManager::YACReaderComicsViewsManager(QSettings *settings, Li
comicsViewStatus = Flow;
break;
case Grid:
comicsView = gridComicsView = new GridComicsView();
connect(libraryWindow->optionsDialog, &YACReaderOptionsDialog::optionsChanged, gridComicsView, &GridComicsView::updateBackgroundConfig);
comicsViewStatus = Grid;
break;
case Info:
comicsView = infoComicsView = new InfoComicsView();
comicsViewStatus = Info;
break;
case Grid:
default:
comicsView = classicComicsView = new ClassicComicsView();
comicsViewStatus = Flow;
comicsView = gridComicsView = new GridComicsView();
connect(libraryWindow->optionsDialog, &YACReaderOptionsDialog::optionsChanged, gridComicsView, &GridComicsView::updateBackgroundConfig);
comicsViewStatus = Grid;
break;
}
doComicsViewConnections();
comicsViewStack->addWidget(comicsViewTransition = new ComicsViewTransition());
comicsViewStack->addWidget(emptyFolderWidget = new EmptyFolderWidget());
comicsViewStack->addWidget(folderContentView = new FolderContentView());
comicsViewStack->addWidget(emptyLabelWidget = new EmptyLabelWidget());
comicsViewStack->addWidget(emptySpecialList = new EmptySpecialListWidget());
comicsViewStack->addWidget(emptyReadingList = new EmptyReadingListWidget());
@ -59,23 +56,46 @@ YACReaderComicsViewsManager::YACReaderComicsViewsManager(QSettings *settings, Li
comicsViewStack->setCurrentWidget(comicsView);
// connections
connect(emptyFolderWidget, &EmptyFolderWidget::copyComicsToCurrentFolder, libraryWindow, &LibraryWindow::copyAndImportComicsToCurrentFolder);
connect(emptyFolderWidget, &EmptyFolderWidget::moveComicsToCurrentFolder, libraryWindow, &LibraryWindow::moveAndImportComicsToCurrentFolder);
connect(folderContentView, &FolderContentView::copyComicsToCurrentFolder, libraryWindow, &LibraryWindow::copyAndImportComicsToCurrentFolder);
connect(folderContentView, &FolderContentView::moveComicsToCurrentFolder, libraryWindow, &LibraryWindow::moveAndImportComicsToCurrentFolder);
}
QWidget *YACReaderComicsViewsManager::containerWidget()
QWidget *YACReaderContentViewsManager::containerWidget()
{
return comicsViewStack;
}
void YACReaderComicsViewsManager::updateCurrentComicView()
void YACReaderContentViewsManager::updateCurrentComicView()
{
if (comicsViewStack->currentWidget() == comicsView) {
comicsView->updateCurrentComicView();
}
}
void YACReaderComicsViewsManager::showComicsView()
void YACReaderContentViewsManager::updateContinueReadingView()
{
if (comicsViewStack->currentWidget() == folderContentView) {
folderContentView->reloadContinueReadingModel();
}
}
void YACReaderContentViewsManager::toFullscreen()
{
if (comicsViewStack->currentWidget() == comicsView) {
comicsView->toFullScreen();
return;
}
}
void YACReaderContentViewsManager::toNormal()
{
if (comicsViewStack->currentWidget() == comicsView) {
comicsView->toNormal();
return;
}
}
void YACReaderContentViewsManager::showComicsView()
{
comicsViewStack->setCurrentWidget(comicsView);
@ -84,50 +104,50 @@ void YACReaderComicsViewsManager::showComicsView()
libraryWindow->sideBar->update();
}
void YACReaderComicsViewsManager::showEmptyFolderView()
void YACReaderContentViewsManager::showFolderContentView()
{
comicsViewStack->setCurrentWidget(emptyFolderWidget);
comicsViewStack->setCurrentWidget(folderContentView);
}
void YACReaderComicsViewsManager::showEmptyLabelView()
void YACReaderContentViewsManager::showEmptyLabelView()
{
comicsViewStack->setCurrentWidget(emptyLabelWidget);
}
void YACReaderComicsViewsManager::showEmptySpecialList()
void YACReaderContentViewsManager::showEmptySpecialList()
{
comicsViewStack->setCurrentWidget(emptySpecialList);
}
void YACReaderComicsViewsManager::showEmptyReadingListWidget()
void YACReaderContentViewsManager::showEmptyReadingListWidget()
{
comicsViewStack->setCurrentWidget(emptyReadingList);
}
void YACReaderComicsViewsManager::showNoSearchResultsView()
void YACReaderContentViewsManager::showNoSearchResultsView()
{
comicsViewStack->setCurrentWidget(noSearchResultsWidget);
}
// TODO recover the current comics selection and restore it in the destination
void YACReaderComicsViewsManager::toggleComicsView()
void YACReaderContentViewsManager::toggleComicsView()
{
if (comicsViewStack->currentWidget() == comicsView) {
QTimer::singleShot(0, this, &YACReaderComicsViewsManager::showComicsViewTransition);
QTimer::singleShot(100, this, &YACReaderComicsViewsManager::_toggleComicsView);
QTimer::singleShot(0, this, &YACReaderContentViewsManager::showComicsViewTransition);
QTimer::singleShot(100, this, &YACReaderContentViewsManager::_toggleComicsView);
} else {
_toggleComicsView();
}
}
void YACReaderComicsViewsManager::focusComicsViewViaShortcut()
void YACReaderContentViewsManager::focusComicsViewViaShortcut()
{
comicsView->focusComicsNavigation(Qt::ShortcutFocusReason);
}
// PROTECTED
void YACReaderComicsViewsManager::disconnectComicsViewConnections(ComicsView *widget)
void YACReaderContentViewsManager::disconnectComicsViewConnections(ComicsView *widget)
{
disconnect(widget, &ComicsView::comicRated, libraryWindow->comicsModel, &ComicModel::updateRating);
disconnect(libraryWindow->showHideMarksAction, &QAction::toggled, widget, &ComicsView::setShowMarks);
@ -140,7 +160,7 @@ void YACReaderComicsViewsManager::disconnectComicsViewConnections(ComicsView *wi
disconnect(comicsView, &ComicsView::customContextMenuItemRequested, libraryWindow, &LibraryWindow::showComicsItemContextMenu);
}
void YACReaderComicsViewsManager::doComicsViewConnections()
void YACReaderContentViewsManager::doComicsViewConnections()
{
connect(comicsView, &ComicsView::comicRated, libraryWindow->comicsModel, &ComicModel::updateRating);
connect(libraryWindow->showHideMarksAction, &QAction::toggled, comicsView, &ComicsView::setShowMarks);
@ -156,7 +176,7 @@ void YACReaderComicsViewsManager::doComicsViewConnections()
connect(comicsView, &ComicsView::moveComicsToCurrentFolder, libraryWindow, &LibraryWindow::moveAndImportComicsToCurrentFolder);
}
void YACReaderComicsViewsManager::switchToComicsView(ComicsView *from, ComicsView *to)
void YACReaderContentViewsManager::switchToComicsView(ComicsView *from, ComicsView *to)
{
// setup views
disconnectComicsViewConnections(from);
@ -180,17 +200,17 @@ void YACReaderComicsViewsManager::switchToComicsView(ComicsView *from, ComicsVie
}
}
void YACReaderComicsViewsManager::showComicsViewTransition()
void YACReaderContentViewsManager::showComicsViewTransition()
{
comicsViewStack->setCurrentWidget(comicsViewTransition);
}
void YACReaderComicsViewsManager::_toggleComicsView()
void YACReaderContentViewsManager::_toggleComicsView()
{
switch (comicsViewStatus) {
case Flow: {
QIcon icoViewsButton;
icoViewsButton.addFile(":/images/main_toolbar/info.png", QSize(), QIcon::Normal);
icoViewsButton.addFile(addExtensionToIconPath(":/images/main_toolbar/info"), QSize(), QIcon::Normal);
libraryWindow->toggleComicsViewAction->setIcon(icoViewsButton);
#ifdef Q_OS_MAC
libraryWindow->libraryToolBar->updateViewSelectorIcon(icoViewsButton);
@ -207,7 +227,7 @@ void YACReaderComicsViewsManager::_toggleComicsView()
case Grid: {
QIcon icoViewsButton;
icoViewsButton.addFile(":/images/main_toolbar/flow.png", QSize(), QIcon::Normal);
icoViewsButton.addFile(addExtensionToIconPath(":/images/main_toolbar/flow"), QSize(), QIcon::Normal);
libraryWindow->toggleComicsViewAction->setIcon(icoViewsButton);
#ifdef Q_OS_MAC
libraryWindow->libraryToolBar->updateViewSelectorIcon(icoViewsButton);
@ -223,7 +243,7 @@ void YACReaderComicsViewsManager::_toggleComicsView()
case Info: {
QIcon icoViewsButton;
icoViewsButton.addFile(":/images/main_toolbar/grid.png", QSize(), QIcon::Normal);
icoViewsButton.addFile(addExtensionToIconPath(":/images/main_toolbar/grid"), QSize(), QIcon::Normal);
libraryWindow->toggleComicsViewAction->setIcon(icoViewsButton);
#ifdef Q_OS_MAC
libraryWindow->libraryToolBar->updateViewSelectorIcon(icoViewsButton);

View File

@ -1,5 +1,5 @@
#ifndef YACREADERCOMICSVIEWSMANAGER_H
#define YACREADERCOMICSVIEWSMANAGER_H
#ifndef YACREADERCONTENTVIEWSMANAGER_H
#define YACREADERCONTENTVIEWSMANAGER_H
#include <QtWidgets>
@ -12,7 +12,7 @@ class ClassicComicsView;
class GridComicsView;
class InfoComicsView;
class ComicsViewTransition;
class EmptyFolderWidget;
class FolderContentView;
class EmptyLabelWidget;
class EmptySpecialListWidget;
class EmptyReadingListWidget;
@ -20,11 +20,11 @@ class NoSearchResultsWidget;
using namespace YACReader;
class YACReaderComicsViewsManager : public QObject
class YACReaderContentViewsManager : public QObject
{
Q_OBJECT
public:
explicit YACReaderComicsViewsManager(QSettings *settings, LibraryWindow *parent = nullptr);
explicit YACReaderContentViewsManager(QSettings *settings, LibraryWindow *parent = nullptr);
QWidget *containerWidget();
@ -32,7 +32,7 @@ public:
ComicsViewTransition *comicsViewTransition;
EmptyFolderWidget *emptyFolderWidget;
FolderContentView *folderContentView;
EmptyLabelWidget *emptyLabelWidget;
EmptySpecialListWidget *emptySpecialList;
EmptyReadingListWidget *emptyReadingList;
@ -40,6 +40,10 @@ public:
NoSearchResultsWidget *noSearchResultsWidget;
void updateCurrentComicView();
void updateContinueReadingView();
void toFullscreen();
void toNormal();
protected:
QStackedWidget *comicsViewStack;
@ -58,7 +62,7 @@ public slots:
void focusComicsViewViaShortcut();
void showComicsView();
void showEmptyFolderView();
void showFolderContentView();
void showEmptyLabelView();
void showEmptySpecialList();
void showEmptyReadingListWidget();
@ -74,4 +78,4 @@ protected slots:
void switchToComicsView(ComicsView *from, ComicsView *to);
};
#endif // COMICSVIEWSMANAGER_H
#endif // YACREADERCONTENTVIEWSMANAGER_H

View File

@ -116,7 +116,7 @@ void YACReaderMainToolBar::resizeEvent(QResizeEvent *event)
void YACReaderMainToolBar::addDivider()
{
QPixmap img(":/images/main_toolbar/divider.png");
QPixmap img(":/images/main_toolbar/divider.svg");
QLabel *divider = new QLabel();
divider->setPixmap(img);

View File

@ -11,17 +11,17 @@
#include "folder_model.h"
#include "reading_list_model.h"
#include "comics_view.h"
#include "empty_folder_widget.h"
#include "folder_content_view.h"
#include "yacreader_search_line_edit.h"
#include "yacreader_global.h"
#include "empty_label_widget.h"
#include "empty_special_list.h"
#include "yacreader_comics_views_manager.h"
#include "yacreader_content_views_manager.h"
#include "QsLog.h"
YACReaderNavigationController::YACReaderNavigationController(LibraryWindow *parent, YACReaderComicsViewsManager *comicsViewsManager)
: QObject(parent), libraryWindow(parent), comicsViewsManager(comicsViewsManager)
YACReaderNavigationController::YACReaderNavigationController(LibraryWindow *parent, YACReaderContentViewsManager *contentViewsManager)
: QObject(parent), libraryWindow(parent), contentViewsManager(contentViewsManager)
{
setupConnections();
}
@ -61,13 +61,13 @@ void YACReaderNavigationController::loadFolderInfo(const QModelIndex &modelIndex
// configure views
if (libraryWindow->comicsModel->rowCount() > 0) {
// updateView
comicsViewsManager->comicsView->setModel(libraryWindow->comicsModel);
comicsViewsManager->showComicsView();
contentViewsManager->comicsView->setModel(libraryWindow->comicsModel);
contentViewsManager->showComicsView();
libraryWindow->disableComicsActions(false);
} else {
// showEmptyFolder
loadEmptyFolderInfo(modelIndex);
comicsViewsManager->showEmptyFolderView();
contentViewsManager->showFolderContentView();
libraryWindow->disableComicsActions(true);
}
@ -110,25 +110,25 @@ void YACReaderNavigationController::loadSpecialListInfo(const QModelIndex &model
break;
}
comicsViewsManager->comicsView->setModel(libraryWindow->comicsModel);
contentViewsManager->comicsView->setModel(libraryWindow->comicsModel);
if (libraryWindow->comicsModel->rowCount() > 0) {
comicsViewsManager->showComicsView();
contentViewsManager->showComicsView();
libraryWindow->disableComicsActions(false);
} else {
// setup empty special list widget
switch (type) {
case ReadingListModel::Favorites:
comicsViewsManager->emptySpecialList->setPixmap(QPixmap(":/images/empty_favorites.png"));
comicsViewsManager->emptySpecialList->setText(tr("No favorites"));
contentViewsManager->emptySpecialList->setPixmap(QPixmap(":/images/empty_favorites.png"));
contentViewsManager->emptySpecialList->setText(tr("No favorites"));
break;
case ReadingListModel::Reading:
comicsViewsManager->emptySpecialList->setPixmap(QPixmap(":/images/empty_current_readings.png"));
comicsViewsManager->emptySpecialList->setText(tr("You are not reading anything yet, come on!!"));
contentViewsManager->emptySpecialList->setPixmap(QPixmap(":/images/empty_current_readings.png"));
contentViewsManager->emptySpecialList->setText(tr("You are not reading anything yet, come on!!"));
break;
}
comicsViewsManager->showEmptySpecialList();
contentViewsManager->showEmptySpecialList();
libraryWindow->disableComicsActions(true);
}
}
@ -138,18 +138,18 @@ void YACReaderNavigationController::loadLabelInfo(const QModelIndex &modelIndex)
qulonglong id = modelIndex.data(ReadingListModel::IDRole).toULongLong();
// check comics in label with id = id
libraryWindow->comicsModel->setupLabelModelData(id, libraryWindow->foldersModel->getDatabase());
comicsViewsManager->comicsView->setModel(libraryWindow->comicsModel);
contentViewsManager->comicsView->setModel(libraryWindow->comicsModel);
// configure views
if (libraryWindow->comicsModel->rowCount() > 0) {
// updateView
comicsViewsManager->showComicsView();
contentViewsManager->showComicsView();
libraryWindow->disableComicsActions(false);
} else {
// showEmptyFolder
// loadEmptyLabelInfo(); //there is no info in an empty label by now, TODO design something
comicsViewsManager->emptyLabelWidget->setColor((YACReader::LabelColors)modelIndex.data(ReadingListModel::LabelColorRole).toInt());
comicsViewsManager->showEmptyLabelView();
contentViewsManager->emptyLabelWidget->setColor((YACReader::LabelColors)modelIndex.data(ReadingListModel::LabelColorRole).toInt());
contentViewsManager->showEmptyLabelView();
libraryWindow->disableComicsActions(true);
}
}
@ -159,15 +159,15 @@ void YACReaderNavigationController::loadReadingListInfo(const QModelIndex &model
qulonglong id = modelIndex.data(ReadingListModel::IDRole).toULongLong();
// check comics in label with id = id
libraryWindow->comicsModel->setupReadingListModelData(id, libraryWindow->foldersModel->getDatabase());
comicsViewsManager->comicsView->setModel(libraryWindow->comicsModel);
contentViewsManager->comicsView->setModel(libraryWindow->comicsModel);
// configure views
if (libraryWindow->comicsModel->rowCount() > 0) {
// updateView
comicsViewsManager->showComicsView();
contentViewsManager->showComicsView();
libraryWindow->disableComicsActions(false);
} else {
comicsViewsManager->showEmptyReadingListWidget();
contentViewsManager->showEmptyReadingListWidget();
libraryWindow->disableComicsActions(true);
}
}
@ -222,7 +222,10 @@ void YACReaderNavigationController::loadIndexFromHistory(const YACReaderLibraryS
case YACReaderLibrarySourceContainer::Folder: {
QModelIndex mi = libraryWindow->foldersModelProxy->mapFromSource(sourceMI);
libraryWindow->foldersView->scrollTo(mi, QAbstractItemView::PositionAtTop);
// currentIndexChanged is about to be emited, but we don't want it to end in YACReaderHistoryController::updateHistory
disconnect(libraryWindow->foldersView, &YACReaderTreeView::currentIndexChanged, this, &YACReaderNavigationController::selectedFolder);
libraryWindow->foldersView->setCurrentIndex(mi);
connect(libraryWindow->foldersView, &YACReaderTreeView::currentIndexChanged, this, &YACReaderNavigationController::selectedFolder);
loadFolderInfo(sourceMI);
break;
}
@ -249,9 +252,18 @@ void YACReaderNavigationController::selectSubfolder(const QModelIndex &sourceMIP
void YACReaderNavigationController::loadEmptyFolderInfo(const QModelIndex &modelIndex)
{
QStringList subfolders;
subfolders = libraryWindow->foldersModel->getSubfoldersNames(modelIndex);
comicsViewsManager->emptyFolderWidget->setSubfolders(modelIndex, subfolders);
auto readingComicsModel = new ComicModel();
auto isRoot = !modelIndex.isValid();
if (isRoot) {
readingComicsModel->setupReadingModelData(libraryWindow->foldersModel->getDatabase());
}
contentViewsManager->folderContentView->setContinueReadingModel(readingComicsModel);
auto subFolderModel = libraryWindow->foldersModel->getSubfoldersModel(modelIndex);
contentViewsManager->folderContentView->setModel(modelIndex, subFolderModel);
}
void YACReaderNavigationController::loadPreviousStatus()
@ -262,11 +274,15 @@ void YACReaderNavigationController::loadPreviousStatus()
void YACReaderNavigationController::setupConnections()
{
// we need YACReaderTreeView::currentIndexChanged to be able to navigate the folders tree using the keyboard cursors
connect(libraryWindow->foldersView, &YACReaderTreeView::currentIndexChanged, this, &YACReaderNavigationController::selectedFolder);
connect(libraryWindow->foldersView, &YACReaderTreeView::clicked, this, &YACReaderNavigationController::selectedFolder);
connect(libraryWindow->listsView, &QAbstractItemView::clicked, this, &YACReaderNavigationController::selectedList);
connect(libraryWindow->historyController, &YACReaderHistoryController::modelIndexSelected, this, &YACReaderNavigationController::selectedIndexFromHistory);
connect(comicsViewsManager->emptyFolderWidget, &EmptyFolderWidget::subfolderSelected, this, &YACReaderNavigationController::selectSubfolder);
connect(contentViewsManager->folderContentView, &FolderContentView::subfolderSelected, this, &YACReaderNavigationController::selectSubfolder);
connect(contentViewsManager->folderContentView, &FolderContentView::openComic, libraryWindow, QOverload<const ComicDB &, const ComicModel::Mode>::of(&LibraryWindow::openComic));
connect(contentViewsManager->folderContentView, &FolderContentView::openFolderContextMenu, libraryWindow, &LibraryWindow::showGridFoldersContextMenu);
connect(contentViewsManager->folderContentView, &FolderContentView::openContinueReadingComicContextMenu, libraryWindow, &LibraryWindow::showContinueReadingContextMenu);
connect(libraryWindow->comicsModel, &ComicModel::isEmpty, this, &YACReaderNavigationController::reselectCurrentSource);
}

View File

@ -4,13 +4,13 @@
#include <QObject>
class LibraryWindow;
class YACReaderLibrarySourceContainer;
class YACReaderComicsViewsManager;
class YACReaderContentViewsManager;
class YACReaderNavigationController : public QObject
{
Q_OBJECT
public:
explicit YACReaderNavigationController(LibraryWindow *parent, YACReaderComicsViewsManager *comicsViewsManager);
explicit YACReaderNavigationController(LibraryWindow *parent, YACReaderContentViewsManager *contentViewsManager);
signals:
@ -44,7 +44,7 @@ public slots:
private:
void setupConnections();
LibraryWindow *libraryWindow;
YACReaderComicsViewsManager *comicsViewsManager;
YACReaderContentViewsManager *contentViewsManager;
// convenience methods
qulonglong folderModelIndexToID(const QModelIndex &mi);

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -5,8 +5,8 @@
#include "library_creator.h"
#include "yacreader_libraries.h"
ConsoleUILibraryCreator::ConsoleUILibraryCreator(QObject *parent)
: QObject(parent), numComicsProcessed(0)
ConsoleUILibraryCreator::ConsoleUILibraryCreator(QSettings *settings, QObject *parent)
: QObject(parent), numComicsProcessed(0), settings(settings)
{
}
@ -19,7 +19,7 @@ void ConsoleUILibraryCreator::createLibrary(const QString &name, const QString &
}
QEventLoop eventLoop;
LibraryCreator *libraryCreator = new LibraryCreator();
LibraryCreator *libraryCreator = new LibraryCreator(settings);
QString cleanPath = QDir::cleanPath(pathDir.absolutePath());
YACReaderLibraries yacreaderLibraries;
@ -56,7 +56,7 @@ void ConsoleUILibraryCreator::updateLibrary(const QString &path)
}
QEventLoop eventLoop;
LibraryCreator *libraryCreator = new LibraryCreator();
LibraryCreator *libraryCreator = new LibraryCreator(settings);
QString cleanPath = QDir::cleanPath(pathDir.absolutePath());
libraryCreator->updateLibrary(cleanPath, QDir::cleanPath(pathDir.absolutePath() + "/.yacreaderlibrary"));

View File

@ -7,7 +7,7 @@ class ConsoleUILibraryCreator : public QObject
{
Q_OBJECT
public:
explicit ConsoleUILibraryCreator(QObject *parent = 0);
explicit ConsoleUILibraryCreator(QSettings *settings, QObject *parent = 0);
void createLibrary(const QString &name, const QString &path);
void updateLibrary(const QString &path);
void addExistingLibrary(const QString &name, const QString &path);
@ -15,6 +15,7 @@ public:
private:
uint numComicsProcessed;
QSettings *settings;
signals:
public slots:

View File

@ -6,7 +6,7 @@
#include "comic_db.h"
#include "db_helper.h"
#include "startup.h"
#include "yacreader_http_server.h"
#include "yacreader_global.h"
#include "yacreader_libraries.h"
#include "yacreader_local_server.h"
@ -124,6 +124,9 @@ int main(int argc, char **argv)
return 0;
}
QSettings *settings = new QSettings(YACReader::getSettingsPath() + "/" + QCoreApplication::applicationName() + ".ini", QSettings::IniFormat);
settings->beginGroup("libraryConfig");
if (command == "start") {
parser.clearPositionalArguments();
parser.addPositionalArgument("start", "Start YACReaderLibraryServer");
@ -190,11 +193,8 @@ int main(int argc, char **argv)
QLOG_INFO() << "YACReaderLibrary starting";
QSettings *settings = new QSettings(YACReader::getSettingsPath() + "/" + QCoreApplication::applicationName() + ".ini", QSettings::IniFormat);
settings->beginGroup("libraryConfig");
// server
Startup *s = new Startup();
YACReaderHttpServer *httpServer = new YACReaderHttpServer();
if (parser.isSet("port")) {
bool valid;
qint32 port = parser.value("port").toInt(&valid);
@ -203,14 +203,14 @@ int main(int argc, char **argv)
parser.showHelp();
return 0;
} else {
s->start(port);
httpServer->start(port);
}
} else {
s->start();
httpServer->start();
}
QLOG_INFO() << "Running on port" << s->getPort();
QLOG_INFO() << "Running on port" << httpServer->getPort();
// Update libraries to new versions
LibrariesUpdater updater;
@ -223,8 +223,8 @@ int main(int argc, char **argv)
QLOG_INFO() << "YACReaderLibrary closed with exit code :" << ret;
// shutdown
s->stop();
delete s;
httpServer->stop();
delete httpServer;
localServer->close();
delete localServer;
#ifdef Q_OS_WIN
@ -244,7 +244,7 @@ int main(int argc, char **argv)
return 0;
}
ConsoleUILibraryCreator *libraryCreatorUI = new ConsoleUILibraryCreator;
ConsoleUILibraryCreator *libraryCreatorUI = new ConsoleUILibraryCreator(settings);
libraryCreatorUI->createLibrary(args.at(1), args.at(2));
return 0;
@ -260,7 +260,7 @@ int main(int argc, char **argv)
return 0;
}
ConsoleUILibraryCreator *libraryCreatorUI = new ConsoleUILibraryCreator;
ConsoleUILibraryCreator *libraryCreatorUI = new ConsoleUILibraryCreator(settings);
libraryCreatorUI->updateLibrary(args.at(1));
return 0;
@ -277,7 +277,7 @@ int main(int argc, char **argv)
return 0;
}
ConsoleUILibraryCreator *libraryCreatorUI = new ConsoleUILibraryCreator;
ConsoleUILibraryCreator *libraryCreatorUI = new ConsoleUILibraryCreator(settings);
libraryCreatorUI->addExistingLibrary(args.at(1), args.at(2));
return 0;
@ -293,7 +293,7 @@ int main(int argc, char **argv)
return 0;
}
ConsoleUILibraryCreator *libraryCreatorUI = new ConsoleUILibraryCreator;
ConsoleUILibraryCreator *libraryCreatorUI = new ConsoleUILibraryCreator(settings);
libraryCreatorUI->removeLibrary(args.at(1));
return 0;

View File

@ -54,7 +54,7 @@ jobs:
- script: |
sudo apt-get update
sudo apt-get install -y qtchooser qtbase5-dev-tools qt5-qmake \
qtbase5-dev qtmultimedia5-dev libpoppler-qt5-dev \
qtbase5-dev qtmultimedia5-dev libpoppler-qt5-dev qttools5-dev-tools \
libqt5opengl5-dev libunarr-dev qtdeclarative5-dev libqt5svg5-dev qtquickcontrols2-5-dev
displayName: 'Install dependencies'
- script: |
@ -94,7 +94,7 @@ jobs:
- script: |
sudo apt-get update
sudo apt-get install -y qtchooser qt6-tools-dev qt6-base-dev-tools qmake6 qmake6-bin \
qt6-base-dev qt6-multimedia-dev qt6-tools-dev-tools libgl-dev \
qt6-base-dev qt6-multimedia-dev qt6-tools-dev-tools libgl-dev qt6-l10n-tools \
libqt6opengl6-dev libunarr-dev qt6-declarative-dev libqt6svg6-dev libqt6core5compat6-dev
displayName: 'Install dependencies'
- script: |

View File

@ -1,85 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<component type="desktop-application">
<id>com.yacreader.YACReader</id>
<metadata_license>FSFAP</metadata_license>
<project_license>GPL-3.0-only</project_license>
<name>YACReader</name>
<developer_name>Luis Ángel San Martín Rodríguez</developer_name>
<summary>Yet another comic reader</summary>
<description>
<p>
Read, browse and manage your comics collection.
All you need to enjoy your digital comics.
</p>
<p>
Browse your comics collections using beautiful, customizable and smooth "comic flow" transitions.
</p>
<p>Features:</p>
<ul>
<li>File support: YACReader supports a wide variety of comic files and image types. rar, zip, cbr, cbz, tar, pdf, 7z and cb7, jpeg, gif, png, tiff and bmp.</li>
<li>Configure your reading: Image rotation, double page mode, full size view, fullscreen mode, customizable background color, custom page fitting mode, bookmarks, resume reading, eye candy 'go to' and more.</li>
<li>Image improvements: Bring to life your old comics with the image adjustments available in the reading mode. Use the brightness, contrast and gamma sliders and enjoy the new vibrant colors.</li>
<li>Track your readings: YACReaderLibrary organizes your comics and keeps track of your reading progress and your collections' status.</li>
<li>Tags (comic vine): Download your comics' information from Comic Vine. Title, number, volumen, authors and more.</li>
<li>Search: Find your comics quickly using the built-in search engine. No matter how big is your collection, YACReaderLibrary will find anything instantly.</li>
</ul>
</description>
<categories>
<category>Graphics</category>
<category>Office</category>
<category>Viewer</category>
</categories>
<launchable type="desktop-id">com.yacreader.YACReader.desktop</launchable>
<launchable type="desktop-id">com.yacreader.YACReader.YACReaderLibrary.desktop</launchable>
<screenshots>
<screenshot type="default">
<caption>YACReader &amp; YACReaderLibrary</caption>
<image>https://www.yacreader.com/images/features/phoca_thumb_l_ss3b.jpg</image>
</screenshot>
<screenshot>
<caption>Properties</caption>
<image>https://www.yacreader.com/images/features/phoca_thumb_l_properties.jpg</image>
</screenshot>
</screenshots>
<url type="homepage">https://www.yacreader.com/</url>
<url type="bugtracker">https://github.com/YACReader/yacreader/issues</url>
<url type="faq">https://www.yacreader.com/support</url>
<url type="help">https://www.yacreader.com/support</url>
<url type="donation">https://www.yacreader.com/donation-why</url>
<url type="contact">https://www.yacreader.com/contact</url>
<provides>
<mediatype>application/x-cbz</mediatype>
<mediatype>application/x-cbr</mediatype>
<mediatype>application/x-cbt</mediatype>
<mediatype>application/x-cb7</mediatype>
<mediatype>application/x-pdf</mediatype>
<mediatype>application/x-zip</mediatype>
<mediatype>application/x-rar</mediatype>
<mediatype>application/x-7z</mediatype>
<mediatype>inode/directory</mediatype>
<mediatype>application/vnd.comicbook-rar</mediatype>
<mediatype>application/vnd.comicbook+zip</mediatype>
<mediatype>application/pdf</mediatype>
<mediatype>application/vnd.rar</mediatype>
<mediatype>application/x-7z-compressed</mediatype>
<mediatype>application/zip</mediatype>
<binary>YACReader</binary>
<binary>YACReaderLibrary</binary>
<binary>YACReaderLibraryServer</binary>
</provides>
<releases>
<release version="9.8.2.2106204" date="2021-06-20">
<description>
<p>YACReaderLibrary</p>
<ul>
<li>Fix opening comics from the continue reading banner.</li>
<li>Make available next/prev comic covers in the iOS app while reading. (ios app 3.16.1 needed)</li>
</ul>
<p>Server</p>
<ul>
<li>Make available next/prev comic covers in the iOS app while reading. (ios app 3.16.1 needed)</li>
</ul>
</description>
</release>
</releases>
</component>

View File

@ -1,126 +0,0 @@
app-id: com.yacreader.YACReader
runtime: org.kde.Platform
runtime-version: "5.15-21.08"
sdk: org.kde.Sdk
command: YACReader
finish-args:
- --share=ipc
- --socket=fallback-x11
- --socket=wayland
- --share=network
- --device=dri
- --filesystem=xdg-documents
- --filesystem=xdg-pictures
cleanup:
- /bin/gn
- /include
- /lib/cmake
- /lib/pkgconfig
- /lib/systemd
- /share/doc
- /share/man
- "*.a"
- "*.la"
modules:
- name: yacreader
# https://aur.archlinux.org/cgit/aur.git/tree/PKGBUILD?h=yacreader
buildsystem: qmake
config-opts:
- CONFIG+=unarr pdfium server_bundled
install-rule: null
make-install-args:
- sub-YACReader-install_subtargets
- sub-YACReaderLibrary-install_subtargets
post-install:
- mv "$FLATPAK_DEST"/share/applications/{YACReader,com.yacreader.YACReader}.desktop
- mv "$FLATPAK_DEST"/share/applications/{YACReaderLibrary,com.yacreader.YACReader.YACReaderLibrary}.desktop
- mv "$FLATPAK_DEST"/share/icons/hicolor/scalable/apps/{YACReader,com.yacreader.YACReader}.svg
- mv "$FLATPAK_DEST"/share/icons/hicolor/scalable/apps/{YACReaderLibrary,com.yacreader.YACReader.YACReaderLibrary}.svg
- sed -i -e 's/^Categories=\(.*\)$/Categories=Office;\1/' -e 's/^Icon=.*$/Icon=com.yacreader.YACReader/' "$FLATPAK_DEST"/share/applications/com.yacreader.YACReader.desktop
- sed -i -e 's/^Categories=\(.*\)$/Categories=Office;\1/' -e 's/^Icon=.*$/Icon=com.yacreader.YACReader.YACReaderLibrary/' "$FLATPAK_DEST"/share/applications/com.yacreader.YACReader.YACReaderLibrary.desktop
- install -D -m644 com.yacreader.YACReader.appdata.xml "$FLATPAK_DEST"/share/metainfo/com.yacreader.YACReader.appdata.xml
sources:
- type: git
url: https://github.com/YACReader/yacreader.git
tag: 9.8.2.2106204
commit: 7394944dccd1ee1f9dd8247e878f6ff8a055b7b8
- type: file
path: com.yacreader.YACReader.appdata.xml
modules:
- name: unarr
buildsystem: cmake
sources:
- type: git
url: https://github.com/selmf/unarr.git
commit: cf4deedfdd2b815ae2ad0f24cfda72c3d8083d14
- name: pdfium
buildsystem: simple
build-commands:
# https://aur.archlinux.org/cgit/aur.git/tree/PKGBUILD?h=libpdfium-nojs
# Fix visibilty for system Freetype
- git -C pdfium/build cherry-pick -n bfd6ff0
# Patch abseil build to be static
- cd "$FLATPAK_BUILDER_BUILDDIR/pdfium/third_party/abseil-cpp"
- sed -i -e 's/component(/static_library(/' -e 's/is_component_build(/false/' pdfium/third_party/abseil-cpp/BUILD.gn
# Use system provided icu library (unbundling)
- mkdir -p pdfium/third_party/icu
- ln -sf ../../build/linux/unbundle/icu.gn pdfium/third_party/icu/BUILD.gn
# Download and decode shim header script needed to unbundle icu (gittiles is weird)
- mkdir -p pdfium/tools/generate_shim_headers
- base64 --decode generate_shim_headers.py > pdfium/tools/generate_shim_headers/generate_shim_headers.py
# Create fake gclient_args.gni file to satisfy include list for build/config/compiler/compiler.gni
- touch pdfium/build/config/gclient_args.gni
# Exclude test fonts from build
- sed -i '/"\/\/third_party\/test_fonts",/s/^/#/g' pdfium/testing/BUILD.gn
# Build
- gn --root=pdfium gen pdfium/out/Release --args="is_clang=false use_sysroot=false is_debug=false symbol_level=0 pdf_enable_v8=false pdf_enable_xfa=false treat_warnings_as_errors=false use_system_libjpeg=true use_system_zlib=true pdf_bundle_freetype=false use_system_freetype=true use_system_lcms2=true use_system_libpng=true use_custom_libcxx=false pdf_is_standalone=true use_system_libopenjpeg2=true is_component_build=true use_gold=false"
- ninja -C pdfium/out/Release pdfium
- sed -e 's/@VERSION@/5005/g' -e 's#^\s*prefix\s*=.*$#prefix='"$FLATPAK_DEST"'#' -i libpdfium.pc
# Install
- install -D -m644 pdfium/LICENSE "$FLATPAK_DEST/share/licenses/pdfium/LICENSE"
- install -D pdfium/public/*.h --target-directory="$FLATPAK_DEST/include/pdfium"
- install -D pdfium/public/cpp/* --target-directory="$FLATPAK_DEST/include/pdfium/cpp"
- install -D pdfium/docs/* --target-directory="$FLATPAK_DEST/share/doc/pdfium"
- install -Dm755 pdfium/out/Release/libpdfium.so --target-directory="$FLATPAK_DEST/lib"
- install -Dm644 libpdfium.pc --target-directory="$FLATPAK_DEST/lib/pkgconfig"
sources:
- type: git
url: https://pdfium.googlesource.com/pdfium
# curl 'https://omahaproxy.appspot.com/linux?channel=stable' | cut -d'.' -f 3
branch: chromium/5005
commit: 62ad9af8a9f9494645b659674b64bb51775cde05
dest: pdfium
- type: git
url: https://chromium.googlesource.com/chromium/src/build.git
# awk '/build_revision/ {print substr($2,2,40)}' pdfium/DEPS
commit: ee10d9605d3bc45e72defd25ce97562e80693655
dest: pdfium/build
- type: git
url: https://chromium.googlesource.com/chromium/src/third_party/abseil-cpp
# awk '/abseil_revision/ {print substr($2,2,40)}' pdfium/DEPS
branch: a13888fac08a45c938255c7d9d59b1640f1940e0
dest: pdfium/third_party/abseil-cpp
- type: file
url: https://chromium.googlesource.com/chromium/src/+/master/tools/generate_shim_headers/generate_shim_headers.py?format=TEXT
dest-filename: generate_shim_headers.py
sha256: f95f0d29e3e12b22a7b86455265c87bc0219a25c09a7fa160d34b608992ea6da
- type: file
url: https://aur.archlinux.org/cgit/aur.git/plain/libpdfium.pc?h=libpdfium-nojs
dest-filename: libpdfium.pc
sha256: 4e8cf32c09568ae4c59244f0a221eee8f87ea4a31ddb31f796a1d818c967d477
modules:
- name: gn
buildsystem: simple
build-options:
env:
CC: gcc
CXX: g++
build-commands:
- ./build/gen.py
- ninja -C out
- install -D out/gn "$FLATPAK_DEST/bin/gn"
sources:
- type: git
url: https://gn.googlesource.com/gn
commit: 80a40b07305373617eba2d5878d353532af77da3
disable-shallow-clone: true

View File

@ -197,6 +197,50 @@ ComicInfo::ComicInfo(const ComicInfo &comicInfo)
ComicInfo::~ComicInfo()
{
}
void ComicInfo::deleteMetadata()
{
title = QVariant();
coverPage = QVariant();
numPages = QVariant();
number = QVariant();
isBis = QVariant();
count = QVariant();
volume = QVariant();
storyArc = QVariant();
arcNumber = QVariant();
arcCount = QVariant();
genere = QVariant();
writer = QVariant();
penciller = QVariant();
inker = QVariant();
colorist = QVariant();
letterer = QVariant();
coverArtist = QVariant();
date = QVariant();
day = QVariant();
month = QVariant();
year = QVariant();
publisher = QVariant();
format = QVariant();
color = QVariant();
ageRating = QVariant();
manga = QVariant();
synopsis = QVariant();
characters = QVariant();
notes = QVariant();
comicVineID = QVariant();
}
// the default operator= should work
ComicInfo &ComicInfo::operator=(const ComicInfo &comicInfo)
{

View File

@ -19,6 +19,8 @@ public:
ComicInfo(const ComicInfo &comicInfo);
~ComicInfo();
void deleteMetadata();
ComicInfo &operator=(const ComicInfo &comicInfo);
bool operator==(const ComicInfo &other) { return id == other.id; }

View File

@ -20,6 +20,20 @@ Folder::Folder(qulonglong folderId, qulonglong parentId, const QString &folderNa
this->path = folderPath;
}
Folder::Folder(qulonglong folderId, qulonglong parentId, const QString &folderName, const QString &folderPath, bool completed, bool finished, bool manga)
: knownParent(true),
knownId(true),
numChildren(-1)
{
this->id = folderId;
this->parentId = parentId;
this->name = folderName;
this->path = folderPath;
this->completed = completed;
this->finished = finished;
this->manga = manga;
}
Folder::Folder(const Folder &folder)
{
operator=(folder);

View File

@ -13,6 +13,7 @@ public:
Folder();
Folder(qulonglong folderId, qulonglong parentId, const QString &folderName, const QString &folderPath);
Folder(qulonglong folderId, qulonglong parentId, const QString &folderName, const QString &folderPath, bool completed, bool finished, bool manga);
Folder(const QString &folderName, const QString &folderPath);
Folder(const Folder &folder);
Folder &operator=(const Folder &other);
@ -94,8 +95,8 @@ public:
}
private:
bool finished;
bool completed;
bool finished; // finished means read, the user has read all the content in this folder
bool completed; // completed means the folder has all the content, e.g. a series got its final issue and the user has collected all of them
bool manga;
qint32 numChildren; //-1 for unknown number of children

View File

@ -1,5 +1,7 @@
#include "yacreader_global.h"
#include <QModelIndex>
using namespace YACReader;
QString YACReader::getSettingsPath()
@ -100,3 +102,20 @@ QDataStream &YACReader::operator>>(QDataStream &stream, OpenComicSource &source)
stream >> source.sourceId;
return stream;
}
void YACReader::iterate(const QModelIndex &index,
const QAbstractItemModel *model,
const std::function<bool(const QModelIndex &)> &iteration)
{
if (index.isValid()) {
auto continueIterating = iteration(index);
if (!continueIterating) {
return;
}
}
if ((index.flags() & Qt::ItemNeverHasChildren) || !model->hasChildren(index))
return;
auto rows = model->rowCount(index);
for (int i = 0; i < rows; ++i)
iterate(model->index(i, 0, index), model, iteration);
}

View File

@ -4,10 +4,12 @@
#include <QStandardPaths>
#include <QDataStream>
#include <QMetaType>
#include <QAbstractItemModel>
#define VERSION "9.9.2"
#define VERSION "9.10.0"
#define REMOTE_BROWSE_PERFORMANCE_WORKAROUND "REMOTE_BROWSE_PERFORMANCE_WORKAROUND"
#define IMPORT_COMIC_INFO_XML_METADATA "IMPORT_COMIC_INFO_XML_METADATA"
#define NUM_DAYS_BETWEEN_VERSION_CHECKS "NUM_DAYS_BETWEEN_VERSION_CHECKS"
#define LAST_VERSION_CHECK "LAST_VERSION_CHECK"
@ -67,6 +69,10 @@ QString getSettingsPath();
QString colorToName(LabelColors colors);
QString labelColorToRGBString(LabelColors color);
void iterate(const QModelIndex &index,
const QAbstractItemModel *model,
const std::function<bool(const QModelIndex &)> &iteration);
}
Q_DECLARE_METATYPE(YACReader::OpenComicSource::Source)

View File

@ -21,9 +21,10 @@ QAction *YACReader::createSeparator()
QIcon YACReader::noHighlightedIcon(const QString &path)
{
QPixmap p(path);
QPixmap sp(path);
QPixmap p = hdpiPixmap(path, sp.size());
QIcon icon; //(path);
QIcon icon;
icon.addFile(path, p.size(), QIcon::Normal);
icon.addFile(path, p.size(), QIcon::Selected);
return icon;
@ -49,3 +50,52 @@ QList<qulonglong> YACReader::mimeDataToComicsIds(const QMimeData *data)
in >> comicIds; // deserialize the list of indentifiers
return comicIds;
}
// TODO some SVG assets are missing in macos (WIP)
// we need two sets of icons, one for the toolbar and one for the context menu because of this bug (QTBUG-96553): https://bugreports.qt.io/browse/QTBUG-96553
QString YACReader::addExtensionToIconPath(const QString &path)
{
#ifdef YACREADER_LIBRARY
#ifdef Q_OS_MAC
return path + ".png";
#else
return path + ".svg";
#endif
#else
return path + ".svg";
#endif
}
QString YACReader::addExtensionToIconPathInToolbar(const QString &path)
{
return path + "_18x18.svg";
}
QAction *YACReader::actionWithCustomIcon(const QIcon &icon, QAction *action)
{
auto a = new QAction(icon, action->text());
a->setEnabled(action->isEnabled());
a->setCheckable(action->isCheckable());
a->setChecked(action->isChecked());
QObject::connect(a, &QAction::triggered, action, &QAction::triggered);
QObject::connect(action, &QAction::changed, action, [=]() {
a->setEnabled(action->isEnabled());
a->setCheckable(action->isCheckable());
a->setChecked(action->isChecked());
});
QObject::connect(a, &QAction::toggled, action, &QAction::setChecked);
QObject::connect(action, &QAction::toggled, a, &QAction::setChecked);
return a;
}
QPixmap YACReader::hdpiPixmap(const QString &file, QSize size)
{
return QIcon(file).pixmap(size);
}

View File

@ -110,6 +110,10 @@ QAction *createSeparator();
QIcon noHighlightedIcon(const QString &path);
void colorize(QImage &img, QColor &col);
QList<qulonglong> mimeDataToComicsIds(const QMimeData *data);
QString addExtensionToIconPath(const QString &path);
QString addExtensionToIconPathInToolbar(const QString &path);
QAction *actionWithCustomIcon(const QIcon &icon, QAction *action);
QPixmap hdpiPixmap(const QString &file, QSize size);
}
#endif

Some files were not shown because too many files have changed in this diff Show More