diff --git a/.gitattributes b/.gitattributes index 8d4a272b..fe38067e 100644 --- a/.gitattributes +++ b/.gitattributes @@ -6,3 +6,82 @@ /dependencies/create-dmg export-ignore .gitignore export-ignore .gitattributes export-ignore + +# Auto detect text files and perform LF normalization +# http://davidlaing.com/2012/09/19/customise-your-gitattributes-to-become-a-git-ninja/ +* text=auto + +# +# The above will handle all files NOT found below +# + +# Documents +*.doc diff=astextplain +*.DOC diff=astextplain +*.docx diff=astextplain +*.DOCX diff=astextplain +*.dot diff=astextplain +*.DOT diff=astextplain +*.pdf diff=astextplain +*.PDF diff=astextplain +*.rtf diff=astextplain +*.RTF diff=astextplain +*.md text +*.adoc text +*.textile text +*.mustache text +*.csv text +*.tab text +*.tsv text +*.sql text + +# Graphics +*.png binary +*.jpg binary +*.jpeg binary +*.gif binary +*.tif binary +*.tiff binary +*.ico binary +# SVG treated as an asset (binary) by default. If you want to treat it as text, +# comment-out the following line and uncomment the line after. +*.svg binary +#*.svg text +*.eps binary + +# Sources +*.c text +*.cc text +*.cxx text +*.cpp text +*.c++ text +*.hpp text +*.h text +*.h++ text +*.hh text + +# Compiled Object files +*.slo binary +*.lo binary +*.o binary +*.obj binary + +# Precompiled Headers +*.gch binary +*.pch binary + +# Compiled Dynamic libraries +*.so binary +*.dylib binary +*.dll binary + +# Compiled Static libraries +*.lai binary +*.la binary +*.a binary +*.lib binary + +# Executables +*.exe binary +*.out binary +*.app binary diff --git a/INSTALL.md b/INSTALL.md index 25845328..97456986 100644 --- a/INSTALL.md +++ b/INSTALL.md @@ -1,111 +1,111 @@ -# Building YACReader from source - -YACReader and YACReaderLibrary are build using qmake. To build and install the -program, run: - -> qmake-qt5 CONFIG+=[Options] -> make -> make install - -from the source dir. For separate builds of YACReader or YACReaderLibrary, -enter their respective subfolders and run the commands from there. - -The headless version of YACReaderLibrary is located in the YACReaderLibraryServer -folder. To build it, enter the folder and run the commands described above. - - -## Build dependencies: - -- Qt >= 5.6 with the following modules: - - declarative - - quickcontrols - - sql - - script - - multimedia - - imageformats - - opengl - - sql-sqlite - - network -- A pdf rendering backend (optional, see below) -- qrencode (optional) -- glu -- (lib)unarr (see below) - -Not all dependencies are needed at build time. For example the qml components in -YACReaderLibrary (GridView, InfoView) will only show a white page if the -required qml modules (declarative, quickcontrols) are missing. -This can also happen if these dependencies are too old (i.e Qt < 5.6 is used). - -## Backends - -### Decompression - -YACReader uses [(lib)unarr](https://github.com/selmf/unarr) for comic book archive -decompression. Most Linux distributions don't ship this library yet, so you will -probably have to build it yourself. - -We recommend using (lib)unarr as a shared library, but we also support static -and embedded builds. Please consult the [README](compressed_archive/unarr/README.txt) -for more information on this topic. - -### PDF - -Starting with version 9.0.0 YACReader supports the following pdf render engines: - -- poppler (Linux/Unix default) -- pdfium (default for Windows and MacOS) -- pdfkit (MacOS only) -- no_pdf (disable pdf support) - -To override the default for a given platform add CONFIG+=[pdfbackend] as an option -when running qmake. - -While the Poppler backend is well tested and has been the standard for YACReader -for a long time, it's performance is a bit lacking. The pdfium engine offers -much better performance (about 10x faster on some pdf files we tested). -However, at the time of this writing, it is not a library that is available -prepackaged for Linux. - -### Other build options: - -You can adjust the installation prefix as well als the path "make install" uses -to install the files. - ->qmake PREFIX=DIR - -sets the default prefix (for example "/", "/usr", "/usr/local"). - ->make install INSTALL_ROOT=DIR - -can be used to install to a different location, which is usefull for packaging. - -Default values: - ->PREFIX=/usr ->INSTALL_ROOT="" - -On embedded devices that don't support desktop OpenGL, it is recommended to use -the no_opengl config option: - -qmake-qt5 CONFIG+=no_opengl - -This will remove any dependency on desktop OpenGL and hardlock YACReader's -coverflow to software rendering. Please note that it does not actually remove -OpenGL from the build, the Qt toolkit will still make use of it. - - -# Feedback and contribution - -If you're compiling YACReader because there is no package available for your -Linux distribution please consider creating and submitting a package or filing a -package request. - -While we do provide packages for .deb and .rpm based distributions as well as an -AUR package for Archlinux and it's derivates, we are in need of downstream packagers -that are willing to make YACReader available as a standard package for their distro. - -If you are interested, please contact @selmf on the YACReader forums or write -an email to info@yacreader.com - -If you have already created a package please let us know so we can add it to -our downloads list ;) +# Building YACReader from source + +YACReader and YACReaderLibrary are build using qmake. To build and install the +program, run: + +> qmake-qt5 CONFIG+=[Options] +> make +> make install + +from the source dir. For separate builds of YACReader or YACReaderLibrary, +enter their respective subfolders and run the commands from there. + +The headless version of YACReaderLibrary is located in the YACReaderLibraryServer +folder. To build it, enter the folder and run the commands described above. + + +## Build dependencies: + +- Qt >= 5.6 with the following modules: + - declarative + - quickcontrols + - sql + - script + - multimedia + - imageformats + - opengl + - sql-sqlite + - network +- A pdf rendering backend (optional, see below) +- qrencode (optional) +- glu +- (lib)unarr (see below) + +Not all dependencies are needed at build time. For example the qml components in +YACReaderLibrary (GridView, InfoView) will only show a white page if the +required qml modules (declarative, quickcontrols) are missing. +This can also happen if these dependencies are too old (i.e Qt < 5.6 is used). + +## Backends + +### Decompression + +YACReader uses [(lib)unarr](https://github.com/selmf/unarr) for comic book archive +decompression. Most Linux distributions don't ship this library yet, so you will +probably have to build it yourself. + +We recommend using (lib)unarr as a shared library, but we also support static +and embedded builds. Please consult the [README](compressed_archive/unarr/README.txt) +for more information on this topic. + +### PDF + +Starting with version 9.0.0 YACReader supports the following pdf render engines: + +- poppler (Linux/Unix default) +- pdfium (default for Windows and MacOS) +- pdfkit (MacOS only) +- no_pdf (disable pdf support) + +To override the default for a given platform add CONFIG+=[pdfbackend] as an option +when running qmake. + +While the Poppler backend is well tested and has been the standard for YACReader +for a long time, it's performance is a bit lacking. The pdfium engine offers +much better performance (about 10x faster on some pdf files we tested). +However, at the time of this writing, it is not a library that is available +prepackaged for Linux. + +### Other build options: + +You can adjust the installation prefix as well als the path "make install" uses +to install the files. + +>qmake PREFIX=DIR + +sets the default prefix (for example "/", "/usr", "/usr/local"). + +>make install INSTALL_ROOT=DIR + +can be used to install to a different location, which is usefull for packaging. + +Default values: + +>PREFIX=/usr +>INSTALL_ROOT="" + +On embedded devices that don't support desktop OpenGL, it is recommended to use +the no_opengl config option: + +qmake-qt5 CONFIG+=no_opengl + +This will remove any dependency on desktop OpenGL and hardlock YACReader's +coverflow to software rendering. Please note that it does not actually remove +OpenGL from the build, the Qt toolkit will still make use of it. + + +# Feedback and contribution + +If you're compiling YACReader because there is no package available for your +Linux distribution please consider creating and submitting a package or filing a +package request. + +While we do provide packages for .deb and .rpm based distributions as well as an +AUR package for Archlinux and it's derivates, we are in need of downstream packagers +that are willing to make YACReader available as a standard package for their distro. + +If you are interested, please contact @selmf on the YACReader forums or write +an email to info@yacreader.com + +If you have already created a package please let us know so we can add it to +our downloads list ;) diff --git a/QsLog/QsLog.cpp b/QsLog/QsLog.cpp index 3114e4f6..b099d6c7 100644 --- a/QsLog/QsLog.cpp +++ b/QsLog/QsLog.cpp @@ -1,249 +1,249 @@ -// Copyright (c) 2013, Razvan Petru -// All rights reserved. - -// Redistribution and use in source and binary forms, with or without modification, -// are permitted provided that the following conditions are met: - -// * Redistributions of source code must retain the above copyright notice, this -// list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright notice, this -// list of conditions and the following disclaimer in the documentation and/or other -// materials provided with the distribution. -// * The name of the contributors may not be used to endorse or promote products -// derived from this software without specific prior written permission. - -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -// IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, -// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE -// OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED -// OF THE POSSIBILITY OF SUCH DAMAGE. - -#include "QsLog.h" -#include "QsLogDest.h" -#ifdef QS_LOG_SEPARATE_THREAD -#include -#include -#endif -#include -#include -#include -#include -#include -#include -#include - -namespace QsLogging -{ -typedef QVector DestinationList; - -static const char TraceString[] = "TRACE"; -static const char DebugString[] = "DEBUG"; -static const char InfoString[] = "INFO "; -static const char WarnString[] = "WARN "; -static const char ErrorString[] = "ERROR"; -static const char FatalString[] = "FATAL"; - -// not using Qt::ISODate because we need the milliseconds too -static const QString fmtDateTime("yyyy-MM-ddThh:mm:ss.zzz"); - -static Logger* sInstance = 0; - -static const char* LevelToText(Level theLevel) -{ - switch (theLevel) { - case TraceLevel: - return TraceString; - case DebugLevel: - return DebugString; - case InfoLevel: - return InfoString; - case WarnLevel: - return WarnString; - case ErrorLevel: - return ErrorString; - case FatalLevel: - return FatalString; - case OffLevel: - return ""; - default: { - assert(!"bad log level"); - return InfoString; - } - } -} - -#ifdef QS_LOG_SEPARATE_THREAD -class LogWriterRunnable : public QRunnable -{ -public: - LogWriterRunnable(QString message, Level level); - virtual void run(); - -private: - QString mMessage; - Level mLevel; -}; -#endif - -class LoggerImpl -{ -public: - LoggerImpl(); - -#ifdef QS_LOG_SEPARATE_THREAD - QThreadPool threadPool; -#endif - QMutex logMutex; - Level level; - DestinationList destList; -}; - -#ifdef QS_LOG_SEPARATE_THREAD -LogWriterRunnable::LogWriterRunnable(QString message, Level level) - : QRunnable() - , mMessage(message) - , mLevel(level) -{ -} - -void LogWriterRunnable::run() -{ - Logger::instance().write(mMessage, mLevel); -} -#endif - - -LoggerImpl::LoggerImpl() - : level(InfoLevel) -{ - // assume at least file + console - destList.reserve(2); -#ifdef QS_LOG_SEPARATE_THREAD - threadPool.setMaxThreadCount(1); - threadPool.setExpiryTimeout(-1); -#endif -} - - -Logger::Logger() - : d(new LoggerImpl) -{ -} - -Logger& Logger::instance() -{ - if (!sInstance) - sInstance = new Logger; - - return *sInstance; -} - -void Logger::destroyInstance() -{ - delete sInstance; - sInstance = 0; -} - -// tries to extract the level from a string log message. If available, conversionSucceeded will -// contain the conversion result. -Level Logger::levelFromLogMessage(const QString& logMessage, bool* conversionSucceeded) -{ - if (conversionSucceeded) - *conversionSucceeded = true; - - if (logMessage.startsWith(QLatin1String(TraceString))) - return TraceLevel; - if (logMessage.startsWith(QLatin1String(DebugString))) - return DebugLevel; - if (logMessage.startsWith(QLatin1String(InfoString))) - return InfoLevel; - if (logMessage.startsWith(QLatin1String(WarnString))) - return WarnLevel; - if (logMessage.startsWith(QLatin1String(ErrorString))) - return ErrorLevel; - if (logMessage.startsWith(QLatin1String(FatalString))) - return FatalLevel; - - if (conversionSucceeded) - *conversionSucceeded = false; - return OffLevel; -} - -Logger::~Logger() -{ -#ifdef QS_LOG_SEPARATE_THREAD - d->threadPool.waitForDone(); -#endif - delete d; - d = 0; -} - -void Logger::addDestination(DestinationPtr destination) -{ - assert(destination.data()); - d->destList.push_back(destination); -} - -void Logger::setLoggingLevel(Level newLevel) -{ - d->level = newLevel; -} - -Level Logger::loggingLevel() const -{ - return d->level; -} - -//! creates the complete log message and passes it to the logger -void Logger::Helper::writeToLog() -{ - const char* const levelName = LevelToText(level); - const QString completeMessage(QString("%1 %2 %3") - .arg(levelName) - .arg(QDateTime::currentDateTime().toString(fmtDateTime)) - .arg(buffer) - ); - - Logger::instance().enqueueWrite(completeMessage, level); -} - -Logger::Helper::~Helper() -{ - try { - writeToLog(); - } - catch(std::exception&) { - // you shouldn't throw exceptions from a sink - assert(!"exception in logger helper destructor"); - //CHANGED throw; - } -} - -//! directs the message to the task queue or writes it directly -void Logger::enqueueWrite(const QString& message, Level level) -{ -#ifdef QS_LOG_SEPARATE_THREAD - LogWriterRunnable *r = new LogWriterRunnable(message, level); - d->threadPool.start(r); -#else - write(message, level); -#endif -} - -//! Sends the message to all the destinations. The level for this message is passed in case -//! it's useful for processing in the destination. -void Logger::write(const QString& message, Level level) -{ - QMutexLocker lock(&d->logMutex); - for (DestinationList::iterator it = d->destList.begin(), - endIt = d->destList.end();it != endIt;++it) { - (*it)->write(message, level); - } -} - -} // end namespace +// Copyright (c) 2013, Razvan Petru +// All rights reserved. + +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: + +// * Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, this +// list of conditions and the following disclaimer in the documentation and/or other +// materials provided with the distribution. +// * The name of the contributors may not be used to endorse or promote products +// derived from this software without specific prior written permission. + +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +// IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +// OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED +// OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "QsLog.h" +#include "QsLogDest.h" +#ifdef QS_LOG_SEPARATE_THREAD +#include +#include +#endif +#include +#include +#include +#include +#include +#include +#include + +namespace QsLogging +{ +typedef QVector DestinationList; + +static const char TraceString[] = "TRACE"; +static const char DebugString[] = "DEBUG"; +static const char InfoString[] = "INFO "; +static const char WarnString[] = "WARN "; +static const char ErrorString[] = "ERROR"; +static const char FatalString[] = "FATAL"; + +// not using Qt::ISODate because we need the milliseconds too +static const QString fmtDateTime("yyyy-MM-ddThh:mm:ss.zzz"); + +static Logger* sInstance = 0; + +static const char* LevelToText(Level theLevel) +{ + switch (theLevel) { + case TraceLevel: + return TraceString; + case DebugLevel: + return DebugString; + case InfoLevel: + return InfoString; + case WarnLevel: + return WarnString; + case ErrorLevel: + return ErrorString; + case FatalLevel: + return FatalString; + case OffLevel: + return ""; + default: { + assert(!"bad log level"); + return InfoString; + } + } +} + +#ifdef QS_LOG_SEPARATE_THREAD +class LogWriterRunnable : public QRunnable +{ +public: + LogWriterRunnable(QString message, Level level); + virtual void run(); + +private: + QString mMessage; + Level mLevel; +}; +#endif + +class LoggerImpl +{ +public: + LoggerImpl(); + +#ifdef QS_LOG_SEPARATE_THREAD + QThreadPool threadPool; +#endif + QMutex logMutex; + Level level; + DestinationList destList; +}; + +#ifdef QS_LOG_SEPARATE_THREAD +LogWriterRunnable::LogWriterRunnable(QString message, Level level) + : QRunnable() + , mMessage(message) + , mLevel(level) +{ +} + +void LogWriterRunnable::run() +{ + Logger::instance().write(mMessage, mLevel); +} +#endif + + +LoggerImpl::LoggerImpl() + : level(InfoLevel) +{ + // assume at least file + console + destList.reserve(2); +#ifdef QS_LOG_SEPARATE_THREAD + threadPool.setMaxThreadCount(1); + threadPool.setExpiryTimeout(-1); +#endif +} + + +Logger::Logger() + : d(new LoggerImpl) +{ +} + +Logger& Logger::instance() +{ + if (!sInstance) + sInstance = new Logger; + + return *sInstance; +} + +void Logger::destroyInstance() +{ + delete sInstance; + sInstance = 0; +} + +// tries to extract the level from a string log message. If available, conversionSucceeded will +// contain the conversion result. +Level Logger::levelFromLogMessage(const QString& logMessage, bool* conversionSucceeded) +{ + if (conversionSucceeded) + *conversionSucceeded = true; + + if (logMessage.startsWith(QLatin1String(TraceString))) + return TraceLevel; + if (logMessage.startsWith(QLatin1String(DebugString))) + return DebugLevel; + if (logMessage.startsWith(QLatin1String(InfoString))) + return InfoLevel; + if (logMessage.startsWith(QLatin1String(WarnString))) + return WarnLevel; + if (logMessage.startsWith(QLatin1String(ErrorString))) + return ErrorLevel; + if (logMessage.startsWith(QLatin1String(FatalString))) + return FatalLevel; + + if (conversionSucceeded) + *conversionSucceeded = false; + return OffLevel; +} + +Logger::~Logger() +{ +#ifdef QS_LOG_SEPARATE_THREAD + d->threadPool.waitForDone(); +#endif + delete d; + d = 0; +} + +void Logger::addDestination(DestinationPtr destination) +{ + assert(destination.data()); + d->destList.push_back(destination); +} + +void Logger::setLoggingLevel(Level newLevel) +{ + d->level = newLevel; +} + +Level Logger::loggingLevel() const +{ + return d->level; +} + +//! creates the complete log message and passes it to the logger +void Logger::Helper::writeToLog() +{ + const char* const levelName = LevelToText(level); + const QString completeMessage(QString("%1 %2 %3") + .arg(levelName) + .arg(QDateTime::currentDateTime().toString(fmtDateTime)) + .arg(buffer) + ); + + Logger::instance().enqueueWrite(completeMessage, level); +} + +Logger::Helper::~Helper() +{ + try { + writeToLog(); + } + catch(std::exception&) { + // you shouldn't throw exceptions from a sink + assert(!"exception in logger helper destructor"); + //CHANGED throw; + } +} + +//! directs the message to the task queue or writes it directly +void Logger::enqueueWrite(const QString& message, Level level) +{ +#ifdef QS_LOG_SEPARATE_THREAD + LogWriterRunnable *r = new LogWriterRunnable(message, level); + d->threadPool.start(r); +#else + write(message, level); +#endif +} + +//! Sends the message to all the destinations. The level for this message is passed in case +//! it's useful for processing in the destination. +void Logger::write(const QString& message, Level level) +{ + QMutexLocker lock(&d->logMutex); + for (DestinationList::iterator it = d->destList.begin(), + endIt = d->destList.end();it != endIt;++it) { + (*it)->write(message, level); + } +} + +} // end namespace diff --git a/QsLog/QsLog.h b/QsLog/QsLog.h index f72e827c..791d9091 100644 --- a/QsLog/QsLog.h +++ b/QsLog/QsLog.h @@ -1,137 +1,137 @@ -// Copyright (c) 2013, Razvan Petru -// All rights reserved. - -// Redistribution and use in source and binary forms, with or without modification, -// are permitted provided that the following conditions are met: - -// * Redistributions of source code must retain the above copyright notice, this -// list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright notice, this -// list of conditions and the following disclaimer in the documentation and/or other -// materials provided with the distribution. -// * The name of the contributors may not be used to endorse or promote products -// derived from this software without specific prior written permission. - -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -// IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, -// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE -// OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED -// OF THE POSSIBILITY OF SUCH DAMAGE. - -#ifndef QSLOG_H -#define QSLOG_H - -#include "QsLogLevel.h" -#include "QsLogDest.h" -#include -#include - -#define QS_LOG_VERSION "2.0b3" - -namespace QsLogging -{ -class Destination; -class LoggerImpl; // d pointer - -class QSLOG_SHARED_OBJECT Logger -{ -public: - static Logger& instance(); - static void destroyInstance(); - static Level levelFromLogMessage(const QString& logMessage, bool* conversionSucceeded = 0); - - ~Logger(); - - //! Adds a log message destination. Don't add null destinations. - void addDestination(DestinationPtr destination); - //! Logging at a level < 'newLevel' will be ignored - void setLoggingLevel(Level newLevel); - //! The default level is INFO - Level loggingLevel() const; - - //! The helper forwards the streaming to QDebug and builds the final - //! log message. - class QSLOG_SHARED_OBJECT Helper - { - public: - explicit Helper(Level logLevel) : - level(logLevel), - qtDebug(&buffer) {} - ~Helper(); - QDebug& stream(){ return qtDebug; } - - private: - void writeToLog(); - - Level level; - QString buffer; - QDebug qtDebug; - }; - -private: - Logger(); - Logger(const Logger&); // not available - Logger& operator=(const Logger&); // not available - - void enqueueWrite(const QString& message, Level level); - void write(const QString& message, Level level); - - LoggerImpl* d; - - friend class LogWriterRunnable; -}; - -} // end namespace - -//! Logging macros: define QS_LOG_LINE_NUMBERS to get the file and line number -//! in the log output. -#ifndef QS_LOG_LINE_NUMBERS -#define QLOG_TRACE() \ - if (QsLogging::Logger::instance().loggingLevel() > QsLogging::TraceLevel) {} \ - else QsLogging::Logger::Helper(QsLogging::TraceLevel).stream() -#define QLOG_DEBUG() \ - if (QsLogging::Logger::instance().loggingLevel() > QsLogging::DebugLevel) {} \ - else QsLogging::Logger::Helper(QsLogging::DebugLevel).stream() -#define QLOG_INFO() \ - if (QsLogging::Logger::instance().loggingLevel() > QsLogging::InfoLevel) {} \ - else QsLogging::Logger::Helper(QsLogging::InfoLevel).stream() -#define QLOG_WARN() \ - if (QsLogging::Logger::instance().loggingLevel() > QsLogging::WarnLevel) {} \ - else QsLogging::Logger::Helper(QsLogging::WarnLevel).stream() -#define QLOG_ERROR() \ - if (QsLogging::Logger::instance().loggingLevel() > QsLogging::ErrorLevel) {} \ - else QsLogging::Logger::Helper(QsLogging::ErrorLevel).stream() -#define QLOG_FATAL() \ - if (QsLogging::Logger::instance().loggingLevel() > QsLogging::FatalLevel) {} \ - else QsLogging::Logger::Helper(QsLogging::FatalLevel).stream() -#else -#define QLOG_TRACE() \ - if (QsLogging::Logger::instance().loggingLevel() > QsLogging::TraceLevel) {} \ - else QsLogging::Logger::Helper(QsLogging::TraceLevel).stream() << __FILE__ << '@' << __LINE__ -#define QLOG_DEBUG() \ - if (QsLogging::Logger::instance().loggingLevel() > QsLogging::DebugLevel) {} \ - else QsLogging::Logger::Helper(QsLogging::DebugLevel).stream() << __FILE__ << '@' << __LINE__ -#define QLOG_INFO() \ - if (QsLogging::Logger::instance().loggingLevel() > QsLogging::InfoLevel) {} \ - else QsLogging::Logger::Helper(QsLogging::InfoLevel).stream() << __FILE__ << '@' << __LINE__ -#define QLOG_WARN() \ - if (QsLogging::Logger::instance().loggingLevel() > QsLogging::WarnLevel) {} \ - else QsLogging::Logger::Helper(QsLogging::WarnLevel).stream() << __FILE__ << '@' << __LINE__ -#define QLOG_ERROR() \ - if (QsLogging::Logger::instance().loggingLevel() > QsLogging::ErrorLevel) {} \ - else QsLogging::Logger::Helper(QsLogging::ErrorLevel).stream() << __FILE__ << '@' << __LINE__ -#define QLOG_FATAL() \ - if (QsLogging::Logger::instance().loggingLevel() > QsLogging::FatalLevel) {} \ - else QsLogging::Logger::Helper(QsLogging::FatalLevel).stream() << __FILE__ << '@' << __LINE__ -#endif - -#ifdef QS_LOG_DISABLE -#include "QsLogDisableForThisFile.h" -#endif - -#endif // QSLOG_H +// Copyright (c) 2013, Razvan Petru +// All rights reserved. + +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: + +// * Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, this +// list of conditions and the following disclaimer in the documentation and/or other +// materials provided with the distribution. +// * The name of the contributors may not be used to endorse or promote products +// derived from this software without specific prior written permission. + +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +// IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +// OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED +// OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef QSLOG_H +#define QSLOG_H + +#include "QsLogLevel.h" +#include "QsLogDest.h" +#include +#include + +#define QS_LOG_VERSION "2.0b3" + +namespace QsLogging +{ +class Destination; +class LoggerImpl; // d pointer + +class QSLOG_SHARED_OBJECT Logger +{ +public: + static Logger& instance(); + static void destroyInstance(); + static Level levelFromLogMessage(const QString& logMessage, bool* conversionSucceeded = 0); + + ~Logger(); + + //! Adds a log message destination. Don't add null destinations. + void addDestination(DestinationPtr destination); + //! Logging at a level < 'newLevel' will be ignored + void setLoggingLevel(Level newLevel); + //! The default level is INFO + Level loggingLevel() const; + + //! The helper forwards the streaming to QDebug and builds the final + //! log message. + class QSLOG_SHARED_OBJECT Helper + { + public: + explicit Helper(Level logLevel) : + level(logLevel), + qtDebug(&buffer) {} + ~Helper(); + QDebug& stream(){ return qtDebug; } + + private: + void writeToLog(); + + Level level; + QString buffer; + QDebug qtDebug; + }; + +private: + Logger(); + Logger(const Logger&); // not available + Logger& operator=(const Logger&); // not available + + void enqueueWrite(const QString& message, Level level); + void write(const QString& message, Level level); + + LoggerImpl* d; + + friend class LogWriterRunnable; +}; + +} // end namespace + +//! Logging macros: define QS_LOG_LINE_NUMBERS to get the file and line number +//! in the log output. +#ifndef QS_LOG_LINE_NUMBERS +#define QLOG_TRACE() \ + if (QsLogging::Logger::instance().loggingLevel() > QsLogging::TraceLevel) {} \ + else QsLogging::Logger::Helper(QsLogging::TraceLevel).stream() +#define QLOG_DEBUG() \ + if (QsLogging::Logger::instance().loggingLevel() > QsLogging::DebugLevel) {} \ + else QsLogging::Logger::Helper(QsLogging::DebugLevel).stream() +#define QLOG_INFO() \ + if (QsLogging::Logger::instance().loggingLevel() > QsLogging::InfoLevel) {} \ + else QsLogging::Logger::Helper(QsLogging::InfoLevel).stream() +#define QLOG_WARN() \ + if (QsLogging::Logger::instance().loggingLevel() > QsLogging::WarnLevel) {} \ + else QsLogging::Logger::Helper(QsLogging::WarnLevel).stream() +#define QLOG_ERROR() \ + if (QsLogging::Logger::instance().loggingLevel() > QsLogging::ErrorLevel) {} \ + else QsLogging::Logger::Helper(QsLogging::ErrorLevel).stream() +#define QLOG_FATAL() \ + if (QsLogging::Logger::instance().loggingLevel() > QsLogging::FatalLevel) {} \ + else QsLogging::Logger::Helper(QsLogging::FatalLevel).stream() +#else +#define QLOG_TRACE() \ + if (QsLogging::Logger::instance().loggingLevel() > QsLogging::TraceLevel) {} \ + else QsLogging::Logger::Helper(QsLogging::TraceLevel).stream() << __FILE__ << '@' << __LINE__ +#define QLOG_DEBUG() \ + if (QsLogging::Logger::instance().loggingLevel() > QsLogging::DebugLevel) {} \ + else QsLogging::Logger::Helper(QsLogging::DebugLevel).stream() << __FILE__ << '@' << __LINE__ +#define QLOG_INFO() \ + if (QsLogging::Logger::instance().loggingLevel() > QsLogging::InfoLevel) {} \ + else QsLogging::Logger::Helper(QsLogging::InfoLevel).stream() << __FILE__ << '@' << __LINE__ +#define QLOG_WARN() \ + if (QsLogging::Logger::instance().loggingLevel() > QsLogging::WarnLevel) {} \ + else QsLogging::Logger::Helper(QsLogging::WarnLevel).stream() << __FILE__ << '@' << __LINE__ +#define QLOG_ERROR() \ + if (QsLogging::Logger::instance().loggingLevel() > QsLogging::ErrorLevel) {} \ + else QsLogging::Logger::Helper(QsLogging::ErrorLevel).stream() << __FILE__ << '@' << __LINE__ +#define QLOG_FATAL() \ + if (QsLogging::Logger::instance().loggingLevel() > QsLogging::FatalLevel) {} \ + else QsLogging::Logger::Helper(QsLogging::FatalLevel).stream() << __FILE__ << '@' << __LINE__ +#endif + +#ifdef QS_LOG_DISABLE +#include "QsLogDisableForThisFile.h" +#endif + +#endif // QSLOG_H diff --git a/QsLog/QsLogDest.cpp b/QsLog/QsLogDest.cpp index ae9f44bc..ff388072 100644 --- a/QsLog/QsLogDest.cpp +++ b/QsLog/QsLogDest.cpp @@ -1,70 +1,70 @@ -// Copyright (c) 2013, Razvan Petru -// All rights reserved. - -// Redistribution and use in source and binary forms, with or without modification, -// are permitted provided that the following conditions are met: - -// * Redistributions of source code must retain the above copyright notice, this -// list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright notice, this -// list of conditions and the following disclaimer in the documentation and/or other -// materials provided with the distribution. -// * The name of the contributors may not be used to endorse or promote products -// derived from this software without specific prior written permission. - -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -// IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, -// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE -// OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED -// OF THE POSSIBILITY OF SUCH DAMAGE. - -#include "QsLogDest.h" -#include "QsLogDestConsole.h" -#include "QsLogDestFile.h" -#include "QsLogDestFunctor.h" -#include - -namespace QsLogging -{ - -Destination::~Destination() -{ -} - -//! destination factory -DestinationPtr DestinationFactory::MakeFileDestination(const QString& filePath, - LogRotationOption rotation, const MaxSizeBytes &sizeInBytesToRotateAfter, - const MaxOldLogCount &oldLogsToKeep) -{ - if (EnableLogRotation == rotation) { - QScopedPointer logRotation(new SizeRotationStrategy); - logRotation->setMaximumSizeInBytes(sizeInBytesToRotateAfter.size); - logRotation->setBackupCount(oldLogsToKeep.count); - - return DestinationPtr(new FileDestination(filePath, RotationStrategyPtr(logRotation.take()))); - } - - return DestinationPtr(new FileDestination(filePath, RotationStrategyPtr(new NullRotationStrategy))); -} - -DestinationPtr DestinationFactory::MakeDebugOutputDestination() -{ - return DestinationPtr(new DebugOutputDestination); -} - -DestinationPtr DestinationFactory::MakeFunctorDestination(QsLogging::Destination::LogFunction f) -{ - return DestinationPtr(new FunctorDestination(f)); -} - -DestinationPtr DestinationFactory::MakeFunctorDestination(QObject *receiver, const char *member) -{ - return DestinationPtr(new FunctorDestination(receiver, member)); -} - -} // end namespace +// Copyright (c) 2013, Razvan Petru +// All rights reserved. + +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: + +// * Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, this +// list of conditions and the following disclaimer in the documentation and/or other +// materials provided with the distribution. +// * The name of the contributors may not be used to endorse or promote products +// derived from this software without specific prior written permission. + +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +// IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +// OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED +// OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "QsLogDest.h" +#include "QsLogDestConsole.h" +#include "QsLogDestFile.h" +#include "QsLogDestFunctor.h" +#include + +namespace QsLogging +{ + +Destination::~Destination() +{ +} + +//! destination factory +DestinationPtr DestinationFactory::MakeFileDestination(const QString& filePath, + LogRotationOption rotation, const MaxSizeBytes &sizeInBytesToRotateAfter, + const MaxOldLogCount &oldLogsToKeep) +{ + if (EnableLogRotation == rotation) { + QScopedPointer logRotation(new SizeRotationStrategy); + logRotation->setMaximumSizeInBytes(sizeInBytesToRotateAfter.size); + logRotation->setBackupCount(oldLogsToKeep.count); + + return DestinationPtr(new FileDestination(filePath, RotationStrategyPtr(logRotation.take()))); + } + + return DestinationPtr(new FileDestination(filePath, RotationStrategyPtr(new NullRotationStrategy))); +} + +DestinationPtr DestinationFactory::MakeDebugOutputDestination() +{ + return DestinationPtr(new DebugOutputDestination); +} + +DestinationPtr DestinationFactory::MakeFunctorDestination(QsLogging::Destination::LogFunction f) +{ + return DestinationPtr(new FunctorDestination(f)); +} + +DestinationPtr DestinationFactory::MakeFunctorDestination(QObject *receiver, const char *member) +{ + return DestinationPtr(new FunctorDestination(receiver, member)); +} + +} // end namespace diff --git a/QsLog/QsLogDest.h b/QsLog/QsLogDest.h index a404487b..4ed6157a 100644 --- a/QsLog/QsLogDest.h +++ b/QsLog/QsLogDest.h @@ -1,99 +1,99 @@ -// Copyright (c) 2013, Razvan Petru -// All rights reserved. - -// Redistribution and use in source and binary forms, with or without modification, -// are permitted provided that the following conditions are met: - -// * Redistributions of source code must retain the above copyright notice, this -// list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright notice, this -// list of conditions and the following disclaimer in the documentation and/or other -// materials provided with the distribution. -// * The name of the contributors may not be used to endorse or promote products -// derived from this software without specific prior written permission. - -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -// IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, -// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE -// OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED -// OF THE POSSIBILITY OF SUCH DAMAGE. - -#ifndef QSLOGDEST_H -#define QSLOGDEST_H - -#include "QsLogLevel.h" -#include -#include -class QString; -class QObject; - -#ifdef QSLOG_IS_SHARED_LIBRARY -#define QSLOG_SHARED_OBJECT Q_DECL_EXPORT -#elif QSLOG_IS_SHARED_LIBRARY_IMPORT -#define QSLOG_SHARED_OBJECT Q_DECL_IMPORT -#else -#define QSLOG_SHARED_OBJECT -#endif - -namespace QsLogging -{ - -class QSLOG_SHARED_OBJECT Destination -{ -public: - typedef void (*LogFunction)(const QString &message, Level level); - -public: - virtual ~Destination(); - virtual void write(const QString& message, Level level) = 0; - virtual bool isValid() = 0; // returns whether the destination was created correctly -}; -typedef QSharedPointer DestinationPtr; - - -// a series of "named" paramaters, to make the file destination creation more readable -enum LogRotationOption -{ - DisableLogRotation = 0, - EnableLogRotation = 1 -}; - -struct QSLOG_SHARED_OBJECT MaxSizeBytes -{ - MaxSizeBytes() : size(0) {} - explicit MaxSizeBytes(qint64 size_) : size(size_) {} - qint64 size; -}; - -struct QSLOG_SHARED_OBJECT MaxOldLogCount -{ - MaxOldLogCount() : count(0) {} - explicit MaxOldLogCount(int count_) : count(count_) {} - int count; -}; - - -//! Creates logging destinations/sinks. The caller shares ownership of the destinations with the logger. -//! After being added to a logger, the caller can discard the pointers. -class QSLOG_SHARED_OBJECT DestinationFactory -{ -public: - static DestinationPtr MakeFileDestination(const QString& filePath, - LogRotationOption rotation = DisableLogRotation, - const MaxSizeBytes &sizeInBytesToRotateAfter = MaxSizeBytes(), - const MaxOldLogCount &oldLogsToKeep = MaxOldLogCount()); - static DestinationPtr MakeDebugOutputDestination(); - // takes a pointer to a function - static DestinationPtr MakeFunctorDestination(Destination::LogFunction f); - // takes a QObject + signal/slot - static DestinationPtr MakeFunctorDestination(QObject *receiver, const char *member); -}; - -} // end namespace - -#endif // QSLOGDEST_H +// Copyright (c) 2013, Razvan Petru +// All rights reserved. + +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: + +// * Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, this +// list of conditions and the following disclaimer in the documentation and/or other +// materials provided with the distribution. +// * The name of the contributors may not be used to endorse or promote products +// derived from this software without specific prior written permission. + +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +// IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +// OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED +// OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef QSLOGDEST_H +#define QSLOGDEST_H + +#include "QsLogLevel.h" +#include +#include +class QString; +class QObject; + +#ifdef QSLOG_IS_SHARED_LIBRARY +#define QSLOG_SHARED_OBJECT Q_DECL_EXPORT +#elif QSLOG_IS_SHARED_LIBRARY_IMPORT +#define QSLOG_SHARED_OBJECT Q_DECL_IMPORT +#else +#define QSLOG_SHARED_OBJECT +#endif + +namespace QsLogging +{ + +class QSLOG_SHARED_OBJECT Destination +{ +public: + typedef void (*LogFunction)(const QString &message, Level level); + +public: + virtual ~Destination(); + virtual void write(const QString& message, Level level) = 0; + virtual bool isValid() = 0; // returns whether the destination was created correctly +}; +typedef QSharedPointer DestinationPtr; + + +// a series of "named" paramaters, to make the file destination creation more readable +enum LogRotationOption +{ + DisableLogRotation = 0, + EnableLogRotation = 1 +}; + +struct QSLOG_SHARED_OBJECT MaxSizeBytes +{ + MaxSizeBytes() : size(0) {} + explicit MaxSizeBytes(qint64 size_) : size(size_) {} + qint64 size; +}; + +struct QSLOG_SHARED_OBJECT MaxOldLogCount +{ + MaxOldLogCount() : count(0) {} + explicit MaxOldLogCount(int count_) : count(count_) {} + int count; +}; + + +//! Creates logging destinations/sinks. The caller shares ownership of the destinations with the logger. +//! After being added to a logger, the caller can discard the pointers. +class QSLOG_SHARED_OBJECT DestinationFactory +{ +public: + static DestinationPtr MakeFileDestination(const QString& filePath, + LogRotationOption rotation = DisableLogRotation, + const MaxSizeBytes &sizeInBytesToRotateAfter = MaxSizeBytes(), + const MaxOldLogCount &oldLogsToKeep = MaxOldLogCount()); + static DestinationPtr MakeDebugOutputDestination(); + // takes a pointer to a function + static DestinationPtr MakeFunctorDestination(Destination::LogFunction f); + // takes a QObject + signal/slot + static DestinationPtr MakeFunctorDestination(QObject *receiver, const char *member); +}; + +} // end namespace + +#endif // QSLOGDEST_H diff --git a/QsLog/QsLogDestConsole.cpp b/QsLog/QsLogDestConsole.cpp index ed7fc53b..bfd9828f 100644 --- a/QsLog/QsLogDestConsole.cpp +++ b/QsLog/QsLogDestConsole.cpp @@ -1,55 +1,55 @@ -// Copyright (c) 2013, Razvan Petru -// All rights reserved. - -// Redistribution and use in source and binary forms, with or without modification, -// are permitted provided that the following conditions are met: - -// * Redistributions of source code must retain the above copyright notice, this -// list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright notice, this -// list of conditions and the following disclaimer in the documentation and/or other -// materials provided with the distribution. -// * The name of the contributors may not be used to endorse or promote products -// derived from this software without specific prior written permission. - -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -// IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, -// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE -// OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED -// OF THE POSSIBILITY OF SUCH DAMAGE. - -#include "QsLogDestConsole.h" -#include -#include - -#if defined(Q_OS_WIN) -#define WIN32_LEAN_AND_MEAN -#include -void QsDebugOutput::output( const QString& message ) -{ - OutputDebugStringW(reinterpret_cast(message.utf16())); - OutputDebugStringW(L"\n"); -} -#elif defined(Q_OS_UNIX) -#include -void QsDebugOutput::output( const QString& message ) -{ - fprintf(stderr, "%s\n", qPrintable(message)); - fflush(stderr); -} -#endif - -void QsLogging::DebugOutputDestination::write(const QString& message, Level) -{ - QsDebugOutput::output(message); -} - -bool QsLogging::DebugOutputDestination::isValid() -{ - return true; -} +// Copyright (c) 2013, Razvan Petru +// All rights reserved. + +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: + +// * Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, this +// list of conditions and the following disclaimer in the documentation and/or other +// materials provided with the distribution. +// * The name of the contributors may not be used to endorse or promote products +// derived from this software without specific prior written permission. + +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +// IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +// OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED +// OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "QsLogDestConsole.h" +#include +#include + +#if defined(Q_OS_WIN) +#define WIN32_LEAN_AND_MEAN +#include +void QsDebugOutput::output( const QString& message ) +{ + OutputDebugStringW(reinterpret_cast(message.utf16())); + OutputDebugStringW(L"\n"); +} +#elif defined(Q_OS_UNIX) +#include +void QsDebugOutput::output( const QString& message ) +{ + fprintf(stderr, "%s\n", qPrintable(message)); + fflush(stderr); +} +#endif + +void QsLogging::DebugOutputDestination::write(const QString& message, Level) +{ + QsDebugOutput::output(message); +} + +bool QsLogging::DebugOutputDestination::isValid() +{ + return true; +} diff --git a/QsLog/QsLogDestConsole.h b/QsLog/QsLogDestConsole.h index f80f490e..d422c231 100644 --- a/QsLog/QsLogDestConsole.h +++ b/QsLog/QsLogDestConsole.h @@ -1,52 +1,52 @@ -// Copyright (c) 2013, Razvan Petru -// All rights reserved. - -// Redistribution and use in source and binary forms, with or without modification, -// are permitted provided that the following conditions are met: - -// * Redistributions of source code must retain the above copyright notice, this -// list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright notice, this -// list of conditions and the following disclaimer in the documentation and/or other -// materials provided with the distribution. -// * The name of the contributors may not be used to endorse or promote products -// derived from this software without specific prior written permission. - -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -// IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, -// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE -// OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED -// OF THE POSSIBILITY OF SUCH DAMAGE. - -#ifndef QSLOGDESTCONSOLE_H -#define QSLOGDESTCONSOLE_H - -#include "QsLogDest.h" - -class QString; - -class QsDebugOutput -{ -public: - static void output(const QString& a_message); -}; - -namespace QsLogging -{ - -// debugger sink -class DebugOutputDestination : public Destination -{ -public: - virtual void write(const QString& message, Level level); - virtual bool isValid(); -}; - -} - -#endif // QSLOGDESTCONSOLE_H +// Copyright (c) 2013, Razvan Petru +// All rights reserved. + +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: + +// * Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, this +// list of conditions and the following disclaimer in the documentation and/or other +// materials provided with the distribution. +// * The name of the contributors may not be used to endorse or promote products +// derived from this software without specific prior written permission. + +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +// IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +// OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED +// OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef QSLOGDESTCONSOLE_H +#define QSLOGDESTCONSOLE_H + +#include "QsLogDest.h" + +class QString; + +class QsDebugOutput +{ +public: + static void output(const QString& a_message); +}; + +namespace QsLogging +{ + +// debugger sink +class DebugOutputDestination : public Destination +{ +public: + virtual void write(const QString& message, Level level); + virtual bool isValid(); +}; + +} + +#endif // QSLOGDESTCONSOLE_H diff --git a/QsLog/QsLogLevel.h b/QsLog/QsLogLevel.h index 62984732..5032f27c 100644 --- a/QsLog/QsLogLevel.h +++ b/QsLog/QsLogLevel.h @@ -1,45 +1,45 @@ -// Copyright (c) 2013, Razvan Petru -// All rights reserved. - -// Redistribution and use in source and binary forms, with or without modification, -// are permitted provided that the following conditions are met: - -// * Redistributions of source code must retain the above copyright notice, this -// list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright notice, this -// list of conditions and the following disclaimer in the documentation and/or other -// materials provided with the distribution. -// * The name of the contributors may not be used to endorse or promote products -// derived from this software without specific prior written permission. - -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -// IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, -// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE -// OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED -// OF THE POSSIBILITY OF SUCH DAMAGE. - -#ifndef QSLOGLEVEL_H -#define QSLOGLEVEL_H - -namespace QsLogging -{ - -enum Level -{ - TraceLevel = 0, - DebugLevel, - InfoLevel, - WarnLevel, - ErrorLevel, - FatalLevel, - OffLevel -}; - -} - -#endif // QSLOGLEVEL_H +// Copyright (c) 2013, Razvan Petru +// All rights reserved. + +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: + +// * Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, this +// list of conditions and the following disclaimer in the documentation and/or other +// materials provided with the distribution. +// * The name of the contributors may not be used to endorse or promote products +// derived from this software without specific prior written permission. + +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +// IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +// OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED +// OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef QSLOGLEVEL_H +#define QSLOGLEVEL_H + +namespace QsLogging +{ + +enum Level +{ + TraceLevel = 0, + DebugLevel, + InfoLevel, + WarnLevel, + ErrorLevel, + FatalLevel, + OffLevel +}; + +} + +#endif // QSLOGLEVEL_H diff --git a/YACReader/bookmarks_dialog.cpp b/YACReader/bookmarks_dialog.cpp index 07df7222..7175fa33 100644 --- a/YACReader/bookmarks_dialog.cpp +++ b/YACReader/bookmarks_dialog.cpp @@ -1,197 +1,197 @@ -#include "bookmarks_dialog.h" - -#include -#include -#include -#include -#include -#include - -#include "bookmarks.h" - -BookmarksDialog::BookmarksDialog(QWidget * parent) - :QDialog(parent) -{ - setModal(true); - - //animation = new QPropertyAnimation(this,"windowOpacity"); - //animation->setDuration(150); - - QHBoxLayout * layout = new QHBoxLayout(); - - //bookmarks - QGridLayout * bookmarksL = new QGridLayout(); - - pages.push_back(new QLabel(tr("Lastest Page"))); - for(int i=0;i<3;i++) - pages.push_back(new QLabel("-")); - - QString labelsStyle = "QLabel {color:white;}"; - - foreach(QLabel * label,pages) - { - label->setStyleSheet(labelsStyle); - } - - int heightDesktopResolution = QApplication::desktop()->screenGeometry().height(); - int height,width; - height = heightDesktopResolution*0.50; - width = height*0.65; - - coverSize = QSize(width,height); - - for(int i=0;i<4;i++) - { - QLabel * l = new QLabel(); - l->setFixedSize(coverSize); - l->setScaledContents(false); - //l->setPixmap(QPixmap(":/images/notCover.png")); - l->installEventFilter(this); - images.push_back(l); - } - - for(int i=0;i<3;i++) - bookmarksL->addWidget(pages.at(i+1),0,i,Qt::AlignCenter); - - for(int i=0;i<3;i++) - bookmarksL->addWidget(images.at(i+1),1,i,Qt::AlignCenter); - - - //last page - QGridLayout * lp = new QGridLayout(); - lp->addWidget(pages.at(0),0,0,Qt::AlignCenter); - lp->addWidget(images.at(0),1,0,Qt::AlignCenter); - - layout->addLayout(bookmarksL); - QFrame *f = new QFrame( this ); - f->setFrameStyle( QFrame::VLine | QFrame::Sunken ); - layout->addWidget(f); - layout->addLayout(lp); - - QHBoxLayout * buttons = new QHBoxLayout(); - - cancel = new QPushButton(tr("Close")); - cancel->setFlat(true); - connect(cancel,SIGNAL(clicked()),this,SLOT(hide())); - buttons->addStretch(); - buttons->addWidget(cancel); - - cancel->setStyleSheet("QPushButton {border: 1px solid #242424; background: #2e2e2e; color:white; padding: 5px 26px 5px 26px; font-size:12px;font-family:Arial; font-weight:bold;}"); - - QVBoxLayout * l = new QVBoxLayout(); - - l->addWidget(new QLabel(""+tr("Click on any image to go to the bookmark")+""),0,Qt::AlignCenter); - l->addLayout(layout); -#ifdef Q_OS_MAC - l->addLayout(buttons); -#endif - - QPalette Pal(palette()); - // set black background - Pal.setColor(QPalette::Background, QColor("#454545")); - this->setAutoFillBackground(true); - this->setPalette(Pal); - - setLayout(l); -} - -void BookmarksDialog::setBookmarks(const Bookmarks & bm) -{ - lastPage = bm.getLastPage(); - if (lastPage > 0) - { - QPixmap p = QPixmap::fromImage(bm.getLastPagePixmap()); - if(p.isNull()) - { - images.at(0)->setAlignment(Qt::AlignHCenter|Qt::AlignVCenter); - images.at(0)->setText(tr("Loading...")); - } - else - { - images.at(0)->setAlignment(Qt::AlignHCenter|Qt::AlignBottom); - images.at(0)->setPixmap(p.scaled(coverSize,Qt::KeepAspectRatio,Qt::SmoothTransformation)); - } - } - else - { - images.at(0)->setAlignment(Qt::AlignHCenter|Qt::AlignVCenter); - images.at(0)->setPixmap(QPixmap(":/images/notCover.png").scaled(coverSize,Qt::KeepAspectRatio,Qt::SmoothTransformation)); - - } - - QList l = bm.getBookmarkPages(); - int s = l.count(); - for(int i=0;isetText(QString::number(l.at(i)+1)); - QPixmap p = QPixmap::fromImage(bm.getBookmarkPixmap(l.at(i))); - if(p.isNull()) - { - images.at(i+1)->setAlignment(Qt::AlignHCenter|Qt::AlignVCenter); - images.at(i+1)->setText(tr("Loading...")); - } - else - { - images.at(i+1)->setAlignment(Qt::AlignHCenter|Qt::AlignBottom); - images.at(i+1)->setPixmap(p.scaled(coverSize,Qt::KeepAspectRatio,Qt::SmoothTransformation)); - } - } - for(int i=s;i<3;i++) - { - pages.at(i+1)->setText("-"); - images.at(i+1)->setAlignment(Qt::AlignHCenter|Qt::AlignVCenter); - images.at(i+1)->setPixmap(QPixmap(":/images/notCover.png").scaled(coverSize,Qt::KeepAspectRatio,Qt::SmoothTransformation)); - } -} - -bool BookmarksDialog::eventFilter(QObject *obj, QEvent *event) -{ - if(event->type() == QEvent::MouseButtonPress) - { - if (obj == images.at(0)) - { - emit(goToPage(lastPage)); - close(); - event->accept(); - } - for(int i=1;i<=3;i++) - { - if(obj == images.at(i)) - { - bool b; - int page = pages.at(i)->text().toInt(&b)-1; - if(b) - { - emit(goToPage(page)); - close(); - } - event->accept(); - } - } - } - // pass the event on to the parent class - return QDialog::eventFilter(obj, event); -} - -void BookmarksDialog::keyPressEvent(QKeyEvent * event) -{ - if(event->key() == Qt::Key_M) - hide(); -} -/* -void BookmarksDialog::show() -{ - QDialog::show(); - disconnect(animation,SIGNAL(finished()),this,SLOT(close())); - animation->setStartValue(0); - animation->setEndValue(1); - animation->start(); -} - -void BookmarksDialog::hide() -{ - connect(animation,SIGNAL(finished()),this,SLOT(close())); - animation->setStartValue(1); - animation->setEndValue(0); - animation->start(); -}*/ +#include "bookmarks_dialog.h" + +#include +#include +#include +#include +#include +#include + +#include "bookmarks.h" + +BookmarksDialog::BookmarksDialog(QWidget * parent) + :QDialog(parent) +{ + setModal(true); + + //animation = new QPropertyAnimation(this,"windowOpacity"); + //animation->setDuration(150); + + QHBoxLayout * layout = new QHBoxLayout(); + + //bookmarks + QGridLayout * bookmarksL = new QGridLayout(); + + pages.push_back(new QLabel(tr("Lastest Page"))); + for(int i=0;i<3;i++) + pages.push_back(new QLabel("-")); + + QString labelsStyle = "QLabel {color:white;}"; + + foreach(QLabel * label,pages) + { + label->setStyleSheet(labelsStyle); + } + + int heightDesktopResolution = QApplication::desktop()->screenGeometry().height(); + int height,width; + height = heightDesktopResolution*0.50; + width = height*0.65; + + coverSize = QSize(width,height); + + for(int i=0;i<4;i++) + { + QLabel * l = new QLabel(); + l->setFixedSize(coverSize); + l->setScaledContents(false); + //l->setPixmap(QPixmap(":/images/notCover.png")); + l->installEventFilter(this); + images.push_back(l); + } + + for(int i=0;i<3;i++) + bookmarksL->addWidget(pages.at(i+1),0,i,Qt::AlignCenter); + + for(int i=0;i<3;i++) + bookmarksL->addWidget(images.at(i+1),1,i,Qt::AlignCenter); + + + //last page + QGridLayout * lp = new QGridLayout(); + lp->addWidget(pages.at(0),0,0,Qt::AlignCenter); + lp->addWidget(images.at(0),1,0,Qt::AlignCenter); + + layout->addLayout(bookmarksL); + QFrame *f = new QFrame( this ); + f->setFrameStyle( QFrame::VLine | QFrame::Sunken ); + layout->addWidget(f); + layout->addLayout(lp); + + QHBoxLayout * buttons = new QHBoxLayout(); + + cancel = new QPushButton(tr("Close")); + cancel->setFlat(true); + connect(cancel,SIGNAL(clicked()),this,SLOT(hide())); + buttons->addStretch(); + buttons->addWidget(cancel); + + cancel->setStyleSheet("QPushButton {border: 1px solid #242424; background: #2e2e2e; color:white; padding: 5px 26px 5px 26px; font-size:12px;font-family:Arial; font-weight:bold;}"); + + QVBoxLayout * l = new QVBoxLayout(); + + l->addWidget(new QLabel(""+tr("Click on any image to go to the bookmark")+""),0,Qt::AlignCenter); + l->addLayout(layout); +#ifdef Q_OS_MAC + l->addLayout(buttons); +#endif + + QPalette Pal(palette()); + // set black background + Pal.setColor(QPalette::Background, QColor("#454545")); + this->setAutoFillBackground(true); + this->setPalette(Pal); + + setLayout(l); +} + +void BookmarksDialog::setBookmarks(const Bookmarks & bm) +{ + lastPage = bm.getLastPage(); + if (lastPage > 0) + { + QPixmap p = QPixmap::fromImage(bm.getLastPagePixmap()); + if(p.isNull()) + { + images.at(0)->setAlignment(Qt::AlignHCenter|Qt::AlignVCenter); + images.at(0)->setText(tr("Loading...")); + } + else + { + images.at(0)->setAlignment(Qt::AlignHCenter|Qt::AlignBottom); + images.at(0)->setPixmap(p.scaled(coverSize,Qt::KeepAspectRatio,Qt::SmoothTransformation)); + } + } + else + { + images.at(0)->setAlignment(Qt::AlignHCenter|Qt::AlignVCenter); + images.at(0)->setPixmap(QPixmap(":/images/notCover.png").scaled(coverSize,Qt::KeepAspectRatio,Qt::SmoothTransformation)); + + } + + QList l = bm.getBookmarkPages(); + int s = l.count(); + for(int i=0;isetText(QString::number(l.at(i)+1)); + QPixmap p = QPixmap::fromImage(bm.getBookmarkPixmap(l.at(i))); + if(p.isNull()) + { + images.at(i+1)->setAlignment(Qt::AlignHCenter|Qt::AlignVCenter); + images.at(i+1)->setText(tr("Loading...")); + } + else + { + images.at(i+1)->setAlignment(Qt::AlignHCenter|Qt::AlignBottom); + images.at(i+1)->setPixmap(p.scaled(coverSize,Qt::KeepAspectRatio,Qt::SmoothTransformation)); + } + } + for(int i=s;i<3;i++) + { + pages.at(i+1)->setText("-"); + images.at(i+1)->setAlignment(Qt::AlignHCenter|Qt::AlignVCenter); + images.at(i+1)->setPixmap(QPixmap(":/images/notCover.png").scaled(coverSize,Qt::KeepAspectRatio,Qt::SmoothTransformation)); + } +} + +bool BookmarksDialog::eventFilter(QObject *obj, QEvent *event) +{ + if(event->type() == QEvent::MouseButtonPress) + { + if (obj == images.at(0)) + { + emit(goToPage(lastPage)); + close(); + event->accept(); + } + for(int i=1;i<=3;i++) + { + if(obj == images.at(i)) + { + bool b; + int page = pages.at(i)->text().toInt(&b)-1; + if(b) + { + emit(goToPage(page)); + close(); + } + event->accept(); + } + } + } + // pass the event on to the parent class + return QDialog::eventFilter(obj, event); +} + +void BookmarksDialog::keyPressEvent(QKeyEvent * event) +{ + if(event->key() == Qt::Key_M) + hide(); +} +/* +void BookmarksDialog::show() +{ + QDialog::show(); + disconnect(animation,SIGNAL(finished()),this,SLOT(close())); + animation->setStartValue(0); + animation->setEndValue(1); + animation->start(); +} + +void BookmarksDialog::hide() +{ + connect(animation,SIGNAL(finished()),this,SLOT(close())); + animation->setStartValue(1); + animation->setEndValue(0); + animation->start(); +}*/ diff --git a/YACReader/bookmarks_dialog.h b/YACReader/bookmarks_dialog.h index c83a2c7e..4838ee75 100644 --- a/YACReader/bookmarks_dialog.h +++ b/YACReader/bookmarks_dialog.h @@ -1,45 +1,45 @@ -#ifndef __BOOKMARKS_DIALOG_H -#define __BOOKMARKS_DIALOG_H - -#include -#include -#include -#include -#include -#include -#include - -#include "bookmarks.h" - - class BookmarksDialog : public QDialog - { - Q_OBJECT - - protected: - QList pages; - QList images; - - int lastPage; - - QPushButton * accept; - QPushButton * cancel; - - QSize coverSize; - - bool eventFilter(QObject *obj, QEvent *event); - void keyPressEvent(QKeyEvent * event); - //QPropertyAnimation * animation; - - public: - BookmarksDialog(QWidget * parent = 0); - - public slots: - void setBookmarks(const Bookmarks & bookmarks); - //void show(); - //void hide(); - - signals: - void goToPage(unsigned int page); - }; - -#endif // BOOKMARKS_DIALOG_H +#ifndef __BOOKMARKS_DIALOG_H +#define __BOOKMARKS_DIALOG_H + +#include +#include +#include +#include +#include +#include +#include + +#include "bookmarks.h" + + class BookmarksDialog : public QDialog + { + Q_OBJECT + + protected: + QList pages; + QList images; + + int lastPage; + + QPushButton * accept; + QPushButton * cancel; + + QSize coverSize; + + bool eventFilter(QObject *obj, QEvent *event); + void keyPressEvent(QKeyEvent * event); + //QPropertyAnimation * animation; + + public: + BookmarksDialog(QWidget * parent = 0); + + public slots: + void setBookmarks(const Bookmarks & bookmarks); + //void show(); + //void hide(); + + signals: + void goToPage(unsigned int page); + }; + +#endif // BOOKMARKS_DIALOG_H diff --git a/YACReader/configuration.cpp b/YACReader/configuration.cpp index 5a0efd4c..36e9aeea 100644 --- a/YACReader/configuration.cpp +++ b/YACReader/configuration.cpp @@ -1,79 +1,79 @@ -#include "configuration.h" - -#include -#include -#include -#include -#include -#include - -#include "yacreader_global.h" - -Configuration::Configuration() -{ - //read configuration - //load("/YACReader.conf"); -} - -QSettings *Configuration::getSettings() -{ - return settings; -} - -/*Configuration::Configuration(const Configuration & conf) -{ - //nothing -}*/ - -void Configuration::load(QSettings * settings) -{ - this->settings = settings; - - //TODO set defaults - if(!settings->contains(PATH)) - settings->setValue(PATH,"."); - if(!settings->contains(GO_TO_FLOW_SIZE)) - settings->setValue(GO_TO_FLOW_SIZE,QSize(126,200)); - if(!settings->contains(MAG_GLASS_SIZE)) - settings->setValue(MAG_GLASS_SIZE,QSize(350,175)); - if(!settings->contains(ZOOM_LEVEL)) - settings->setValue(MAG_GLASS_SIZE,QSize(350,175)); - if(!settings->contains(FLOW_TYPE)) - settings->setValue(FLOW_TYPE,0); - if(!settings->contains(FULLSCREEN)) - settings->setValue(FULLSCREEN,false); - if(!settings->contains(Y_WINDOW_SIZE)) - settings->setValue(Y_WINDOW_SIZE,QSize(0,0)); - if(!settings->contains(MAXIMIZED)) - settings->setValue(MAXIMIZED,false); - if(!settings->contains(DOUBLE_PAGE)) - settings->setValue(DOUBLE_PAGE,false); - if(!settings->contains(BACKGROUND_COLOR)) - settings->setValue(BACKGROUND_COLOR,QColor(40,40,40)); - if(!settings->contains(ALWAYS_ON_TOP)) - settings->setValue(ALWAYS_ON_TOP,false); - if(!settings->contains(SHOW_TOOLBARS)) - settings->setValue(SHOW_TOOLBARS, true); - if(!settings->contains(QUICK_NAVI_MODE)) - settings->setValue(QUICK_NAVI_MODE, false); - //old fit stuff - /*if(!settings->contains(FIT)) - settings->setValue(FIT,false); - if(!settings->contains(FIT_TO_WIDTH_RATIO)) - settings->setValue(FIT_TO_WIDTH_RATIO,1); - if(!settings->contains(ADJUST_TO_FULL_SIZE)) - settings->setValue(ADJUST_TO_FULL_SIZE,false); - */ - } -void Configuration::updateOpenRecentList (QString path) -{ - QStringList list = openRecentList(); - list.removeAll(path); - list.prepend(path); - //TODO: Make list lenght configurable - while (list.length() > getOpenRecentSize()) - { - list.removeLast(); - } - settings->setValue("recentFiles", list); -} +#include "configuration.h" + +#include +#include +#include +#include +#include +#include + +#include "yacreader_global.h" + +Configuration::Configuration() +{ + //read configuration + //load("/YACReader.conf"); +} + +QSettings *Configuration::getSettings() +{ + return settings; +} + +/*Configuration::Configuration(const Configuration & conf) +{ + //nothing +}*/ + +void Configuration::load(QSettings * settings) +{ + this->settings = settings; + + //TODO set defaults + if(!settings->contains(PATH)) + settings->setValue(PATH,"."); + if(!settings->contains(GO_TO_FLOW_SIZE)) + settings->setValue(GO_TO_FLOW_SIZE,QSize(126,200)); + if(!settings->contains(MAG_GLASS_SIZE)) + settings->setValue(MAG_GLASS_SIZE,QSize(350,175)); + if(!settings->contains(ZOOM_LEVEL)) + settings->setValue(MAG_GLASS_SIZE,QSize(350,175)); + if(!settings->contains(FLOW_TYPE)) + settings->setValue(FLOW_TYPE,0); + if(!settings->contains(FULLSCREEN)) + settings->setValue(FULLSCREEN,false); + if(!settings->contains(Y_WINDOW_SIZE)) + settings->setValue(Y_WINDOW_SIZE,QSize(0,0)); + if(!settings->contains(MAXIMIZED)) + settings->setValue(MAXIMIZED,false); + if(!settings->contains(DOUBLE_PAGE)) + settings->setValue(DOUBLE_PAGE,false); + if(!settings->contains(BACKGROUND_COLOR)) + settings->setValue(BACKGROUND_COLOR,QColor(40,40,40)); + if(!settings->contains(ALWAYS_ON_TOP)) + settings->setValue(ALWAYS_ON_TOP,false); + if(!settings->contains(SHOW_TOOLBARS)) + settings->setValue(SHOW_TOOLBARS, true); + if(!settings->contains(QUICK_NAVI_MODE)) + settings->setValue(QUICK_NAVI_MODE, false); + //old fit stuff + /*if(!settings->contains(FIT)) + settings->setValue(FIT,false); + if(!settings->contains(FIT_TO_WIDTH_RATIO)) + settings->setValue(FIT_TO_WIDTH_RATIO,1); + if(!settings->contains(ADJUST_TO_FULL_SIZE)) + settings->setValue(ADJUST_TO_FULL_SIZE,false); + */ + } +void Configuration::updateOpenRecentList (QString path) +{ + QStringList list = openRecentList(); + list.removeAll(path); + list.prepend(path); + //TODO: Make list lenght configurable + while (list.length() > getOpenRecentSize()) + { + list.removeLast(); + } + settings->setValue("recentFiles", list); +} diff --git a/YACReader/configuration.h b/YACReader/configuration.h index 96f78a13..93abfa0f 100644 --- a/YACReader/configuration.h +++ b/YACReader/configuration.h @@ -1,117 +1,117 @@ -#ifndef __CONFIGURATION_H -#define __CONFIGURATION_H -#include -#include -#include -#include -#include -#include -#include - -#include "yacreader_global_gui.h" - -#define CONF_FILE_PATH "." -#define SLIDE_ASPECT_RATIO 1.585 - -using namespace YACReader; - - class Configuration : public QObject - { - Q_OBJECT - - private: - QSettings * settings; - - QString defaultPath; - //configuration properties - QSize magnifyingGlassSize; - QSize gotoSlideSize; - float zoomLevel; - bool adjustToWidth; - bool fullScreen; - FlowType flowType; - float fitToWidthRatio; - QPoint windowPos; - QSize windowSize; - bool maximized; - bool doublePage; - bool doubleMangaPage; - bool alwaysOnTop; - bool adjustToFullSize; - QColor backgroundColor; - - Configuration(); - //Configuration(const Configuration & conf); - void load(const QString & path = CONF_FILE_PATH); - - - public: - static Configuration & getConfiguration() - { - static Configuration configuration; - return configuration; - }; - QSettings *getSettings(); - void load(QSettings * settings); - QString getDefaultPath() { return settings->value(PATH).toString(); } - void setDefaultPath(QString defaultPath){settings->setValue(PATH,defaultPath);} - QSize getMagnifyingGlassSize() { return settings->value(MAG_GLASS_SIZE).toSize();} - void setMagnifyingGlassSize(const QSize & mgs) { settings->setValue(MAG_GLASS_SIZE,mgs);} - QSize getGotoSlideSize() { return settings->value(GO_TO_FLOW_SIZE).toSize();} - void setGotoSlideSize(const QSize & gss) { settings->setValue(GO_TO_FLOW_SIZE,gss);} - float getZoomLevel() { return settings->value(ZOOM_LEVEL).toFloat();} - void setZoomLevel(float zl) { settings->setValue(ZOOM_LEVEL,zl);} - - //Unified enum based fitmode - YACReader::FitMode getFitMode() { return static_cast(settings->value(FITMODE, YACReader::FitMode::FullPage).toInt()); } - void setFitMode ( YACReader::FitMode fitMode ){ settings->setValue(FITMODE, static_cast(fitMode)); } - - //openRecent - int getOpenRecentSize() { return settings->value("recentSize", 25).toInt();} - QStringList openRecentList() { return settings->value("recentFiles").toStringList(); } - void updateOpenRecentList (QString path); - void clearOpenRecentList() { settings->remove("recentFiles"); } - - //Old fitmodes - /* - bool getAdjustToWidth() {return settings->value(FIT).toBool();} - void setAdjustToWidth(bool atw=true) {settings->setValue(FIT,atw);} - float getFitToWidthRatio(){return settings->value(FIT_TO_WIDTH_RATIO).toFloat();} - void setFitToWidthRatio(float r){settings->setValue(FIT_TO_WIDTH_RATIO,r);} - bool getAdjustToFullSize(){return settings->value(ADJUST_TO_FULL_SIZE).toBool();} - void setAdjustToFullSize(bool b){settings->setValue(ADJUST_TO_FULL_SIZE,b);} - */ - - FlowType getFlowType(){return (FlowType)settings->value(FLOW_TYPE_SW).toInt();} - void setFlowType(FlowType type){settings->setValue(FLOW_TYPE_SW,type);} - bool getFullScreen(){return settings->value(FULLSCREEN).toBool();} - void setFullScreen(bool f){settings->setValue(FULLSCREEN,f);} - - QPoint getPos(){return settings->value(Y_WINDOW_POS).toPoint();} - void setPos(QPoint p){settings->setValue(Y_WINDOW_POS,p);} - QSize getSize(){return settings->value(Y_WINDOW_SIZE).toSize();} - void setSize(QSize s){settings->setValue(Y_WINDOW_SIZE,s);} - bool getMaximized(){return settings->value(MAXIMIZED).toBool();} - void setMaximized(bool b){settings->setValue(MAXIMIZED,b);} - bool getDoublePage(){return settings->value(DOUBLE_PAGE).toBool();} - void setDoublePage(bool b){settings->setValue(DOUBLE_PAGE,b);} - bool getDoubleMangaPage(){return settings->value(DOUBLE_MANGA_PAGE).toBool();} - void setDoubleMangaPage(bool b){settings->setValue(DOUBLE_MANGA_PAGE,b);} - - QColor getBackgroundColor(){return settings->value(BACKGROUND_COLOR).value();} - void setBackgroundColor(const QColor& color){settings->value(BACKGROUND_COLOR,color);} - bool getAlwaysOnTop(){return settings->value(ALWAYS_ON_TOP).toBool();} - void setAlwaysOnTop(bool b){ settings->setValue(ALWAYS_ON_TOP,b);} - bool getShowToolbars(){return settings->value(SHOW_TOOLBARS).toBool();} - void setShowToolbars(bool b){settings->setValue(SHOW_TOOLBARS,b);} - bool getShowInformation(){return settings->value(SHOW_INFO,false).toBool();} - void setShowInformation(bool b){settings->setValue(SHOW_INFO,b);} - QDate getLastVersionCheck(){return settings->value(LAST_VERSION_CHECK).toDate();} - void setLastVersionCheck(const QDate & date){ settings->setValue(LAST_VERSION_CHECK,date);} - int getNumDaysBetweenVersionChecks() {return settings->value(NUM_DAYS_BETWEEN_VERSION_CHECKS,1).toInt();} - void setNumDaysBetweenVersionChecks(int days) {return settings->setValue(NUM_DAYS_BETWEEN_VERSION_CHECKS,days);} - bool getQuickNaviMode(){return settings->value(QUICK_NAVI_MODE).toBool();} - bool getDisableShowOnMouseOver(){return settings->value(DISABLE_MOUSE_OVER_GOTO_FLOW).toBool();} - }; - -#endif +#ifndef __CONFIGURATION_H +#define __CONFIGURATION_H +#include +#include +#include +#include +#include +#include +#include + +#include "yacreader_global_gui.h" + +#define CONF_FILE_PATH "." +#define SLIDE_ASPECT_RATIO 1.585 + +using namespace YACReader; + + class Configuration : public QObject + { + Q_OBJECT + + private: + QSettings * settings; + + QString defaultPath; + //configuration properties + QSize magnifyingGlassSize; + QSize gotoSlideSize; + float zoomLevel; + bool adjustToWidth; + bool fullScreen; + FlowType flowType; + float fitToWidthRatio; + QPoint windowPos; + QSize windowSize; + bool maximized; + bool doublePage; + bool doubleMangaPage; + bool alwaysOnTop; + bool adjustToFullSize; + QColor backgroundColor; + + Configuration(); + //Configuration(const Configuration & conf); + void load(const QString & path = CONF_FILE_PATH); + + + public: + static Configuration & getConfiguration() + { + static Configuration configuration; + return configuration; + }; + QSettings *getSettings(); + void load(QSettings * settings); + QString getDefaultPath() { return settings->value(PATH).toString(); } + void setDefaultPath(QString defaultPath){settings->setValue(PATH,defaultPath);} + QSize getMagnifyingGlassSize() { return settings->value(MAG_GLASS_SIZE).toSize();} + void setMagnifyingGlassSize(const QSize & mgs) { settings->setValue(MAG_GLASS_SIZE,mgs);} + QSize getGotoSlideSize() { return settings->value(GO_TO_FLOW_SIZE).toSize();} + void setGotoSlideSize(const QSize & gss) { settings->setValue(GO_TO_FLOW_SIZE,gss);} + float getZoomLevel() { return settings->value(ZOOM_LEVEL).toFloat();} + void setZoomLevel(float zl) { settings->setValue(ZOOM_LEVEL,zl);} + + //Unified enum based fitmode + YACReader::FitMode getFitMode() { return static_cast(settings->value(FITMODE, YACReader::FitMode::FullPage).toInt()); } + void setFitMode ( YACReader::FitMode fitMode ){ settings->setValue(FITMODE, static_cast(fitMode)); } + + //openRecent + int getOpenRecentSize() { return settings->value("recentSize", 25).toInt();} + QStringList openRecentList() { return settings->value("recentFiles").toStringList(); } + void updateOpenRecentList (QString path); + void clearOpenRecentList() { settings->remove("recentFiles"); } + + //Old fitmodes + /* + bool getAdjustToWidth() {return settings->value(FIT).toBool();} + void setAdjustToWidth(bool atw=true) {settings->setValue(FIT,atw);} + float getFitToWidthRatio(){return settings->value(FIT_TO_WIDTH_RATIO).toFloat();} + void setFitToWidthRatio(float r){settings->setValue(FIT_TO_WIDTH_RATIO,r);} + bool getAdjustToFullSize(){return settings->value(ADJUST_TO_FULL_SIZE).toBool();} + void setAdjustToFullSize(bool b){settings->setValue(ADJUST_TO_FULL_SIZE,b);} + */ + + FlowType getFlowType(){return (FlowType)settings->value(FLOW_TYPE_SW).toInt();} + void setFlowType(FlowType type){settings->setValue(FLOW_TYPE_SW,type);} + bool getFullScreen(){return settings->value(FULLSCREEN).toBool();} + void setFullScreen(bool f){settings->setValue(FULLSCREEN,f);} + + QPoint getPos(){return settings->value(Y_WINDOW_POS).toPoint();} + void setPos(QPoint p){settings->setValue(Y_WINDOW_POS,p);} + QSize getSize(){return settings->value(Y_WINDOW_SIZE).toSize();} + void setSize(QSize s){settings->setValue(Y_WINDOW_SIZE,s);} + bool getMaximized(){return settings->value(MAXIMIZED).toBool();} + void setMaximized(bool b){settings->setValue(MAXIMIZED,b);} + bool getDoublePage(){return settings->value(DOUBLE_PAGE).toBool();} + void setDoublePage(bool b){settings->setValue(DOUBLE_PAGE,b);} + bool getDoubleMangaPage(){return settings->value(DOUBLE_MANGA_PAGE).toBool();} + void setDoubleMangaPage(bool b){settings->setValue(DOUBLE_MANGA_PAGE,b);} + + QColor getBackgroundColor(){return settings->value(BACKGROUND_COLOR).value();} + void setBackgroundColor(const QColor& color){settings->value(BACKGROUND_COLOR,color);} + bool getAlwaysOnTop(){return settings->value(ALWAYS_ON_TOP).toBool();} + void setAlwaysOnTop(bool b){ settings->setValue(ALWAYS_ON_TOP,b);} + bool getShowToolbars(){return settings->value(SHOW_TOOLBARS).toBool();} + void setShowToolbars(bool b){settings->setValue(SHOW_TOOLBARS,b);} + bool getShowInformation(){return settings->value(SHOW_INFO,false).toBool();} + void setShowInformation(bool b){settings->setValue(SHOW_INFO,b);} + QDate getLastVersionCheck(){return settings->value(LAST_VERSION_CHECK).toDate();} + void setLastVersionCheck(const QDate & date){ settings->setValue(LAST_VERSION_CHECK,date);} + int getNumDaysBetweenVersionChecks() {return settings->value(NUM_DAYS_BETWEEN_VERSION_CHECKS,1).toInt();} + void setNumDaysBetweenVersionChecks(int days) {return settings->setValue(NUM_DAYS_BETWEEN_VERSION_CHECKS,days);} + bool getQuickNaviMode(){return settings->value(QUICK_NAVI_MODE).toBool();} + bool getDisableShowOnMouseOver(){return settings->value(DISABLE_MOUSE_OVER_GOTO_FLOW).toBool();} + }; + +#endif diff --git a/YACReader/goto_dialog.cpp b/YACReader/goto_dialog.cpp index ed774432..2b931583 100644 --- a/YACReader/goto_dialog.cpp +++ b/YACReader/goto_dialog.cpp @@ -1,84 +1,84 @@ -#include "goto_dialog.h" - -#include -#include -#include - - - -GoToDialog::GoToDialog(QWidget * parent) -:QDialog(parent) -{ - setupUI(); -} - -void GoToDialog::setupUI() -{ - textLabel = new QLabel(tr("Page : ")); - pageNumber = new QLineEdit; - v = new QIntValidator(this); - v->setBottom(1); - pageNumber->setValidator(v); - textLabel->setBuddy(pageNumber); - textLabel->setAlignment(Qt::AlignRight|Qt::AlignVCenter); - - accept = new QPushButton(tr("Go To")); - connect(accept,SIGNAL(clicked()),this,SLOT(goTo())); - cancel = new QPushButton(tr("Cancel")); - connect(cancel,SIGNAL(clicked()),this,SLOT(close())); - - QHBoxLayout *topLayout = new QHBoxLayout; - - topLayout->addWidget(textLabel); - topLayout->addWidget(pageNumber); - - QHBoxLayout *bottomLayout = new QHBoxLayout; - bottomLayout->addStretch(); - bottomLayout->addWidget(accept); - bottomLayout->addWidget(cancel); - - QVBoxLayout *mainLayout = new QVBoxLayout; - mainLayout->addWidget(numPagesLabel = new QLabel(tr("Total pages : "))); - mainLayout->addLayout(topLayout); - mainLayout->addStretch(); - mainLayout->addLayout(bottomLayout); - - QHBoxLayout *imgMainLayout = new QHBoxLayout; - QLabel * imgLabel = new QLabel(); - QPixmap p(":/images/goto.png"); - imgLabel->setPixmap(p); - imgMainLayout->addWidget(imgLabel); - imgMainLayout->addLayout(mainLayout); - - setLayout(imgMainLayout); - - setWindowTitle(tr("Go to...")); - setModal (true); - - pageNumber->setFocusPolicy(Qt::StrongFocus); - pageNumber->setFocus(); -} - -void GoToDialog::goTo() -{ - unsigned int page = pageNumber->text().toInt(); - pageNumber->clear(); - - if(page >= 1) - emit(goToPage(page-1)); - - close(); - -} - -void GoToDialog::setNumPages(unsigned int numPages) -{ - numPagesLabel->setText(tr("Total pages : ")+QString::number(numPages)); - v->setTop(numPages); -} - -void GoToDialog::open() -{ - pageNumber->setFocus(); - QDialog::open(); -} +#include "goto_dialog.h" + +#include +#include +#include + + + +GoToDialog::GoToDialog(QWidget * parent) +:QDialog(parent) +{ + setupUI(); +} + +void GoToDialog::setupUI() +{ + textLabel = new QLabel(tr("Page : ")); + pageNumber = new QLineEdit; + v = new QIntValidator(this); + v->setBottom(1); + pageNumber->setValidator(v); + textLabel->setBuddy(pageNumber); + textLabel->setAlignment(Qt::AlignRight|Qt::AlignVCenter); + + accept = new QPushButton(tr("Go To")); + connect(accept,SIGNAL(clicked()),this,SLOT(goTo())); + cancel = new QPushButton(tr("Cancel")); + connect(cancel,SIGNAL(clicked()),this,SLOT(close())); + + QHBoxLayout *topLayout = new QHBoxLayout; + + topLayout->addWidget(textLabel); + topLayout->addWidget(pageNumber); + + QHBoxLayout *bottomLayout = new QHBoxLayout; + bottomLayout->addStretch(); + bottomLayout->addWidget(accept); + bottomLayout->addWidget(cancel); + + QVBoxLayout *mainLayout = new QVBoxLayout; + mainLayout->addWidget(numPagesLabel = new QLabel(tr("Total pages : "))); + mainLayout->addLayout(topLayout); + mainLayout->addStretch(); + mainLayout->addLayout(bottomLayout); + + QHBoxLayout *imgMainLayout = new QHBoxLayout; + QLabel * imgLabel = new QLabel(); + QPixmap p(":/images/goto.png"); + imgLabel->setPixmap(p); + imgMainLayout->addWidget(imgLabel); + imgMainLayout->addLayout(mainLayout); + + setLayout(imgMainLayout); + + setWindowTitle(tr("Go to...")); + setModal (true); + + pageNumber->setFocusPolicy(Qt::StrongFocus); + pageNumber->setFocus(); +} + +void GoToDialog::goTo() +{ + unsigned int page = pageNumber->text().toInt(); + pageNumber->clear(); + + if(page >= 1) + emit(goToPage(page-1)); + + close(); + +} + +void GoToDialog::setNumPages(unsigned int numPages) +{ + numPagesLabel->setText(tr("Total pages : ")+QString::number(numPages)); + v->setTop(numPages); +} + +void GoToDialog::open() +{ + pageNumber->setFocus(); + QDialog::open(); +} diff --git a/YACReader/goto_dialog.h b/YACReader/goto_dialog.h index 54253605..bf19444e 100644 --- a/YACReader/goto_dialog.h +++ b/YACReader/goto_dialog.h @@ -1,32 +1,32 @@ -#ifndef __GOTODIALOG_H -#define __GOTODIALOG_H - -#include -#include -#include -#include -#include - - class GoToDialog : public QDialog - { - Q_OBJECT - public: - GoToDialog(QWidget * parent = 0); - private: - QLabel * numPagesLabel; - QLabel * textLabel; - QLineEdit * pageNumber; - QIntValidator * v; - QPushButton * accept; - QPushButton * cancel; - void setupUI(); - public slots: - void goTo(); - void setNumPages(unsigned int numPages); - void open(); - signals: - void goToPage(unsigned int page); - }; - -#endif - +#ifndef __GOTODIALOG_H +#define __GOTODIALOG_H + +#include +#include +#include +#include +#include + + class GoToDialog : public QDialog + { + Q_OBJECT + public: + GoToDialog(QWidget * parent = 0); + private: + QLabel * numPagesLabel; + QLabel * textLabel; + QLineEdit * pageNumber; + QIntValidator * v; + QPushButton * accept; + QPushButton * cancel; + void setupUI(); + public slots: + void goTo(); + void setNumPages(unsigned int numPages); + void open(); + signals: + void goToPage(unsigned int page); + }; + +#endif + diff --git a/YACReader/goto_flow.cpp b/YACReader/goto_flow.cpp index 091924c5..167074de 100644 --- a/YACReader/goto_flow.cpp +++ b/YACReader/goto_flow.cpp @@ -1,322 +1,322 @@ -#include "goto_flow.h" -#include "configuration.h" -#include "comic.h" - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "yacreader_flow.h" - -#include "goto_flow_toolbar.h" - - -GoToFlow::GoToFlow(QWidget *parent,FlowType flowType) - :GoToFlowWidget(parent),ready(false) -{ - updateTimer = new QTimer; - connect(updateTimer, SIGNAL(timeout()), this, SLOT(updateImageData())); - - worker = new PageLoader(&mutexGoToFlow); - - flow = new YACReaderFlow(this,flowType); - flow->setReflectionEffect(PictureFlow::PlainReflection); - imageSize = Configuration::getConfiguration().getGotoSlideSize(); - - flow->setSlideSize(imageSize); - connect(flow,SIGNAL(centerIndexChanged(int)),this,SLOT(setPageNumber(int))); - connect(flow,SIGNAL(selected(unsigned int)),this,SIGNAL(goToPage(unsigned int))); - - connect(toolBar,SIGNAL(goTo(unsigned int)),this,SIGNAL(goToPage(unsigned int))); - connect(toolBar,SIGNAL(setCenter(unsigned int)),flow,SLOT(showSlide(unsigned int))); - - mainLayout->addWidget(flow); - toolBar->raise(); - - resize(static_cast(5*imageSize.width()),toolBar->height() + static_cast(imageSize.height()*1.7)); - - this->setCursor(QCursor(Qt::ArrowCursor)); -} - -GoToFlow::~GoToFlow() -{ - delete flow; - delete updateTimer; - worker->deleteLater(); -} - -void GoToFlow::keyPressEvent(QKeyEvent *event) -{ - switch (event->key()) - { - case Qt::Key_Left: case Qt::Key_Right: case Qt::Key_Up: - QApplication::sendEvent(flow,event); - return; - default: - break; - } - - GoToFlowWidget::keyPressEvent(event); -} - -void GoToFlow::resizeEvent(QResizeEvent *event) -{ - QWidget::resizeEvent(event); - - toolBar->move(0, event->size().height() - toolBar->height()); - toolBar->setFixedWidth(width()); -} - - -void GoToFlow::centerSlide(int slide) -{ - if(flow->centerIndex()!=slide) - { - flow->setCenterIndex(slide); - if(ready)// load images if pages are loaded. - { - //worker->reset(); //BUG FIXED : image didn't load if worker was working - preload(); - } - } -} - -void GoToFlow::setNumSlides(unsigned int slides) -{ - // numPagesLabel->setText(tr("Total pages : ")+QString::number(slides)); - // numPagesLabel->adjustSize(); - imagesReady.clear(); - imagesReady.fill(false,slides); - - rawImages.clear(); - rawImages.resize(slides); - - toolBar->setTop(slides); - - SlideInitializer * si = new SlideInitializer(&mutexGoToFlow,flow,slides); - - imagesLoaded.clear(); - imagesLoaded.fill(false,slides); - - imagesSetted.clear(); - imagesSetted.fill(false,slides); - - numImagesLoaded = 0; - - connect(flow, SIGNAL(centerIndexChanged(int)), this, SLOT(preload())); - connect(flow, SIGNAL(centerIndexChangedSilent(int)), this, SLOT(preload())); - - ready = true; - worker->reset(); - - si->start(); -} - -void GoToFlow::reset() -{ - updateTimer->stop(); - /*imagesLoaded.clear(); - numImagesLoaded = 0; - imagesReady.clear(); - rawImages.clear();*/ - ready = false; -} - -void GoToFlow::setImageReady(int index,const QByteArray & image) -{ - rawImages[index]=image; - imagesReady[index]=true; - preload(); -} - -void GoToFlow::preload() -{ - if(numImagesLoaded < imagesLoaded.size()) - updateTimer->start(30); //TODO comprobar rendimiento, antes era 70 -} - -void GoToFlow::updateImageData() -{ - // can't do anything, wait for the next possibility - if(worker->busy()) - return; - - // set image of last one - int idx = worker->index(); - if( idx >= 0 && !worker->result().isNull()) - { - if(!imagesSetted[idx]) - { - flow->setSlide(idx, worker->result()); - imagesSetted[idx] = true; - numImagesLoaded++; - rawImages[idx].clear();; //release memory - imagesLoaded[idx]=true; - } - - } - - // try to load only few images on the left and right side - // i.e. all visible ones plus some extra -#define COUNT 8 - int indexes[2*COUNT+1]; - int center = flow->centerIndex(); - indexes[0] = center; - for(int j = 0; j < COUNT; j++) - { - indexes[j*2+1] = center+j+1; - indexes[j*2+2] = center-j-1; - } - for(int c = 0; c < 2*COUNT+1; c++) - { - int i = indexes[c]; - if((i >= 0) && (i < flow->slideCount())) - if(!imagesLoaded[i]&&imagesReady[i])//slide(i).isNull()) - { - // schedule thumbnail generation - - worker->generate(i, flow->slideSize(),rawImages[i]); - return; - } - - } - - // no need to generate anything? stop polling... - updateTimer->stop(); -} - -void GoToFlow::wheelEvent(QWheelEvent * event) -{ - if(event->delta()<0) - flow->showNext(); - else - flow->showPrevious(); - event->accept(); -} - -void GoToFlow::setFlowType(FlowType flowType) -{ - flow->setFlowType(flowType); -} - -void GoToFlow::updateConfig(QSettings * settings) -{ - GoToFlowWidget::updateConfig(settings); - - imageSize = Configuration::getConfiguration().getGotoSlideSize(); - flow->setFlowType(Configuration::getConfiguration().getFlowType()); - resize(5*imageSize.width(), toolBar->height() + imageSize.height()*1.7); - updateSize(); -} - -void GoToFlow::setFlowRightToLeft(bool b) -{ - flow->setFlowRightToLeft(b); -} - -//----------------------------------------------------------------------------- -//SlideInitializer -//----------------------------------------------------------------------------- -SlideInitializer::SlideInitializer(QMutex * m,PictureFlow * flow,int slides) - :QThread(),mutex(m),_flow(flow),_slides(slides) -{ - -} -void SlideInitializer::run() -{ - mutex->lock(); - - _flow->clear(); - for(int i=0;i<_slides;i++) - _flow->addSlide(QImage()); - _flow->setCenterIndex(0); - - mutex->unlock(); -} -//----------------------------------------------------------------------------- -//PageLoader -//----------------------------------------------------------------------------- - - -PageLoader::PageLoader(QMutex * m): - QThread(),mutex(m), restart(false), working(false), idx(-1) -{ -} - -PageLoader::~PageLoader() -{ - mutex->lock(); - condition.wakeOne(); - mutex->unlock(); - wait(); -} - -bool PageLoader::busy() const -{ - return isRunning() ? working : false; -} - -void PageLoader::generate(int index, QSize size,const QByteArray & rImage) -{ - mutex->lock(); - this->idx = index; - //this->img = QImage(); - this->size = size; - this->rawImage = rImage; - mutex->unlock(); - - if (!isRunning()) - start(); - else - { - // already running, wake up whenever ready - restart = true; - condition.wakeOne(); - } -} - -void PageLoader::run() -{ - for(;;) - { - // copy necessary data - mutex->lock(); - this->working = true; - //int idx = this->idx; - - - QImage image; - image.loadFromData(this->rawImage); - // let everyone knows it is ready - image = image.scaled(this->size,Qt::KeepAspectRatio,Qt::SmoothTransformation); - - mutex->unlock(); - - mutex->lock(); - this->working = false; - this->img = image; - mutex->unlock(); - - // put to sleep - mutex->lock(); - if (!this->restart) - condition.wait(mutex); - restart = false; - mutex->unlock(); - } -} +#include "goto_flow.h" +#include "configuration.h" +#include "comic.h" + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "yacreader_flow.h" + +#include "goto_flow_toolbar.h" + + +GoToFlow::GoToFlow(QWidget *parent,FlowType flowType) + :GoToFlowWidget(parent),ready(false) +{ + updateTimer = new QTimer; + connect(updateTimer, SIGNAL(timeout()), this, SLOT(updateImageData())); + + worker = new PageLoader(&mutexGoToFlow); + + flow = new YACReaderFlow(this,flowType); + flow->setReflectionEffect(PictureFlow::PlainReflection); + imageSize = Configuration::getConfiguration().getGotoSlideSize(); + + flow->setSlideSize(imageSize); + connect(flow,SIGNAL(centerIndexChanged(int)),this,SLOT(setPageNumber(int))); + connect(flow,SIGNAL(selected(unsigned int)),this,SIGNAL(goToPage(unsigned int))); + + connect(toolBar,SIGNAL(goTo(unsigned int)),this,SIGNAL(goToPage(unsigned int))); + connect(toolBar,SIGNAL(setCenter(unsigned int)),flow,SLOT(showSlide(unsigned int))); + + mainLayout->addWidget(flow); + toolBar->raise(); + + resize(static_cast(5*imageSize.width()),toolBar->height() + static_cast(imageSize.height()*1.7)); + + this->setCursor(QCursor(Qt::ArrowCursor)); +} + +GoToFlow::~GoToFlow() +{ + delete flow; + delete updateTimer; + worker->deleteLater(); +} + +void GoToFlow::keyPressEvent(QKeyEvent *event) +{ + switch (event->key()) + { + case Qt::Key_Left: case Qt::Key_Right: case Qt::Key_Up: + QApplication::sendEvent(flow,event); + return; + default: + break; + } + + GoToFlowWidget::keyPressEvent(event); +} + +void GoToFlow::resizeEvent(QResizeEvent *event) +{ + QWidget::resizeEvent(event); + + toolBar->move(0, event->size().height() - toolBar->height()); + toolBar->setFixedWidth(width()); +} + + +void GoToFlow::centerSlide(int slide) +{ + if(flow->centerIndex()!=slide) + { + flow->setCenterIndex(slide); + if(ready)// load images if pages are loaded. + { + //worker->reset(); //BUG FIXED : image didn't load if worker was working + preload(); + } + } +} + +void GoToFlow::setNumSlides(unsigned int slides) +{ + // numPagesLabel->setText(tr("Total pages : ")+QString::number(slides)); + // numPagesLabel->adjustSize(); + imagesReady.clear(); + imagesReady.fill(false,slides); + + rawImages.clear(); + rawImages.resize(slides); + + toolBar->setTop(slides); + + SlideInitializer * si = new SlideInitializer(&mutexGoToFlow,flow,slides); + + imagesLoaded.clear(); + imagesLoaded.fill(false,slides); + + imagesSetted.clear(); + imagesSetted.fill(false,slides); + + numImagesLoaded = 0; + + connect(flow, SIGNAL(centerIndexChanged(int)), this, SLOT(preload())); + connect(flow, SIGNAL(centerIndexChangedSilent(int)), this, SLOT(preload())); + + ready = true; + worker->reset(); + + si->start(); +} + +void GoToFlow::reset() +{ + updateTimer->stop(); + /*imagesLoaded.clear(); + numImagesLoaded = 0; + imagesReady.clear(); + rawImages.clear();*/ + ready = false; +} + +void GoToFlow::setImageReady(int index,const QByteArray & image) +{ + rawImages[index]=image; + imagesReady[index]=true; + preload(); +} + +void GoToFlow::preload() +{ + if(numImagesLoaded < imagesLoaded.size()) + updateTimer->start(30); //TODO comprobar rendimiento, antes era 70 +} + +void GoToFlow::updateImageData() +{ + // can't do anything, wait for the next possibility + if(worker->busy()) + return; + + // set image of last one + int idx = worker->index(); + if( idx >= 0 && !worker->result().isNull()) + { + if(!imagesSetted[idx]) + { + flow->setSlide(idx, worker->result()); + imagesSetted[idx] = true; + numImagesLoaded++; + rawImages[idx].clear();; //release memory + imagesLoaded[idx]=true; + } + + } + + // try to load only few images on the left and right side + // i.e. all visible ones plus some extra +#define COUNT 8 + int indexes[2*COUNT+1]; + int center = flow->centerIndex(); + indexes[0] = center; + for(int j = 0; j < COUNT; j++) + { + indexes[j*2+1] = center+j+1; + indexes[j*2+2] = center-j-1; + } + for(int c = 0; c < 2*COUNT+1; c++) + { + int i = indexes[c]; + if((i >= 0) && (i < flow->slideCount())) + if(!imagesLoaded[i]&&imagesReady[i])//slide(i).isNull()) + { + // schedule thumbnail generation + + worker->generate(i, flow->slideSize(),rawImages[i]); + return; + } + + } + + // no need to generate anything? stop polling... + updateTimer->stop(); +} + +void GoToFlow::wheelEvent(QWheelEvent * event) +{ + if(event->delta()<0) + flow->showNext(); + else + flow->showPrevious(); + event->accept(); +} + +void GoToFlow::setFlowType(FlowType flowType) +{ + flow->setFlowType(flowType); +} + +void GoToFlow::updateConfig(QSettings * settings) +{ + GoToFlowWidget::updateConfig(settings); + + imageSize = Configuration::getConfiguration().getGotoSlideSize(); + flow->setFlowType(Configuration::getConfiguration().getFlowType()); + resize(5*imageSize.width(), toolBar->height() + imageSize.height()*1.7); + updateSize(); +} + +void GoToFlow::setFlowRightToLeft(bool b) +{ + flow->setFlowRightToLeft(b); +} + +//----------------------------------------------------------------------------- +//SlideInitializer +//----------------------------------------------------------------------------- +SlideInitializer::SlideInitializer(QMutex * m,PictureFlow * flow,int slides) + :QThread(),mutex(m),_flow(flow),_slides(slides) +{ + +} +void SlideInitializer::run() +{ + mutex->lock(); + + _flow->clear(); + for(int i=0;i<_slides;i++) + _flow->addSlide(QImage()); + _flow->setCenterIndex(0); + + mutex->unlock(); +} +//----------------------------------------------------------------------------- +//PageLoader +//----------------------------------------------------------------------------- + + +PageLoader::PageLoader(QMutex * m): + QThread(),mutex(m), restart(false), working(false), idx(-1) +{ +} + +PageLoader::~PageLoader() +{ + mutex->lock(); + condition.wakeOne(); + mutex->unlock(); + wait(); +} + +bool PageLoader::busy() const +{ + return isRunning() ? working : false; +} + +void PageLoader::generate(int index, QSize size,const QByteArray & rImage) +{ + mutex->lock(); + this->idx = index; + //this->img = QImage(); + this->size = size; + this->rawImage = rImage; + mutex->unlock(); + + if (!isRunning()) + start(); + else + { + // already running, wake up whenever ready + restart = true; + condition.wakeOne(); + } +} + +void PageLoader::run() +{ + for(;;) + { + // copy necessary data + mutex->lock(); + this->working = true; + //int idx = this->idx; + + + QImage image; + image.loadFromData(this->rawImage); + // let everyone knows it is ready + image = image.scaled(this->size,Qt::KeepAspectRatio,Qt::SmoothTransformation); + + mutex->unlock(); + + mutex->lock(); + this->working = false; + this->img = image; + mutex->unlock(); + + // put to sleep + mutex->lock(); + if (!this->restart) + condition.wait(mutex); + restart = false; + mutex->unlock(); + } +} diff --git a/YACReader/goto_flow.h b/YACReader/goto_flow.h index be157fa7..337b1ec0 100644 --- a/YACReader/goto_flow.h +++ b/YACReader/goto_flow.h @@ -1,114 +1,114 @@ -#ifndef __GOTO_FLOW_H -#define __GOTO_FLOW_H - -#include "goto_flow_widget.h" -#include "yacreader_global_gui.h" - -#include - -#include -#include - -class QLineEdit; -class QPushButton; -class QPixmap; -class QThread; -class QSize; -class QIntValidator; -class QWaitCondition; -class QEvent; -class QLabel; - - -class Comic; -class SlideInitializer; -class PageLoader; -class YACReaderFlow; -class PictureFlow; -class QKeyEvent; - -class GoToFlow : public GoToFlowWidget -{ - Q_OBJECT -public: - GoToFlow(QWidget* parent = 0,FlowType flowType = CoverFlowLike); - ~GoToFlow(); - bool ready; //comic is ready for read. -private: - YACReaderFlow * flow; - void keyPressEvent(QKeyEvent* event); - //Comic * comic; - QSize imageSize; - - QVector imagesLoaded; - QVector imagesSetted; - int numImagesLoaded; - QVector imagesReady; - QVector rawImages; - QTimer* updateTimer; - PageLoader* worker; - virtual void wheelEvent(QWheelEvent * event); - QMutex mutexGoToFlow; - -private slots: - void preload(); - void updateImageData(); - void resizeEvent(QResizeEvent *event); - - public slots: - void centerSlide(int slide); - void reset(); - void setNumSlides(unsigned int slides); - void setImageReady(int index,const QByteArray & image); - void setFlowType(FlowType flowType); - void updateConfig(QSettings * settings); - void setFlowRightToLeft(bool b); - -signals: - void goToPage(unsigned int page); - -}; -//----------------------------------------------------------------------------- -//SlideInitializer -//----------------------------------------------------------------------------- -class SlideInitializer : public QThread -{ -public: - SlideInitializer(QMutex * m,PictureFlow * flow,int slides); -private: - QMutex * mutex; - PictureFlow * _flow; - int _slides; - void run(); -}; -//----------------------------------------------------------------------------- -//PageLoader -//----------------------------------------------------------------------------- - -class PageLoader : public QThread -{ -public: - PageLoader(QMutex * m); - ~PageLoader(); - // returns FALSE if worker is still busy and can't take the task - bool busy() const; - void generate(int index, QSize size,const QByteArray & rImage); - void reset(){idx = -1;}; - int index() const { return idx; } - QImage result() const { return img; } -protected: - void run(); -private: - QMutex * mutex; - QWaitCondition condition; - - bool restart; - bool working; - int idx; - - QSize size; - QImage img; - QByteArray rawImage; -}; - -#endif +#ifndef __GOTO_FLOW_H +#define __GOTO_FLOW_H + +#include "goto_flow_widget.h" +#include "yacreader_global_gui.h" + +#include + +#include +#include + +class QLineEdit; +class QPushButton; +class QPixmap; +class QThread; +class QSize; +class QIntValidator; +class QWaitCondition; +class QEvent; +class QLabel; + + +class Comic; +class SlideInitializer; +class PageLoader; +class YACReaderFlow; +class PictureFlow; +class QKeyEvent; + +class GoToFlow : public GoToFlowWidget +{ + Q_OBJECT +public: + GoToFlow(QWidget* parent = 0,FlowType flowType = CoverFlowLike); + ~GoToFlow(); + bool ready; //comic is ready for read. +private: + YACReaderFlow * flow; + void keyPressEvent(QKeyEvent* event); + //Comic * comic; + QSize imageSize; + + QVector imagesLoaded; + QVector imagesSetted; + int numImagesLoaded; + QVector imagesReady; + QVector rawImages; + QTimer* updateTimer; + PageLoader* worker; + virtual void wheelEvent(QWheelEvent * event); + QMutex mutexGoToFlow; + +private slots: + void preload(); + void updateImageData(); + void resizeEvent(QResizeEvent *event); + + public slots: + void centerSlide(int slide); + void reset(); + void setNumSlides(unsigned int slides); + void setImageReady(int index,const QByteArray & image); + void setFlowType(FlowType flowType); + void updateConfig(QSettings * settings); + void setFlowRightToLeft(bool b); + +signals: + void goToPage(unsigned int page); + +}; +//----------------------------------------------------------------------------- +//SlideInitializer +//----------------------------------------------------------------------------- +class SlideInitializer : public QThread +{ +public: + SlideInitializer(QMutex * m,PictureFlow * flow,int slides); +private: + QMutex * mutex; + PictureFlow * _flow; + int _slides; + void run(); +}; +//----------------------------------------------------------------------------- +//PageLoader +//----------------------------------------------------------------------------- + +class PageLoader : public QThread +{ +public: + PageLoader(QMutex * m); + ~PageLoader(); + // returns FALSE if worker is still busy and can't take the task + bool busy() const; + void generate(int index, QSize size,const QByteArray & rImage); + void reset(){idx = -1;}; + int index() const { return idx; } + QImage result() const { return img; } +protected: + void run(); +private: + QMutex * mutex; + QWaitCondition condition; + + bool restart; + bool working; + int idx; + + QSize size; + QImage img; + QByteArray rawImage; +}; + +#endif diff --git a/YACReader/goto_flow_gl.cpp b/YACReader/goto_flow_gl.cpp index 80dca124..eca6ec5d 100644 --- a/YACReader/goto_flow_gl.cpp +++ b/YACReader/goto_flow_gl.cpp @@ -1,167 +1,167 @@ -#include "goto_flow_gl.h" - -#include -#include -#include -#include -#include -#include - -#include "configuration.h" - -#include "goto_flow_toolbar.h" - - -GoToFlowGL::GoToFlowGL(QWidget* parent, FlowType flowType) - :GoToFlowWidget(parent) -{ - Q_UNUSED(flowType) - flow = new YACReaderPageFlowGL(this); - flow->setShowMarks(false); - - imageSize = Configuration::getConfiguration().getGotoSlideSize(); - - flow->setSlideSize(imageSize); - connect(flow,SIGNAL(centerIndexChanged(int)),this,SLOT(setPageNumber(int))); - connect(flow,SIGNAL(selected(unsigned int)),this,SIGNAL(goToPage(unsigned int))); - - connect(toolBar,SIGNAL(goTo(unsigned int)),this,SIGNAL(goToPage(unsigned int))); - connect(toolBar,SIGNAL(setCenter(unsigned int)),flow,SLOT(setCenterIndex(unsigned int))); - - mainLayout->addWidget(flow); - toolBar->raise(); - - resize(static_cast(5*imageSize.width()),toolBar->height() + static_cast(imageSize.height()*1.7)); - - this->setCursor(QCursor(Qt::ArrowCursor)); -} - -GoToFlowGL::~GoToFlowGL() -{ - delete flow; -} - -void GoToFlowGL::reset() -{ - flow->reset(); -} - -void GoToFlowGL::centerSlide(int slide) -{ - if(flow->centerIndex()!=slide) - { - flow->setCenterIndex(slide); - } -} - -void GoToFlowGL::setFlowType(FlowType flowType) -{ - if(flowType == CoverFlowLike) - flow->setPreset(presetYACReaderFlowClassicConfig); - else if(flowType == Strip) - flow->setPreset(presetYACReaderFlowStripeConfig); - else if(flowType == StripOverlapped) - flow->setPreset(presetYACReaderFlowOverlappedStripeConfig); - else - flow->setPreset(defaultYACReaderFlowConfig); -} - -void GoToFlowGL::setNumSlides(unsigned int slides) -{ - flow->populate(slides); - toolBar->setTop(slides); -} -void GoToFlowGL::setImageReady(int index,const QByteArray & imageData) -{ - flow->rawImages[index] = imageData; - flow->imagesReady[index] = true; -} - -void GoToFlowGL::updateConfig(QSettings * settings) -{ - GoToFlowWidget::updateConfig(settings); - - Performance performance = medium; - switch (settings->value(PERFORMANCE).toInt()) - { - case 0: - performance = low; - break; - case 1: - performance = medium; - break; - case 2: - performance = high; - break; - case 3: - performance = ultraHigh; - break; - } - - imageSize = Configuration::getConfiguration().getGotoSlideSize(); - resize(5*imageSize.width(), toolBar->height() + imageSize.height()*1.7); - updateSize(); - - flow->setPerformance(performance); - - switch (settings->value(FLOW_TYPE_GL).toInt()) - { - case FlowType::CoverFlowLike: - flow->setPreset(presetYACReaderFlowClassicConfig); - break; - case FlowType::Strip: - flow->setPreset(presetYACReaderFlowStripeConfig); - break; - case FlowType::StripOverlapped: - flow->setPreset(presetYACReaderFlowOverlappedStripeConfig); - break; - case FlowType::Modern: - flow->setPreset(defaultYACReaderFlowConfig); - break; - case FlowType::Roulette: - flow->setPreset(pressetYACReaderFlowDownConfig); - break; - case FlowType::Custom: - flow->setCF_RX(settings->value(X_ROTATION).toInt()); - flow->setCF_Y(settings->value(Y_POSITION).toInt()); - flow->setX_Distance(settings->value(COVER_DISTANCE).toInt()); - flow->setCenter_Distance(settings->value(CENTRAL_DISTANCE).toInt()); - flow->setCF_Z(settings->value(ZOOM_LEVEL).toInt()); - flow->setY_Distance(settings->value(Y_COVER_OFFSET).toInt()); - flow->setZ_Distance(settings->value(Z_COVER_OFFSET).toInt()); - flow->setRotation(settings->value(COVER_ROTATION).toInt()); - flow->setFadeOutDist(settings->value(FADE_OUT_DIST).toInt()); - flow->setLightStrenght(settings->value(LIGHT_STRENGTH).toInt()); - flow->setMaxAngle(settings->value(MAX_ANGLE).toInt()); - break; - } - if (Configuration::getConfiguration().getQuickNaviMode()) - flow->setFadeOutDist(20); -} - -void GoToFlowGL::keyPressEvent(QKeyEvent* event) -{ - switch (event->key()) - { - case Qt::Key_Left: case Qt::Key_Right: case Qt::Key_Up: - QApplication::sendEvent(flow,event); - return; - default: - break; - } - - GoToFlowWidget::keyPressEvent(event); -} - -void GoToFlowGL::resizeEvent(QResizeEvent *event) -{ - QWidget::resizeEvent(event); - - toolBar->move(0, event->size().height() - toolBar->height()); - toolBar->setFixedWidth(width()); -} - -void GoToFlowGL::setFlowRightToLeft(bool b) -{ - flow->setFlowRightToLeft(b); -} +#include "goto_flow_gl.h" + +#include +#include +#include +#include +#include +#include + +#include "configuration.h" + +#include "goto_flow_toolbar.h" + + +GoToFlowGL::GoToFlowGL(QWidget* parent, FlowType flowType) + :GoToFlowWidget(parent) +{ + Q_UNUSED(flowType) + flow = new YACReaderPageFlowGL(this); + flow->setShowMarks(false); + + imageSize = Configuration::getConfiguration().getGotoSlideSize(); + + flow->setSlideSize(imageSize); + connect(flow,SIGNAL(centerIndexChanged(int)),this,SLOT(setPageNumber(int))); + connect(flow,SIGNAL(selected(unsigned int)),this,SIGNAL(goToPage(unsigned int))); + + connect(toolBar,SIGNAL(goTo(unsigned int)),this,SIGNAL(goToPage(unsigned int))); + connect(toolBar,SIGNAL(setCenter(unsigned int)),flow,SLOT(setCenterIndex(unsigned int))); + + mainLayout->addWidget(flow); + toolBar->raise(); + + resize(static_cast(5*imageSize.width()),toolBar->height() + static_cast(imageSize.height()*1.7)); + + this->setCursor(QCursor(Qt::ArrowCursor)); +} + +GoToFlowGL::~GoToFlowGL() +{ + delete flow; +} + +void GoToFlowGL::reset() +{ + flow->reset(); +} + +void GoToFlowGL::centerSlide(int slide) +{ + if(flow->centerIndex()!=slide) + { + flow->setCenterIndex(slide); + } +} + +void GoToFlowGL::setFlowType(FlowType flowType) +{ + if(flowType == CoverFlowLike) + flow->setPreset(presetYACReaderFlowClassicConfig); + else if(flowType == Strip) + flow->setPreset(presetYACReaderFlowStripeConfig); + else if(flowType == StripOverlapped) + flow->setPreset(presetYACReaderFlowOverlappedStripeConfig); + else + flow->setPreset(defaultYACReaderFlowConfig); +} + +void GoToFlowGL::setNumSlides(unsigned int slides) +{ + flow->populate(slides); + toolBar->setTop(slides); +} +void GoToFlowGL::setImageReady(int index,const QByteArray & imageData) +{ + flow->rawImages[index] = imageData; + flow->imagesReady[index] = true; +} + +void GoToFlowGL::updateConfig(QSettings * settings) +{ + GoToFlowWidget::updateConfig(settings); + + Performance performance = medium; + switch (settings->value(PERFORMANCE).toInt()) + { + case 0: + performance = low; + break; + case 1: + performance = medium; + break; + case 2: + performance = high; + break; + case 3: + performance = ultraHigh; + break; + } + + imageSize = Configuration::getConfiguration().getGotoSlideSize(); + resize(5*imageSize.width(), toolBar->height() + imageSize.height()*1.7); + updateSize(); + + flow->setPerformance(performance); + + switch (settings->value(FLOW_TYPE_GL).toInt()) + { + case FlowType::CoverFlowLike: + flow->setPreset(presetYACReaderFlowClassicConfig); + break; + case FlowType::Strip: + flow->setPreset(presetYACReaderFlowStripeConfig); + break; + case FlowType::StripOverlapped: + flow->setPreset(presetYACReaderFlowOverlappedStripeConfig); + break; + case FlowType::Modern: + flow->setPreset(defaultYACReaderFlowConfig); + break; + case FlowType::Roulette: + flow->setPreset(pressetYACReaderFlowDownConfig); + break; + case FlowType::Custom: + flow->setCF_RX(settings->value(X_ROTATION).toInt()); + flow->setCF_Y(settings->value(Y_POSITION).toInt()); + flow->setX_Distance(settings->value(COVER_DISTANCE).toInt()); + flow->setCenter_Distance(settings->value(CENTRAL_DISTANCE).toInt()); + flow->setCF_Z(settings->value(ZOOM_LEVEL).toInt()); + flow->setY_Distance(settings->value(Y_COVER_OFFSET).toInt()); + flow->setZ_Distance(settings->value(Z_COVER_OFFSET).toInt()); + flow->setRotation(settings->value(COVER_ROTATION).toInt()); + flow->setFadeOutDist(settings->value(FADE_OUT_DIST).toInt()); + flow->setLightStrenght(settings->value(LIGHT_STRENGTH).toInt()); + flow->setMaxAngle(settings->value(MAX_ANGLE).toInt()); + break; + } + if (Configuration::getConfiguration().getQuickNaviMode()) + flow->setFadeOutDist(20); +} + +void GoToFlowGL::keyPressEvent(QKeyEvent* event) +{ + switch (event->key()) + { + case Qt::Key_Left: case Qt::Key_Right: case Qt::Key_Up: + QApplication::sendEvent(flow,event); + return; + default: + break; + } + + GoToFlowWidget::keyPressEvent(event); +} + +void GoToFlowGL::resizeEvent(QResizeEvent *event) +{ + QWidget::resizeEvent(event); + + toolBar->move(0, event->size().height() - toolBar->height()); + toolBar->setFixedWidth(width()); +} + +void GoToFlowGL::setFlowRightToLeft(bool b) +{ + flow->setFlowRightToLeft(b); +} diff --git a/YACReader/goto_flow_gl.h b/YACReader/goto_flow_gl.h index 1feca85d..c111bc40 100644 --- a/YACReader/goto_flow_gl.h +++ b/YACReader/goto_flow_gl.h @@ -1,40 +1,40 @@ -#ifndef __GOTO_FLOW_GL_H -#define __GOTO_FLOW_GL_H - -#include "yacreader_global.h" -#include "goto_flow_widget.h" -#include "yacreader_flow_gl.h" - -class QLineEdit; -class QIntValidator; -class QPushButton; -class QPushButton; -class QSize; -class QKeyEvent; - -class GoToFlowGL : public GoToFlowWidget -{ - Q_OBJECT -public: - GoToFlowGL(QWidget* parent = 0,FlowType flowType = CoverFlowLike); - ~GoToFlowGL(); - void reset(); - void centerSlide(int slide); - void setFlowType(FlowType flowType); - void setNumSlides(unsigned int slides); - void setImageReady(int index,const QByteArray & image); - - void updateConfig(QSettings * settings); - void setFlowRightToLeft(bool b); - -signals: - void goToPage(unsigned int page); -private: - YACReaderPageFlowGL * flow; - void keyPressEvent(QKeyEvent* event); - void resizeEvent(QResizeEvent *event); - //Comic * comic; - QSize imageSize; -}; - -#endif +#ifndef __GOTO_FLOW_GL_H +#define __GOTO_FLOW_GL_H + +#include "yacreader_global.h" +#include "goto_flow_widget.h" +#include "yacreader_flow_gl.h" + +class QLineEdit; +class QIntValidator; +class QPushButton; +class QPushButton; +class QSize; +class QKeyEvent; + +class GoToFlowGL : public GoToFlowWidget +{ + Q_OBJECT +public: + GoToFlowGL(QWidget* parent = 0,FlowType flowType = CoverFlowLike); + ~GoToFlowGL(); + void reset(); + void centerSlide(int slide); + void setFlowType(FlowType flowType); + void setNumSlides(unsigned int slides); + void setImageReady(int index,const QByteArray & image); + + void updateConfig(QSettings * settings); + void setFlowRightToLeft(bool b); + +signals: + void goToPage(unsigned int page); +private: + YACReaderPageFlowGL * flow; + void keyPressEvent(QKeyEvent* event); + void resizeEvent(QResizeEvent *event); + //Comic * comic; + QSize imageSize; +}; + +#endif diff --git a/YACReader/goto_flow_toolbar.cpp b/YACReader/goto_flow_toolbar.cpp index 94fa576a..0a465fee 100644 --- a/YACReader/goto_flow_toolbar.cpp +++ b/YACReader/goto_flow_toolbar.cpp @@ -1,132 +1,132 @@ -#include "goto_flow_toolbar.h" - -#include - -#include "configuration.h" - -GoToFlowToolBar::GoToFlowToolBar(QWidget * parent) - :QStackedWidget(parent) -{ - //elementos interactivos - QWidget * normal = new QWidget(this); // container widget - QWidget * quickNavi = new QWidget(this); // container widget - addWidget(normal); - addWidget(quickNavi); - QHBoxLayout * normalLayout = new QHBoxLayout(normal); - QHBoxLayout * naviLayout = new QHBoxLayout(quickNavi); - normal->setLayout(normalLayout); - quickNavi->setLayout(naviLayout); - - slider = new QSlider(Qt::Horizontal,this); - slider->setStyleSheet( - "QSlider::groove:horizontal {" - " border: 1px solid #22FFFFFF;" - " border-radius: 1px;" - " background: #77000000;" - " margin: 2px 0;" - " padding: 1px;" - "}" - "QSlider::handle:horizontal {" - " background: #55FFFFFF;" - " width: 48px;" - " border-radius: 1px;" - "}" - ); - - connect(slider, &QSlider::valueChanged, this, [&](int v) { emit(setCenter(v)); }); - - pageHint = new QLabel("" + tr("Page : ") + "",this); - v = new QIntValidator(this); - v->setBottom(1); - edit = new QLineEdit(this); - edit->setValidator(v); - edit->setAlignment(Qt::AlignRight|Qt::AlignVCenter); - edit->setStyleSheet("QLineEdit {border: 1px solid #77000000; background: #55000000; color: white; padding: 3px 5px 5px 5px; margin: 13px 5px 12px 5px; font-weight:bold}"); - QPixmap p(":/images/imgEdit.png"); - edit->setFixedSize(54,50); - edit->setAttribute(Qt::WA_MacShowFocusRect,false); - //edit->setAttribute(Qt::WA_LayoutUsesWidgetRect,true); - //edit->resize(QSize(54,50)); - edit->setSizePolicy(QSizePolicy(QSizePolicy::Fixed,QSizePolicy::Fixed)); - //edit->setAutoFillBackground(false); - connect(edit,SIGNAL(returnPressed()),this,SLOT(goTo())); - - QString centerButtonCSS = "QPushButton {background-image: url(:/images/imgCenterSlide.png); width: 100%; height:100%; background-repeat: none; border: none;} " - "QPushButton:focus { border: none; outline: none;}" - "QPushButton:pressed {background-image: url(:/images/imgCenterSlidePressed.png); width: 100%; height:100%; background-repeat: none; border: none;} "; - centerButton = new QPushButton(this); - //centerButton->setIcon(QIcon(":/images/center.png")); - centerButton->setStyleSheet(centerButtonCSS); - centerButton->setFixedSize(26,50); - centerButton->setAttribute(Qt::WA_LayoutUsesWidgetRect,true); - connect(centerButton,SIGNAL(clicked()),this,SLOT(centerSlide())); - - QString goToButtonCSS = "QPushButton {background-image: url(:/images/imgGoToSlide.png); width: 100%; height:100%; background-repeat: none; border: none;} " - "QPushButton:focus { border: none; outline: none;}" - "QPushButton:pressed {background-image: url(:/images/imgGoToSlidePressed.png); width: 100%; height:100%; background-repeat: none; border: none;} "; - goToButton = new QPushButton(this); - //goToButton->setIcon(QIcon(":/images/goto.png")); - goToButton->setStyleSheet(goToButtonCSS); - goToButton->setFixedSize(32,50); - goToButton->setAttribute(Qt::WA_LayoutUsesWidgetRect,true); - - connect(goToButton,SIGNAL(clicked()),this,SLOT(goTo())); - - normalLayout->setMargin(0); - normalLayout->setSpacing(0); - normalLayout->addStretch(); - normalLayout->addWidget(pageHint); - normalLayout->addWidget(edit); - normalLayout->addWidget(centerButton); - normalLayout->addWidget(goToButton); - normalLayout->addStretch(); - - naviLayout->setContentsMargins(5, 0, 0, 0); - naviLayout->setSpacing(2); - naviLayout->addWidget(slider); - naviLayout->addWidget(goToButton); - - updateOptions(); - - setFixedHeight(50); -} - -void GoToFlowToolBar::paintEvent(QPaintEvent *) -{ - QPainter painter(this); - painter.fillRect(0,0,width(),height(),QColor("#99000000")); -} - -void GoToFlowToolBar::setPage(int pageNumber) -{ - edit->setText(QString::number(pageNumber+1)); - slider->setValue(pageNumber); -} - -void GoToFlowToolBar::setTop(int numPages) -{ - v->setTop(numPages); - slider->setMaximum(numPages-1); // min is 0 -} - -void GoToFlowToolBar::goTo() -{ - if(edit->text().toInt()!=0) - emit(goTo(edit->text().toInt()-1)); -} - -void GoToFlowToolBar::centerSlide() -{ - if(edit->text().toInt()!=0) - emit(setCenter(edit->text().toInt()-1)); -} - -void GoToFlowToolBar::updateOptions() -{ - if (Configuration::getConfiguration().getQuickNaviMode()) - setCurrentIndex(1); - else - setCurrentIndex(0); - - slider->setInvertedAppearance(Configuration::getConfiguration().getDoubleMangaPage()); -} +#include "goto_flow_toolbar.h" + +#include + +#include "configuration.h" + +GoToFlowToolBar::GoToFlowToolBar(QWidget * parent) + :QStackedWidget(parent) +{ + //elementos interactivos + QWidget * normal = new QWidget(this); // container widget + QWidget * quickNavi = new QWidget(this); // container widget + addWidget(normal); + addWidget(quickNavi); + QHBoxLayout * normalLayout = new QHBoxLayout(normal); + QHBoxLayout * naviLayout = new QHBoxLayout(quickNavi); + normal->setLayout(normalLayout); + quickNavi->setLayout(naviLayout); + + slider = new QSlider(Qt::Horizontal,this); + slider->setStyleSheet( + "QSlider::groove:horizontal {" + " border: 1px solid #22FFFFFF;" + " border-radius: 1px;" + " background: #77000000;" + " margin: 2px 0;" + " padding: 1px;" + "}" + "QSlider::handle:horizontal {" + " background: #55FFFFFF;" + " width: 48px;" + " border-radius: 1px;" + "}" + ); + + connect(slider, &QSlider::valueChanged, this, [&](int v) { emit(setCenter(v)); }); + + pageHint = new QLabel("" + tr("Page : ") + "",this); + v = new QIntValidator(this); + v->setBottom(1); + edit = new QLineEdit(this); + edit->setValidator(v); + edit->setAlignment(Qt::AlignRight|Qt::AlignVCenter); + edit->setStyleSheet("QLineEdit {border: 1px solid #77000000; background: #55000000; color: white; padding: 3px 5px 5px 5px; margin: 13px 5px 12px 5px; font-weight:bold}"); + QPixmap p(":/images/imgEdit.png"); + edit->setFixedSize(54,50); + edit->setAttribute(Qt::WA_MacShowFocusRect,false); + //edit->setAttribute(Qt::WA_LayoutUsesWidgetRect,true); + //edit->resize(QSize(54,50)); + edit->setSizePolicy(QSizePolicy(QSizePolicy::Fixed,QSizePolicy::Fixed)); + //edit->setAutoFillBackground(false); + connect(edit,SIGNAL(returnPressed()),this,SLOT(goTo())); + + QString centerButtonCSS = "QPushButton {background-image: url(:/images/imgCenterSlide.png); width: 100%; height:100%; background-repeat: none; border: none;} " + "QPushButton:focus { border: none; outline: none;}" + "QPushButton:pressed {background-image: url(:/images/imgCenterSlidePressed.png); width: 100%; height:100%; background-repeat: none; border: none;} "; + centerButton = new QPushButton(this); + //centerButton->setIcon(QIcon(":/images/center.png")); + centerButton->setStyleSheet(centerButtonCSS); + centerButton->setFixedSize(26,50); + centerButton->setAttribute(Qt::WA_LayoutUsesWidgetRect,true); + connect(centerButton,SIGNAL(clicked()),this,SLOT(centerSlide())); + + QString goToButtonCSS = "QPushButton {background-image: url(:/images/imgGoToSlide.png); width: 100%; height:100%; background-repeat: none; border: none;} " + "QPushButton:focus { border: none; outline: none;}" + "QPushButton:pressed {background-image: url(:/images/imgGoToSlidePressed.png); width: 100%; height:100%; background-repeat: none; border: none;} "; + goToButton = new QPushButton(this); + //goToButton->setIcon(QIcon(":/images/goto.png")); + goToButton->setStyleSheet(goToButtonCSS); + goToButton->setFixedSize(32,50); + goToButton->setAttribute(Qt::WA_LayoutUsesWidgetRect,true); + + connect(goToButton,SIGNAL(clicked()),this,SLOT(goTo())); + + normalLayout->setMargin(0); + normalLayout->setSpacing(0); + normalLayout->addStretch(); + normalLayout->addWidget(pageHint); + normalLayout->addWidget(edit); + normalLayout->addWidget(centerButton); + normalLayout->addWidget(goToButton); + normalLayout->addStretch(); + + naviLayout->setContentsMargins(5, 0, 0, 0); + naviLayout->setSpacing(2); + naviLayout->addWidget(slider); + naviLayout->addWidget(goToButton); + + updateOptions(); + + setFixedHeight(50); +} + +void GoToFlowToolBar::paintEvent(QPaintEvent *) +{ + QPainter painter(this); + painter.fillRect(0,0,width(),height(),QColor("#99000000")); +} + +void GoToFlowToolBar::setPage(int pageNumber) +{ + edit->setText(QString::number(pageNumber+1)); + slider->setValue(pageNumber); +} + +void GoToFlowToolBar::setTop(int numPages) +{ + v->setTop(numPages); + slider->setMaximum(numPages-1); // min is 0 +} + +void GoToFlowToolBar::goTo() +{ + if(edit->text().toInt()!=0) + emit(goTo(edit->text().toInt()-1)); +} + +void GoToFlowToolBar::centerSlide() +{ + if(edit->text().toInt()!=0) + emit(setCenter(edit->text().toInt()-1)); +} + +void GoToFlowToolBar::updateOptions() +{ + if (Configuration::getConfiguration().getQuickNaviMode()) + setCurrentIndex(1); + else + setCurrentIndex(0); + + slider->setInvertedAppearance(Configuration::getConfiguration().getDoubleMangaPage()); +} diff --git a/YACReader/goto_flow_toolbar.h b/YACReader/goto_flow_toolbar.h index 91a9270a..2a772dc8 100644 --- a/YACReader/goto_flow_toolbar.h +++ b/YACReader/goto_flow_toolbar.h @@ -1,40 +1,40 @@ -#ifndef GOTO_FLOW_TOOLBAR_H -#define GOTO_FLOW_TOOLBAR_H - -#include -#include - -class QLineEdit; -class QIntValidator; -class QPushButton; -class QSlider; -class QLabel; - -class GoToFlowToolBar : public QStackedWidget -{ - Q_OBJECT - private: - QLineEdit * edit; - QSlider * slider; - QIntValidator * v; - QPushButton * centerButton; - QPushButton * goToButton; - QLabel * pageHint; - QWidget * bar; - void paintEvent(QPaintEvent *); - - public: - GoToFlowToolBar(QWidget * parent = 0); - - public slots: - void setPage(int pageNumber); - void setTop(int numPages); - void goTo(); - void centerSlide(); - void updateOptions(); - signals: - void setCenter(unsigned int); - void goTo(unsigned int); -}; - -#endif +#ifndef GOTO_FLOW_TOOLBAR_H +#define GOTO_FLOW_TOOLBAR_H + +#include +#include + +class QLineEdit; +class QIntValidator; +class QPushButton; +class QSlider; +class QLabel; + +class GoToFlowToolBar : public QStackedWidget +{ + Q_OBJECT + private: + QLineEdit * edit; + QSlider * slider; + QIntValidator * v; + QPushButton * centerButton; + QPushButton * goToButton; + QLabel * pageHint; + QWidget * bar; + void paintEvent(QPaintEvent *); + + public: + GoToFlowToolBar(QWidget * parent = 0); + + public slots: + void setPage(int pageNumber); + void setTop(int numPages); + void goTo(); + void centerSlide(); + void updateOptions(); + signals: + void setCenter(unsigned int); + void goTo(unsigned int); +}; + +#endif diff --git a/YACReader/goto_flow_widget.cpp b/YACReader/goto_flow_widget.cpp index acb31468..2b31fa58 100644 --- a/YACReader/goto_flow_widget.cpp +++ b/YACReader/goto_flow_widget.cpp @@ -1,81 +1,81 @@ -#include "goto_flow_widget.h" - -#include -#include -#include -#include - -#include "goto_flow_toolbar.h" -#include "configuration.h" - -GoToFlowWidget::GoToFlowWidget(QWidget * parent) - :QWidget(parent) -{ - mainLayout = new QVBoxLayout; - mainLayout->setMargin(0); - mainLayout->setSpacing(0); - - toolBar = new GoToFlowToolBar(this); - - setLayout(mainLayout); - - //toolBar->installEventFilter(this); -} - -GoToFlowWidget::~GoToFlowWidget() { - delete toolBar; - delete mainLayout; -} - -void GoToFlowWidget::setPageNumber(int page) -{ - toolBar->setPage(page); -} - -void GoToFlowWidget::keyPressEvent(QKeyEvent* event) -{ - switch (event->key()) - { - case Qt::Key_Return: case Qt::Key_Enter: - toolBar->goTo(); - toolBar->centerSlide(); - break; - case Qt::Key_Space: - toolBar->centerSlide(); - break; - case Qt::Key_S: - QCoreApplication::sendEvent(this->parent(),event); - break; - } - - event->accept(); -} - -void GoToFlowWidget::updateConfig(QSettings * settings) -{ - Q_UNUSED(settings) - toolBar->updateOptions(); -} - -void GoToFlowWidget::updateSize() -{ - // called by parent in resizeEvent - // no need to update width when QuickNaviMode disabled - // height is set in updateConfig - if (Configuration::getConfiguration().getQuickNaviMode() && parentWidget() != nullptr) - resize(parentWidget()->width(),height()); -} - -/*bool GoToFlowWidget::eventFilter(QObject * target, QEvent * event) -{ - if(event->type() == QEvent::KeyPress) - { - QKeyEvent * e = static_cast(event); - if(e->key()==Qt::Key_S || e->key() == Qt::Key_Space) - { - this->keyPressEvent(e); - return true; - } - } - return QWidget::eventFilter(target,event); -}*/ +#include "goto_flow_widget.h" + +#include +#include +#include +#include + +#include "goto_flow_toolbar.h" +#include "configuration.h" + +GoToFlowWidget::GoToFlowWidget(QWidget * parent) + :QWidget(parent) +{ + mainLayout = new QVBoxLayout; + mainLayout->setMargin(0); + mainLayout->setSpacing(0); + + toolBar = new GoToFlowToolBar(this); + + setLayout(mainLayout); + + //toolBar->installEventFilter(this); +} + +GoToFlowWidget::~GoToFlowWidget() { + delete toolBar; + delete mainLayout; +} + +void GoToFlowWidget::setPageNumber(int page) +{ + toolBar->setPage(page); +} + +void GoToFlowWidget::keyPressEvent(QKeyEvent* event) +{ + switch (event->key()) + { + case Qt::Key_Return: case Qt::Key_Enter: + toolBar->goTo(); + toolBar->centerSlide(); + break; + case Qt::Key_Space: + toolBar->centerSlide(); + break; + case Qt::Key_S: + QCoreApplication::sendEvent(this->parent(),event); + break; + } + + event->accept(); +} + +void GoToFlowWidget::updateConfig(QSettings * settings) +{ + Q_UNUSED(settings) + toolBar->updateOptions(); +} + +void GoToFlowWidget::updateSize() +{ + // called by parent in resizeEvent + // no need to update width when QuickNaviMode disabled + // height is set in updateConfig + if (Configuration::getConfiguration().getQuickNaviMode() && parentWidget() != nullptr) + resize(parentWidget()->width(),height()); +} + +/*bool GoToFlowWidget::eventFilter(QObject * target, QEvent * event) +{ + if(event->type() == QEvent::KeyPress) + { + QKeyEvent * e = static_cast(event); + if(e->key()==Qt::Key_S || e->key() == Qt::Key_Space) + { + this->keyPressEvent(e); + return true; + } + } + return QWidget::eventFilter(target,event); +}*/ diff --git a/YACReader/goto_flow_widget.h b/YACReader/goto_flow_widget.h index a981fa2c..8e95f930 100644 --- a/YACReader/goto_flow_widget.h +++ b/YACReader/goto_flow_widget.h @@ -1,40 +1,40 @@ -#ifndef __GOTO_FLOW_WIDGET_H -#define __GOTO_FLOW_WIDGET_H - -#include -#include -#include "yacreader_global_gui.h" - -using namespace YACReader; - -class QSettings; -class GoToFlowToolBar; -class QVBoxLayout; - -class GoToFlowWidget : public QWidget -{ - Q_OBJECT -protected: - QVBoxLayout * mainLayout; - GoToFlowToolBar * toolBar; -public: - GoToFlowWidget(QWidget * paret = 0); - virtual ~GoToFlowWidget() = 0; -public slots: - virtual void reset() = 0; - virtual void centerSlide(int slide) = 0; - virtual void setPageNumber(int page); - virtual void setFlowType(FlowType flowType) = 0; - virtual void setNumSlides(unsigned int slides) = 0; - virtual void setImageReady(int index,const QByteArray & image) = 0; - virtual void updateSize(); - virtual void updateConfig(QSettings * settings); - virtual void setFlowRightToLeft(bool b) = 0; - -protected: - void keyPressEvent(QKeyEvent* event); - //bool eventFilter(QObject *, QEvent *); - -}; - -#endif +#ifndef __GOTO_FLOW_WIDGET_H +#define __GOTO_FLOW_WIDGET_H + +#include +#include +#include "yacreader_global_gui.h" + +using namespace YACReader; + +class QSettings; +class GoToFlowToolBar; +class QVBoxLayout; + +class GoToFlowWidget : public QWidget +{ + Q_OBJECT +protected: + QVBoxLayout * mainLayout; + GoToFlowToolBar * toolBar; +public: + GoToFlowWidget(QWidget * paret = 0); + virtual ~GoToFlowWidget() = 0; +public slots: + virtual void reset() = 0; + virtual void centerSlide(int slide) = 0; + virtual void setPageNumber(int page); + virtual void setFlowType(FlowType flowType) = 0; + virtual void setNumSlides(unsigned int slides) = 0; + virtual void setImageReady(int index,const QByteArray & image) = 0; + virtual void updateSize(); + virtual void updateConfig(QSettings * settings); + virtual void setFlowRightToLeft(bool b) = 0; + +protected: + void keyPressEvent(QKeyEvent* event); + //bool eventFilter(QObject *, QEvent *); + +}; + +#endif diff --git a/YACReader/magnifying_glass.cpp b/YACReader/magnifying_glass.cpp index c86f202e..1f0404fb 100644 --- a/YACReader/magnifying_glass.cpp +++ b/YACReader/magnifying_glass.cpp @@ -1,292 +1,292 @@ -#include "magnifying_glass.h" -#include "viewer.h" -#include "configuration.h" -#include "shortcuts_manager.h" - -#include - -MagnifyingGlass::MagnifyingGlass(int w, int h, QWidget * parent) -:QLabel(parent),zoomLevel(0.5) -{ - setup(QSize(w,h)); -} - -MagnifyingGlass::MagnifyingGlass(const QSize & size, QWidget * parent) -:QLabel(parent),zoomLevel(0.5) -{ - setup(size); -} - -void MagnifyingGlass::setup(const QSize & size) -{ - resize(size); - setScaledContents(true); - setMouseTracking(true); - setCursor(QCursor(QBitmap(1,1),QBitmap(1,1))); -} - -void MagnifyingGlass::mouseMoveEvent(QMouseEvent * event) -{ - updateImage(); - event->accept(); -} - -void MagnifyingGlass::updateImage(int x, int y) -{ - //image section augmented - int zoomWidth = static_cast(width() * zoomLevel); - int zoomHeight = static_cast(height() * zoomLevel); - Viewer * p = (Viewer *)parent(); - int currentPos = p->verticalScrollBar()->sliderPosition(); - const QPixmap * image = p->pixmap(); - int iWidth = image->width(); - int iHeight = image->height(); - float wFactor = static_cast(iWidth) / p->widget()->width(); - float hFactor = static_cast(iHeight) / p->widget()->height(); - zoomWidth *= wFactor; - zoomHeight *= hFactor; - if(p->verticalScrollBar()->minimum()==p->verticalScrollBar()->maximum()) - { - int xp = static_cast(((x-p->widget()->pos().x())*wFactor)-zoomWidth/2); - int yp = static_cast((y-p->widget()->pos().y()+currentPos)*hFactor-zoomHeight/2); - int xOffset=0; - int yOffset=0; - int zw=zoomWidth; - int zh=zoomHeight; - //int wOffset,hOffset=0; - bool outImage = false; - if(xp<0) - { - xOffset = -xp; - xp=0; - zw = zw - xOffset; - outImage = true; - } - if(yp<0) - { - yOffset = -yp; - yp=0; - zh = zh - yOffset; - outImage = true; - } - - if(xp+zoomWidth >= image->width()) - { - zw -= xp+zw - image->width(); - outImage = true; - } - if(yp+zoomHeight >= image->height()) - { - zh -= yp+zh - image->height(); - outImage = true; - } - if(outImage) - { - QImage img(zoomWidth,zoomHeight,QImage::Format_RGB32); - img.fill(Configuration::getConfiguration().getBackgroundColor()); - if(zw>0&&zh>0) - { - QPainter painter(&img); - painter.drawPixmap(xOffset,yOffset,p->pixmap()->copy(xp,yp,zw,zh)); - } - setPixmap(QPixmap().fromImage(img)); - } - else - setPixmap(p->pixmap()->copy(xp,yp,zoomWidth,zoomHeight)); - } - else - { - int xp = static_cast(((x-p->widget()->pos().x())*wFactor)-zoomWidth/2); - int yp = static_cast((y+currentPos)*hFactor-zoomHeight/2); - int xOffset=0; - int yOffset=0; - int zw=zoomWidth; - int zh=zoomHeight; - //int wOffset,hOffset=0; - bool outImage = false; - if(xp<0) - { - xOffset = -xp; - xp=0; - zw = zw - xOffset; - outImage = true; - } - if(yp<0) - { - yOffset = -yp; - yp=0; - zh = zh - yOffset; - outImage = true; - } - - if(xp+zoomWidth >= image->width()) - { - zw -= xp+zw - image->width(); - outImage = true; - } - if(yp+zoomHeight >= image->height()) - { - zh -= yp+zh - image->height(); - outImage = true; - } - if(outImage) - { - QImage img(zoomWidth,zoomHeight,QImage::Format_RGB32); - img.fill(Configuration::getConfiguration().getBackgroundColor()); - if(zw>0&&zh>0) - { - QPainter painter(&img); - painter.drawPixmap(xOffset,yOffset,p->pixmap()->copy(xp,yp,zw,zh)); - } - setPixmap(QPixmap().fromImage(img)); - } - else - setPixmap(p->pixmap()->copy(xp,yp,zoomWidth,zoomHeight)); - } - move(static_cast(x-float(width())/2),static_cast(y-float(height())/2)); -} - -void MagnifyingGlass::updateImage() -{ - if(isVisible()) - { - QPoint p = QPoint(cursor().pos().x(),cursor().pos().y()); - p = this->parentWidget()->mapFromGlobal(p); - updateImage(p.x(),p.y()); - } -} -void MagnifyingGlass::wheelEvent(QWheelEvent * event) -{ - switch(event->modifiers()) - { - //size - case Qt::NoModifier: - if(event->delta()<0) - sizeUp(); - else - sizeDown(); - break; - //size height - case Qt::ControlModifier: - if(event->delta()<0) - heightUp(); - else - heightDown(); - break; - //size width - case Qt::AltModifier: - if(event->delta()<0) - widthUp(); - else - widthDown(); - break; - //zoom level - case Qt::ShiftModifier: - if(event->delta()<0) - zoomIn(); - else - zoomOut(); - break; - } - updateImage(); - event->setAccepted(true); -} -void MagnifyingGlass::zoomIn() -{ - if(zoomLevel>0.2f) - zoomLevel -= 0.025f; -} - -void MagnifyingGlass::zoomOut() -{ - if(zoomLevel<0.9f) - zoomLevel += 0.025f; -} - -void MagnifyingGlass::sizeUp() -{ - Viewer * p = (Viewer *)parent(); - if(width()<(p->width()*0.90f)) - resize(width()+30,height()+15); -} - -void MagnifyingGlass::sizeDown() -{ - if(width()>175) - resize(width()-30,height()-15); -} - -void MagnifyingGlass::heightUp() -{ - Viewer * p = (Viewer *)parent(); - if(height()<(p->height()*0.90f)) - resize(width(),height()+15); -} - -void MagnifyingGlass::heightDown() -{ - if(height()>80) - resize(width(),height()-15); -} - -void MagnifyingGlass::widthUp() -{ - Viewer * p = (Viewer *)parent(); - if(width()<(p->width()*0.90f)) - resize(width()+30,height()); -} - -void MagnifyingGlass::widthDown() -{ - if(width()>175) - resize(width()-30,height()); -} - -void MagnifyingGlass::keyPressEvent(QKeyEvent *event) -{ - bool validKey = false; - - int _key = event->key(); - Qt::KeyboardModifiers modifiers = event->modifiers(); - - if(modifiers & Qt::ShiftModifier) - _key |= Qt::SHIFT; - if (modifiers & Qt::ControlModifier) - _key |= Qt::CTRL; - if (modifiers & Qt::MetaModifier) - _key |= Qt::META; - if (modifiers & Qt::AltModifier) - _key |= Qt::ALT; - - QKeySequence key(_key); - - if (key == ShortcutsManager::getShortcutsManager().getShortcut(SIZE_UP_MGLASS_ACTION_Y)) - { - sizeUp(); - validKey = true; - } - - else if (key == ShortcutsManager::getShortcutsManager().getShortcut(SIZE_DOWN_MGLASS_ACTION_Y)) - { - sizeDown(); - validKey = true; - } - - else if (key == ShortcutsManager::getShortcutsManager().getShortcut(ZOOM_IN_MGLASS_ACTION_Y)) - { - zoomIn(); - validKey = true; - } - - else if (key == ShortcutsManager::getShortcutsManager().getShortcut(ZOOM_OUT_MGLASS_ACTION_Y)) - { - zoomOut(); - validKey = true; - } - - if(validKey) - { - updateImage(); - event->setAccepted(true); - } -} +#include "magnifying_glass.h" +#include "viewer.h" +#include "configuration.h" +#include "shortcuts_manager.h" + +#include + +MagnifyingGlass::MagnifyingGlass(int w, int h, QWidget * parent) +:QLabel(parent),zoomLevel(0.5) +{ + setup(QSize(w,h)); +} + +MagnifyingGlass::MagnifyingGlass(const QSize & size, QWidget * parent) +:QLabel(parent),zoomLevel(0.5) +{ + setup(size); +} + +void MagnifyingGlass::setup(const QSize & size) +{ + resize(size); + setScaledContents(true); + setMouseTracking(true); + setCursor(QCursor(QBitmap(1,1),QBitmap(1,1))); +} + +void MagnifyingGlass::mouseMoveEvent(QMouseEvent * event) +{ + updateImage(); + event->accept(); +} + +void MagnifyingGlass::updateImage(int x, int y) +{ + //image section augmented + int zoomWidth = static_cast(width() * zoomLevel); + int zoomHeight = static_cast(height() * zoomLevel); + Viewer * p = (Viewer *)parent(); + int currentPos = p->verticalScrollBar()->sliderPosition(); + const QPixmap * image = p->pixmap(); + int iWidth = image->width(); + int iHeight = image->height(); + float wFactor = static_cast(iWidth) / p->widget()->width(); + float hFactor = static_cast(iHeight) / p->widget()->height(); + zoomWidth *= wFactor; + zoomHeight *= hFactor; + if(p->verticalScrollBar()->minimum()==p->verticalScrollBar()->maximum()) + { + int xp = static_cast(((x-p->widget()->pos().x())*wFactor)-zoomWidth/2); + int yp = static_cast((y-p->widget()->pos().y()+currentPos)*hFactor-zoomHeight/2); + int xOffset=0; + int yOffset=0; + int zw=zoomWidth; + int zh=zoomHeight; + //int wOffset,hOffset=0; + bool outImage = false; + if(xp<0) + { + xOffset = -xp; + xp=0; + zw = zw - xOffset; + outImage = true; + } + if(yp<0) + { + yOffset = -yp; + yp=0; + zh = zh - yOffset; + outImage = true; + } + + if(xp+zoomWidth >= image->width()) + { + zw -= xp+zw - image->width(); + outImage = true; + } + if(yp+zoomHeight >= image->height()) + { + zh -= yp+zh - image->height(); + outImage = true; + } + if(outImage) + { + QImage img(zoomWidth,zoomHeight,QImage::Format_RGB32); + img.fill(Configuration::getConfiguration().getBackgroundColor()); + if(zw>0&&zh>0) + { + QPainter painter(&img); + painter.drawPixmap(xOffset,yOffset,p->pixmap()->copy(xp,yp,zw,zh)); + } + setPixmap(QPixmap().fromImage(img)); + } + else + setPixmap(p->pixmap()->copy(xp,yp,zoomWidth,zoomHeight)); + } + else + { + int xp = static_cast(((x-p->widget()->pos().x())*wFactor)-zoomWidth/2); + int yp = static_cast((y+currentPos)*hFactor-zoomHeight/2); + int xOffset=0; + int yOffset=0; + int zw=zoomWidth; + int zh=zoomHeight; + //int wOffset,hOffset=0; + bool outImage = false; + if(xp<0) + { + xOffset = -xp; + xp=0; + zw = zw - xOffset; + outImage = true; + } + if(yp<0) + { + yOffset = -yp; + yp=0; + zh = zh - yOffset; + outImage = true; + } + + if(xp+zoomWidth >= image->width()) + { + zw -= xp+zw - image->width(); + outImage = true; + } + if(yp+zoomHeight >= image->height()) + { + zh -= yp+zh - image->height(); + outImage = true; + } + if(outImage) + { + QImage img(zoomWidth,zoomHeight,QImage::Format_RGB32); + img.fill(Configuration::getConfiguration().getBackgroundColor()); + if(zw>0&&zh>0) + { + QPainter painter(&img); + painter.drawPixmap(xOffset,yOffset,p->pixmap()->copy(xp,yp,zw,zh)); + } + setPixmap(QPixmap().fromImage(img)); + } + else + setPixmap(p->pixmap()->copy(xp,yp,zoomWidth,zoomHeight)); + } + move(static_cast(x-float(width())/2),static_cast(y-float(height())/2)); +} + +void MagnifyingGlass::updateImage() +{ + if(isVisible()) + { + QPoint p = QPoint(cursor().pos().x(),cursor().pos().y()); + p = this->parentWidget()->mapFromGlobal(p); + updateImage(p.x(),p.y()); + } +} +void MagnifyingGlass::wheelEvent(QWheelEvent * event) +{ + switch(event->modifiers()) + { + //size + case Qt::NoModifier: + if(event->delta()<0) + sizeUp(); + else + sizeDown(); + break; + //size height + case Qt::ControlModifier: + if(event->delta()<0) + heightUp(); + else + heightDown(); + break; + //size width + case Qt::AltModifier: + if(event->delta()<0) + widthUp(); + else + widthDown(); + break; + //zoom level + case Qt::ShiftModifier: + if(event->delta()<0) + zoomIn(); + else + zoomOut(); + break; + } + updateImage(); + event->setAccepted(true); +} +void MagnifyingGlass::zoomIn() +{ + if(zoomLevel>0.2f) + zoomLevel -= 0.025f; +} + +void MagnifyingGlass::zoomOut() +{ + if(zoomLevel<0.9f) + zoomLevel += 0.025f; +} + +void MagnifyingGlass::sizeUp() +{ + Viewer * p = (Viewer *)parent(); + if(width()<(p->width()*0.90f)) + resize(width()+30,height()+15); +} + +void MagnifyingGlass::sizeDown() +{ + if(width()>175) + resize(width()-30,height()-15); +} + +void MagnifyingGlass::heightUp() +{ + Viewer * p = (Viewer *)parent(); + if(height()<(p->height()*0.90f)) + resize(width(),height()+15); +} + +void MagnifyingGlass::heightDown() +{ + if(height()>80) + resize(width(),height()-15); +} + +void MagnifyingGlass::widthUp() +{ + Viewer * p = (Viewer *)parent(); + if(width()<(p->width()*0.90f)) + resize(width()+30,height()); +} + +void MagnifyingGlass::widthDown() +{ + if(width()>175) + resize(width()-30,height()); +} + +void MagnifyingGlass::keyPressEvent(QKeyEvent *event) +{ + bool validKey = false; + + int _key = event->key(); + Qt::KeyboardModifiers modifiers = event->modifiers(); + + if(modifiers & Qt::ShiftModifier) + _key |= Qt::SHIFT; + if (modifiers & Qt::ControlModifier) + _key |= Qt::CTRL; + if (modifiers & Qt::MetaModifier) + _key |= Qt::META; + if (modifiers & Qt::AltModifier) + _key |= Qt::ALT; + + QKeySequence key(_key); + + if (key == ShortcutsManager::getShortcutsManager().getShortcut(SIZE_UP_MGLASS_ACTION_Y)) + { + sizeUp(); + validKey = true; + } + + else if (key == ShortcutsManager::getShortcutsManager().getShortcut(SIZE_DOWN_MGLASS_ACTION_Y)) + { + sizeDown(); + validKey = true; + } + + else if (key == ShortcutsManager::getShortcutsManager().getShortcut(ZOOM_IN_MGLASS_ACTION_Y)) + { + zoomIn(); + validKey = true; + } + + else if (key == ShortcutsManager::getShortcutsManager().getShortcut(ZOOM_OUT_MGLASS_ACTION_Y)) + { + zoomOut(); + validKey = true; + } + + if(validKey) + { + updateImage(); + event->setAccepted(true); + } +} diff --git a/YACReader/magnifying_glass.h b/YACReader/magnifying_glass.h index 519e3404..024affb5 100644 --- a/YACReader/magnifying_glass.h +++ b/YACReader/magnifying_glass.h @@ -1,34 +1,34 @@ -#ifndef __MAGNIFYING_GLASS -#define __MAGNIFYING_GLASS - -#include -#include -#include -#include - - class MagnifyingGlass : public QLabel - { - Q_OBJECT - private: - float zoomLevel; - void setup(const QSize & size); - void keyPressEvent(QKeyEvent * event); - public: - MagnifyingGlass(int width,int height,QWidget * parent); - MagnifyingGlass(const QSize & size, QWidget * parent); - void mouseMoveEvent(QMouseEvent * event); - public slots: - void updateImage(int x, int y); - void updateImage(); - void wheelEvent(QWheelEvent * event); - void zoomIn(); - void zoomOut(); - void sizeUp(); - void sizeDown(); - void heightUp(); - void heightDown(); - void widthUp(); - void widthDown(); - }; - -#endif +#ifndef __MAGNIFYING_GLASS +#define __MAGNIFYING_GLASS + +#include +#include +#include +#include + + class MagnifyingGlass : public QLabel + { + Q_OBJECT + private: + float zoomLevel; + void setup(const QSize & size); + void keyPressEvent(QKeyEvent * event); + public: + MagnifyingGlass(int width,int height,QWidget * parent); + MagnifyingGlass(const QSize & size, QWidget * parent); + void mouseMoveEvent(QMouseEvent * event); + public slots: + void updateImage(int x, int y); + void updateImage(); + void wheelEvent(QWheelEvent * event); + void zoomIn(); + void zoomOut(); + void sizeUp(); + void sizeDown(); + void heightUp(); + void heightDown(); + void widthUp(); + void widthDown(); + }; + +#endif diff --git a/YACReader/main.cpp b/YACReader/main.cpp index 7e318cee..c7b85513 100644 --- a/YACReader/main.cpp +++ b/YACReader/main.cpp @@ -1,142 +1,142 @@ -#include -#include -#include -#include - -#include "main_window_viewer.h" -#include "configuration.h" -#include "exit_check.h" - -#include "QsLog.h" -#include "QsLogDest.h" - -using namespace QsLogging; - -#if defined(WIN32) && defined(_DEBUG) - #define _CRTDBG_MAP_ALLOC - #include - #include - #define DEBUG_NEW new( _NORMAL_BLOCK, __FILE__, __LINE__ ) - #define new DEBUG_NEW -#endif - -#ifdef Q_OS_MAC -#include -#include -class YACReaderApplication: public QApplication -{ - public: - YACReaderApplication(int & argc, char ** argv) : QApplication(argc,argv) - {} - - void setWindow(MainWindowViewer * w) - { - window = w; - } - - protected: - bool event(QEvent * event) - { - switch(event->type()) - { - case QEvent::FileOpen: - window->openComicFromPath(static_cast(event)->file()); - return true; - default: - return QApplication::event(event); - } - } - private: - MainWindowViewer * window; -}; -#endif - -int main(int argc, char * argv[]) -{ - -#if defined(_MSC_VER) && defined(_DEBUG) - _CrtSetDbgFlag ( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF ); -#endif - -#ifdef Q_OS_MAC - YACReaderApplication app(argc,argv); -#else - QApplication app(argc, argv); -#endif - -#ifdef FORCE_ANGLE - app.setAttribute(Qt::AA_UseOpenGLES); -#endif - - app.setApplicationName("YACReader"); - app.setOrganizationName("YACReader"); - app.setAttribute(Qt::AA_UseHighDpiPixmaps); - if (QIcon::hasThemeIcon("YACReader")) { - app.setWindowIcon(QIcon::fromTheme("YACReader")); - } - - // simple commandline parser - QCommandLineParser parser; - parser.addHelpOption(); - parser.addVersionOption(); - parser.addPositionalArgument("[File|Directory]", "File or directory to open."); - QCommandLineOption comicId("comicId", "", "comicId"); - QCommandLineOption libraryId("libraryId", "", "libraryId"); - // hide comicId and libraryId from help - #if QT_VERSION >= 0x050800 - comicId.setFlags(QCommandLineOption::HiddenFromHelp); - libraryId.setFlags(QCommandLineOption::HiddenFromHelp); - #else - comicId.setHidden(true); - libraryId.setHidden(true); - #endif - - // process - parser.addOption(comicId); - parser.addOption(libraryId); - parser.process(app); - - QString destLog = YACReader::getSettingsPath()+"/yacreader.log"; - QDir().mkpath(YACReader::getSettingsPath()); - - Logger& logger = Logger::instance(); - logger.setLoggingLevel(QsLogging::InfoLevel); - - DestinationPtr fileDestination(DestinationFactory::MakeFileDestination( - destLog, EnableLogRotation, MaxSizeBytes(1048576), MaxOldLogCount(2))); - DestinationPtr debugDestination(DestinationFactory::MakeDebugOutputDestination()); - logger.addDestination(debugDestination); - logger.addDestination(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); -#else - translator.load(QCoreApplication::applicationDirPath()+"/languages/yacreader_"+sufix); -#endif - app.installTranslator(&translator); - MainWindowViewer * mwv = new MainWindowViewer(); - - // some arguments need to be parsed after MainWindowViewer creation - QStringList arglist = parser.positionalArguments(); - if (parser.isSet(comicId) && parser.isSet(libraryId) && arglist.count() >=1) - { - mwv->open(arglist.at(0), parser.value(comicId).toULongLong(), parser.value(libraryId).toULongLong()); - } - else if (arglist.count() >= 1) - { - mwv->openComicFromPath(arglist.at(0)); - } - -#ifdef Q_OS_MAC - app.setWindow(mwv); -#endif - mwv->show(); - int ret = app.exec(); - delete mwv; - - //Configuration::getConfiguration().save(); - YACReader::exitCheck(ret); - return ret; -} +#include +#include +#include +#include + +#include "main_window_viewer.h" +#include "configuration.h" +#include "exit_check.h" + +#include "QsLog.h" +#include "QsLogDest.h" + +using namespace QsLogging; + +#if defined(WIN32) && defined(_DEBUG) + #define _CRTDBG_MAP_ALLOC + #include + #include + #define DEBUG_NEW new( _NORMAL_BLOCK, __FILE__, __LINE__ ) + #define new DEBUG_NEW +#endif + +#ifdef Q_OS_MAC +#include +#include +class YACReaderApplication: public QApplication +{ + public: + YACReaderApplication(int & argc, char ** argv) : QApplication(argc,argv) + {} + + void setWindow(MainWindowViewer * w) + { + window = w; + } + + protected: + bool event(QEvent * event) + { + switch(event->type()) + { + case QEvent::FileOpen: + window->openComicFromPath(static_cast(event)->file()); + return true; + default: + return QApplication::event(event); + } + } + private: + MainWindowViewer * window; +}; +#endif + +int main(int argc, char * argv[]) +{ + +#if defined(_MSC_VER) && defined(_DEBUG) + _CrtSetDbgFlag ( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF ); +#endif + +#ifdef Q_OS_MAC + YACReaderApplication app(argc,argv); +#else + QApplication app(argc, argv); +#endif + +#ifdef FORCE_ANGLE + app.setAttribute(Qt::AA_UseOpenGLES); +#endif + + app.setApplicationName("YACReader"); + app.setOrganizationName("YACReader"); + app.setAttribute(Qt::AA_UseHighDpiPixmaps); + if (QIcon::hasThemeIcon("YACReader")) { + app.setWindowIcon(QIcon::fromTheme("YACReader")); + } + + // simple commandline parser + QCommandLineParser parser; + parser.addHelpOption(); + parser.addVersionOption(); + parser.addPositionalArgument("[File|Directory]", "File or directory to open."); + QCommandLineOption comicId("comicId", "", "comicId"); + QCommandLineOption libraryId("libraryId", "", "libraryId"); + // hide comicId and libraryId from help + #if QT_VERSION >= 0x050800 + comicId.setFlags(QCommandLineOption::HiddenFromHelp); + libraryId.setFlags(QCommandLineOption::HiddenFromHelp); + #else + comicId.setHidden(true); + libraryId.setHidden(true); + #endif + + // process + parser.addOption(comicId); + parser.addOption(libraryId); + parser.process(app); + + QString destLog = YACReader::getSettingsPath()+"/yacreader.log"; + QDir().mkpath(YACReader::getSettingsPath()); + + Logger& logger = Logger::instance(); + logger.setLoggingLevel(QsLogging::InfoLevel); + + DestinationPtr fileDestination(DestinationFactory::MakeFileDestination( + destLog, EnableLogRotation, MaxSizeBytes(1048576), MaxOldLogCount(2))); + DestinationPtr debugDestination(DestinationFactory::MakeDebugOutputDestination()); + logger.addDestination(debugDestination); + logger.addDestination(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); +#else + translator.load(QCoreApplication::applicationDirPath()+"/languages/yacreader_"+sufix); +#endif + app.installTranslator(&translator); + MainWindowViewer * mwv = new MainWindowViewer(); + + // some arguments need to be parsed after MainWindowViewer creation + QStringList arglist = parser.positionalArguments(); + if (parser.isSet(comicId) && parser.isSet(libraryId) && arglist.count() >=1) + { + mwv->open(arglist.at(0), parser.value(comicId).toULongLong(), parser.value(libraryId).toULongLong()); + } + else if (arglist.count() >= 1) + { + mwv->openComicFromPath(arglist.at(0)); + } + +#ifdef Q_OS_MAC + app.setWindow(mwv); +#endif + mwv->show(); + int ret = app.exec(); + delete mwv; + + //Configuration::getConfiguration().save(); + YACReader::exitCheck(ret); + return ret; +} diff --git a/YACReader/main_window_viewer.cpp b/YACReader/main_window_viewer.cpp index 8429fac3..87f35f4f 100644 --- a/YACReader/main_window_viewer.cpp +++ b/YACReader/main_window_viewer.cpp @@ -1,1706 +1,1706 @@ -#include "main_window_viewer.h" -#include "configuration.h" -#include "viewer.h" -#include "goto_dialog.h" -#include "custom_widgets.h" -#include "options_dialog.h" -#include "check_new_version.h" -#include "comic.h" -#include "bookmarks_dialog.h" -#include "shortcuts_dialog.h" -#include "width_slider.h" -#include "qnaturalsorting.h" -#include "help_about_dialog.h" -#include "yacreader_tool_bar_stretch.h" - -#include "comic_db.h" -#include "yacreader_local_client.h" - -#include "yacreader_global.h" -#include "edit_shortcuts_dialog.h" -#include "shortcuts_manager.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* 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),alwaysOnTop(false),currentDirectory("."),currentDirectoryImgDest("."),isClient(false) -{ - loadConfiguration(); - setupUI(); -} - -MainWindowViewer::~MainWindowViewer() -{ - delete settings; - delete viewer; - delete had; - - //delete sliderAction; - delete openAction; - delete openFolderAction; - delete openLatestComicAction; - delete saveImageAction; - delete openPreviousComicAction; - delete openNextComicAction; - delete prevAction; - delete nextAction; - delete adjustHeightAction; - delete adjustWidthAction; - delete leftRotationAction; - delete rightRotationAction; - delete doublePageAction; - delete doubleMangaPageAction; - delete increasePageZoomAction; - delete decreasePageZoomAction; - delete resetZoomAction; - delete goToPageAction; - delete optionsAction; - delete helpAboutAction; - delete showMagnifyingGlassAction; - delete setBookmarkAction; - delete showBookmarksAction; - delete showShorcutsAction; - delete showInfoAction; - delete closeAction; - delete showDictionaryAction; - delete alwaysOnTopAction; - delete adjustToFullSizeAction; - delete fitToPageAction; - delete showFlowAction; - -} -void MainWindowViewer::loadConfiguration() -{ - settings = new QSettings(YACReader::getSettingsPath()+"/YACReader.ini",QSettings::IniFormat); - - Configuration & config = Configuration::getConfiguration(); - config.load(settings); - currentDirectory = config.getDefaultPath(); - fullscreen = config.getFullScreen(); -} - -void MainWindowViewer::setupUI() -{ - //setUnifiedTitleAndToolBarOnMac(true); - - viewer = new Viewer(this); - connect(viewer,SIGNAL(reset()),this,SLOT(processReset())); - //detected end of comic - connect(viewer,SIGNAL(openNextComic()),this,SLOT(openNextComic())); - //detected start of comic - connect(viewer,SIGNAL(openPreviousComic()),this,SLOT(openPreviousComic())); - - setCentralWidget(viewer); - int heightDesktopResolution = QApplication::desktop()->screenGeometry().height(); - int widthDesktopResolution = QApplication::desktop()->screenGeometry().width(); - int height,width; - height = static_cast(heightDesktopResolution*0.84); - width = static_cast(height*0.70); - Configuration & conf = Configuration::getConfiguration(); - QPoint p = conf.getPos(); - QSize s = conf.getSize(); - if(s.width()!=0) - { - move(p); - resize(s); - } - else - { - move(QPoint((widthDesktopResolution-width)/2,((heightDesktopResolution-height)-40)/2)); - resize(QSize(width,height)); - } - - had = new HelpAboutDialog(this); //TODO load data - - had->loadAboutInformation(":/files/about.html"); - had->loadHelp(":/files/helpYACReader.html"); - - optionsDialog = new OptionsDialog(this); - connect(optionsDialog,SIGNAL(accepted()),viewer,SLOT(updateOptions())); - connect(optionsDialog, SIGNAL(optionsChanged()),this,SLOT(reloadOptions())); - connect(optionsDialog,SIGNAL(changedFilters(int,int,int)),viewer,SLOT(updateFilters(int,int,int))); - - optionsDialog->restoreOptions(settings); - //shortcutsDialog = new ShortcutsDialog(this); - editShortcutsDialog = new EditShortcutsDialog(this); - connect(optionsDialog,SIGNAL(editShortcuts()),editShortcutsDialog,SLOT(show())); - - createActions(); - setUpShortcutsManagement(); - - createToolBars(); - - setWindowTitle("YACReader"); - - checkNewVersion(); - - viewer->setFocusPolicy(Qt::StrongFocus); - - - //if(Configuration::getConfiguration().getAlwaysOnTop()) - //{ - // setWindowFlags(this->windowFlags() | Qt::CustomizeWindowHint | Qt::WindowStaysOnTopHint); - //} - - previousWindowFlags = windowFlags(); - previousPos = pos(); - previousSize = size(); - - if(fullscreen) - toFullScreen(); - if(conf.getMaximized()) - showMaximized(); - - setAcceptDrops(true); - - if(Configuration::getConfiguration().getShowToolbars() && !Configuration::getConfiguration().getFullScreen()) - showToolBars(); - else - hideToolBars(); -} - -void MainWindowViewer::createActions() -{ - openAction = new QAction(tr("&Open"),this); - openAction->setIcon(QIcon(":/images/viewer_toolbar/open.png")); - openAction->setToolTip(tr("Open a comic")); - openAction->setData(OPEN_ACTION_Y); - openAction->setShortcut(ShortcutsManager::getShortcutsManager().getShortcut(OPEN_ACTION_Y)); - connect(openAction, SIGNAL(triggered()), this, SLOT(open())); - - openFolderAction = new QAction(tr("Open Folder"),this); - openFolderAction->setIcon(QIcon(":/images/viewer_toolbar/openFolder.png")); - openFolderAction->setToolTip(tr("Open image folder")); - openFolderAction->setData(OPEN_FOLDER_ACTION_Y); - openFolderAction->setShortcut(ShortcutsManager::getShortcutsManager().getShortcut(OPEN_FOLDER_ACTION_Y)); - connect(openFolderAction, SIGNAL(triggered()), this, SLOT(openFolder())); - - openLatestComicAction = new QAction(tr("Open latest comic"), this); - openLatestComicAction->setToolTip(tr("Open the latest comic opened in the previous reading session")); - openLatestComicAction->setData(OPEN_LATEST_COMIC_Y); - openLatestComicAction->setShortcut(ShortcutsManager::getShortcutsManager().getShortcut(OPEN_LATEST_COMIC_Y)); - connect(openLatestComicAction, SIGNAL(triggered()), this, SLOT(openLatestComic())); - - QAction* recentFileAction = nullptr; - //TODO: Replace limit with a configurable value - for (int i = 0; i < Configuration::getConfiguration().getOpenRecentSize(); i++) - { - recentFileAction = new QAction(this); - recentFileAction->setVisible(false); - QObject::connect(recentFileAction, &QAction::triggered, this, &MainWindowViewer::openRecent); - recentFilesActionList.append(recentFileAction); - } - - clearRecentFilesAction = new QAction(tr("Clear"),this); - clearRecentFilesAction->setToolTip(tr("Clear open recent list")); - connect(clearRecentFilesAction, &QAction::triggered, this, &MainWindowViewer::clearRecentFiles); - - saveImageAction = new QAction(tr("Save"),this); - saveImageAction->setIcon(QIcon(":/images/viewer_toolbar/save.png")); - saveImageAction->setToolTip(tr("Save current page")); - saveImageAction->setDisabled(true); - saveImageAction->setData(SAVE_IMAGE_ACTION_Y); - saveImageAction->setShortcut(ShortcutsManager::getShortcutsManager().getShortcut(SAVE_IMAGE_ACTION_Y)); - connect(saveImageAction,SIGNAL(triggered()),this,SLOT(saveImage())); - - openPreviousComicAction = new QAction(tr("Previous Comic"),this); - openPreviousComicAction->setIcon(QIcon(":/images/viewer_toolbar/openPrevious.png")); - openPreviousComicAction->setToolTip(tr("Open previous comic")); - openPreviousComicAction->setDisabled(true); - openPreviousComicAction->setData(OPEN_PREVIOUS_COMIC_ACTION_Y); - openPreviousComicAction->setShortcut(ShortcutsManager::getShortcutsManager().getShortcut(OPEN_PREVIOUS_COMIC_ACTION_Y)); - connect(openPreviousComicAction,SIGNAL(triggered()),this,SLOT(openPreviousComic())); - - openNextComicAction = new QAction(tr("Next Comic"),this); - openNextComicAction->setIcon(QIcon(":/images/viewer_toolbar/openNext.png")); - openNextComicAction->setToolTip(tr("Open next comic")); - openNextComicAction->setDisabled(true); - openNextComicAction->setData(OPEN_NEXT_COMIC_ACTION_Y); - openNextComicAction->setShortcut(ShortcutsManager::getShortcutsManager().getShortcut(OPEN_NEXT_COMIC_ACTION_Y)); - connect(openNextComicAction,SIGNAL(triggered()),this,SLOT(openNextComic())); - - prevAction = new QAction(tr("&Previous"),this); - prevAction->setIcon(QIcon(":/images/viewer_toolbar/previous.png")); - prevAction->setShortcutContext(Qt::WidgetShortcut); - prevAction->setToolTip(tr("Go to previous page")); - prevAction->setDisabled(true); - prevAction->setData(PREV_ACTION_Y); - prevAction->setShortcut(ShortcutsManager::getShortcutsManager().getShortcut(PREV_ACTION_Y)); - connect(prevAction, SIGNAL(triggered()),viewer,SLOT(prev())); - - nextAction = new QAction(tr("&Next"),this); - nextAction->setIcon(QIcon(":/images/viewer_toolbar/next.png")); - nextAction->setShortcutContext(Qt::WidgetShortcut); - nextAction->setToolTip(tr("Go to next page")); - nextAction->setDisabled(true); - nextAction->setData(NEXT_ACTION_Y); - nextAction->setShortcut(ShortcutsManager::getShortcutsManager().getShortcut(NEXT_ACTION_Y)); - connect(nextAction, SIGNAL(triggered()),viewer,SLOT(next())); - - adjustHeightAction = new QAction(tr("Fit Height"),this); - adjustHeightAction->setIcon(QIcon(":/images/viewer_toolbar/toHeight.png")); - //adjustWidth->setCheckable(true); - adjustHeightAction->setDisabled(true); - adjustHeightAction->setToolTip(tr("Fit image to height")); - //adjustWidth->setIcon(QIcon(":/images/fitWidth.png")); - adjustHeightAction->setData(ADJUST_HEIGHT_ACTION_Y); - adjustHeightAction->setShortcut(ShortcutsManager::getShortcutsManager().getShortcut(ADJUST_HEIGHT_ACTION_Y)); - adjustHeightAction->setCheckable(true); - connect(adjustHeightAction, SIGNAL(triggered()),this,SLOT(fitToHeight())); - - adjustWidthAction = new QAction(tr("Fit Width"),this); - adjustWidthAction->setIcon(QIcon(":/images/viewer_toolbar/toWidth.png")); - //adjustWidth->setCheckable(true); - adjustWidthAction->setDisabled(true); - adjustWidthAction->setToolTip(tr("Fit image to width")); - //adjustWidth->setIcon(QIcon(":/images/fitWidth.png")); - adjustWidthAction->setData(ADJUST_WIDTH_ACTION_Y); - adjustWidthAction->setShortcut(ShortcutsManager::getShortcutsManager().getShortcut(ADJUST_WIDTH_ACTION_Y)); - adjustWidthAction->setCheckable(true); - connect(adjustWidthAction, SIGNAL(triggered()),this,SLOT(fitToWidth())); - - adjustToFullSizeAction = new QAction(tr("Show full size"),this); - adjustToFullSizeAction->setIcon(QIcon(":/images/viewer_toolbar/full.png")); - adjustToFullSizeAction->setCheckable(false); - adjustToFullSizeAction->setDisabled(true); - adjustToFullSizeAction->setData(ADJUST_TO_FULL_SIZE_ACTION_Y); - adjustToFullSizeAction->setShortcut(ShortcutsManager::getShortcutsManager().getShortcut(ADJUST_TO_FULL_SIZE_ACTION_Y)); - adjustToFullSizeAction->setCheckable(true); - connect(adjustToFullSizeAction,SIGNAL(triggered()),this,SLOT(adjustToFullSizeSwitch())); - - fitToPageAction = new QAction(tr("Fit to page"),this); - fitToPageAction->setIcon(QIcon(":/images/viewer_toolbar/fitToPage.png")); - fitToPageAction->setDisabled(true); - fitToPageAction->setData(FIT_TO_PAGE_ACTION_Y); - fitToPageAction->setShortcut(ShortcutsManager::getShortcutsManager().getShortcut(FIT_TO_PAGE_ACTION_Y)); - fitToPageAction->setCheckable(true); - connect(fitToPageAction,SIGNAL(triggered()),this,SLOT(fitToPageSwitch())); - - //fit modes have to be exclusive and checkable - QActionGroup *fitModes = new QActionGroup(this); - fitModes->addAction(adjustHeightAction); - fitModes->addAction(adjustWidthAction); - fitModes->addAction(adjustToFullSizeAction); - fitModes->addAction(fitToPageAction); - - switch(Configuration::getConfiguration().getFitMode()) - { - case YACReader::FitMode::ToWidth: - adjustWidthAction->setChecked(true); - break; - case YACReader::FitMode::ToHeight: - adjustHeightAction->setChecked(true); - break; - case YACReader::FitMode::FullRes: - adjustToFullSizeAction->setChecked(true); - break; - case YACReader::FitMode::FullPage: - fitToPageAction->setChecked(true); - break; - default: - fitToPageAction->setChecked(true); - } - - resetZoomAction = new QAction(tr("Reset zoom"), this); - resetZoomAction->setDisabled(true); - resetZoomAction->setData(RESET_ZOOM_ACTION_Y); - resetZoomAction->setShortcut(ShortcutsManager::getShortcutsManager().getShortcut(RESET_ZOOM_ACTION_Y)); - connect(resetZoomAction,SIGNAL(triggered()),this,SLOT(resetZoomLevel())); - - showZoomSliderlAction = new QAction(tr("Show zoom slider"), this); - showZoomSliderlAction->setIcon(QIcon(":/images/viewer_toolbar/zoom.png")); - showZoomSliderlAction->setDisabled(true); - - increasePageZoomAction = new QAction(tr("Zoom+"),this); - increasePageZoomAction->setDisabled(true); - increasePageZoomAction->setData(ZOOM_PLUS_ACTION_Y); - increasePageZoomAction->setShortcut(ShortcutsManager::getShortcutsManager().getShortcut(ZOOM_PLUS_ACTION_Y)); - connect(increasePageZoomAction,SIGNAL(triggered()),this,SLOT(increasePageZoomLevel())); - - decreasePageZoomAction = new QAction(tr("Zoom-"),this); - decreasePageZoomAction->setDisabled(true); - decreasePageZoomAction->setData(ZOOM_MINUS_ACTION_Y); - decreasePageZoomAction->setShortcut(ShortcutsManager::getShortcutsManager().getShortcut(ZOOM_MINUS_ACTION_Y)); - connect(decreasePageZoomAction,SIGNAL(triggered()),this,SLOT(decreasePageZoomLevel())); - - leftRotationAction = new QAction(tr("Rotate image to the left"),this); - leftRotationAction->setIcon(QIcon(":/images/viewer_toolbar/rotateL.png")); - leftRotationAction->setDisabled(true); - leftRotationAction->setData(LEFT_ROTATION_ACTION_Y); - leftRotationAction->setShortcut(ShortcutsManager::getShortcutsManager().getShortcut(LEFT_ROTATION_ACTION_Y)); - connect(leftRotationAction, SIGNAL(triggered()),viewer,SLOT(rotateLeft())); - - rightRotationAction = new QAction(tr("Rotate image to the right"),this); - rightRotationAction->setIcon(QIcon(":/images/viewer_toolbar/rotateR.png")); - rightRotationAction->setDisabled(true); - rightRotationAction->setData(RIGHT_ROTATION_ACTION_Y); - rightRotationAction->setShortcut(ShortcutsManager::getShortcutsManager().getShortcut(RIGHT_ROTATION_ACTION_Y)); - connect(rightRotationAction, SIGNAL(triggered()),viewer,SLOT(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->setDisabled(true); - doublePageAction->setCheckable(true); - doublePageAction->setChecked(Configuration::getConfiguration().getDoublePage()); - doublePageAction->setData(DOUBLE_PAGE_ACTION_Y); - doublePageAction->setShortcut(ShortcutsManager::getShortcutsManager().getShortcut(DOUBLE_PAGE_ACTION_Y)); - connect(doublePageAction, SIGNAL(triggered()),viewer,SLOT(doublePageSwitch())); - - //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->setDisabled(true); - doubleMangaPageAction->setCheckable(true); - doubleMangaPageAction->setChecked(Configuration::getConfiguration().getDoubleMangaPage()); - doubleMangaPageAction->setData(DOUBLE_MANGA_PAGE_ACTION_Y); - doubleMangaPageAction->setShortcut(ShortcutsManager::getShortcutsManager().getShortcut(DOUBLE_MANGA_PAGE_ACTION_Y)); - connect(doubleMangaPageAction, SIGNAL(triggered()),viewer,SLOT(doubleMangaPageSwitch())); - - goToPageAction = new QAction(tr("Go To"),this); - goToPageAction->setIcon(QIcon(":/images/viewer_toolbar/goto.png")); - goToPageAction->setDisabled(true); - goToPageAction->setToolTip(tr("Go to page ...")); - goToPageAction->setData(GO_TO_PAGE_ACTION_Y); - goToPageAction->setShortcut(ShortcutsManager::getShortcutsManager().getShortcut(GO_TO_PAGE_ACTION_Y)); - connect(goToPageAction, SIGNAL(triggered()),viewer,SLOT(showGoToDialog())); - - optionsAction = new QAction(tr("Options"),this); - 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")); - - connect(optionsAction, SIGNAL(triggered()),optionsDialog,SLOT(show())); - - helpAboutAction = new QAction(tr("Help"),this); - helpAboutAction->setToolTip(tr("Help, About YACReader")); - helpAboutAction->setIcon(QIcon(":/images/viewer_toolbar/help.png")); - helpAboutAction->setData(HELP_ABOUT_ACTION_Y); - helpAboutAction->setShortcut(ShortcutsManager::getShortcutsManager().getShortcut(HELP_ABOUT_ACTION_Y)); - connect(helpAboutAction, SIGNAL(triggered()),had,SLOT(show())); - - showMagnifyingGlassAction = new QAction(tr("Magnifying glass"),this); - showMagnifyingGlassAction->setToolTip(tr("Switch Magnifying glass")); - showMagnifyingGlassAction->setIcon(QIcon(":/images/viewer_toolbar/magnifyingGlass.png")); - showMagnifyingGlassAction->setDisabled(true); - showMagnifyingGlassAction->setCheckable(true); - showMagnifyingGlassAction->setData(SHOW_MAGNIFYING_GLASS_ACTION_Y); - showMagnifyingGlassAction->setShortcut(ShortcutsManager::getShortcutsManager().getShortcut(SHOW_MAGNIFYING_GLASS_ACTION_Y)); - connect(showMagnifyingGlassAction, SIGNAL(triggered()),viewer,SLOT(magnifyingGlassSwitch())); - - 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->setDisabled(true); - setBookmarkAction->setCheckable(true); - setBookmarkAction->setData(SET_BOOKMARK_ACTION_Y); - setBookmarkAction->setShortcut(ShortcutsManager::getShortcutsManager().getShortcut(SET_BOOKMARK_ACTION_Y)); - connect(setBookmarkAction,SIGNAL(triggered (bool)),viewer,SLOT(setBookmark(bool))); - connect(viewer,SIGNAL(pageAvailable(bool)),setBookmarkAction,SLOT(setEnabled(bool))); - connect(viewer,SIGNAL(pageIsBookmark(bool)),setBookmarkAction,SLOT(setChecked(bool))); - - 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->setDisabled(true); - showBookmarksAction->setData(SHOW_BOOKMARKS_ACTION_Y); - showBookmarksAction->setShortcut(ShortcutsManager::getShortcutsManager().getShortcut(SHOW_BOOKMARKS_ACTION_Y)); - connect(showBookmarksAction, SIGNAL(triggered()),viewer->getBookmarksDialog(),SLOT(show())); - - showShorcutsAction = new QAction(tr("Show keyboard shortcuts"), this ); - showShorcutsAction->setIcon(QIcon(":/images/viewer_toolbar/shortcuts.png")); - showShorcutsAction->setData(SHOW_SHORCUTS_ACTION_Y); - showShorcutsAction->setShortcut(ShortcutsManager::getShortcutsManager().getShortcut(SHOW_SHORCUTS_ACTION_Y)); - //connect(showShorcutsAction, SIGNAL(triggered()),shortcutsDialog,SLOT(show())); - connect(showShorcutsAction, SIGNAL(triggered()), editShortcutsDialog, SLOT(show())); - - showInfoAction = new QAction(tr("Show Info"),this); - showInfoAction->setIcon(QIcon(":/images/viewer_toolbar/info.png")); - showInfoAction->setDisabled(true); - showInfoAction->setData(SHOW_INFO_ACTION_Y); - showInfoAction->setShortcut(ShortcutsManager::getShortcutsManager().getShortcut(SHOW_INFO_ACTION_Y)); - connect(showInfoAction, SIGNAL(triggered()),viewer,SLOT(informationSwitch())); - - closeAction = new QAction(tr("Close"),this); - closeAction->setIcon(QIcon(":/images/viewer_toolbar/close.png")); - closeAction->setData(CLOSE_ACTION_Y); - closeAction->setShortcut(ShortcutsManager::getShortcutsManager().getShortcut(CLOSE_ACTION_Y)); - connect(closeAction,SIGNAL(triggered()),this,SLOT(close())); - - showDictionaryAction = new QAction(tr("Show Dictionary"),this); - showDictionaryAction->setIcon(QIcon(":/images/viewer_toolbar/translator.png")); - //showDictionaryAction->setCheckable(true); - showDictionaryAction->setDisabled(true); - showDictionaryAction->setData(SHOW_DICTIONARY_ACTION_Y); - showDictionaryAction->setShortcut(ShortcutsManager::getShortcutsManager().getShortcut(SHOW_DICTIONARY_ACTION_Y)); - connect(showDictionaryAction,SIGNAL(triggered()),viewer,SLOT(translatorSwitch())); - - //deprecated - alwaysOnTopAction = new QAction(tr("Always on top"),this); - alwaysOnTopAction->setIcon(QIcon(":/images/alwaysOnTop.png")); - alwaysOnTopAction->setCheckable(true); - alwaysOnTopAction->setDisabled(true); - alwaysOnTopAction->setChecked(Configuration::getConfiguration().getAlwaysOnTop()); - alwaysOnTopAction->setData(ALWAYS_ON_TOP_ACTION_Y); - alwaysOnTopAction->setShortcut(ShortcutsManager::getShortcutsManager().getShortcut(ALWAYS_ON_TOP_ACTION_Y)); - connect(alwaysOnTopAction,SIGNAL(triggered()),this,SLOT(alwaysOnTopSwitch())); - - showFlowAction = new QAction(tr("Show go to flow"),this); - showFlowAction->setIcon(QIcon(":/images/viewer_toolbar/flow.png")); - showFlowAction->setDisabled(true); - showFlowAction->setData(SHOW_FLOW_ACTION_Y); - showFlowAction->setShortcut(ShortcutsManager::getShortcutsManager().getShortcut(SHOW_FLOW_ACTION_Y)); - connect(showFlowAction,SIGNAL(triggered()),viewer,SLOT(goToFlowSwitch())); - - showEditShortcutsAction = new QAction(tr("Edit shortcuts"),this); - showEditShortcutsAction->setData(SHOW_EDIT_SHORTCUTS_ACTION_Y); - showEditShortcutsAction->setShortcut(ShortcutsManager::getShortcutsManager().getShortcut(SHOW_EDIT_SHORTCUTS_ACTION_Y)); - connect(showEditShortcutsAction,SIGNAL(triggered()),editShortcutsDialog,SLOT(show())); -} - -void MainWindowViewer::createToolBars() -{ -#ifdef Q_OS_MAC - comicToolBar = new YACReaderMacOSXToolbar(this); -#else - comicToolBar = addToolBar(tr("&File")); -#endif - -#ifdef Q_OS_MAC - //comicToolBar->setIconSize(QSize(16,16)); -#else - comicToolBar->setIconSize(QSize(18,18)); - comicToolBar->setStyleSheet("QToolBar{border:none;}"); -#endif - -#ifdef Q_OS_MAC - comicToolBar->addAction(openAction); - comicToolBar->addAction(openFolderAction); -#else - QMenu * recentmenu = new QMenu(tr("Open recent")); - recentmenu->addActions(recentFilesActionList); - recentmenu->addSeparator(); - recentmenu->addAction(clearRecentFilesAction); - refreshRecentFilesActionList(); - - QToolButton * tb = new QToolButton(); - tb->addAction(openAction); - tb->addAction(openLatestComicAction); - tb->addAction(openFolderAction); - tb->addAction(recentmenu->menuAction()); - tb->setPopupMode(QToolButton::MenuButtonPopup); - tb->setDefaultAction(openAction); - - comicToolBar->addWidget(tb); -#endif - - comicToolBar->addAction(saveImageAction); - comicToolBar->addAction(openPreviousComicAction); - comicToolBar->addAction(openNextComicAction); - - comicToolBar->addSeparator(); - - comicToolBar->addAction(prevAction); - comicToolBar->addAction(nextAction); - comicToolBar->addAction(goToPageAction); - - comicToolBar->addSeparator(); - - comicToolBar->addAction(adjustWidthAction); - comicToolBar->addAction(adjustHeightAction); - comicToolBar->addAction(adjustToFullSizeAction); - comicToolBar->addAction(fitToPageAction); - - zoomSliderAction = new YACReaderSlider(this); - zoomSliderAction->hide(); - - comicToolBar->addAction(showZoomSliderlAction); - - connect(showZoomSliderlAction,SIGNAL(triggered()),this,SLOT(toggleFitToWidthSlider())); - connect(zoomSliderAction, SIGNAL(zoomRatioChanged(int)),viewer,SLOT(updateZoomRatio(int))); - connect(viewer,SIGNAL(zoomUpdated(int)),zoomSliderAction,SLOT(updateZoomRatio(int))); - - comicToolBar->addAction(leftRotationAction); - comicToolBar->addAction(rightRotationAction); - comicToolBar->addAction(doublePageAction); - comicToolBar->addAction(doubleMangaPageAction); - - comicToolBar->addSeparator(); - - comicToolBar->addAction(showMagnifyingGlassAction); - - comicToolBar->addSeparator(); - - comicToolBar->addAction(setBookmarkAction); - comicToolBar->addAction(showBookmarksAction); - - comicToolBar->addSeparator(); - - comicToolBar->addAction(showDictionaryAction); - comicToolBar->addAction(showFlowAction); - comicToolBar->addAction(showInfoAction); - -#ifdef Q_OS_MAC - comicToolBar->addStretch(); -#else - comicToolBar->addWidget(new YACReaderToolBarStretch()); -#endif - - - comicToolBar->addAction(showShorcutsAction); - comicToolBar->addAction(optionsAction); - comicToolBar->addAction(helpAboutAction); - //comicToolBar->addAction(closeAction); - -#ifndef Q_OS_MAC - comicToolBar->setMovable(false); -#endif - - viewer->addAction(openAction); - viewer->addAction(openFolderAction); - viewer->addAction(saveImageAction); - viewer->addAction(openPreviousComicAction); - viewer->addAction(openNextComicAction); - YACReader::addSperator(viewer); - - viewer->addAction(prevAction); - viewer->addAction(nextAction); - viewer->addAction(goToPageAction); - viewer->addAction(adjustHeightAction); - viewer->addAction(adjustWidthAction); - viewer->addAction(adjustToFullSizeAction); - viewer->addAction(fitToPageAction); - viewer->addAction(leftRotationAction); - viewer->addAction(rightRotationAction); - viewer->addAction(doublePageAction); - viewer->addAction(doubleMangaPageAction); - YACReader::addSperator(viewer); - - viewer->addAction(showMagnifyingGlassAction); - viewer->addAction(increasePageZoomAction); - viewer->addAction(decreasePageZoomAction); - viewer->addAction(resetZoomAction); - YACReader::addSperator(viewer); - - viewer->addAction(setBookmarkAction); - viewer->addAction(showBookmarksAction); - YACReader::addSperator(viewer); - - viewer->addAction(showDictionaryAction); - viewer->addAction(showFlowAction); - viewer->addAction(showInfoAction); - YACReader::addSperator(viewer); - - viewer->addAction(showShorcutsAction); - viewer->addAction(showEditShortcutsAction); - viewer->addAction(optionsAction); - viewer->addAction(helpAboutAction); - YACReader::addSperator(viewer); - - viewer->addAction(closeAction); - - viewer->setContextMenuPolicy(Qt::ActionsContextMenu); - - //MacOSX app menus -#ifdef Q_OS_MAC - QMenuBar * menuBar = this->menuBar(); - //about / preferences - //TODO - - //file - QMenu * fileMenu = new QMenu(tr("File")); - - fileMenu->addAction(openAction); - fileMenu->addAction(openLatestComicAction); - fileMenu->addAction(openFolderAction); - fileMenu->addSeparator(); - fileMenu->addAction(saveImageAction); - fileMenu->addSeparator(); - - QMenu * recentmenu = new QMenu(tr("Open recent")); - recentmenu->addActions(recentFilesActionList); - recentmenu->addSeparator(); - recentmenu->addAction(clearRecentFilesAction); - refreshRecentFilesActionList(); - fileMenu->addMenu(recentmenu); - - fileMenu->addSeparator(); - fileMenu->addAction(closeAction); - - QMenu * editMenu = new QMenu(tr("Edit")); - editMenu->addAction(leftRotationAction); - editMenu->addAction(rightRotationAction); - - QMenu * viewMenu = new QMenu(tr("View")); - viewMenu->addAction(adjustHeightAction); - viewMenu->addAction(adjustWidthAction); - viewMenu->addAction(fitToPageAction); - viewMenu->addAction(adjustToFullSizeAction); - viewMenu->addSeparator(); - viewMenu->addAction(increasePageZoomAction); - viewMenu->addAction(decreasePageZoomAction); - viewMenu->addAction(resetZoomAction); - viewMenu->addAction(showZoomSliderlAction); - viewMenu->addSeparator(); - viewMenu->addAction(doublePageAction); - viewMenu->addAction(doubleMangaPageAction); - viewMenu->addSeparator(); - viewMenu->addAction(showMagnifyingGlassAction); - - QMenu * goMenu = new QMenu(tr("Go")); - goMenu->addAction(prevAction); - goMenu->addAction(nextAction); - goMenu->addAction(goToPageAction); - goMenu->addSeparator(); - goMenu->addAction(setBookmarkAction); - goMenu->addAction(showBookmarksAction); - - QMenu * windowMenu = new QMenu(tr("Window")); - windowMenu->addAction(optionsAction); // this action goes to MacOS's Preference menu by Qt - windowMenu->addAction(showShorcutsAction); - windowMenu->addAction(showFlowAction); - windowMenu->addAction(showInfoAction); - windowMenu->addAction(showDictionaryAction); - - QMenu * helpMenu = new QMenu(tr("Help")); - helpMenu->addAction(helpAboutAction); - - menuBar->addMenu(fileMenu); - menuBar->addMenu(editMenu); - menuBar->addMenu(viewMenu); - menuBar->addMenu(goMenu); - menuBar->addMenu(windowMenu); - menuBar->addMenu(helpMenu); - - //tool bar - //QMenu * toolbarMenu = new QMenu(tr("Toolbar")); - //toolbarMenu->addAction(); - //TODO - - //menu->addMenu(toolbarMenu); - - //attach toolbar - - comicToolBar->attachToWindow(this->windowHandle()); - -#endif - -} - -void MainWindowViewer::refreshRecentFilesActionList() -{ - QStringList recentFilePaths = Configuration::getConfiguration().openRecentList(); - - //TODO: Replace limit with something configurable - int iteration = (recentFilePaths.size() < Configuration::getConfiguration().getOpenRecentSize()) - ? recentFilePaths.size() : Configuration::getConfiguration().getOpenRecentSize(); - for (int i = 0; i < iteration; i++) - { - QString strippedName = QFileInfo(recentFilePaths.at(i)).fileName(); - recentFilesActionList.at(i)->setText(strippedName); - recentFilesActionList.at(i)->setData(recentFilePaths.at(i)); - recentFilesActionList.at(i)->setVisible(true); - } - - for (int i = iteration; i < Configuration::getConfiguration().getOpenRecentSize(); i++) - { - recentFilesActionList.at(i)->setVisible(false); - } -} - -void MainWindowViewer::clearRecentFiles() -{ - Configuration::getConfiguration().clearOpenRecentList(); - refreshRecentFilesActionList(); -} - -void MainWindowViewer::openRecent() -{ - QAction *action = qobject_cast(sender()); - - openComicFromRecentAction(action); -} - -void MainWindowViewer::openLatestComic() -{ - if (recentFilesActionList.isEmpty()) - { - return; - } - - openComicFromRecentAction(recentFilesActionList[0]); -} - -void MainWindowViewer::openComicFromRecentAction(QAction *action) -{ - if (action == nullptr) - { - return; - } - - QFileInfo info1 (action->data().toString()); - if (info1.exists()) - { - if (info1.isFile()) - { - openComicFromPath(action->data().toString()); - } - else if (info1.isDir()) - { - openFolderFromPath(action->data().toString()); - } - } -} - -void MainWindowViewer::reloadOptions() -{ - viewer->updateConfig(settings); -} - -void MainWindowViewer::open() -{ - QFileDialog openDialog; -#ifndef use_unarr - QString pathFile = openDialog.getOpenFileName(this,tr("Open Comic"),currentDirectory,tr("Comic files") + "(*.cbr *.cbz *.rar *.zip *.tar *.pdf *.7z *.cb7 *.arj *.cbt)"); -#else - QString pathFile = openDialog.getOpenFileName(this,tr("Open Comic"),currentDirectory,tr("Comic files") + "(*.cbr *.cbz *.rar *.zip *.tar *.pdf *.cbt)"); -#endif - if (!pathFile.isEmpty()) - { - openComicFromPath(pathFile); - } -} - -void MainWindowViewer::open(QString path, ComicDB & comic, QList & siblings) -{ - //currentComicDB = comic; - //siblingComics = siblings; - - QFileInfo fi(path); - - if(!comic.info.title.isNull() && !comic.info.title.toString().isEmpty()) - setWindowTitle("YACReader - " + comic.info.title.toString()); - else - setWindowTitle("YACReader - " + fi.fileName()); - - viewer->open(path,comic); - enableActions(); - int index = siblings.indexOf(comic); - - optionsDialog->setFilters(currentComicDB.info.brightness, currentComicDB.info.contrast, currentComicDB.info.gamma); - - if(index>0) - openPreviousComicAction->setDisabled(false); - else - openPreviousComicAction->setDisabled(true); - - if(index+1setDisabled(false); - else - openNextComicAction->setDisabled(true); -} - -void MainWindowViewer::open(QString path, qint64 comicId, qint64 libraryId) -{ - //QString pathFile = QCoreApplication::arguments().at(1); - currentDirectory = path; - //quint64 comicId = QCoreApplication::arguments().at(2).split("=").at(1).toULongLong(); - //libraryId = QCoreApplication::arguments().at(3).split("=").at(1).toULongLong(); - this->libraryId=libraryId; -// this->path=path; - - enableActions(); - - currentComicDB.id = comicId; - YACReaderLocalClient client; - int tries = 1; - bool success = false; - while(!(success = client.requestComicInfo(libraryId,currentComicDB,siblingComics)) && tries != 0) - tries--; - - if(success) - { - isClient = true; - open(path+currentComicDB.path,currentComicDB,siblingComics); - } - else - { - isClient = false; - QMessageBox::information(this,"Connection Error", "Unable to connect to YACReaderLibrary"); - //error - } - - optionsDialog->setFilters(currentComicDB.info.brightness, currentComicDB.info.contrast, currentComicDB.info.gamma); -} - -void MainWindowViewer::openComicFromPath(QString pathFile) -{ - openComic(pathFile); - isClient = false; //this method is used for direct openings -} - -//isClient shouldn't be modified when a siblinig comic is opened -void MainWindowViewer::openSiblingComic(QString pathFile) -{ - openComic(pathFile); -} - -void MainWindowViewer::openComic(QString pathFile) -{ - QFileInfo fi(pathFile); - currentDirectory = fi.dir().absolutePath(); - getSiblingComics(fi.absolutePath(),fi.fileName()); - - setWindowTitle("YACReader - " + fi.fileName()); - - enableActions(); - - viewer->open(pathFile); - Configuration::getConfiguration().updateOpenRecentList(fi.absoluteFilePath()); - refreshRecentFilesActionList(); - } - -void MainWindowViewer::openFolder() -{ - QFileDialog openDialog; - QString pathDir = openDialog.getExistingDirectory(this,tr("Open folder"),currentDirectory); - if (!pathDir.isEmpty()) - { - openFolderFromPath(pathDir); - isClient = false; - } -} - -void MainWindowViewer::openFolderFromPath(QString pathDir) -{ - currentDirectory = pathDir; //TODO ?? - QFileInfo fi(pathDir); - getSiblingComics(fi.absolutePath(),fi.fileName()); - - setWindowTitle("YACReader - " + fi.fileName()); - - enableActions(); - - viewer->open(pathDir); - Configuration::getConfiguration().updateOpenRecentList(fi.absoluteFilePath()); - refreshRecentFilesActionList(); -} - -void MainWindowViewer::openFolderFromPath(QString pathDir, QString atFileName) -{ - currentDirectory = pathDir; //TODO ?? - QFileInfo fi(pathDir); - getSiblingComics(fi.absolutePath(),fi.fileName()); - - setWindowTitle("YACReader - " + fi.fileName()); - - enableActions(); - - QDir d(pathDir); - d.setFilter(QDir::Files|QDir::NoDotAndDotDot); - d.setNameFilters(Comic::getSupportedImageFormats()); - d.setSorting(QDir::Name|QDir::IgnoreCase|QDir::LocaleAware); - QStringList list = d.entryList(); - - qSort(list.begin(),list.end(),naturalSortLessThanCI); - int i = 0; - foreach(QString path,list) - { - if(path.endsWith(atFileName)) - break; - i++; - } - - int index = 0; - if(i < list.count()) - index = i; - - viewer->open(pathDir,index); -} - -void MainWindowViewer::saveImage() -{ - QFileDialog saveDialog; - QString pathFile = saveDialog.getSaveFileName(this,tr("Save current page"),currentDirectoryImgDest+"/"+tr("page_%1.jpg").arg(viewer->getIndex()),tr("Image files (*.jpg)")); - if (!pathFile.isEmpty()) - { - QFileInfo fi(pathFile); - currentDirectoryImgDest = fi.absolutePath(); - const QPixmap * p = viewer->pixmap(); - if(p!=NULL) - p->save(pathFile); - } -} - -void MainWindowViewer::enableActions() -{ - saveImageAction->setDisabled(false); - prevAction->setDisabled(false); - nextAction->setDisabled(false); - adjustHeightAction->setDisabled(false); - adjustWidthAction->setDisabled(false); - goToPageAction->setDisabled(false); - //alwaysOnTopAction->setDisabled(false); - leftRotationAction->setDisabled(false); - rightRotationAction->setDisabled(false); - showMagnifyingGlassAction->setDisabled(false); - doublePageAction->setDisabled(false); - doubleMangaPageAction->setDisabled(false); - adjustToFullSizeAction->setDisabled(false); - adjustToFullSizeAction->setDisabled(false); - fitToPageAction->setDisabled(false); - showZoomSliderlAction->setDisabled(false); - increasePageZoomAction->setDisabled(false); - decreasePageZoomAction->setDisabled(false); - resetZoomAction->setDisabled(false); - //setBookmark->setDisabled(false); - showBookmarksAction->setDisabled(false); - showInfoAction->setDisabled(false); //TODO enable goTo and showInfo (or update) when numPages emited - showDictionaryAction->setDisabled(false); - showFlowAction->setDisabled(false); - -#ifdef Q_OS_MAC - activateWindow(); - raise(); -#endif -} -void MainWindowViewer::disableActions() -{ - saveImageAction->setDisabled(true); - prevAction->setDisabled(true); - nextAction->setDisabled(true); - adjustHeightAction->setDisabled(true); - adjustWidthAction->setDisabled(true); - goToPageAction->setDisabled(true); - //alwaysOnTopAction->setDisabled(true); - leftRotationAction->setDisabled(true); - rightRotationAction->setDisabled(true); - showMagnifyingGlassAction->setDisabled(true); - doublePageAction->setDisabled(true); - doubleMangaPageAction->setDisabled(true); - adjustToFullSizeAction->setDisabled(true); - fitToPageAction->setDisabled(true); - showZoomSliderlAction->setDisabled(true); - increasePageZoomAction->setDisabled(true); - decreasePageZoomAction->setDisabled(true); - resetZoomAction->setDisabled(true); - setBookmarkAction->setDisabled(true); - showBookmarksAction->setDisabled(true); - showInfoAction->setDisabled(true); //TODO enable goTo and showInfo (or update) when numPages emited - openPreviousComicAction->setDisabled(true); - openNextComicAction->setDisabled(true); - showDictionaryAction->setDisabled(true); - showFlowAction->setDisabled(true); -} - -void MainWindowViewer::keyPressEvent(QKeyEvent *event) -{ - //TODO remove unused keys - int _key = event->key(); - Qt::KeyboardModifiers modifiers = event->modifiers(); - - if(modifiers & Qt::ShiftModifier) - _key |= Qt::SHIFT; - if (modifiers & Qt::ControlModifier) - _key |= Qt::CTRL; - if (modifiers & Qt::MetaModifier) - _key |= Qt::META; - if (modifiers & Qt::AltModifier) - _key |= Qt::ALT; - - QKeySequence key(_key); - - if (key == ShortcutsManager::getShortcutsManager().getShortcut(TOGGLE_FULL_SCREEN_ACTION_Y)) - { - toggleFullScreen(); - event->accept(); - } - else if (key == ShortcutsManager::getShortcutsManager().getShortcut(TOGGLE_TOOL_BARS_ACTION_Y)) - { - toggleToolBars(); - event->accept(); - } - else if (key == ShortcutsManager::getShortcutsManager().getShortcut(CHANGE_FIT_ACTION_Y)) - { - toggleWidthHeight(); - event->accept(); - } - else - QWidget::keyPressEvent(event); -} - -void MainWindowViewer::mouseDoubleClickEvent ( QMouseEvent * event ) -{ - toggleFullScreen(); - event->accept(); -} - -void MainWindowViewer::toggleFullScreen() -{ - fullscreen?toNormal():toFullScreen(); - Configuration::getConfiguration().setFullScreen(fullscreen = !fullscreen); -} - -#ifdef Q_OS_WIN //fullscreen mode in Windows for preventing this bug: QTBUG-41309 https://bugreports.qt.io/browse/QTBUG-41309 - -void MainWindowViewer::toFullScreen() -{ - fromMaximized = this->isMaximized(); - - hideToolBars(); - viewer->hide(); - viewer->fullscreen = true;//TODO, change by the right use of windowState(); - - previousWindowFlags = windowFlags(); - previousPos = pos(); - previousSize = size(); - - showNormal(); - setWindowFlags(previousWindowFlags | Qt::FramelessWindowHint); - - const QRect r = windowHandle()->screen()->geometry(); - - move(r.x(), r.y()); - resize(r.width(),r.height()+1); - show(); - - viewer->show(); - if(viewer->magnifyingGlassIsVisible()) - viewer->showMagnifyingGlass(); -} - -void MainWindowViewer::toNormal() -{ - //show all - viewer->hide(); - viewer->fullscreen = false;//TODO, change by the right use of windowState(); - //viewer->hideMagnifyingGlass(); - - setWindowFlags(previousWindowFlags); - move(previousPos); - resize(previousSize); - show(); - - if(fromMaximized) - showMaximized(); - - if(Configuration::getConfiguration().getShowToolbars()) - showToolBars(); - viewer->show(); - if(viewer->magnifyingGlassIsVisible()) - viewer->showMagnifyingGlass(); -} - -#else -void MainWindowViewer::toFullScreen() -{ - fromMaximized = this->isMaximized(); - - hideToolBars(); - viewer->hide(); - viewer->fullscreen = true;//TODO, change by the right use of windowState(); - setWindowState(Qt::WindowFullScreen); - viewer->show(); - if(viewer->magnifyingGlassIsVisible()) - viewer->showMagnifyingGlass(); -} - -void MainWindowViewer::toNormal() -{ - //show all - viewer->hide(); - viewer->fullscreen = false;//TODO, change by the right use of windowState(); - //viewer->hideMagnifyingGlass(); - if(fromMaximized) - showMaximized(); - else - showNormal(); - - if(Configuration::getConfiguration().getShowToolbars()) - showToolBars(); - viewer->show(); - if(viewer->magnifyingGlassIsVisible()) - viewer->showMagnifyingGlass(); -} -#endif - -void MainWindowViewer::toggleToolBars() -{ - toolbars?hideToolBars():showToolBars(); - - Configuration::getConfiguration().setShowToolbars(toolbars); -#ifndef Q_OS_MAC - comicToolBar->setMovable(false); -#endif -} -void MainWindowViewer::hideToolBars() -{ - //hide all - this->comicToolBar->hide(); - toolbars = false; -} - -void MainWindowViewer::showToolBars() -{ - this->comicToolBar->show(); - toolbars = true; -} -void MainWindowViewer::fitToWidth() -{ - Configuration::getConfiguration().setFitMode(YACReader::FitMode::ToWidth); - viewer->setZoomFactor(100); - viewer->updatePage(); -} -void MainWindowViewer::fitToHeight() -{ - Configuration::getConfiguration().setFitMode(YACReader::FitMode::ToHeight); - viewer->setZoomFactor(100); - viewer->updatePage(); -} - -void MainWindowViewer::toggleWidthHeight() -{ - //Only switch to "Fit to height" when we're in "Fit to width" - if (Configuration::getConfiguration().getFitMode() == YACReader::FitMode::ToWidth) - { - adjustHeightAction->trigger(); - } - //Default to "Fit to width" in all other cases - else - { - adjustWidthAction->trigger(); - } -} -void MainWindowViewer::checkNewVersion() -{ - Configuration & conf = Configuration::getConfiguration(); - QDate lastCheck = conf.getLastVersionCheck(); - QDate current = QDate::currentDate(); - if(lastCheck.isNull() || lastCheck.daysTo(current) >= conf.getNumDaysBetweenVersionChecks()) - { - versionChecker = new HttpVersionChecker(); - - connect(versionChecker,SIGNAL(newVersionDetected()), - this,SLOT(newVersion())); - - QTimer * tT = new QTimer; - tT->setSingleShot(true); - connect(tT, SIGNAL(timeout()), versionChecker, SLOT(get())); - //versionChecker->get(); //TOD� - tT->start(100); - - conf.setLastVersionCheck(current); - } -} - -void MainWindowViewer::processReset() -{ - if(isClient) - { - if(siblingComics.count()>1) - { - bool openNextB = openNextComicAction->isEnabled(); - bool openPrevB = openPreviousComicAction->isEnabled(); - disableActions(); - openNextComicAction->setEnabled(openNextB); - openPreviousComicAction->setEnabled(openPrevB); - } - else - disableActions(); - } - else - disableActions(); -} - -void MainWindowViewer::setUpShortcutsManagement() -{ - //actions holder - QObject * orphanActions = new QObject; - - QList allActions; - QList tmpList; - - - editShortcutsDialog->addActionsGroup(tr("Comics"),QIcon(":/images/shortcuts_group_comics.png"), - tmpList = { openAction, - openLatestComicAction, - openFolderAction, - saveImageAction, - openPreviousComicAction, - openNextComicAction }); - - allActions << tmpList; - - //keys without actions (General) - QAction * toggleFullScreenAction = new QAction(tr("Toggle fullscreen mode"),orphanActions); - toggleFullScreenAction->setData(TOGGLE_FULL_SCREEN_ACTION_Y); - toggleFullScreenAction->setShortcut(ShortcutsManager::getShortcutsManager().getShortcut(TOGGLE_FULL_SCREEN_ACTION_Y)); - - QAction * toggleToolbarsAction = new QAction(tr("Hide/show toolbar"),orphanActions); - toggleToolbarsAction->setData(TOGGLE_TOOL_BARS_ACTION_Y); - toggleToolbarsAction->setShortcut(ShortcutsManager::getShortcutsManager().getShortcut(TOGGLE_TOOL_BARS_ACTION_Y)); - - editShortcutsDialog->addActionsGroup(tr("General"),QIcon(":/images/shortcuts_group_general.png"), - tmpList = QList() - << optionsAction - << helpAboutAction - << showShorcutsAction - << showInfoAction - << closeAction - << showDictionaryAction - << showFlowAction - << toggleFullScreenAction - << toggleToolbarsAction - << showEditShortcutsAction); - - allActions << tmpList; - - //keys without actions (MGlass) - QAction * sizeUpMglassAction = new QAction(tr("Size up magnifying glass"),orphanActions); - sizeUpMglassAction->setData(SIZE_UP_MGLASS_ACTION_Y); - sizeUpMglassAction->setShortcut(ShortcutsManager::getShortcutsManager().getShortcut(SIZE_UP_MGLASS_ACTION_Y)); - - QAction * sizeDownMglassAction = new QAction(tr("Size down magnifying glass"),orphanActions); - sizeDownMglassAction->setData(SIZE_DOWN_MGLASS_ACTION_Y); - sizeDownMglassAction->setShortcut(ShortcutsManager::getShortcutsManager().getShortcut(SIZE_DOWN_MGLASS_ACTION_Y)); - - QAction * zoomInMglassAction = new QAction(tr("Zoom in magnifying glass"),orphanActions); - zoomInMglassAction->setData(ZOOM_IN_MGLASS_ACTION_Y); - zoomInMglassAction->setShortcut(ShortcutsManager::getShortcutsManager().getShortcut(ZOOM_IN_MGLASS_ACTION_Y)); - - QAction * zoomOutMglassAction = new QAction(tr("Zoom out magnifying glass"),orphanActions); - zoomOutMglassAction->setData(ZOOM_OUT_MGLASS_ACTION_Y); - zoomOutMglassAction->setShortcut(ShortcutsManager::getShortcutsManager().getShortcut(ZOOM_OUT_MGLASS_ACTION_Y)); - - editShortcutsDialog->addActionsGroup(tr("Magnifiying glass"),QIcon(":/images/shortcuts_group_mglass.png"), - tmpList = QList() - << showMagnifyingGlassAction - << sizeUpMglassAction - << sizeDownMglassAction - << zoomInMglassAction - << zoomOutMglassAction); - - allActions << tmpList; - - //keys without actions - QAction * toggleFitToScreenAction = new QAction(tr("Toggle between fit to width and fit to height"),orphanActions); - toggleFitToScreenAction->setData(CHANGE_FIT_ACTION_Y); - toggleFitToScreenAction->setShortcut(ShortcutsManager::getShortcutsManager().getShortcut(CHANGE_FIT_ACTION_Y)); - - editShortcutsDialog->addActionsGroup(tr("Page adjustement"),QIcon(":/images/shortcuts_group_page.png"), - tmpList = QList() - << adjustHeightAction - << adjustWidthAction - << toggleFitToScreenAction - << leftRotationAction - << rightRotationAction - << doublePageAction - << doubleMangaPageAction - << adjustToFullSizeAction - << increasePageZoomAction - << decreasePageZoomAction - << resetZoomAction); - - allActions << tmpList; - - QAction * autoScrollForwardAction = new QAction(tr("Autoscroll down"),orphanActions); - autoScrollForwardAction->setData(AUTO_SCROLL_FORWARD_ACTION_Y); - autoScrollForwardAction->setShortcut(ShortcutsManager::getShortcutsManager().getShortcut(AUTO_SCROLL_FORWARD_ACTION_Y)); - - QAction * autoScrollBackwardAction = new QAction(tr("Autoscroll up"),orphanActions); - autoScrollBackwardAction->setData(AUTO_SCROLL_BACKWARD_ACTION_Y); - autoScrollBackwardAction->setShortcut(ShortcutsManager::getShortcutsManager().getShortcut(AUTO_SCROLL_BACKWARD_ACTION_Y)); - - QAction * autoScrollForwardHorizontalFirstAction = new QAction(tr("Autoscroll forward, horizontal first"),orphanActions); - autoScrollForwardHorizontalFirstAction->setData(AUTO_SCROLL_FORWARD_HORIZONTAL_FIRST_ACTION_Y); - autoScrollForwardHorizontalFirstAction->setShortcut(ShortcutsManager::getShortcutsManager().getShortcut(AUTO_SCROLL_FORWARD_HORIZONTAL_FIRST_ACTION_Y)); - - QAction * autoScrollBackwardHorizontalFirstAction = new QAction(tr("Autoscroll backward, horizontal first"),orphanActions); - autoScrollBackwardHorizontalFirstAction->setData(AUTO_SCROLL_BACKWARD_HORIZONTAL_FIRST_ACTION_Y); - autoScrollBackwardHorizontalFirstAction->setShortcut(ShortcutsManager::getShortcutsManager().getShortcut(AUTO_SCROLL_BACKWARD_HORIZONTAL_FIRST_ACTION_Y)); - - QAction * autoScrollForwardVerticalFirstAction = new QAction(tr("Autoscroll forward, vertical first"),orphanActions); - autoScrollForwardVerticalFirstAction->setData(AUTO_SCROLL_FORWARD_VERTICAL_FIRST_ACTION_Y); - autoScrollForwardVerticalFirstAction->setShortcut(ShortcutsManager::getShortcutsManager().getShortcut(AUTO_SCROLL_FORWARD_VERTICAL_FIRST_ACTION_Y)); - - QAction * autoScrollBackwardVerticalFirstAction = new QAction(tr("Autoscroll backward, vertical first"),orphanActions); - autoScrollBackwardVerticalFirstAction->setData(AUTO_SCROLL_BACKWARD_VERTICAL_FIRST_ACTION_Y); - autoScrollBackwardVerticalFirstAction->setShortcut(ShortcutsManager::getShortcutsManager().getShortcut(AUTO_SCROLL_BACKWARD_VERTICAL_FIRST_ACTION_Y)); - - QAction * moveDownAction = new QAction(tr("Move down"),orphanActions); - moveDownAction->setData(MOVE_DOWN_ACTION_Y); - moveDownAction->setShortcut(ShortcutsManager::getShortcutsManager().getShortcut(MOVE_DOWN_ACTION_Y)); - - QAction * moveUpAction = new QAction(tr("Move up"),orphanActions); - moveUpAction->setData(MOVE_UP_ACTION_Y); - moveUpAction->setShortcut(ShortcutsManager::getShortcutsManager().getShortcut(MOVE_UP_ACTION_Y)); - - QAction * moveLeftAction = new QAction(tr("Move left"),orphanActions); - moveLeftAction->setData(MOVE_LEFT_ACTION_Y); - moveLeftAction->setShortcut(ShortcutsManager::getShortcutsManager().getShortcut(MOVE_LEFT_ACTION_Y)); - - QAction * moveRightAction = new QAction(tr("Move right"),orphanActions); - moveRightAction->setData(MOVE_RIGHT_ACTION_Y); - moveRightAction->setShortcut(ShortcutsManager::getShortcutsManager().getShortcut(MOVE_RIGHT_ACTION_Y)); - - QAction * goToFirstPageAction = new QAction(tr("Go to the first page"),orphanActions); - goToFirstPageAction->setData(GO_TO_FIRST_PAGE_ACTION_Y); - goToFirstPageAction->setShortcut(ShortcutsManager::getShortcutsManager().getShortcut(GO_TO_FIRST_PAGE_ACTION_Y)); - - QAction * goToLastPageAction = new QAction(tr("Go to the last page"),orphanActions); - goToLastPageAction->setData(GO_TO_LAST_PAGE_ACTION_Y); - goToLastPageAction->setShortcut(ShortcutsManager::getShortcutsManager().getShortcut(GO_TO_LAST_PAGE_ACTION_Y)); - - editShortcutsDialog->addActionsGroup(tr("Reading"),QIcon(":/images/shortcuts_group_reading.png"), - tmpList = QList() - << nextAction - << prevAction - << setBookmarkAction - << showBookmarksAction - << autoScrollForwardAction - << autoScrollBackwardAction - << autoScrollForwardHorizontalFirstAction - << autoScrollBackwardHorizontalFirstAction - << autoScrollForwardVerticalFirstAction - << autoScrollBackwardVerticalFirstAction - << moveDownAction - << moveUpAction - << moveLeftAction - << moveRightAction - << goToFirstPageAction - << goToLastPageAction - << goToPageAction); - - allActions << tmpList; - - ShortcutsManager::getShortcutsManager().registerActions(allActions); - -} - -void MainWindowViewer::toggleFitToWidthSlider() -{ - int y; - -#ifdef Q_OS_MAC - y = 0; -#else - y = this->comicToolBar->frameSize().height(); -#endif - - if(zoomSliderAction->isVisible()) - { - zoomSliderAction->hide(); - } - else - { - zoomSliderAction->move(250, y); - zoomSliderAction->show(); - } -} - -void MainWindowViewer::newVersion() -{ - QMessageBox msgBox; - msgBox.setText(tr("There is a new version available")); - msgBox.setInformativeText(tr("Do you want to download the new version?")); - msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::Ignore | QMessageBox::No); - msgBox.setDefaultButton(QMessageBox::Yes); - msgBox.button(QMessageBox::Ignore)->setText(tr("Remind me in 14 days")); - msgBox.button(QMessageBox::No)->setText(tr("Not now")); - msgBox.setWindowFlags(Qt::WindowStaysOnTopHint); - msgBox.setModal(true); - int ret = msgBox.exec(); - - switch(ret) - { - case QMessageBox::Yes: - QDesktopServices::openUrl(QUrl("http://www.yacreader.com")); - break; - case QMessageBox::No: - Configuration::getConfiguration().setNumDaysBetweenVersionChecks(1); - break; - case QMessageBox::Ignore: - Configuration::getConfiguration().setNumDaysBetweenVersionChecks(14); - break; - } -} - -void MainWindowViewer::closeEvent ( QCloseEvent * event ) -{ - Q_UNUSED(event) - - if(isClient) - sendComic(); - - viewer->save(); - Configuration & conf = Configuration::getConfiguration(); - if(!fullscreen && !isMaximized()) - { - conf.setPos(pos()); - conf.setSize(size()); - } - conf.setMaximized(isMaximized()); - - emit (closed()); -} - -void MainWindowViewer::openPreviousComic() -{ - if(!siblingComics.isEmpty() && isClient) - { - sendComic(); - - int currentIndex = siblingComics.indexOf(currentComicDB); - if (currentIndex == -1) - return; - if(currentIndex-1 >= 0 && currentIndex-1 < siblingComics.count()) - { - siblingComics[currentIndex] = currentComicDB; //updated - currentComicDB = siblingComics.at(currentIndex-1); - open(currentDirectory+currentComicDB.path,currentComicDB,siblingComics); - } - return; - } - if(!previousComicPath.isEmpty()) - { - openSiblingComic(previousComicPath); - } -} - -void MainWindowViewer::openNextComic() -{ - if(!siblingComics.isEmpty() && isClient) - { - sendComic(); - - int currentIndex = siblingComics.indexOf(currentComicDB); - if (currentIndex == -1) - return; - if(currentIndex+1 > 0 && currentIndex+1 < siblingComics.count()) - { - siblingComics[currentIndex] = currentComicDB; //updated - currentComicDB = siblingComics.at(currentIndex+1); - open(currentDirectory+currentComicDB.path,currentComicDB,siblingComics); - } - return; - } - if(!nextComicPath.isEmpty()) - { - openSiblingComic(nextComicPath); - } -} - -void MainWindowViewer::getSiblingComics(QString path,QString currentComic) -{ - QDir d(path); - d.setFilter(QDir::Files|QDir::NoDotAndDotDot); -#ifndef use_unarr - d.setNameFilters(QStringList() << "*.cbr" << "*.cbz" << "*.rar" << "*.zip" << "*.tar" << "*.pdf" << "*.7z" << "*.cb7" << "*.arj" << "*.cbt"); -#else - d.setNameFilters(QStringList() << "*.cbr" << "*.cbz" << "*.rar" << "*.zip" << "*.tar" << "*.pdf" << "*.cbt"); -#endif - d.setSorting(QDir::Name|QDir::IgnoreCase|QDir::LocaleAware); - QStringList list = d.entryList(); - qSort(list.begin(),list.end(),naturalSortLessThanCI); - //std::sort(list.begin(),list.end(),naturalSortLessThanCI); - int index = list.indexOf(currentComic); - if(index == -1) //comic not found - { - /*QFile f(QCoreApplication::applicationDirPath()+"/errorLog.txt"); - if(!f.open(QIODevice::WriteOnly)) - { - QMessageBox::critical(NULL,tr("Saving error log file...."),tr("There was a problem saving YACReader error log file. Please, check if you have enough permissions in the YACReader root folder.")); - } - else - { - QTextStream txtS(&f); - txtS << "METHOD : MainWindowViewer::getSiblingComics" << '\n'; - txtS << "ERROR : current comic not found in its own path" << '\n'; - txtS << path << '\n'; - txtS << currentComic << '\n'; - txtS << "Comic list count : " + list.count() << '\n'; - foreach(QString s, list){ - txtS << s << '\n'; - } - f.close(); - }*/ - } - - previousComicPath = nextComicPath = ""; - if(index>0) - { - previousComicPath = path+"/"+list.at(index-1); - openPreviousComicAction->setDisabled(false); - } - else - openPreviousComicAction->setDisabled(true); - - if(index+1setDisabled(false); - } - else - openNextComicAction->setDisabled(true); -} - -void MainWindowViewer::dropEvent(QDropEvent *event) -{ - QList urlList; - QString fName; - QFileInfo info; - - if (event->mimeData()->hasUrls()) - { - urlList = event->mimeData()->urls(); - - if ( urlList.size() > 0 ) - { - fName = urlList[0].toLocalFile(); // convert first QUrl to local path - info.setFile( fName ); // information about file - if (info.isFile()) - { - QStringList imageSuffixs = Comic::getSupportedImageLiteralFormats(); - if(imageSuffixs.contains(info.suffix())) //image dropped - openFolderFromPath(info.absoluteDir().absolutePath(),info.fileName()); - else - openComicFromPath(fName); // if is file, setText - } - else - if(info.isDir()) - openFolderFromPath(fName); - - isClient = false; - } - } - - event->acceptProposedAction(); -} -void MainWindowViewer::dragEnterEvent(QDragEnterEvent *event) -{ - // accept just text/uri-list mime format - if (event->mimeData()->hasFormat("text/uri-list")) - { - event->acceptProposedAction(); - isClient = false; - } -} - -void MainWindowViewer::alwaysOnTopSwitch() -{ - if(!Configuration::getConfiguration().getAlwaysOnTop()) - { - setWindowFlags(this->windowFlags() | Qt::CustomizeWindowHint | Qt::WindowStaysOnTopHint); //always on top - show(); - } - else - { - setWindowFlags(this->windowFlags() ^ (Qt::CustomizeWindowHint | Qt::WindowStaysOnTopHint)); - show(); - } - Configuration::getConfiguration().setAlwaysOnTop(!Configuration::getConfiguration().getAlwaysOnTop()); -} - -void MainWindowViewer::adjustToFullSizeSwitch() -{ - Configuration::getConfiguration().setFitMode(YACReader::FitMode::FullRes); - viewer->setZoomFactor(100); - viewer->updatePage(); -} - -void MainWindowViewer::fitToPageSwitch() -{ - Configuration::getConfiguration().setFitMode(YACReader::FitMode::FullPage); - viewer->setZoomFactor(100); - viewer->updatePage(); -} - -void MainWindowViewer::resetZoomLevel() -{ - viewer->setZoomFactor(100); - viewer->updatePage(); -} - -void MainWindowViewer::increasePageZoomLevel() -{ - viewer->increaseZoomFactor(); -} - -void MainWindowViewer::decreasePageZoomLevel() -{ - viewer->decreaseZoomFactor(); -} - -void MainWindowViewer::sendComic() -{ - YACReaderLocalClient * client = new YACReaderLocalClient; - - connect(client, &YACReaderLocalClient::finished, client, &YACReaderLocalClient::deleteLater); - currentComicDB.info.lastTimeOpened = QDateTime::currentMSecsSinceEpoch() / 1000; - - viewer->updateComic(currentComicDB); - - if (currentComicDB.info.currentPage == currentComicDB.info.numPages) { - int currentIndex = siblingComics.indexOf(currentComicDB); - if(currentIndex+1 > 0 && currentIndex+1 < siblingComics.count()) - { - ComicDB & nextComic = siblingComics[currentIndex+1]; - nextComic.info.hasBeenOpened = true; - int retries = 1; - while(!client->sendComicInfo(libraryId, currentComicDB, nextComic.id) && retries!=0) - retries--; - } - } else { - int retries = 1; - while(!client->sendComicInfo(libraryId, currentComicDB) && retries!=0) - retries--; - } -} +#include "main_window_viewer.h" +#include "configuration.h" +#include "viewer.h" +#include "goto_dialog.h" +#include "custom_widgets.h" +#include "options_dialog.h" +#include "check_new_version.h" +#include "comic.h" +#include "bookmarks_dialog.h" +#include "shortcuts_dialog.h" +#include "width_slider.h" +#include "qnaturalsorting.h" +#include "help_about_dialog.h" +#include "yacreader_tool_bar_stretch.h" + +#include "comic_db.h" +#include "yacreader_local_client.h" + +#include "yacreader_global.h" +#include "edit_shortcuts_dialog.h" +#include "shortcuts_manager.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* 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),alwaysOnTop(false),currentDirectory("."),currentDirectoryImgDest("."),isClient(false) +{ + loadConfiguration(); + setupUI(); +} + +MainWindowViewer::~MainWindowViewer() +{ + delete settings; + delete viewer; + delete had; + + //delete sliderAction; + delete openAction; + delete openFolderAction; + delete openLatestComicAction; + delete saveImageAction; + delete openPreviousComicAction; + delete openNextComicAction; + delete prevAction; + delete nextAction; + delete adjustHeightAction; + delete adjustWidthAction; + delete leftRotationAction; + delete rightRotationAction; + delete doublePageAction; + delete doubleMangaPageAction; + delete increasePageZoomAction; + delete decreasePageZoomAction; + delete resetZoomAction; + delete goToPageAction; + delete optionsAction; + delete helpAboutAction; + delete showMagnifyingGlassAction; + delete setBookmarkAction; + delete showBookmarksAction; + delete showShorcutsAction; + delete showInfoAction; + delete closeAction; + delete showDictionaryAction; + delete alwaysOnTopAction; + delete adjustToFullSizeAction; + delete fitToPageAction; + delete showFlowAction; + +} +void MainWindowViewer::loadConfiguration() +{ + settings = new QSettings(YACReader::getSettingsPath()+"/YACReader.ini",QSettings::IniFormat); + + Configuration & config = Configuration::getConfiguration(); + config.load(settings); + currentDirectory = config.getDefaultPath(); + fullscreen = config.getFullScreen(); +} + +void MainWindowViewer::setupUI() +{ + //setUnifiedTitleAndToolBarOnMac(true); + + viewer = new Viewer(this); + connect(viewer,SIGNAL(reset()),this,SLOT(processReset())); + //detected end of comic + connect(viewer,SIGNAL(openNextComic()),this,SLOT(openNextComic())); + //detected start of comic + connect(viewer,SIGNAL(openPreviousComic()),this,SLOT(openPreviousComic())); + + setCentralWidget(viewer); + int heightDesktopResolution = QApplication::desktop()->screenGeometry().height(); + int widthDesktopResolution = QApplication::desktop()->screenGeometry().width(); + int height,width; + height = static_cast(heightDesktopResolution*0.84); + width = static_cast(height*0.70); + Configuration & conf = Configuration::getConfiguration(); + QPoint p = conf.getPos(); + QSize s = conf.getSize(); + if(s.width()!=0) + { + move(p); + resize(s); + } + else + { + move(QPoint((widthDesktopResolution-width)/2,((heightDesktopResolution-height)-40)/2)); + resize(QSize(width,height)); + } + + had = new HelpAboutDialog(this); //TODO load data + + had->loadAboutInformation(":/files/about.html"); + had->loadHelp(":/files/helpYACReader.html"); + + optionsDialog = new OptionsDialog(this); + connect(optionsDialog,SIGNAL(accepted()),viewer,SLOT(updateOptions())); + connect(optionsDialog, SIGNAL(optionsChanged()),this,SLOT(reloadOptions())); + connect(optionsDialog,SIGNAL(changedFilters(int,int,int)),viewer,SLOT(updateFilters(int,int,int))); + + optionsDialog->restoreOptions(settings); + //shortcutsDialog = new ShortcutsDialog(this); + editShortcutsDialog = new EditShortcutsDialog(this); + connect(optionsDialog,SIGNAL(editShortcuts()),editShortcutsDialog,SLOT(show())); + + createActions(); + setUpShortcutsManagement(); + + createToolBars(); + + setWindowTitle("YACReader"); + + checkNewVersion(); + + viewer->setFocusPolicy(Qt::StrongFocus); + + + //if(Configuration::getConfiguration().getAlwaysOnTop()) + //{ + // setWindowFlags(this->windowFlags() | Qt::CustomizeWindowHint | Qt::WindowStaysOnTopHint); + //} + + previousWindowFlags = windowFlags(); + previousPos = pos(); + previousSize = size(); + + if(fullscreen) + toFullScreen(); + if(conf.getMaximized()) + showMaximized(); + + setAcceptDrops(true); + + if(Configuration::getConfiguration().getShowToolbars() && !Configuration::getConfiguration().getFullScreen()) + showToolBars(); + else + hideToolBars(); +} + +void MainWindowViewer::createActions() +{ + openAction = new QAction(tr("&Open"),this); + openAction->setIcon(QIcon(":/images/viewer_toolbar/open.png")); + openAction->setToolTip(tr("Open a comic")); + openAction->setData(OPEN_ACTION_Y); + openAction->setShortcut(ShortcutsManager::getShortcutsManager().getShortcut(OPEN_ACTION_Y)); + connect(openAction, SIGNAL(triggered()), this, SLOT(open())); + + openFolderAction = new QAction(tr("Open Folder"),this); + openFolderAction->setIcon(QIcon(":/images/viewer_toolbar/openFolder.png")); + openFolderAction->setToolTip(tr("Open image folder")); + openFolderAction->setData(OPEN_FOLDER_ACTION_Y); + openFolderAction->setShortcut(ShortcutsManager::getShortcutsManager().getShortcut(OPEN_FOLDER_ACTION_Y)); + connect(openFolderAction, SIGNAL(triggered()), this, SLOT(openFolder())); + + openLatestComicAction = new QAction(tr("Open latest comic"), this); + openLatestComicAction->setToolTip(tr("Open the latest comic opened in the previous reading session")); + openLatestComicAction->setData(OPEN_LATEST_COMIC_Y); + openLatestComicAction->setShortcut(ShortcutsManager::getShortcutsManager().getShortcut(OPEN_LATEST_COMIC_Y)); + connect(openLatestComicAction, SIGNAL(triggered()), this, SLOT(openLatestComic())); + + QAction* recentFileAction = nullptr; + //TODO: Replace limit with a configurable value + for (int i = 0; i < Configuration::getConfiguration().getOpenRecentSize(); i++) + { + recentFileAction = new QAction(this); + recentFileAction->setVisible(false); + QObject::connect(recentFileAction, &QAction::triggered, this, &MainWindowViewer::openRecent); + recentFilesActionList.append(recentFileAction); + } + + clearRecentFilesAction = new QAction(tr("Clear"),this); + clearRecentFilesAction->setToolTip(tr("Clear open recent list")); + connect(clearRecentFilesAction, &QAction::triggered, this, &MainWindowViewer::clearRecentFiles); + + saveImageAction = new QAction(tr("Save"),this); + saveImageAction->setIcon(QIcon(":/images/viewer_toolbar/save.png")); + saveImageAction->setToolTip(tr("Save current page")); + saveImageAction->setDisabled(true); + saveImageAction->setData(SAVE_IMAGE_ACTION_Y); + saveImageAction->setShortcut(ShortcutsManager::getShortcutsManager().getShortcut(SAVE_IMAGE_ACTION_Y)); + connect(saveImageAction,SIGNAL(triggered()),this,SLOT(saveImage())); + + openPreviousComicAction = new QAction(tr("Previous Comic"),this); + openPreviousComicAction->setIcon(QIcon(":/images/viewer_toolbar/openPrevious.png")); + openPreviousComicAction->setToolTip(tr("Open previous comic")); + openPreviousComicAction->setDisabled(true); + openPreviousComicAction->setData(OPEN_PREVIOUS_COMIC_ACTION_Y); + openPreviousComicAction->setShortcut(ShortcutsManager::getShortcutsManager().getShortcut(OPEN_PREVIOUS_COMIC_ACTION_Y)); + connect(openPreviousComicAction,SIGNAL(triggered()),this,SLOT(openPreviousComic())); + + openNextComicAction = new QAction(tr("Next Comic"),this); + openNextComicAction->setIcon(QIcon(":/images/viewer_toolbar/openNext.png")); + openNextComicAction->setToolTip(tr("Open next comic")); + openNextComicAction->setDisabled(true); + openNextComicAction->setData(OPEN_NEXT_COMIC_ACTION_Y); + openNextComicAction->setShortcut(ShortcutsManager::getShortcutsManager().getShortcut(OPEN_NEXT_COMIC_ACTION_Y)); + connect(openNextComicAction,SIGNAL(triggered()),this,SLOT(openNextComic())); + + prevAction = new QAction(tr("&Previous"),this); + prevAction->setIcon(QIcon(":/images/viewer_toolbar/previous.png")); + prevAction->setShortcutContext(Qt::WidgetShortcut); + prevAction->setToolTip(tr("Go to previous page")); + prevAction->setDisabled(true); + prevAction->setData(PREV_ACTION_Y); + prevAction->setShortcut(ShortcutsManager::getShortcutsManager().getShortcut(PREV_ACTION_Y)); + connect(prevAction, SIGNAL(triggered()),viewer,SLOT(prev())); + + nextAction = new QAction(tr("&Next"),this); + nextAction->setIcon(QIcon(":/images/viewer_toolbar/next.png")); + nextAction->setShortcutContext(Qt::WidgetShortcut); + nextAction->setToolTip(tr("Go to next page")); + nextAction->setDisabled(true); + nextAction->setData(NEXT_ACTION_Y); + nextAction->setShortcut(ShortcutsManager::getShortcutsManager().getShortcut(NEXT_ACTION_Y)); + connect(nextAction, SIGNAL(triggered()),viewer,SLOT(next())); + + adjustHeightAction = new QAction(tr("Fit Height"),this); + adjustHeightAction->setIcon(QIcon(":/images/viewer_toolbar/toHeight.png")); + //adjustWidth->setCheckable(true); + adjustHeightAction->setDisabled(true); + adjustHeightAction->setToolTip(tr("Fit image to height")); + //adjustWidth->setIcon(QIcon(":/images/fitWidth.png")); + adjustHeightAction->setData(ADJUST_HEIGHT_ACTION_Y); + adjustHeightAction->setShortcut(ShortcutsManager::getShortcutsManager().getShortcut(ADJUST_HEIGHT_ACTION_Y)); + adjustHeightAction->setCheckable(true); + connect(adjustHeightAction, SIGNAL(triggered()),this,SLOT(fitToHeight())); + + adjustWidthAction = new QAction(tr("Fit Width"),this); + adjustWidthAction->setIcon(QIcon(":/images/viewer_toolbar/toWidth.png")); + //adjustWidth->setCheckable(true); + adjustWidthAction->setDisabled(true); + adjustWidthAction->setToolTip(tr("Fit image to width")); + //adjustWidth->setIcon(QIcon(":/images/fitWidth.png")); + adjustWidthAction->setData(ADJUST_WIDTH_ACTION_Y); + adjustWidthAction->setShortcut(ShortcutsManager::getShortcutsManager().getShortcut(ADJUST_WIDTH_ACTION_Y)); + adjustWidthAction->setCheckable(true); + connect(adjustWidthAction, SIGNAL(triggered()),this,SLOT(fitToWidth())); + + adjustToFullSizeAction = new QAction(tr("Show full size"),this); + adjustToFullSizeAction->setIcon(QIcon(":/images/viewer_toolbar/full.png")); + adjustToFullSizeAction->setCheckable(false); + adjustToFullSizeAction->setDisabled(true); + adjustToFullSizeAction->setData(ADJUST_TO_FULL_SIZE_ACTION_Y); + adjustToFullSizeAction->setShortcut(ShortcutsManager::getShortcutsManager().getShortcut(ADJUST_TO_FULL_SIZE_ACTION_Y)); + adjustToFullSizeAction->setCheckable(true); + connect(adjustToFullSizeAction,SIGNAL(triggered()),this,SLOT(adjustToFullSizeSwitch())); + + fitToPageAction = new QAction(tr("Fit to page"),this); + fitToPageAction->setIcon(QIcon(":/images/viewer_toolbar/fitToPage.png")); + fitToPageAction->setDisabled(true); + fitToPageAction->setData(FIT_TO_PAGE_ACTION_Y); + fitToPageAction->setShortcut(ShortcutsManager::getShortcutsManager().getShortcut(FIT_TO_PAGE_ACTION_Y)); + fitToPageAction->setCheckable(true); + connect(fitToPageAction,SIGNAL(triggered()),this,SLOT(fitToPageSwitch())); + + //fit modes have to be exclusive and checkable + QActionGroup *fitModes = new QActionGroup(this); + fitModes->addAction(adjustHeightAction); + fitModes->addAction(adjustWidthAction); + fitModes->addAction(adjustToFullSizeAction); + fitModes->addAction(fitToPageAction); + + switch(Configuration::getConfiguration().getFitMode()) + { + case YACReader::FitMode::ToWidth: + adjustWidthAction->setChecked(true); + break; + case YACReader::FitMode::ToHeight: + adjustHeightAction->setChecked(true); + break; + case YACReader::FitMode::FullRes: + adjustToFullSizeAction->setChecked(true); + break; + case YACReader::FitMode::FullPage: + fitToPageAction->setChecked(true); + break; + default: + fitToPageAction->setChecked(true); + } + + resetZoomAction = new QAction(tr("Reset zoom"), this); + resetZoomAction->setDisabled(true); + resetZoomAction->setData(RESET_ZOOM_ACTION_Y); + resetZoomAction->setShortcut(ShortcutsManager::getShortcutsManager().getShortcut(RESET_ZOOM_ACTION_Y)); + connect(resetZoomAction,SIGNAL(triggered()),this,SLOT(resetZoomLevel())); + + showZoomSliderlAction = new QAction(tr("Show zoom slider"), this); + showZoomSliderlAction->setIcon(QIcon(":/images/viewer_toolbar/zoom.png")); + showZoomSliderlAction->setDisabled(true); + + increasePageZoomAction = new QAction(tr("Zoom+"),this); + increasePageZoomAction->setDisabled(true); + increasePageZoomAction->setData(ZOOM_PLUS_ACTION_Y); + increasePageZoomAction->setShortcut(ShortcutsManager::getShortcutsManager().getShortcut(ZOOM_PLUS_ACTION_Y)); + connect(increasePageZoomAction,SIGNAL(triggered()),this,SLOT(increasePageZoomLevel())); + + decreasePageZoomAction = new QAction(tr("Zoom-"),this); + decreasePageZoomAction->setDisabled(true); + decreasePageZoomAction->setData(ZOOM_MINUS_ACTION_Y); + decreasePageZoomAction->setShortcut(ShortcutsManager::getShortcutsManager().getShortcut(ZOOM_MINUS_ACTION_Y)); + connect(decreasePageZoomAction,SIGNAL(triggered()),this,SLOT(decreasePageZoomLevel())); + + leftRotationAction = new QAction(tr("Rotate image to the left"),this); + leftRotationAction->setIcon(QIcon(":/images/viewer_toolbar/rotateL.png")); + leftRotationAction->setDisabled(true); + leftRotationAction->setData(LEFT_ROTATION_ACTION_Y); + leftRotationAction->setShortcut(ShortcutsManager::getShortcutsManager().getShortcut(LEFT_ROTATION_ACTION_Y)); + connect(leftRotationAction, SIGNAL(triggered()),viewer,SLOT(rotateLeft())); + + rightRotationAction = new QAction(tr("Rotate image to the right"),this); + rightRotationAction->setIcon(QIcon(":/images/viewer_toolbar/rotateR.png")); + rightRotationAction->setDisabled(true); + rightRotationAction->setData(RIGHT_ROTATION_ACTION_Y); + rightRotationAction->setShortcut(ShortcutsManager::getShortcutsManager().getShortcut(RIGHT_ROTATION_ACTION_Y)); + connect(rightRotationAction, SIGNAL(triggered()),viewer,SLOT(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->setDisabled(true); + doublePageAction->setCheckable(true); + doublePageAction->setChecked(Configuration::getConfiguration().getDoublePage()); + doublePageAction->setData(DOUBLE_PAGE_ACTION_Y); + doublePageAction->setShortcut(ShortcutsManager::getShortcutsManager().getShortcut(DOUBLE_PAGE_ACTION_Y)); + connect(doublePageAction, SIGNAL(triggered()),viewer,SLOT(doublePageSwitch())); + + //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->setDisabled(true); + doubleMangaPageAction->setCheckable(true); + doubleMangaPageAction->setChecked(Configuration::getConfiguration().getDoubleMangaPage()); + doubleMangaPageAction->setData(DOUBLE_MANGA_PAGE_ACTION_Y); + doubleMangaPageAction->setShortcut(ShortcutsManager::getShortcutsManager().getShortcut(DOUBLE_MANGA_PAGE_ACTION_Y)); + connect(doubleMangaPageAction, SIGNAL(triggered()),viewer,SLOT(doubleMangaPageSwitch())); + + goToPageAction = new QAction(tr("Go To"),this); + goToPageAction->setIcon(QIcon(":/images/viewer_toolbar/goto.png")); + goToPageAction->setDisabled(true); + goToPageAction->setToolTip(tr("Go to page ...")); + goToPageAction->setData(GO_TO_PAGE_ACTION_Y); + goToPageAction->setShortcut(ShortcutsManager::getShortcutsManager().getShortcut(GO_TO_PAGE_ACTION_Y)); + connect(goToPageAction, SIGNAL(triggered()),viewer,SLOT(showGoToDialog())); + + optionsAction = new QAction(tr("Options"),this); + 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")); + + connect(optionsAction, SIGNAL(triggered()),optionsDialog,SLOT(show())); + + helpAboutAction = new QAction(tr("Help"),this); + helpAboutAction->setToolTip(tr("Help, About YACReader")); + helpAboutAction->setIcon(QIcon(":/images/viewer_toolbar/help.png")); + helpAboutAction->setData(HELP_ABOUT_ACTION_Y); + helpAboutAction->setShortcut(ShortcutsManager::getShortcutsManager().getShortcut(HELP_ABOUT_ACTION_Y)); + connect(helpAboutAction, SIGNAL(triggered()),had,SLOT(show())); + + showMagnifyingGlassAction = new QAction(tr("Magnifying glass"),this); + showMagnifyingGlassAction->setToolTip(tr("Switch Magnifying glass")); + showMagnifyingGlassAction->setIcon(QIcon(":/images/viewer_toolbar/magnifyingGlass.png")); + showMagnifyingGlassAction->setDisabled(true); + showMagnifyingGlassAction->setCheckable(true); + showMagnifyingGlassAction->setData(SHOW_MAGNIFYING_GLASS_ACTION_Y); + showMagnifyingGlassAction->setShortcut(ShortcutsManager::getShortcutsManager().getShortcut(SHOW_MAGNIFYING_GLASS_ACTION_Y)); + connect(showMagnifyingGlassAction, SIGNAL(triggered()),viewer,SLOT(magnifyingGlassSwitch())); + + 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->setDisabled(true); + setBookmarkAction->setCheckable(true); + setBookmarkAction->setData(SET_BOOKMARK_ACTION_Y); + setBookmarkAction->setShortcut(ShortcutsManager::getShortcutsManager().getShortcut(SET_BOOKMARK_ACTION_Y)); + connect(setBookmarkAction,SIGNAL(triggered (bool)),viewer,SLOT(setBookmark(bool))); + connect(viewer,SIGNAL(pageAvailable(bool)),setBookmarkAction,SLOT(setEnabled(bool))); + connect(viewer,SIGNAL(pageIsBookmark(bool)),setBookmarkAction,SLOT(setChecked(bool))); + + 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->setDisabled(true); + showBookmarksAction->setData(SHOW_BOOKMARKS_ACTION_Y); + showBookmarksAction->setShortcut(ShortcutsManager::getShortcutsManager().getShortcut(SHOW_BOOKMARKS_ACTION_Y)); + connect(showBookmarksAction, SIGNAL(triggered()),viewer->getBookmarksDialog(),SLOT(show())); + + showShorcutsAction = new QAction(tr("Show keyboard shortcuts"), this ); + showShorcutsAction->setIcon(QIcon(":/images/viewer_toolbar/shortcuts.png")); + showShorcutsAction->setData(SHOW_SHORCUTS_ACTION_Y); + showShorcutsAction->setShortcut(ShortcutsManager::getShortcutsManager().getShortcut(SHOW_SHORCUTS_ACTION_Y)); + //connect(showShorcutsAction, SIGNAL(triggered()),shortcutsDialog,SLOT(show())); + connect(showShorcutsAction, SIGNAL(triggered()), editShortcutsDialog, SLOT(show())); + + showInfoAction = new QAction(tr("Show Info"),this); + showInfoAction->setIcon(QIcon(":/images/viewer_toolbar/info.png")); + showInfoAction->setDisabled(true); + showInfoAction->setData(SHOW_INFO_ACTION_Y); + showInfoAction->setShortcut(ShortcutsManager::getShortcutsManager().getShortcut(SHOW_INFO_ACTION_Y)); + connect(showInfoAction, SIGNAL(triggered()),viewer,SLOT(informationSwitch())); + + closeAction = new QAction(tr("Close"),this); + closeAction->setIcon(QIcon(":/images/viewer_toolbar/close.png")); + closeAction->setData(CLOSE_ACTION_Y); + closeAction->setShortcut(ShortcutsManager::getShortcutsManager().getShortcut(CLOSE_ACTION_Y)); + connect(closeAction,SIGNAL(triggered()),this,SLOT(close())); + + showDictionaryAction = new QAction(tr("Show Dictionary"),this); + showDictionaryAction->setIcon(QIcon(":/images/viewer_toolbar/translator.png")); + //showDictionaryAction->setCheckable(true); + showDictionaryAction->setDisabled(true); + showDictionaryAction->setData(SHOW_DICTIONARY_ACTION_Y); + showDictionaryAction->setShortcut(ShortcutsManager::getShortcutsManager().getShortcut(SHOW_DICTIONARY_ACTION_Y)); + connect(showDictionaryAction,SIGNAL(triggered()),viewer,SLOT(translatorSwitch())); + + //deprecated + alwaysOnTopAction = new QAction(tr("Always on top"),this); + alwaysOnTopAction->setIcon(QIcon(":/images/alwaysOnTop.png")); + alwaysOnTopAction->setCheckable(true); + alwaysOnTopAction->setDisabled(true); + alwaysOnTopAction->setChecked(Configuration::getConfiguration().getAlwaysOnTop()); + alwaysOnTopAction->setData(ALWAYS_ON_TOP_ACTION_Y); + alwaysOnTopAction->setShortcut(ShortcutsManager::getShortcutsManager().getShortcut(ALWAYS_ON_TOP_ACTION_Y)); + connect(alwaysOnTopAction,SIGNAL(triggered()),this,SLOT(alwaysOnTopSwitch())); + + showFlowAction = new QAction(tr("Show go to flow"),this); + showFlowAction->setIcon(QIcon(":/images/viewer_toolbar/flow.png")); + showFlowAction->setDisabled(true); + showFlowAction->setData(SHOW_FLOW_ACTION_Y); + showFlowAction->setShortcut(ShortcutsManager::getShortcutsManager().getShortcut(SHOW_FLOW_ACTION_Y)); + connect(showFlowAction,SIGNAL(triggered()),viewer,SLOT(goToFlowSwitch())); + + showEditShortcutsAction = new QAction(tr("Edit shortcuts"),this); + showEditShortcutsAction->setData(SHOW_EDIT_SHORTCUTS_ACTION_Y); + showEditShortcutsAction->setShortcut(ShortcutsManager::getShortcutsManager().getShortcut(SHOW_EDIT_SHORTCUTS_ACTION_Y)); + connect(showEditShortcutsAction,SIGNAL(triggered()),editShortcutsDialog,SLOT(show())); +} + +void MainWindowViewer::createToolBars() +{ +#ifdef Q_OS_MAC + comicToolBar = new YACReaderMacOSXToolbar(this); +#else + comicToolBar = addToolBar(tr("&File")); +#endif + +#ifdef Q_OS_MAC + //comicToolBar->setIconSize(QSize(16,16)); +#else + comicToolBar->setIconSize(QSize(18,18)); + comicToolBar->setStyleSheet("QToolBar{border:none;}"); +#endif + +#ifdef Q_OS_MAC + comicToolBar->addAction(openAction); + comicToolBar->addAction(openFolderAction); +#else + QMenu * recentmenu = new QMenu(tr("Open recent")); + recentmenu->addActions(recentFilesActionList); + recentmenu->addSeparator(); + recentmenu->addAction(clearRecentFilesAction); + refreshRecentFilesActionList(); + + QToolButton * tb = new QToolButton(); + tb->addAction(openAction); + tb->addAction(openLatestComicAction); + tb->addAction(openFolderAction); + tb->addAction(recentmenu->menuAction()); + tb->setPopupMode(QToolButton::MenuButtonPopup); + tb->setDefaultAction(openAction); + + comicToolBar->addWidget(tb); +#endif + + comicToolBar->addAction(saveImageAction); + comicToolBar->addAction(openPreviousComicAction); + comicToolBar->addAction(openNextComicAction); + + comicToolBar->addSeparator(); + + comicToolBar->addAction(prevAction); + comicToolBar->addAction(nextAction); + comicToolBar->addAction(goToPageAction); + + comicToolBar->addSeparator(); + + comicToolBar->addAction(adjustWidthAction); + comicToolBar->addAction(adjustHeightAction); + comicToolBar->addAction(adjustToFullSizeAction); + comicToolBar->addAction(fitToPageAction); + + zoomSliderAction = new YACReaderSlider(this); + zoomSliderAction->hide(); + + comicToolBar->addAction(showZoomSliderlAction); + + connect(showZoomSliderlAction,SIGNAL(triggered()),this,SLOT(toggleFitToWidthSlider())); + connect(zoomSliderAction, SIGNAL(zoomRatioChanged(int)),viewer,SLOT(updateZoomRatio(int))); + connect(viewer,SIGNAL(zoomUpdated(int)),zoomSliderAction,SLOT(updateZoomRatio(int))); + + comicToolBar->addAction(leftRotationAction); + comicToolBar->addAction(rightRotationAction); + comicToolBar->addAction(doublePageAction); + comicToolBar->addAction(doubleMangaPageAction); + + comicToolBar->addSeparator(); + + comicToolBar->addAction(showMagnifyingGlassAction); + + comicToolBar->addSeparator(); + + comicToolBar->addAction(setBookmarkAction); + comicToolBar->addAction(showBookmarksAction); + + comicToolBar->addSeparator(); + + comicToolBar->addAction(showDictionaryAction); + comicToolBar->addAction(showFlowAction); + comicToolBar->addAction(showInfoAction); + +#ifdef Q_OS_MAC + comicToolBar->addStretch(); +#else + comicToolBar->addWidget(new YACReaderToolBarStretch()); +#endif + + + comicToolBar->addAction(showShorcutsAction); + comicToolBar->addAction(optionsAction); + comicToolBar->addAction(helpAboutAction); + //comicToolBar->addAction(closeAction); + +#ifndef Q_OS_MAC + comicToolBar->setMovable(false); +#endif + + viewer->addAction(openAction); + viewer->addAction(openFolderAction); + viewer->addAction(saveImageAction); + viewer->addAction(openPreviousComicAction); + viewer->addAction(openNextComicAction); + YACReader::addSperator(viewer); + + viewer->addAction(prevAction); + viewer->addAction(nextAction); + viewer->addAction(goToPageAction); + viewer->addAction(adjustHeightAction); + viewer->addAction(adjustWidthAction); + viewer->addAction(adjustToFullSizeAction); + viewer->addAction(fitToPageAction); + viewer->addAction(leftRotationAction); + viewer->addAction(rightRotationAction); + viewer->addAction(doublePageAction); + viewer->addAction(doubleMangaPageAction); + YACReader::addSperator(viewer); + + viewer->addAction(showMagnifyingGlassAction); + viewer->addAction(increasePageZoomAction); + viewer->addAction(decreasePageZoomAction); + viewer->addAction(resetZoomAction); + YACReader::addSperator(viewer); + + viewer->addAction(setBookmarkAction); + viewer->addAction(showBookmarksAction); + YACReader::addSperator(viewer); + + viewer->addAction(showDictionaryAction); + viewer->addAction(showFlowAction); + viewer->addAction(showInfoAction); + YACReader::addSperator(viewer); + + viewer->addAction(showShorcutsAction); + viewer->addAction(showEditShortcutsAction); + viewer->addAction(optionsAction); + viewer->addAction(helpAboutAction); + YACReader::addSperator(viewer); + + viewer->addAction(closeAction); + + viewer->setContextMenuPolicy(Qt::ActionsContextMenu); + + //MacOSX app menus +#ifdef Q_OS_MAC + QMenuBar * menuBar = this->menuBar(); + //about / preferences + //TODO + + //file + QMenu * fileMenu = new QMenu(tr("File")); + + fileMenu->addAction(openAction); + fileMenu->addAction(openLatestComicAction); + fileMenu->addAction(openFolderAction); + fileMenu->addSeparator(); + fileMenu->addAction(saveImageAction); + fileMenu->addSeparator(); + + QMenu * recentmenu = new QMenu(tr("Open recent")); + recentmenu->addActions(recentFilesActionList); + recentmenu->addSeparator(); + recentmenu->addAction(clearRecentFilesAction); + refreshRecentFilesActionList(); + fileMenu->addMenu(recentmenu); + + fileMenu->addSeparator(); + fileMenu->addAction(closeAction); + + QMenu * editMenu = new QMenu(tr("Edit")); + editMenu->addAction(leftRotationAction); + editMenu->addAction(rightRotationAction); + + QMenu * viewMenu = new QMenu(tr("View")); + viewMenu->addAction(adjustHeightAction); + viewMenu->addAction(adjustWidthAction); + viewMenu->addAction(fitToPageAction); + viewMenu->addAction(adjustToFullSizeAction); + viewMenu->addSeparator(); + viewMenu->addAction(increasePageZoomAction); + viewMenu->addAction(decreasePageZoomAction); + viewMenu->addAction(resetZoomAction); + viewMenu->addAction(showZoomSliderlAction); + viewMenu->addSeparator(); + viewMenu->addAction(doublePageAction); + viewMenu->addAction(doubleMangaPageAction); + viewMenu->addSeparator(); + viewMenu->addAction(showMagnifyingGlassAction); + + QMenu * goMenu = new QMenu(tr("Go")); + goMenu->addAction(prevAction); + goMenu->addAction(nextAction); + goMenu->addAction(goToPageAction); + goMenu->addSeparator(); + goMenu->addAction(setBookmarkAction); + goMenu->addAction(showBookmarksAction); + + QMenu * windowMenu = new QMenu(tr("Window")); + windowMenu->addAction(optionsAction); // this action goes to MacOS's Preference menu by Qt + windowMenu->addAction(showShorcutsAction); + windowMenu->addAction(showFlowAction); + windowMenu->addAction(showInfoAction); + windowMenu->addAction(showDictionaryAction); + + QMenu * helpMenu = new QMenu(tr("Help")); + helpMenu->addAction(helpAboutAction); + + menuBar->addMenu(fileMenu); + menuBar->addMenu(editMenu); + menuBar->addMenu(viewMenu); + menuBar->addMenu(goMenu); + menuBar->addMenu(windowMenu); + menuBar->addMenu(helpMenu); + + //tool bar + //QMenu * toolbarMenu = new QMenu(tr("Toolbar")); + //toolbarMenu->addAction(); + //TODO + + //menu->addMenu(toolbarMenu); + + //attach toolbar + + comicToolBar->attachToWindow(this->windowHandle()); + +#endif + +} + +void MainWindowViewer::refreshRecentFilesActionList() +{ + QStringList recentFilePaths = Configuration::getConfiguration().openRecentList(); + + //TODO: Replace limit with something configurable + int iteration = (recentFilePaths.size() < Configuration::getConfiguration().getOpenRecentSize()) + ? recentFilePaths.size() : Configuration::getConfiguration().getOpenRecentSize(); + for (int i = 0; i < iteration; i++) + { + QString strippedName = QFileInfo(recentFilePaths.at(i)).fileName(); + recentFilesActionList.at(i)->setText(strippedName); + recentFilesActionList.at(i)->setData(recentFilePaths.at(i)); + recentFilesActionList.at(i)->setVisible(true); + } + + for (int i = iteration; i < Configuration::getConfiguration().getOpenRecentSize(); i++) + { + recentFilesActionList.at(i)->setVisible(false); + } +} + +void MainWindowViewer::clearRecentFiles() +{ + Configuration::getConfiguration().clearOpenRecentList(); + refreshRecentFilesActionList(); +} + +void MainWindowViewer::openRecent() +{ + QAction *action = qobject_cast(sender()); + + openComicFromRecentAction(action); +} + +void MainWindowViewer::openLatestComic() +{ + if (recentFilesActionList.isEmpty()) + { + return; + } + + openComicFromRecentAction(recentFilesActionList[0]); +} + +void MainWindowViewer::openComicFromRecentAction(QAction *action) +{ + if (action == nullptr) + { + return; + } + + QFileInfo info1 (action->data().toString()); + if (info1.exists()) + { + if (info1.isFile()) + { + openComicFromPath(action->data().toString()); + } + else if (info1.isDir()) + { + openFolderFromPath(action->data().toString()); + } + } +} + +void MainWindowViewer::reloadOptions() +{ + viewer->updateConfig(settings); +} + +void MainWindowViewer::open() +{ + QFileDialog openDialog; +#ifndef use_unarr + QString pathFile = openDialog.getOpenFileName(this,tr("Open Comic"),currentDirectory,tr("Comic files") + "(*.cbr *.cbz *.rar *.zip *.tar *.pdf *.7z *.cb7 *.arj *.cbt)"); +#else + QString pathFile = openDialog.getOpenFileName(this,tr("Open Comic"),currentDirectory,tr("Comic files") + "(*.cbr *.cbz *.rar *.zip *.tar *.pdf *.cbt)"); +#endif + if (!pathFile.isEmpty()) + { + openComicFromPath(pathFile); + } +} + +void MainWindowViewer::open(QString path, ComicDB & comic, QList & siblings) +{ + //currentComicDB = comic; + //siblingComics = siblings; + + QFileInfo fi(path); + + if(!comic.info.title.isNull() && !comic.info.title.toString().isEmpty()) + setWindowTitle("YACReader - " + comic.info.title.toString()); + else + setWindowTitle("YACReader - " + fi.fileName()); + + viewer->open(path,comic); + enableActions(); + int index = siblings.indexOf(comic); + + optionsDialog->setFilters(currentComicDB.info.brightness, currentComicDB.info.contrast, currentComicDB.info.gamma); + + if(index>0) + openPreviousComicAction->setDisabled(false); + else + openPreviousComicAction->setDisabled(true); + + if(index+1setDisabled(false); + else + openNextComicAction->setDisabled(true); +} + +void MainWindowViewer::open(QString path, qint64 comicId, qint64 libraryId) +{ + //QString pathFile = QCoreApplication::arguments().at(1); + currentDirectory = path; + //quint64 comicId = QCoreApplication::arguments().at(2).split("=").at(1).toULongLong(); + //libraryId = QCoreApplication::arguments().at(3).split("=").at(1).toULongLong(); + this->libraryId=libraryId; +// this->path=path; + + enableActions(); + + currentComicDB.id = comicId; + YACReaderLocalClient client; + int tries = 1; + bool success = false; + while(!(success = client.requestComicInfo(libraryId,currentComicDB,siblingComics)) && tries != 0) + tries--; + + if(success) + { + isClient = true; + open(path+currentComicDB.path,currentComicDB,siblingComics); + } + else + { + isClient = false; + QMessageBox::information(this,"Connection Error", "Unable to connect to YACReaderLibrary"); + //error + } + + optionsDialog->setFilters(currentComicDB.info.brightness, currentComicDB.info.contrast, currentComicDB.info.gamma); +} + +void MainWindowViewer::openComicFromPath(QString pathFile) +{ + openComic(pathFile); + isClient = false; //this method is used for direct openings +} + +//isClient shouldn't be modified when a siblinig comic is opened +void MainWindowViewer::openSiblingComic(QString pathFile) +{ + openComic(pathFile); +} + +void MainWindowViewer::openComic(QString pathFile) +{ + QFileInfo fi(pathFile); + currentDirectory = fi.dir().absolutePath(); + getSiblingComics(fi.absolutePath(),fi.fileName()); + + setWindowTitle("YACReader - " + fi.fileName()); + + enableActions(); + + viewer->open(pathFile); + Configuration::getConfiguration().updateOpenRecentList(fi.absoluteFilePath()); + refreshRecentFilesActionList(); + } + +void MainWindowViewer::openFolder() +{ + QFileDialog openDialog; + QString pathDir = openDialog.getExistingDirectory(this,tr("Open folder"),currentDirectory); + if (!pathDir.isEmpty()) + { + openFolderFromPath(pathDir); + isClient = false; + } +} + +void MainWindowViewer::openFolderFromPath(QString pathDir) +{ + currentDirectory = pathDir; //TODO ?? + QFileInfo fi(pathDir); + getSiblingComics(fi.absolutePath(),fi.fileName()); + + setWindowTitle("YACReader - " + fi.fileName()); + + enableActions(); + + viewer->open(pathDir); + Configuration::getConfiguration().updateOpenRecentList(fi.absoluteFilePath()); + refreshRecentFilesActionList(); +} + +void MainWindowViewer::openFolderFromPath(QString pathDir, QString atFileName) +{ + currentDirectory = pathDir; //TODO ?? + QFileInfo fi(pathDir); + getSiblingComics(fi.absolutePath(),fi.fileName()); + + setWindowTitle("YACReader - " + fi.fileName()); + + enableActions(); + + QDir d(pathDir); + d.setFilter(QDir::Files|QDir::NoDotAndDotDot); + d.setNameFilters(Comic::getSupportedImageFormats()); + d.setSorting(QDir::Name|QDir::IgnoreCase|QDir::LocaleAware); + QStringList list = d.entryList(); + + qSort(list.begin(),list.end(),naturalSortLessThanCI); + int i = 0; + foreach(QString path,list) + { + if(path.endsWith(atFileName)) + break; + i++; + } + + int index = 0; + if(i < list.count()) + index = i; + + viewer->open(pathDir,index); +} + +void MainWindowViewer::saveImage() +{ + QFileDialog saveDialog; + QString pathFile = saveDialog.getSaveFileName(this,tr("Save current page"),currentDirectoryImgDest+"/"+tr("page_%1.jpg").arg(viewer->getIndex()),tr("Image files (*.jpg)")); + if (!pathFile.isEmpty()) + { + QFileInfo fi(pathFile); + currentDirectoryImgDest = fi.absolutePath(); + const QPixmap * p = viewer->pixmap(); + if(p!=NULL) + p->save(pathFile); + } +} + +void MainWindowViewer::enableActions() +{ + saveImageAction->setDisabled(false); + prevAction->setDisabled(false); + nextAction->setDisabled(false); + adjustHeightAction->setDisabled(false); + adjustWidthAction->setDisabled(false); + goToPageAction->setDisabled(false); + //alwaysOnTopAction->setDisabled(false); + leftRotationAction->setDisabled(false); + rightRotationAction->setDisabled(false); + showMagnifyingGlassAction->setDisabled(false); + doublePageAction->setDisabled(false); + doubleMangaPageAction->setDisabled(false); + adjustToFullSizeAction->setDisabled(false); + adjustToFullSizeAction->setDisabled(false); + fitToPageAction->setDisabled(false); + showZoomSliderlAction->setDisabled(false); + increasePageZoomAction->setDisabled(false); + decreasePageZoomAction->setDisabled(false); + resetZoomAction->setDisabled(false); + //setBookmark->setDisabled(false); + showBookmarksAction->setDisabled(false); + showInfoAction->setDisabled(false); //TODO enable goTo and showInfo (or update) when numPages emited + showDictionaryAction->setDisabled(false); + showFlowAction->setDisabled(false); + +#ifdef Q_OS_MAC + activateWindow(); + raise(); +#endif +} +void MainWindowViewer::disableActions() +{ + saveImageAction->setDisabled(true); + prevAction->setDisabled(true); + nextAction->setDisabled(true); + adjustHeightAction->setDisabled(true); + adjustWidthAction->setDisabled(true); + goToPageAction->setDisabled(true); + //alwaysOnTopAction->setDisabled(true); + leftRotationAction->setDisabled(true); + rightRotationAction->setDisabled(true); + showMagnifyingGlassAction->setDisabled(true); + doublePageAction->setDisabled(true); + doubleMangaPageAction->setDisabled(true); + adjustToFullSizeAction->setDisabled(true); + fitToPageAction->setDisabled(true); + showZoomSliderlAction->setDisabled(true); + increasePageZoomAction->setDisabled(true); + decreasePageZoomAction->setDisabled(true); + resetZoomAction->setDisabled(true); + setBookmarkAction->setDisabled(true); + showBookmarksAction->setDisabled(true); + showInfoAction->setDisabled(true); //TODO enable goTo and showInfo (or update) when numPages emited + openPreviousComicAction->setDisabled(true); + openNextComicAction->setDisabled(true); + showDictionaryAction->setDisabled(true); + showFlowAction->setDisabled(true); +} + +void MainWindowViewer::keyPressEvent(QKeyEvent *event) +{ + //TODO remove unused keys + int _key = event->key(); + Qt::KeyboardModifiers modifiers = event->modifiers(); + + if(modifiers & Qt::ShiftModifier) + _key |= Qt::SHIFT; + if (modifiers & Qt::ControlModifier) + _key |= Qt::CTRL; + if (modifiers & Qt::MetaModifier) + _key |= Qt::META; + if (modifiers & Qt::AltModifier) + _key |= Qt::ALT; + + QKeySequence key(_key); + + if (key == ShortcutsManager::getShortcutsManager().getShortcut(TOGGLE_FULL_SCREEN_ACTION_Y)) + { + toggleFullScreen(); + event->accept(); + } + else if (key == ShortcutsManager::getShortcutsManager().getShortcut(TOGGLE_TOOL_BARS_ACTION_Y)) + { + toggleToolBars(); + event->accept(); + } + else if (key == ShortcutsManager::getShortcutsManager().getShortcut(CHANGE_FIT_ACTION_Y)) + { + toggleWidthHeight(); + event->accept(); + } + else + QWidget::keyPressEvent(event); +} + +void MainWindowViewer::mouseDoubleClickEvent ( QMouseEvent * event ) +{ + toggleFullScreen(); + event->accept(); +} + +void MainWindowViewer::toggleFullScreen() +{ + fullscreen?toNormal():toFullScreen(); + Configuration::getConfiguration().setFullScreen(fullscreen = !fullscreen); +} + +#ifdef Q_OS_WIN //fullscreen mode in Windows for preventing this bug: QTBUG-41309 https://bugreports.qt.io/browse/QTBUG-41309 + +void MainWindowViewer::toFullScreen() +{ + fromMaximized = this->isMaximized(); + + hideToolBars(); + viewer->hide(); + viewer->fullscreen = true;//TODO, change by the right use of windowState(); + + previousWindowFlags = windowFlags(); + previousPos = pos(); + previousSize = size(); + + showNormal(); + setWindowFlags(previousWindowFlags | Qt::FramelessWindowHint); + + const QRect r = windowHandle()->screen()->geometry(); + + move(r.x(), r.y()); + resize(r.width(),r.height()+1); + show(); + + viewer->show(); + if(viewer->magnifyingGlassIsVisible()) + viewer->showMagnifyingGlass(); +} + +void MainWindowViewer::toNormal() +{ + //show all + viewer->hide(); + viewer->fullscreen = false;//TODO, change by the right use of windowState(); + //viewer->hideMagnifyingGlass(); + + setWindowFlags(previousWindowFlags); + move(previousPos); + resize(previousSize); + show(); + + if(fromMaximized) + showMaximized(); + + if(Configuration::getConfiguration().getShowToolbars()) + showToolBars(); + viewer->show(); + if(viewer->magnifyingGlassIsVisible()) + viewer->showMagnifyingGlass(); +} + +#else +void MainWindowViewer::toFullScreen() +{ + fromMaximized = this->isMaximized(); + + hideToolBars(); + viewer->hide(); + viewer->fullscreen = true;//TODO, change by the right use of windowState(); + setWindowState(Qt::WindowFullScreen); + viewer->show(); + if(viewer->magnifyingGlassIsVisible()) + viewer->showMagnifyingGlass(); +} + +void MainWindowViewer::toNormal() +{ + //show all + viewer->hide(); + viewer->fullscreen = false;//TODO, change by the right use of windowState(); + //viewer->hideMagnifyingGlass(); + if(fromMaximized) + showMaximized(); + else + showNormal(); + + if(Configuration::getConfiguration().getShowToolbars()) + showToolBars(); + viewer->show(); + if(viewer->magnifyingGlassIsVisible()) + viewer->showMagnifyingGlass(); +} +#endif + +void MainWindowViewer::toggleToolBars() +{ + toolbars?hideToolBars():showToolBars(); + + Configuration::getConfiguration().setShowToolbars(toolbars); +#ifndef Q_OS_MAC + comicToolBar->setMovable(false); +#endif +} +void MainWindowViewer::hideToolBars() +{ + //hide all + this->comicToolBar->hide(); + toolbars = false; +} + +void MainWindowViewer::showToolBars() +{ + this->comicToolBar->show(); + toolbars = true; +} +void MainWindowViewer::fitToWidth() +{ + Configuration::getConfiguration().setFitMode(YACReader::FitMode::ToWidth); + viewer->setZoomFactor(100); + viewer->updatePage(); +} +void MainWindowViewer::fitToHeight() +{ + Configuration::getConfiguration().setFitMode(YACReader::FitMode::ToHeight); + viewer->setZoomFactor(100); + viewer->updatePage(); +} + +void MainWindowViewer::toggleWidthHeight() +{ + //Only switch to "Fit to height" when we're in "Fit to width" + if (Configuration::getConfiguration().getFitMode() == YACReader::FitMode::ToWidth) + { + adjustHeightAction->trigger(); + } + //Default to "Fit to width" in all other cases + else + { + adjustWidthAction->trigger(); + } +} +void MainWindowViewer::checkNewVersion() +{ + Configuration & conf = Configuration::getConfiguration(); + QDate lastCheck = conf.getLastVersionCheck(); + QDate current = QDate::currentDate(); + if(lastCheck.isNull() || lastCheck.daysTo(current) >= conf.getNumDaysBetweenVersionChecks()) + { + versionChecker = new HttpVersionChecker(); + + connect(versionChecker,SIGNAL(newVersionDetected()), + this,SLOT(newVersion())); + + QTimer * tT = new QTimer; + tT->setSingleShot(true); + connect(tT, SIGNAL(timeout()), versionChecker, SLOT(get())); + //versionChecker->get(); //TOD� + tT->start(100); + + conf.setLastVersionCheck(current); + } +} + +void MainWindowViewer::processReset() +{ + if(isClient) + { + if(siblingComics.count()>1) + { + bool openNextB = openNextComicAction->isEnabled(); + bool openPrevB = openPreviousComicAction->isEnabled(); + disableActions(); + openNextComicAction->setEnabled(openNextB); + openPreviousComicAction->setEnabled(openPrevB); + } + else + disableActions(); + } + else + disableActions(); +} + +void MainWindowViewer::setUpShortcutsManagement() +{ + //actions holder + QObject * orphanActions = new QObject; + + QList allActions; + QList tmpList; + + + editShortcutsDialog->addActionsGroup(tr("Comics"),QIcon(":/images/shortcuts_group_comics.png"), + tmpList = { openAction, + openLatestComicAction, + openFolderAction, + saveImageAction, + openPreviousComicAction, + openNextComicAction }); + + allActions << tmpList; + + //keys without actions (General) + QAction * toggleFullScreenAction = new QAction(tr("Toggle fullscreen mode"),orphanActions); + toggleFullScreenAction->setData(TOGGLE_FULL_SCREEN_ACTION_Y); + toggleFullScreenAction->setShortcut(ShortcutsManager::getShortcutsManager().getShortcut(TOGGLE_FULL_SCREEN_ACTION_Y)); + + QAction * toggleToolbarsAction = new QAction(tr("Hide/show toolbar"),orphanActions); + toggleToolbarsAction->setData(TOGGLE_TOOL_BARS_ACTION_Y); + toggleToolbarsAction->setShortcut(ShortcutsManager::getShortcutsManager().getShortcut(TOGGLE_TOOL_BARS_ACTION_Y)); + + editShortcutsDialog->addActionsGroup(tr("General"),QIcon(":/images/shortcuts_group_general.png"), + tmpList = QList() + << optionsAction + << helpAboutAction + << showShorcutsAction + << showInfoAction + << closeAction + << showDictionaryAction + << showFlowAction + << toggleFullScreenAction + << toggleToolbarsAction + << showEditShortcutsAction); + + allActions << tmpList; + + //keys without actions (MGlass) + QAction * sizeUpMglassAction = new QAction(tr("Size up magnifying glass"),orphanActions); + sizeUpMglassAction->setData(SIZE_UP_MGLASS_ACTION_Y); + sizeUpMglassAction->setShortcut(ShortcutsManager::getShortcutsManager().getShortcut(SIZE_UP_MGLASS_ACTION_Y)); + + QAction * sizeDownMglassAction = new QAction(tr("Size down magnifying glass"),orphanActions); + sizeDownMglassAction->setData(SIZE_DOWN_MGLASS_ACTION_Y); + sizeDownMglassAction->setShortcut(ShortcutsManager::getShortcutsManager().getShortcut(SIZE_DOWN_MGLASS_ACTION_Y)); + + QAction * zoomInMglassAction = new QAction(tr("Zoom in magnifying glass"),orphanActions); + zoomInMglassAction->setData(ZOOM_IN_MGLASS_ACTION_Y); + zoomInMglassAction->setShortcut(ShortcutsManager::getShortcutsManager().getShortcut(ZOOM_IN_MGLASS_ACTION_Y)); + + QAction * zoomOutMglassAction = new QAction(tr("Zoom out magnifying glass"),orphanActions); + zoomOutMglassAction->setData(ZOOM_OUT_MGLASS_ACTION_Y); + zoomOutMglassAction->setShortcut(ShortcutsManager::getShortcutsManager().getShortcut(ZOOM_OUT_MGLASS_ACTION_Y)); + + editShortcutsDialog->addActionsGroup(tr("Magnifiying glass"),QIcon(":/images/shortcuts_group_mglass.png"), + tmpList = QList() + << showMagnifyingGlassAction + << sizeUpMglassAction + << sizeDownMglassAction + << zoomInMglassAction + << zoomOutMglassAction); + + allActions << tmpList; + + //keys without actions + QAction * toggleFitToScreenAction = new QAction(tr("Toggle between fit to width and fit to height"),orphanActions); + toggleFitToScreenAction->setData(CHANGE_FIT_ACTION_Y); + toggleFitToScreenAction->setShortcut(ShortcutsManager::getShortcutsManager().getShortcut(CHANGE_FIT_ACTION_Y)); + + editShortcutsDialog->addActionsGroup(tr("Page adjustement"),QIcon(":/images/shortcuts_group_page.png"), + tmpList = QList() + << adjustHeightAction + << adjustWidthAction + << toggleFitToScreenAction + << leftRotationAction + << rightRotationAction + << doublePageAction + << doubleMangaPageAction + << adjustToFullSizeAction + << increasePageZoomAction + << decreasePageZoomAction + << resetZoomAction); + + allActions << tmpList; + + QAction * autoScrollForwardAction = new QAction(tr("Autoscroll down"),orphanActions); + autoScrollForwardAction->setData(AUTO_SCROLL_FORWARD_ACTION_Y); + autoScrollForwardAction->setShortcut(ShortcutsManager::getShortcutsManager().getShortcut(AUTO_SCROLL_FORWARD_ACTION_Y)); + + QAction * autoScrollBackwardAction = new QAction(tr("Autoscroll up"),orphanActions); + autoScrollBackwardAction->setData(AUTO_SCROLL_BACKWARD_ACTION_Y); + autoScrollBackwardAction->setShortcut(ShortcutsManager::getShortcutsManager().getShortcut(AUTO_SCROLL_BACKWARD_ACTION_Y)); + + QAction * autoScrollForwardHorizontalFirstAction = new QAction(tr("Autoscroll forward, horizontal first"),orphanActions); + autoScrollForwardHorizontalFirstAction->setData(AUTO_SCROLL_FORWARD_HORIZONTAL_FIRST_ACTION_Y); + autoScrollForwardHorizontalFirstAction->setShortcut(ShortcutsManager::getShortcutsManager().getShortcut(AUTO_SCROLL_FORWARD_HORIZONTAL_FIRST_ACTION_Y)); + + QAction * autoScrollBackwardHorizontalFirstAction = new QAction(tr("Autoscroll backward, horizontal first"),orphanActions); + autoScrollBackwardHorizontalFirstAction->setData(AUTO_SCROLL_BACKWARD_HORIZONTAL_FIRST_ACTION_Y); + autoScrollBackwardHorizontalFirstAction->setShortcut(ShortcutsManager::getShortcutsManager().getShortcut(AUTO_SCROLL_BACKWARD_HORIZONTAL_FIRST_ACTION_Y)); + + QAction * autoScrollForwardVerticalFirstAction = new QAction(tr("Autoscroll forward, vertical first"),orphanActions); + autoScrollForwardVerticalFirstAction->setData(AUTO_SCROLL_FORWARD_VERTICAL_FIRST_ACTION_Y); + autoScrollForwardVerticalFirstAction->setShortcut(ShortcutsManager::getShortcutsManager().getShortcut(AUTO_SCROLL_FORWARD_VERTICAL_FIRST_ACTION_Y)); + + QAction * autoScrollBackwardVerticalFirstAction = new QAction(tr("Autoscroll backward, vertical first"),orphanActions); + autoScrollBackwardVerticalFirstAction->setData(AUTO_SCROLL_BACKWARD_VERTICAL_FIRST_ACTION_Y); + autoScrollBackwardVerticalFirstAction->setShortcut(ShortcutsManager::getShortcutsManager().getShortcut(AUTO_SCROLL_BACKWARD_VERTICAL_FIRST_ACTION_Y)); + + QAction * moveDownAction = new QAction(tr("Move down"),orphanActions); + moveDownAction->setData(MOVE_DOWN_ACTION_Y); + moveDownAction->setShortcut(ShortcutsManager::getShortcutsManager().getShortcut(MOVE_DOWN_ACTION_Y)); + + QAction * moveUpAction = new QAction(tr("Move up"),orphanActions); + moveUpAction->setData(MOVE_UP_ACTION_Y); + moveUpAction->setShortcut(ShortcutsManager::getShortcutsManager().getShortcut(MOVE_UP_ACTION_Y)); + + QAction * moveLeftAction = new QAction(tr("Move left"),orphanActions); + moveLeftAction->setData(MOVE_LEFT_ACTION_Y); + moveLeftAction->setShortcut(ShortcutsManager::getShortcutsManager().getShortcut(MOVE_LEFT_ACTION_Y)); + + QAction * moveRightAction = new QAction(tr("Move right"),orphanActions); + moveRightAction->setData(MOVE_RIGHT_ACTION_Y); + moveRightAction->setShortcut(ShortcutsManager::getShortcutsManager().getShortcut(MOVE_RIGHT_ACTION_Y)); + + QAction * goToFirstPageAction = new QAction(tr("Go to the first page"),orphanActions); + goToFirstPageAction->setData(GO_TO_FIRST_PAGE_ACTION_Y); + goToFirstPageAction->setShortcut(ShortcutsManager::getShortcutsManager().getShortcut(GO_TO_FIRST_PAGE_ACTION_Y)); + + QAction * goToLastPageAction = new QAction(tr("Go to the last page"),orphanActions); + goToLastPageAction->setData(GO_TO_LAST_PAGE_ACTION_Y); + goToLastPageAction->setShortcut(ShortcutsManager::getShortcutsManager().getShortcut(GO_TO_LAST_PAGE_ACTION_Y)); + + editShortcutsDialog->addActionsGroup(tr("Reading"),QIcon(":/images/shortcuts_group_reading.png"), + tmpList = QList() + << nextAction + << prevAction + << setBookmarkAction + << showBookmarksAction + << autoScrollForwardAction + << autoScrollBackwardAction + << autoScrollForwardHorizontalFirstAction + << autoScrollBackwardHorizontalFirstAction + << autoScrollForwardVerticalFirstAction + << autoScrollBackwardVerticalFirstAction + << moveDownAction + << moveUpAction + << moveLeftAction + << moveRightAction + << goToFirstPageAction + << goToLastPageAction + << goToPageAction); + + allActions << tmpList; + + ShortcutsManager::getShortcutsManager().registerActions(allActions); + +} + +void MainWindowViewer::toggleFitToWidthSlider() +{ + int y; + +#ifdef Q_OS_MAC + y = 0; +#else + y = this->comicToolBar->frameSize().height(); +#endif + + if(zoomSliderAction->isVisible()) + { + zoomSliderAction->hide(); + } + else + { + zoomSliderAction->move(250, y); + zoomSliderAction->show(); + } +} + +void MainWindowViewer::newVersion() +{ + QMessageBox msgBox; + msgBox.setText(tr("There is a new version available")); + msgBox.setInformativeText(tr("Do you want to download the new version?")); + msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::Ignore | QMessageBox::No); + msgBox.setDefaultButton(QMessageBox::Yes); + msgBox.button(QMessageBox::Ignore)->setText(tr("Remind me in 14 days")); + msgBox.button(QMessageBox::No)->setText(tr("Not now")); + msgBox.setWindowFlags(Qt::WindowStaysOnTopHint); + msgBox.setModal(true); + int ret = msgBox.exec(); + + switch(ret) + { + case QMessageBox::Yes: + QDesktopServices::openUrl(QUrl("http://www.yacreader.com")); + break; + case QMessageBox::No: + Configuration::getConfiguration().setNumDaysBetweenVersionChecks(1); + break; + case QMessageBox::Ignore: + Configuration::getConfiguration().setNumDaysBetweenVersionChecks(14); + break; + } +} + +void MainWindowViewer::closeEvent ( QCloseEvent * event ) +{ + Q_UNUSED(event) + + if(isClient) + sendComic(); + + viewer->save(); + Configuration & conf = Configuration::getConfiguration(); + if(!fullscreen && !isMaximized()) + { + conf.setPos(pos()); + conf.setSize(size()); + } + conf.setMaximized(isMaximized()); + + emit (closed()); +} + +void MainWindowViewer::openPreviousComic() +{ + if(!siblingComics.isEmpty() && isClient) + { + sendComic(); + + int currentIndex = siblingComics.indexOf(currentComicDB); + if (currentIndex == -1) + return; + if(currentIndex-1 >= 0 && currentIndex-1 < siblingComics.count()) + { + siblingComics[currentIndex] = currentComicDB; //updated + currentComicDB = siblingComics.at(currentIndex-1); + open(currentDirectory+currentComicDB.path,currentComicDB,siblingComics); + } + return; + } + if(!previousComicPath.isEmpty()) + { + openSiblingComic(previousComicPath); + } +} + +void MainWindowViewer::openNextComic() +{ + if(!siblingComics.isEmpty() && isClient) + { + sendComic(); + + int currentIndex = siblingComics.indexOf(currentComicDB); + if (currentIndex == -1) + return; + if(currentIndex+1 > 0 && currentIndex+1 < siblingComics.count()) + { + siblingComics[currentIndex] = currentComicDB; //updated + currentComicDB = siblingComics.at(currentIndex+1); + open(currentDirectory+currentComicDB.path,currentComicDB,siblingComics); + } + return; + } + if(!nextComicPath.isEmpty()) + { + openSiblingComic(nextComicPath); + } +} + +void MainWindowViewer::getSiblingComics(QString path,QString currentComic) +{ + QDir d(path); + d.setFilter(QDir::Files|QDir::NoDotAndDotDot); +#ifndef use_unarr + d.setNameFilters(QStringList() << "*.cbr" << "*.cbz" << "*.rar" << "*.zip" << "*.tar" << "*.pdf" << "*.7z" << "*.cb7" << "*.arj" << "*.cbt"); +#else + d.setNameFilters(QStringList() << "*.cbr" << "*.cbz" << "*.rar" << "*.zip" << "*.tar" << "*.pdf" << "*.cbt"); +#endif + d.setSorting(QDir::Name|QDir::IgnoreCase|QDir::LocaleAware); + QStringList list = d.entryList(); + qSort(list.begin(),list.end(),naturalSortLessThanCI); + //std::sort(list.begin(),list.end(),naturalSortLessThanCI); + int index = list.indexOf(currentComic); + if(index == -1) //comic not found + { + /*QFile f(QCoreApplication::applicationDirPath()+"/errorLog.txt"); + if(!f.open(QIODevice::WriteOnly)) + { + QMessageBox::critical(NULL,tr("Saving error log file...."),tr("There was a problem saving YACReader error log file. Please, check if you have enough permissions in the YACReader root folder.")); + } + else + { + QTextStream txtS(&f); + txtS << "METHOD : MainWindowViewer::getSiblingComics" << '\n'; + txtS << "ERROR : current comic not found in its own path" << '\n'; + txtS << path << '\n'; + txtS << currentComic << '\n'; + txtS << "Comic list count : " + list.count() << '\n'; + foreach(QString s, list){ + txtS << s << '\n'; + } + f.close(); + }*/ + } + + previousComicPath = nextComicPath = ""; + if(index>0) + { + previousComicPath = path+"/"+list.at(index-1); + openPreviousComicAction->setDisabled(false); + } + else + openPreviousComicAction->setDisabled(true); + + if(index+1setDisabled(false); + } + else + openNextComicAction->setDisabled(true); +} + +void MainWindowViewer::dropEvent(QDropEvent *event) +{ + QList urlList; + QString fName; + QFileInfo info; + + if (event->mimeData()->hasUrls()) + { + urlList = event->mimeData()->urls(); + + if ( urlList.size() > 0 ) + { + fName = urlList[0].toLocalFile(); // convert first QUrl to local path + info.setFile( fName ); // information about file + if (info.isFile()) + { + QStringList imageSuffixs = Comic::getSupportedImageLiteralFormats(); + if(imageSuffixs.contains(info.suffix())) //image dropped + openFolderFromPath(info.absoluteDir().absolutePath(),info.fileName()); + else + openComicFromPath(fName); // if is file, setText + } + else + if(info.isDir()) + openFolderFromPath(fName); + + isClient = false; + } + } + + event->acceptProposedAction(); +} +void MainWindowViewer::dragEnterEvent(QDragEnterEvent *event) +{ + // accept just text/uri-list mime format + if (event->mimeData()->hasFormat("text/uri-list")) + { + event->acceptProposedAction(); + isClient = false; + } +} + +void MainWindowViewer::alwaysOnTopSwitch() +{ + if(!Configuration::getConfiguration().getAlwaysOnTop()) + { + setWindowFlags(this->windowFlags() | Qt::CustomizeWindowHint | Qt::WindowStaysOnTopHint); //always on top + show(); + } + else + { + setWindowFlags(this->windowFlags() ^ (Qt::CustomizeWindowHint | Qt::WindowStaysOnTopHint)); + show(); + } + Configuration::getConfiguration().setAlwaysOnTop(!Configuration::getConfiguration().getAlwaysOnTop()); +} + +void MainWindowViewer::adjustToFullSizeSwitch() +{ + Configuration::getConfiguration().setFitMode(YACReader::FitMode::FullRes); + viewer->setZoomFactor(100); + viewer->updatePage(); +} + +void MainWindowViewer::fitToPageSwitch() +{ + Configuration::getConfiguration().setFitMode(YACReader::FitMode::FullPage); + viewer->setZoomFactor(100); + viewer->updatePage(); +} + +void MainWindowViewer::resetZoomLevel() +{ + viewer->setZoomFactor(100); + viewer->updatePage(); +} + +void MainWindowViewer::increasePageZoomLevel() +{ + viewer->increaseZoomFactor(); +} + +void MainWindowViewer::decreasePageZoomLevel() +{ + viewer->decreaseZoomFactor(); +} + +void MainWindowViewer::sendComic() +{ + YACReaderLocalClient * client = new YACReaderLocalClient; + + connect(client, &YACReaderLocalClient::finished, client, &YACReaderLocalClient::deleteLater); + currentComicDB.info.lastTimeOpened = QDateTime::currentMSecsSinceEpoch() / 1000; + + viewer->updateComic(currentComicDB); + + if (currentComicDB.info.currentPage == currentComicDB.info.numPages) { + int currentIndex = siblingComics.indexOf(currentComicDB); + if(currentIndex+1 > 0 && currentIndex+1 < siblingComics.count()) + { + ComicDB & nextComic = siblingComics[currentIndex+1]; + nextComic.info.hasBeenOpened = true; + int retries = 1; + while(!client->sendComicInfo(libraryId, currentComicDB, nextComic.id) && retries!=0) + retries--; + } + } else { + int retries = 1; + while(!client->sendComicInfo(libraryId, currentComicDB) && retries!=0) + retries--; + } +} diff --git a/YACReader/main_window_viewer.h b/YACReader/main_window_viewer.h index a0a697b7..074c8094 100644 --- a/YACReader/main_window_viewer.h +++ b/YACReader/main_window_viewer.h @@ -1,187 +1,187 @@ -#ifndef __MAIN_WINDOW_VIEWER_H -#define __MAIN_WINDOW_VIEWER_H -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef Q_OS_MAC - #include "yacreader_macosx_toolbar.h" -#endif - -#include "comic_db.h" - -class Comic; -class Viewer; -class OptionsDialog; -class HelpAboutDialog; -class HttpVersionChecker; -class ShortcutsDialog; -class YACReaderSliderAction; -class YACReaderSlider; -class EditShortcutsDialog; - - class MainWindowViewer : public QMainWindow - { - Q_OBJECT - - public slots: - void open(); - void open(QString path, ComicDB & comic, QList & siblings); - void open(QString path, qint64 comicId, qint64 libraryId); - void openFolder(); - void openRecent(); - void openLatestComic(); - void openComicFromRecentAction(QAction *action); - void saveImage(); - void toggleToolBars(); - void hideToolBars(); - void showToolBars(); - void enableActions(); - void disableActions(); - void toggleFullScreen(); - void toFullScreen(); - void toNormal(); - void loadConfiguration(); - void newVersion(); - void openPreviousComic(); - void openNextComic(); - void openComicFromPath(QString pathFile); - void openSiblingComic(QString pathFile); - void openComic(QString pathFile); - void openFolderFromPath(QString pathDir); - void openFolderFromPath(QString pathFile, QString atFileName); - void alwaysOnTopSwitch(); - void adjustToFullSizeSwitch(); - void fitToPageSwitch(); - void resetZoomLevel(); - void increasePageZoomLevel(); - void decreasePageZoomLevel(); - void reloadOptions(); - void fitToWidth(); - void fitToHeight(); - void toggleWidthHeight(); - void checkNewVersion(); - void processReset(); - void setUpShortcutsManagement(); - - void toggleFitToWidthSlider(); - - /*void viewComic(); - void prev(); - void next(); - void updatePage();*/ - - - private: - //!State - bool fullscreen; - bool toolbars; - bool alwaysOnTop; - bool fromMaximized; - - //QTBUG-41883 - QSize _size; - QPoint _pos; - - QString currentDirectory; - QString currentDirectoryImgDest; - //!Widgets - Viewer * viewer; - //GoToDialog * goToDialog; - OptionsDialog * optionsDialog; - HelpAboutDialog * had; - //ShortcutsDialog * shortcutsDialog; - EditShortcutsDialog * editShortcutsDialog; - - //! ToolBars - #ifdef Q_OS_MAC - YACReaderMacOSXToolbar * comicToolBar; -#else - QToolBar * comicToolBar; -#endif - - //! Actions - QAction *openAction; - QAction *openFolderAction; - QAction *openLatestComicAction; - QList recentFilesActionList; - QAction *clearRecentFilesAction; - QAction *saveImageAction; - QAction *openPreviousComicAction; - QAction *openNextComicAction; - QAction *nextAction; - QAction *prevAction; - QAction *adjustWidthAction; - QAction *adjustHeightAction; - QAction *goToPageAction; - QAction *optionsAction; - QAction *helpAboutAction; - QAction *showMagnifyingGlassAction; - QAction *setBookmarkAction; - QAction *showBookmarksAction; - QAction *leftRotationAction; - QAction *rightRotationAction; - QAction *showInfoAction; - QAction *closeAction; - QAction *doublePageAction; - QAction *doubleMangaPageAction; - QAction *showShorcutsAction; - QAction *showDictionaryAction; - QAction *alwaysOnTopAction; - QAction *adjustToFullSizeAction; - QAction *fitToPageAction; - QAction *resetZoomAction; - QAction *showZoomSliderlAction; - QAction *increasePageZoomAction; - QAction *decreasePageZoomAction; - QAction *showFlowAction; - - QAction *showEditShortcutsAction; - - YACReaderSlider * zoomSliderAction; - - HttpVersionChecker * versionChecker; - QString previousComicPath; - QString nextComicPath; - //! Método que inicializa el interfaz. - void setupUI(); - void createActions(); - void createToolBars(); - void refreshRecentFilesActionList(); - void clearRecentFiles(); - void getSiblingComics(QString path,QString currentComic); - - //! Manejadores de evento: - void keyPressEvent(QKeyEvent *event); - //void resizeEvent(QResizeEvent * event); - void mouseDoubleClickEvent ( QMouseEvent * event ); - void dropEvent(QDropEvent *event); - void dragEnterEvent(QDragEnterEvent *event); - - QSettings * settings; - - ComicDB currentComicDB; - QList siblingComics; - bool isClient; - QString startComicPath; - quint64 libraryId; - - //fullscreen mode in Windows for preventing this bug: QTBUG-41309 https://bugreports.qt.io/browse/QTBUG-41309 - Qt::WindowFlags previousWindowFlags; - QPoint previousPos; - QSize previousSize; -signals: - void closed(); - protected: - virtual void closeEvent ( QCloseEvent * event ); - void sendComic(); - public: - MainWindowViewer(); - ~MainWindowViewer(); - }; -#endif +#ifndef __MAIN_WINDOW_VIEWER_H +#define __MAIN_WINDOW_VIEWER_H +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef Q_OS_MAC + #include "yacreader_macosx_toolbar.h" +#endif + +#include "comic_db.h" + +class Comic; +class Viewer; +class OptionsDialog; +class HelpAboutDialog; +class HttpVersionChecker; +class ShortcutsDialog; +class YACReaderSliderAction; +class YACReaderSlider; +class EditShortcutsDialog; + + class MainWindowViewer : public QMainWindow + { + Q_OBJECT + + public slots: + void open(); + void open(QString path, ComicDB & comic, QList & siblings); + void open(QString path, qint64 comicId, qint64 libraryId); + void openFolder(); + void openRecent(); + void openLatestComic(); + void openComicFromRecentAction(QAction *action); + void saveImage(); + void toggleToolBars(); + void hideToolBars(); + void showToolBars(); + void enableActions(); + void disableActions(); + void toggleFullScreen(); + void toFullScreen(); + void toNormal(); + void loadConfiguration(); + void newVersion(); + void openPreviousComic(); + void openNextComic(); + void openComicFromPath(QString pathFile); + void openSiblingComic(QString pathFile); + void openComic(QString pathFile); + void openFolderFromPath(QString pathDir); + void openFolderFromPath(QString pathFile, QString atFileName); + void alwaysOnTopSwitch(); + void adjustToFullSizeSwitch(); + void fitToPageSwitch(); + void resetZoomLevel(); + void increasePageZoomLevel(); + void decreasePageZoomLevel(); + void reloadOptions(); + void fitToWidth(); + void fitToHeight(); + void toggleWidthHeight(); + void checkNewVersion(); + void processReset(); + void setUpShortcutsManagement(); + + void toggleFitToWidthSlider(); + + /*void viewComic(); + void prev(); + void next(); + void updatePage();*/ + + + private: + //!State + bool fullscreen; + bool toolbars; + bool alwaysOnTop; + bool fromMaximized; + + //QTBUG-41883 + QSize _size; + QPoint _pos; + + QString currentDirectory; + QString currentDirectoryImgDest; + //!Widgets + Viewer * viewer; + //GoToDialog * goToDialog; + OptionsDialog * optionsDialog; + HelpAboutDialog * had; + //ShortcutsDialog * shortcutsDialog; + EditShortcutsDialog * editShortcutsDialog; + + //! ToolBars + #ifdef Q_OS_MAC + YACReaderMacOSXToolbar * comicToolBar; +#else + QToolBar * comicToolBar; +#endif + + //! Actions + QAction *openAction; + QAction *openFolderAction; + QAction *openLatestComicAction; + QList recentFilesActionList; + QAction *clearRecentFilesAction; + QAction *saveImageAction; + QAction *openPreviousComicAction; + QAction *openNextComicAction; + QAction *nextAction; + QAction *prevAction; + QAction *adjustWidthAction; + QAction *adjustHeightAction; + QAction *goToPageAction; + QAction *optionsAction; + QAction *helpAboutAction; + QAction *showMagnifyingGlassAction; + QAction *setBookmarkAction; + QAction *showBookmarksAction; + QAction *leftRotationAction; + QAction *rightRotationAction; + QAction *showInfoAction; + QAction *closeAction; + QAction *doublePageAction; + QAction *doubleMangaPageAction; + QAction *showShorcutsAction; + QAction *showDictionaryAction; + QAction *alwaysOnTopAction; + QAction *adjustToFullSizeAction; + QAction *fitToPageAction; + QAction *resetZoomAction; + QAction *showZoomSliderlAction; + QAction *increasePageZoomAction; + QAction *decreasePageZoomAction; + QAction *showFlowAction; + + QAction *showEditShortcutsAction; + + YACReaderSlider * zoomSliderAction; + + HttpVersionChecker * versionChecker; + QString previousComicPath; + QString nextComicPath; + //! Método que inicializa el interfaz. + void setupUI(); + void createActions(); + void createToolBars(); + void refreshRecentFilesActionList(); + void clearRecentFiles(); + void getSiblingComics(QString path,QString currentComic); + + //! Manejadores de evento: + void keyPressEvent(QKeyEvent *event); + //void resizeEvent(QResizeEvent * event); + void mouseDoubleClickEvent ( QMouseEvent * event ); + void dropEvent(QDropEvent *event); + void dragEnterEvent(QDragEnterEvent *event); + + QSettings * settings; + + ComicDB currentComicDB; + QList siblingComics; + bool isClient; + QString startComicPath; + quint64 libraryId; + + //fullscreen mode in Windows for preventing this bug: QTBUG-41309 https://bugreports.qt.io/browse/QTBUG-41309 + Qt::WindowFlags previousWindowFlags; + QPoint previousPos; + QSize previousSize; +signals: + void closed(); + protected: + virtual void closeEvent ( QCloseEvent * event ); + void sendComic(); + public: + MainWindowViewer(); + ~MainWindowViewer(); + }; +#endif diff --git a/YACReader/notifications_label_widget.cpp b/YACReader/notifications_label_widget.cpp index a1767dfd..999d0ca7 100644 --- a/YACReader/notifications_label_widget.cpp +++ b/YACReader/notifications_label_widget.cpp @@ -1,76 +1,76 @@ -#include "notifications_label_widget.h" - -#include - -NotificationsLabelWidget::NotificationsLabelWidget(QWidget * parent) - :QWidget(parent) -{ - QVBoxLayout *layout = new QVBoxLayout; - layout->setSpacing(0); - layout->setMargin(0); - - setAttribute(Qt::WA_LayoutUsesWidgetRect,true); - effect = new QGraphicsOpacityEffect(this); - effect->setOpacity(1.0); - - anim = new QPropertyAnimation(effect,"opacity"); - anim->setDuration(500); - anim->setStartValue(1.0); - anim->setEndValue(0.0); - anim->setEasingCurve(QEasingCurve::InExpo); - - connect(anim,SIGNAL(finished()),this,SLOT(hide())); - - textLabel = new QLabel(this); - textLabel->setAlignment(Qt::AlignVCenter|Qt::AlignHCenter); - textLabel->setStyleSheet("QLabel { color : white; font-size:24px; }"); - textLabel->setAttribute(Qt::WA_LayoutUsesWidgetRect,true); - - textLabel->setFixedSize(200, 120); - - //TODO check if the effects still be broken in OSX yet -#ifndef Q_OS_MAC - this->setGraphicsEffect(effect); -#endif - - layout->addWidget(textLabel); - setLayout(layout); - - setFixedSize(200, 120); - updatePosition(); -} - -void NotificationsLabelWidget::paintEvent(QPaintEvent *) -{ - QPainter painter(this); - painter.setRenderHint(QPainter::Antialiasing); - QPainterPath path; - path.addRoundedRect(QRectF(0, 0, width(), height()), 5.0, 5.0); - painter.setPen(Qt::NoPen); - painter.fillPath(path, QColor("#BB000000")); - painter.drawPath(path); -} - -void NotificationsLabelWidget::flash() -{ - updatePosition(); - anim->stop(); - anim->start(); - - setVisible(true); -} - -void NotificationsLabelWidget::setText(const QString & text) -{ - textLabel->setText(text); -} - -void NotificationsLabelWidget::updatePosition() -{ - QWidget * parent = dynamic_cast(this->parent()); - if(parent == 0) - { - return; - } - move(QPoint((parent->geometry().size().width()-this->width())/2,(parent->geometry().size().height()-this->height())/2)); -} +#include "notifications_label_widget.h" + +#include + +NotificationsLabelWidget::NotificationsLabelWidget(QWidget * parent) + :QWidget(parent) +{ + QVBoxLayout *layout = new QVBoxLayout; + layout->setSpacing(0); + layout->setMargin(0); + + setAttribute(Qt::WA_LayoutUsesWidgetRect,true); + effect = new QGraphicsOpacityEffect(this); + effect->setOpacity(1.0); + + anim = new QPropertyAnimation(effect,"opacity"); + anim->setDuration(500); + anim->setStartValue(1.0); + anim->setEndValue(0.0); + anim->setEasingCurve(QEasingCurve::InExpo); + + connect(anim,SIGNAL(finished()),this,SLOT(hide())); + + textLabel = new QLabel(this); + textLabel->setAlignment(Qt::AlignVCenter|Qt::AlignHCenter); + textLabel->setStyleSheet("QLabel { color : white; font-size:24px; }"); + textLabel->setAttribute(Qt::WA_LayoutUsesWidgetRect,true); + + textLabel->setFixedSize(200, 120); + + //TODO check if the effects still be broken in OSX yet +#ifndef Q_OS_MAC + this->setGraphicsEffect(effect); +#endif + + layout->addWidget(textLabel); + setLayout(layout); + + setFixedSize(200, 120); + updatePosition(); +} + +void NotificationsLabelWidget::paintEvent(QPaintEvent *) +{ + QPainter painter(this); + painter.setRenderHint(QPainter::Antialiasing); + QPainterPath path; + path.addRoundedRect(QRectF(0, 0, width(), height()), 5.0, 5.0); + painter.setPen(Qt::NoPen); + painter.fillPath(path, QColor("#BB000000")); + painter.drawPath(path); +} + +void NotificationsLabelWidget::flash() +{ + updatePosition(); + anim->stop(); + anim->start(); + + setVisible(true); +} + +void NotificationsLabelWidget::setText(const QString & text) +{ + textLabel->setText(text); +} + +void NotificationsLabelWidget::updatePosition() +{ + QWidget * parent = dynamic_cast(this->parent()); + if(parent == 0) + { + return; + } + move(QPoint((parent->geometry().size().width()-this->width())/2,(parent->geometry().size().height()-this->height())/2)); +} diff --git a/YACReader/notifications_label_widget.h b/YACReader/notifications_label_widget.h index 12ded1ac..eeafe952 100644 --- a/YACReader/notifications_label_widget.h +++ b/YACReader/notifications_label_widget.h @@ -1,30 +1,30 @@ -#ifndef NOTIFICATIONS_LABEL_WIDGET_H -#define NOTIFICATIONS_LABEL_WIDGET_H - -#include - -class QLabel; -class QPropertyAnimation; -class QGraphicsOpacityEffect; - -class NotificationsLabelWidget : public QWidget -{ -Q_OBJECT -private: - QLabel * textLabel; - QPropertyAnimation * anim; - QGraphicsOpacityEffect * effect; - -protected: - void paintEvent(QPaintEvent *); - -public: - NotificationsLabelWidget(QWidget * parent); - -public slots: - void flash(); - void setText(const QString & text); - void updatePosition(); -}; - -#endif +#ifndef NOTIFICATIONS_LABEL_WIDGET_H +#define NOTIFICATIONS_LABEL_WIDGET_H + +#include + +class QLabel; +class QPropertyAnimation; +class QGraphicsOpacityEffect; + +class NotificationsLabelWidget : public QWidget +{ +Q_OBJECT +private: + QLabel * textLabel; + QPropertyAnimation * anim; + QGraphicsOpacityEffect * effect; + +protected: + void paintEvent(QPaintEvent *); + +public: + NotificationsLabelWidget(QWidget * parent); + +public slots: + void flash(); + void setText(const QString & text); + void updatePosition(); +}; + +#endif diff --git a/YACReader/options_dialog.cpp b/YACReader/options_dialog.cpp index f9eec307..88371980 100644 --- a/YACReader/options_dialog.cpp +++ b/YACReader/options_dialog.cpp @@ -1,325 +1,325 @@ -#include "options_dialog.h" -#include "configuration.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "yacreader_spin_slider_widget.h" -#include "yacreader_flow_config_widget.h" -#ifndef NO_OPENGL -#include "yacreader_gl_flow_config_widget.h" -#endif - -OptionsDialog::OptionsDialog(QWidget * parent) - :YACReaderOptionsDialog(parent) -{ - - QTabWidget * tabWidget = new QTabWidget(); - - QVBoxLayout * layout = new QVBoxLayout(this); - - QWidget * pageGeneral = new QWidget(); - QWidget * pageFlow = new QWidget(); - QWidget * pageImage = new QWidget(); - QVBoxLayout * layoutGeneral = new QVBoxLayout(); - QVBoxLayout * layoutFlow = new QVBoxLayout(); - QVBoxLayout * layoutImageV = new QVBoxLayout(); - QGridLayout * layoutImage = new QGridLayout(); - - QGroupBox *slideSizeBox = new QGroupBox(tr("\"Go to flow\" size")); - //slideSizeLabel = new QLabel(,this); - slideSize = new QSlider(this); - slideSize->setMinimum(125); - slideSize->setMaximum(350); - slideSize->setPageStep(5); - slideSize->setOrientation(Qt::Horizontal); - QHBoxLayout * slideLayout = new QHBoxLayout(); - slideLayout->addWidget(slideSize); - slideSizeBox->setLayout(slideLayout); - - QGroupBox *pathBox = new QGroupBox(tr("My comics path")); - - QHBoxLayout * path = new QHBoxLayout(); - path->addWidget(pathEdit = new QLineEdit()); - path->addWidget(pathFindButton = new QPushButton(QIcon(":/images/find_folder.png"),"")); - pathBox->setLayout(path); - - connect(pathFindButton,SIGNAL(clicked()),this,SLOT(findFolder())); - - //fitToWidthRatioLabel = new QLabel(tr("Page width stretch"),this); - /*QGroupBox *fitBox = new QGroupBox(tr("Page width stretch")); - fitToWidthRatioS = new QSlider(this); - fitToWidthRatioS->setMinimum(50); - fitToWidthRatioS->setMaximum(100); - fitToWidthRatioS->setPageStep(5); - fitToWidthRatioS->setOrientation(Qt::Horizontal); - //connect(fitToWidthRatioS,SIGNAL(valueChanged(int)),this,SLOT(fitToWidthRatio(int))); - QHBoxLayout * fitLayout = new QHBoxLayout; - fitLayout->addWidget(fitToWidthRatioS); - fitBox->setLayout(fitLayout);*/ - - QHBoxLayout * colorSelection = new QHBoxLayout; - backgroundColor = new QLabel(); - QPalette pal = backgroundColor->palette(); - pal.setColor(backgroundColor->backgroundRole(), Qt::black); - backgroundColor->setPalette(pal); - backgroundColor->setAutoFillBackground(true); - - colorDialog = new QColorDialog(Qt::red,this); - connect(colorDialog,SIGNAL(colorSelected(QColor)),this,SLOT(updateColor(QColor))); - - QGroupBox *colorBox = new QGroupBox(tr("Background color")); - //backgroundColor->setMinimumWidth(100); - colorSelection->addWidget(backgroundColor); - colorSelection->addWidget(selectBackgroundColorButton = new QPushButton(tr("Choose"))); - colorSelection->setStretchFactor(backgroundColor,1); - colorSelection->setStretchFactor(selectBackgroundColorButton,0); - //colorSelection->addStretch(); - connect(selectBackgroundColorButton, SIGNAL(clicked()), colorDialog, SLOT(show())); - colorBox->setLayout(colorSelection); - - brightnessS = new YACReaderSpinSliderWidget(this,true); - brightnessS->setRange(0,100); - //brightnessS->setText(tr("Brightness")); - brightnessS->setTracking(false); - connect(brightnessS,SIGNAL(valueChanged(int)),this,SLOT(brightnessChanged(int))); - - contrastS = new YACReaderSpinSliderWidget(this,true); - contrastS->setRange(0,250); - //contrastS->setText(tr("Contrast")); - contrastS->setTracking(false); - connect(contrastS,SIGNAL(valueChanged(int)),this,SLOT(contrastChanged(int))); - - gammaS = new YACReaderSpinSliderWidget(this,true); - gammaS->setRange(0,250); - //gammaS->setText(tr("Gamma")); - gammaS->setTracking(false); - connect(gammaS,SIGNAL(valueChanged(int)),this,SLOT(gammaChanged(int))); - //connect(brightnessS,SIGNAL(valueChanged(int)),this,SIGNAL(changedOptions())); - - quickNavi = new QCheckBox(tr("Quick Navigation Mode")); - disableShowOnMouseOver = new QCheckBox(tr("Disable mouse over activation")); - - QHBoxLayout * buttons = new QHBoxLayout(); - buttons->addStretch(); - buttons->addWidget(new QLabel(tr("Restart is needed"))); - buttons->addWidget(accept); - buttons->addWidget(cancel); - - layoutGeneral->addWidget(pathBox); - layoutGeneral->addWidget(slideSizeBox); - //layoutGeneral->addWidget(fitBox); - layoutGeneral->addWidget(colorBox); - layoutGeneral->addWidget(shortcutsBox); - layoutGeneral->addStretch(); - - layoutFlow->addWidget(sw); -#ifndef NO_OPENGL - layoutFlow->addWidget(gl); - layoutFlow->addWidget(useGL); -#endif - layoutFlow->addWidget(quickNavi); - layoutFlow->addWidget(disableShowOnMouseOver); - layoutFlow->addStretch(); - - layoutImage->addWidget(new QLabel(tr("Brightness")),0,0); - layoutImage->addWidget(new QLabel(tr("Contrast")),1,0); - layoutImage->addWidget(new QLabel(tr("Gamma")),2,0); - layoutImage->addWidget(brightnessS,0,1); - layoutImage->addWidget(contrastS,1,1); - layoutImage->addWidget(gammaS,2,1); - QPushButton * pushButton = new QPushButton(tr("Reset")); - connect(pushButton,SIGNAL(pressed()),this,SLOT(resetImageConfig())); - layoutImage->addWidget(pushButton,3,0); - layoutImage->setColumnStretch(1,1); - - - QGroupBox *imageBox = new QGroupBox(tr("Image options")); - imageBox->setLayout(layoutImage); - layoutImageV->addWidget(imageBox); - layoutImageV->addStretch(); - - - pageGeneral->setLayout(layoutGeneral); - pageFlow->setLayout(layoutFlow); - pageImage->setLayout(layoutImageV); - - tabWidget->addTab(pageGeneral,tr("General")); - tabWidget->addTab(pageFlow,tr("Page Flow")); - tabWidget->addTab(pageImage,tr("Image adjustment")); - - layout->addWidget(tabWidget); - layout->addLayout(buttons); - - setLayout(layout); - - //disable vSyncCheck -#ifndef NO_OPENGL - gl->vSyncCheck->hide(); -#endif - //restoreOptions(); //load options - //resize(400,0); - setModal (true); - setWindowTitle(tr("Options")); - - this->layout()->setSizeConstraint(QLayout::SetFixedSize); -} - -void OptionsDialog::findFolder() -{ - QString s = QFileDialog::getExistingDirectory(0,tr("Comics directory"),"."); - if(!s.isEmpty()) - { - pathEdit->setText(s); - } -} - -void OptionsDialog::saveOptions() -{ - - settings->setValue(GO_TO_FLOW_SIZE,QSize(static_cast(slideSize->sliderPosition()/SLIDE_ASPECT_RATIO),slideSize->sliderPosition())); - - if(sw->radio1->isChecked()) - settings->setValue(FLOW_TYPE_SW,0); - if(sw->radio2->isChecked()) - settings->setValue(FLOW_TYPE_SW,1); - if(sw->radio3->isChecked()) - settings->setValue(FLOW_TYPE_SW,2); - - settings->setValue(PATH,pathEdit->text()); - - settings->setValue(BACKGROUND_COLOR,colorDialog->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()); - - YACReaderOptionsDialog::saveOptions(); -} - -void OptionsDialog::restoreOptions(QSettings * settings) -{ - YACReaderOptionsDialog::restoreOptions(settings); - - slideSize->setSliderPosition(settings->value(GO_TO_FLOW_SIZE).toSize().height()); - switch(settings->value(FLOW_TYPE_SW).toInt()) - { - case 0: - sw->radio1->setChecked(true); - break; - case 1: - sw->radio2->setChecked(true); - break; - case 2: - sw->radio3->setChecked(true); - break; - default: - sw->radio1->setChecked(true); - break; - } - - pathEdit->setText(settings->value(PATH).toString()); - - updateColor(settings->value(BACKGROUND_COLOR).value()); - //fitToWidthRatioS->setSliderPosition(settings->value(FIT_TO_WIDTH_RATIO).toFloat()*100); - - quickNavi->setChecked(settings->value(QUICK_NAVI_MODE).toBool()); - disableShowOnMouseOver->setChecked(settings->value(DISABLE_MOUSE_OVER_GOTO_FLOW).toBool()); - - brightnessS->setValue(settings->value(BRIGHTNESS,0).toInt()); - contrastS->setValue(settings->value(CONTRAST,100).toInt()); - gammaS->setValue(settings->value(GAMMA,100).toInt()); -} - - -void OptionsDialog::updateColor(const QColor & color) -{ - QPalette pal = backgroundColor->palette(); - pal.setColor(backgroundColor->backgroundRole(), color); - backgroundColor->setPalette(pal); - backgroundColor->setAutoFillBackground(true); - colorDialog->setCurrentColor(color); - - settings->setValue(BACKGROUND_COLOR,color); - - emit(changedOptions()); -} - -/*void OptionsDialog::fitToWidthRatio(int value) -{ - Configuration::getConfiguration().setFitToWidthRatio(value/100.0); - emit(fitToWidthRatioChanged(value/100.0)); -}*/ - -void OptionsDialog::brightnessChanged(int value) -{ - QSettings settings(YACReader::getSettingsPath()+"/YACReader.ini",QSettings::IniFormat); - settings.setValue(BRIGHTNESS,value); - emit changedFilters(brightnessS->getValue(), contrastS->getValue(), gammaS->getValue()); - //emit(changedImageOptions()); -} - -void OptionsDialog::contrastChanged(int value) -{ - QSettings settings(YACReader::getSettingsPath()+"/YACReader.ini",QSettings::IniFormat); - settings.setValue(CONTRAST,value); - emit changedFilters(brightnessS->getValue(), contrastS->getValue(), gammaS->getValue()); - ///emit(changedImageOptions()); -} - -void OptionsDialog::gammaChanged(int value) -{ - QSettings settings(YACReader::getSettingsPath()+"/YACReader.ini",QSettings::IniFormat); - settings.setValue(GAMMA,value); - emit changedFilters(brightnessS->getValue(), contrastS->getValue(), gammaS->getValue()); - //emit(changedImageOptions()); -} - -void OptionsDialog::resetImageConfig() -{ - brightnessS->setValue(0); - contrastS->setValue(100); - gammaS->setValue(100); - QSettings settings(YACReader::getSettingsPath()+"/YACReader.ini",QSettings::IniFormat); - settings.setValue(BRIGHTNESS,0); - settings.setValue(CONTRAST,100); - settings.setValue(GAMMA,100); - emit changedFilters(brightnessS->getValue(), contrastS->getValue(), gammaS->getValue()); - //emit(changedImageOptions()); -} - -void OptionsDialog::show() -{ - //TODO solucionar el tema de las settings, esto sólo debería aparecer en una única línea de código - QSettings *s = new QSettings(YACReader::getSettingsPath()+"/YACReader.ini",QSettings::IniFormat); - //fitToWidthRatioS->disconnect(); - //fitToWidthRatioS->setSliderPosition(settings->value(FIT_TO_WIDTH_RATIO).toFloat()*100); - //connect(fitToWidthRatioS,SIGNAL(valueChanged(int)),this,SLOT(fitToWidthRatio(int))); - QDialog::show(); - delete s; -} - -void OptionsDialog::setFilters(int brightness, int contrast, int gamma) -{ - if(brightness != -1) - brightnessS->setValue(brightness); - else - brightnessS->setValue(0); - if(contrast != -1) - contrastS->setValue(contrast); - else - contrastS->setValue(100); - if(gamma != -1) - gammaS->setValue(gamma); - else - gammaS->setValue(100); - -} +#include "options_dialog.h" +#include "configuration.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "yacreader_spin_slider_widget.h" +#include "yacreader_flow_config_widget.h" +#ifndef NO_OPENGL +#include "yacreader_gl_flow_config_widget.h" +#endif + +OptionsDialog::OptionsDialog(QWidget * parent) + :YACReaderOptionsDialog(parent) +{ + + QTabWidget * tabWidget = new QTabWidget(); + + QVBoxLayout * layout = new QVBoxLayout(this); + + QWidget * pageGeneral = new QWidget(); + QWidget * pageFlow = new QWidget(); + QWidget * pageImage = new QWidget(); + QVBoxLayout * layoutGeneral = new QVBoxLayout(); + QVBoxLayout * layoutFlow = new QVBoxLayout(); + QVBoxLayout * layoutImageV = new QVBoxLayout(); + QGridLayout * layoutImage = new QGridLayout(); + + QGroupBox *slideSizeBox = new QGroupBox(tr("\"Go to flow\" size")); + //slideSizeLabel = new QLabel(,this); + slideSize = new QSlider(this); + slideSize->setMinimum(125); + slideSize->setMaximum(350); + slideSize->setPageStep(5); + slideSize->setOrientation(Qt::Horizontal); + QHBoxLayout * slideLayout = new QHBoxLayout(); + slideLayout->addWidget(slideSize); + slideSizeBox->setLayout(slideLayout); + + QGroupBox *pathBox = new QGroupBox(tr("My comics path")); + + QHBoxLayout * path = new QHBoxLayout(); + path->addWidget(pathEdit = new QLineEdit()); + path->addWidget(pathFindButton = new QPushButton(QIcon(":/images/find_folder.png"),"")); + pathBox->setLayout(path); + + connect(pathFindButton,SIGNAL(clicked()),this,SLOT(findFolder())); + + //fitToWidthRatioLabel = new QLabel(tr("Page width stretch"),this); + /*QGroupBox *fitBox = new QGroupBox(tr("Page width stretch")); + fitToWidthRatioS = new QSlider(this); + fitToWidthRatioS->setMinimum(50); + fitToWidthRatioS->setMaximum(100); + fitToWidthRatioS->setPageStep(5); + fitToWidthRatioS->setOrientation(Qt::Horizontal); + //connect(fitToWidthRatioS,SIGNAL(valueChanged(int)),this,SLOT(fitToWidthRatio(int))); + QHBoxLayout * fitLayout = new QHBoxLayout; + fitLayout->addWidget(fitToWidthRatioS); + fitBox->setLayout(fitLayout);*/ + + QHBoxLayout * colorSelection = new QHBoxLayout; + backgroundColor = new QLabel(); + QPalette pal = backgroundColor->palette(); + pal.setColor(backgroundColor->backgroundRole(), Qt::black); + backgroundColor->setPalette(pal); + backgroundColor->setAutoFillBackground(true); + + colorDialog = new QColorDialog(Qt::red,this); + connect(colorDialog,SIGNAL(colorSelected(QColor)),this,SLOT(updateColor(QColor))); + + QGroupBox *colorBox = new QGroupBox(tr("Background color")); + //backgroundColor->setMinimumWidth(100); + colorSelection->addWidget(backgroundColor); + colorSelection->addWidget(selectBackgroundColorButton = new QPushButton(tr("Choose"))); + colorSelection->setStretchFactor(backgroundColor,1); + colorSelection->setStretchFactor(selectBackgroundColorButton,0); + //colorSelection->addStretch(); + connect(selectBackgroundColorButton, SIGNAL(clicked()), colorDialog, SLOT(show())); + colorBox->setLayout(colorSelection); + + brightnessS = new YACReaderSpinSliderWidget(this,true); + brightnessS->setRange(0,100); + //brightnessS->setText(tr("Brightness")); + brightnessS->setTracking(false); + connect(brightnessS,SIGNAL(valueChanged(int)),this,SLOT(brightnessChanged(int))); + + contrastS = new YACReaderSpinSliderWidget(this,true); + contrastS->setRange(0,250); + //contrastS->setText(tr("Contrast")); + contrastS->setTracking(false); + connect(contrastS,SIGNAL(valueChanged(int)),this,SLOT(contrastChanged(int))); + + gammaS = new YACReaderSpinSliderWidget(this,true); + gammaS->setRange(0,250); + //gammaS->setText(tr("Gamma")); + gammaS->setTracking(false); + connect(gammaS,SIGNAL(valueChanged(int)),this,SLOT(gammaChanged(int))); + //connect(brightnessS,SIGNAL(valueChanged(int)),this,SIGNAL(changedOptions())); + + quickNavi = new QCheckBox(tr("Quick Navigation Mode")); + disableShowOnMouseOver = new QCheckBox(tr("Disable mouse over activation")); + + QHBoxLayout * buttons = new QHBoxLayout(); + buttons->addStretch(); + buttons->addWidget(new QLabel(tr("Restart is needed"))); + buttons->addWidget(accept); + buttons->addWidget(cancel); + + layoutGeneral->addWidget(pathBox); + layoutGeneral->addWidget(slideSizeBox); + //layoutGeneral->addWidget(fitBox); + layoutGeneral->addWidget(colorBox); + layoutGeneral->addWidget(shortcutsBox); + layoutGeneral->addStretch(); + + layoutFlow->addWidget(sw); +#ifndef NO_OPENGL + layoutFlow->addWidget(gl); + layoutFlow->addWidget(useGL); +#endif + layoutFlow->addWidget(quickNavi); + layoutFlow->addWidget(disableShowOnMouseOver); + layoutFlow->addStretch(); + + layoutImage->addWidget(new QLabel(tr("Brightness")),0,0); + layoutImage->addWidget(new QLabel(tr("Contrast")),1,0); + layoutImage->addWidget(new QLabel(tr("Gamma")),2,0); + layoutImage->addWidget(brightnessS,0,1); + layoutImage->addWidget(contrastS,1,1); + layoutImage->addWidget(gammaS,2,1); + QPushButton * pushButton = new QPushButton(tr("Reset")); + connect(pushButton,SIGNAL(pressed()),this,SLOT(resetImageConfig())); + layoutImage->addWidget(pushButton,3,0); + layoutImage->setColumnStretch(1,1); + + + QGroupBox *imageBox = new QGroupBox(tr("Image options")); + imageBox->setLayout(layoutImage); + layoutImageV->addWidget(imageBox); + layoutImageV->addStretch(); + + + pageGeneral->setLayout(layoutGeneral); + pageFlow->setLayout(layoutFlow); + pageImage->setLayout(layoutImageV); + + tabWidget->addTab(pageGeneral,tr("General")); + tabWidget->addTab(pageFlow,tr("Page Flow")); + tabWidget->addTab(pageImage,tr("Image adjustment")); + + layout->addWidget(tabWidget); + layout->addLayout(buttons); + + setLayout(layout); + + //disable vSyncCheck +#ifndef NO_OPENGL + gl->vSyncCheck->hide(); +#endif + //restoreOptions(); //load options + //resize(400,0); + setModal (true); + setWindowTitle(tr("Options")); + + this->layout()->setSizeConstraint(QLayout::SetFixedSize); +} + +void OptionsDialog::findFolder() +{ + QString s = QFileDialog::getExistingDirectory(0,tr("Comics directory"),"."); + if(!s.isEmpty()) + { + pathEdit->setText(s); + } +} + +void OptionsDialog::saveOptions() +{ + + settings->setValue(GO_TO_FLOW_SIZE,QSize(static_cast(slideSize->sliderPosition()/SLIDE_ASPECT_RATIO),slideSize->sliderPosition())); + + if(sw->radio1->isChecked()) + settings->setValue(FLOW_TYPE_SW,0); + if(sw->radio2->isChecked()) + settings->setValue(FLOW_TYPE_SW,1); + if(sw->radio3->isChecked()) + settings->setValue(FLOW_TYPE_SW,2); + + settings->setValue(PATH,pathEdit->text()); + + settings->setValue(BACKGROUND_COLOR,colorDialog->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()); + + YACReaderOptionsDialog::saveOptions(); +} + +void OptionsDialog::restoreOptions(QSettings * settings) +{ + YACReaderOptionsDialog::restoreOptions(settings); + + slideSize->setSliderPosition(settings->value(GO_TO_FLOW_SIZE).toSize().height()); + switch(settings->value(FLOW_TYPE_SW).toInt()) + { + case 0: + sw->radio1->setChecked(true); + break; + case 1: + sw->radio2->setChecked(true); + break; + case 2: + sw->radio3->setChecked(true); + break; + default: + sw->radio1->setChecked(true); + break; + } + + pathEdit->setText(settings->value(PATH).toString()); + + updateColor(settings->value(BACKGROUND_COLOR).value()); + //fitToWidthRatioS->setSliderPosition(settings->value(FIT_TO_WIDTH_RATIO).toFloat()*100); + + quickNavi->setChecked(settings->value(QUICK_NAVI_MODE).toBool()); + disableShowOnMouseOver->setChecked(settings->value(DISABLE_MOUSE_OVER_GOTO_FLOW).toBool()); + + brightnessS->setValue(settings->value(BRIGHTNESS,0).toInt()); + contrastS->setValue(settings->value(CONTRAST,100).toInt()); + gammaS->setValue(settings->value(GAMMA,100).toInt()); +} + + +void OptionsDialog::updateColor(const QColor & color) +{ + QPalette pal = backgroundColor->palette(); + pal.setColor(backgroundColor->backgroundRole(), color); + backgroundColor->setPalette(pal); + backgroundColor->setAutoFillBackground(true); + colorDialog->setCurrentColor(color); + + settings->setValue(BACKGROUND_COLOR,color); + + emit(changedOptions()); +} + +/*void OptionsDialog::fitToWidthRatio(int value) +{ + Configuration::getConfiguration().setFitToWidthRatio(value/100.0); + emit(fitToWidthRatioChanged(value/100.0)); +}*/ + +void OptionsDialog::brightnessChanged(int value) +{ + QSettings settings(YACReader::getSettingsPath()+"/YACReader.ini",QSettings::IniFormat); + settings.setValue(BRIGHTNESS,value); + emit changedFilters(brightnessS->getValue(), contrastS->getValue(), gammaS->getValue()); + //emit(changedImageOptions()); +} + +void OptionsDialog::contrastChanged(int value) +{ + QSettings settings(YACReader::getSettingsPath()+"/YACReader.ini",QSettings::IniFormat); + settings.setValue(CONTRAST,value); + emit changedFilters(brightnessS->getValue(), contrastS->getValue(), gammaS->getValue()); + ///emit(changedImageOptions()); +} + +void OptionsDialog::gammaChanged(int value) +{ + QSettings settings(YACReader::getSettingsPath()+"/YACReader.ini",QSettings::IniFormat); + settings.setValue(GAMMA,value); + emit changedFilters(brightnessS->getValue(), contrastS->getValue(), gammaS->getValue()); + //emit(changedImageOptions()); +} + +void OptionsDialog::resetImageConfig() +{ + brightnessS->setValue(0); + contrastS->setValue(100); + gammaS->setValue(100); + QSettings settings(YACReader::getSettingsPath()+"/YACReader.ini",QSettings::IniFormat); + settings.setValue(BRIGHTNESS,0); + settings.setValue(CONTRAST,100); + settings.setValue(GAMMA,100); + emit changedFilters(brightnessS->getValue(), contrastS->getValue(), gammaS->getValue()); + //emit(changedImageOptions()); +} + +void OptionsDialog::show() +{ + //TODO solucionar el tema de las settings, esto sólo debería aparecer en una única línea de código + QSettings *s = new QSettings(YACReader::getSettingsPath()+"/YACReader.ini",QSettings::IniFormat); + //fitToWidthRatioS->disconnect(); + //fitToWidthRatioS->setSliderPosition(settings->value(FIT_TO_WIDTH_RATIO).toFloat()*100); + //connect(fitToWidthRatioS,SIGNAL(valueChanged(int)),this,SLOT(fitToWidthRatio(int))); + QDialog::show(); + delete s; +} + +void OptionsDialog::setFilters(int brightness, int contrast, int gamma) +{ + if(brightness != -1) + brightnessS->setValue(brightness); + else + brightnessS->setValue(0); + if(contrast != -1) + contrastS->setValue(contrast); + else + contrastS->setValue(100); + if(gamma != -1) + gammaS->setValue(gamma); + else + gammaS->setValue(100); + +} diff --git a/YACReader/options_dialog.h b/YACReader/options_dialog.h index 95bc5403..a80cd3cf 100644 --- a/YACReader/options_dialog.h +++ b/YACReader/options_dialog.h @@ -1,72 +1,72 @@ -#ifndef __OPTIONS_DIALOG_H -#define __OPTIONS_DIALOG_H - -#include "yacreader_options_dialog.h" - -class QDialog; -class QLabel; -class QLineEdit; -class QPushButton; -class QSlider; -class QPushButton; -class QRadioButton; -class QColorDialog; -class YACReaderSpinSliderWidget; - - -class OptionsDialog : public YACReaderOptionsDialog -{ -Q_OBJECT - public: - OptionsDialog(QWidget * parent = 0); - private: - //QLabel * pathLabel; - QLineEdit * pathEdit; - QPushButton * pathFindButton; - QCheckBox * quickNavi; - QCheckBox * disableShowOnMouseOver; - - QLabel * magGlassSizeLabel; - - QLabel * zoomLevel; - - //QLabel * slideSizeLabel; - QSlider * slideSize; - - //QLabel * fitToWidthRatioLabel; - //QSlider * fitToWidthRatioS; - - QLabel * backgroundColor; - QPushButton * selectBackgroundColorButton; - - QColorDialog * colorDialog; - - YACReaderSpinSliderWidget * brightnessS; - - YACReaderSpinSliderWidget * contrastS; - - YACReaderSpinSliderWidget * gammaS; - - public slots: - void saveOptions(); - void restoreOptions(QSettings * settings); - void findFolder(); - void updateColor(const QColor & color); - //void fitToWidthRatio(int value); - void brightnessChanged(int value); - void contrastChanged(int value); - void gammaChanged(int value); - void resetImageConfig(); - void show(); - void setFilters(int brightness, int contrast, int gamma); - -signals: - void changedOptions(); - void changedImageOptions(); - void changedFilters(int brightness, int contrast, int gamma); - //void fitToWidthRatioChanged(float ratio); - -}; - - -#endif +#ifndef __OPTIONS_DIALOG_H +#define __OPTIONS_DIALOG_H + +#include "yacreader_options_dialog.h" + +class QDialog; +class QLabel; +class QLineEdit; +class QPushButton; +class QSlider; +class QPushButton; +class QRadioButton; +class QColorDialog; +class YACReaderSpinSliderWidget; + + +class OptionsDialog : public YACReaderOptionsDialog +{ +Q_OBJECT + public: + OptionsDialog(QWidget * parent = 0); + private: + //QLabel * pathLabel; + QLineEdit * pathEdit; + QPushButton * pathFindButton; + QCheckBox * quickNavi; + QCheckBox * disableShowOnMouseOver; + + QLabel * magGlassSizeLabel; + + QLabel * zoomLevel; + + //QLabel * slideSizeLabel; + QSlider * slideSize; + + //QLabel * fitToWidthRatioLabel; + //QSlider * fitToWidthRatioS; + + QLabel * backgroundColor; + QPushButton * selectBackgroundColorButton; + + QColorDialog * colorDialog; + + YACReaderSpinSliderWidget * brightnessS; + + YACReaderSpinSliderWidget * contrastS; + + YACReaderSpinSliderWidget * gammaS; + + public slots: + void saveOptions(); + void restoreOptions(QSettings * settings); + void findFolder(); + void updateColor(const QColor & color); + //void fitToWidthRatio(int value); + void brightnessChanged(int value); + void contrastChanged(int value); + void gammaChanged(int value); + void resetImageConfig(); + void show(); + void setFilters(int brightness, int contrast, int gamma); + +signals: + void changedOptions(); + void changedImageOptions(); + void changedFilters(int brightness, int contrast, int gamma); + //void fitToWidthRatioChanged(float ratio); + +}; + + +#endif diff --git a/YACReader/page_label_widget.cpp b/YACReader/page_label_widget.cpp index 19a12c9b..71fb7627 100644 --- a/YACReader/page_label_widget.cpp +++ b/YACReader/page_label_widget.cpp @@ -1,105 +1,105 @@ -#include "page_label_widget.h" - -#include - -PageLabelWidget::PageLabelWidget(QWidget * parent) - :QWidget(parent) -{ - animation = new QPropertyAnimation(this,"pos"); - animation->setDuration(150); - animation->setEndValue(QPoint((parent->geometry().size().width()-this->width()),-this->height())); - - int verticalRes = QApplication::desktop()->screenGeometry().height(); - - QHBoxLayout *layout = new QHBoxLayout; - layout->setMargin(0); - setContentsMargins(0,0,0,0); - - QSize labelSize; - if (verticalRes <= 1024) - labelSize = QSize(135, 30); - else if (verticalRes <= 1200) - labelSize = QSize(170, 35); - else - labelSize = QSize(205, 45); - - textLabel = new QLabel(this); - textLabel->setAlignment(Qt::AlignVCenter|Qt::AlignHCenter); - if(verticalRes <= 1024) - textLabel->setStyleSheet("QLabel { color : white; font-size:12px; padding-left:8px; }"); - else if (verticalRes <= 1200) - textLabel->setStyleSheet("QLabel { color : white; font-size:16px; padding-left:8px;}"); - else - textLabel->setStyleSheet("QLabel { color : white; font-size:20px; padding-left:8px; }"); - - setFixedSize(labelSize); - - if(parent != 0) - move(QPoint((parent->geometry().size().width()-this->width()),-this->height())); - - layout->addWidget(textLabel, 0 , Qt::AlignCenter); - setLayout(layout); -} - -void PageLabelWidget::show() -{ - if(this->pos().y() <= 0 && animation->state()!=QPropertyAnimation::Running) - { - QWidget * parent = dynamic_cast(this->parent()); - if(parent == 0) - { - return; - } - - QWidget::show(); - //connect(animation,SIGNAL(finished()),this,SLOT(QWidget::hide())); - animation->disconnect(); - - animation->setStartValue(QPoint((parent->geometry().size().width()-this->width()),-this->height())); - animation->setEndValue(QPoint((parent->geometry().size().width()-this->width()),0)); - animation->start(); - } -} - -void PageLabelWidget::hide() -{ - if(this->pos().y() >= 0 && animation->state()!=QPropertyAnimation::Running) - { - QWidget * parent = dynamic_cast(this->parent()); - if(parent == 0) - { - return; - } - //connect(animation,SIGNAL(finished()),this,SLOT(setHidden())); - animation->setStartValue(QPoint((parent->geometry().size().width()-this->width()),0)); - animation->setEndValue(QPoint((parent->geometry().size().width()-this->width()),-this->height())); - animation->start(); - } -} - -void PageLabelWidget::setText(const QString & text) -{ - textLabel->setText(text); -} - -void PageLabelWidget::paintEvent(QPaintEvent *) -{ - QPainter painter(this); - - painter.fillRect(0,0,width(),height(),QColor("#BB000000")); -} - -void PageLabelWidget::updatePosition() -{ - QWidget * parent = dynamic_cast(this->parent()); - if(parent == 0) - { - return; - } - - animation->stop(); - if (animation->endValue().toPoint().y() == 0) - move(QPoint((parent->geometry().size().width()-this->width()),0)); - else - move(QPoint((parent->geometry().size().width()-this->width()),-this->height())); -} +#include "page_label_widget.h" + +#include + +PageLabelWidget::PageLabelWidget(QWidget * parent) + :QWidget(parent) +{ + animation = new QPropertyAnimation(this,"pos"); + animation->setDuration(150); + animation->setEndValue(QPoint((parent->geometry().size().width()-this->width()),-this->height())); + + int verticalRes = QApplication::desktop()->screenGeometry().height(); + + QHBoxLayout *layout = new QHBoxLayout; + layout->setMargin(0); + setContentsMargins(0,0,0,0); + + QSize labelSize; + if (verticalRes <= 1024) + labelSize = QSize(135, 30); + else if (verticalRes <= 1200) + labelSize = QSize(170, 35); + else + labelSize = QSize(205, 45); + + textLabel = new QLabel(this); + textLabel->setAlignment(Qt::AlignVCenter|Qt::AlignHCenter); + if(verticalRes <= 1024) + textLabel->setStyleSheet("QLabel { color : white; font-size:12px; padding-left:8px; }"); + else if (verticalRes <= 1200) + textLabel->setStyleSheet("QLabel { color : white; font-size:16px; padding-left:8px;}"); + else + textLabel->setStyleSheet("QLabel { color : white; font-size:20px; padding-left:8px; }"); + + setFixedSize(labelSize); + + if(parent != 0) + move(QPoint((parent->geometry().size().width()-this->width()),-this->height())); + + layout->addWidget(textLabel, 0 , Qt::AlignCenter); + setLayout(layout); +} + +void PageLabelWidget::show() +{ + if(this->pos().y() <= 0 && animation->state()!=QPropertyAnimation::Running) + { + QWidget * parent = dynamic_cast(this->parent()); + if(parent == 0) + { + return; + } + + QWidget::show(); + //connect(animation,SIGNAL(finished()),this,SLOT(QWidget::hide())); + animation->disconnect(); + + animation->setStartValue(QPoint((parent->geometry().size().width()-this->width()),-this->height())); + animation->setEndValue(QPoint((parent->geometry().size().width()-this->width()),0)); + animation->start(); + } +} + +void PageLabelWidget::hide() +{ + if(this->pos().y() >= 0 && animation->state()!=QPropertyAnimation::Running) + { + QWidget * parent = dynamic_cast(this->parent()); + if(parent == 0) + { + return; + } + //connect(animation,SIGNAL(finished()),this,SLOT(setHidden())); + animation->setStartValue(QPoint((parent->geometry().size().width()-this->width()),0)); + animation->setEndValue(QPoint((parent->geometry().size().width()-this->width()),-this->height())); + animation->start(); + } +} + +void PageLabelWidget::setText(const QString & text) +{ + textLabel->setText(text); +} + +void PageLabelWidget::paintEvent(QPaintEvent *) +{ + QPainter painter(this); + + painter.fillRect(0,0,width(),height(),QColor("#BB000000")); +} + +void PageLabelWidget::updatePosition() +{ + QWidget * parent = dynamic_cast(this->parent()); + if(parent == 0) + { + return; + } + + animation->stop(); + if (animation->endValue().toPoint().y() == 0) + move(QPoint((parent->geometry().size().width()-this->width()),0)); + else + move(QPoint((parent->geometry().size().width()-this->width()),-this->height())); +} diff --git a/YACReader/page_label_widget.h b/YACReader/page_label_widget.h index 5d70d74f..188a72d8 100644 --- a/YACReader/page_label_widget.h +++ b/YACReader/page_label_widget.h @@ -1,29 +1,29 @@ -#ifndef PAGE_LABEL_WIDGET_H -#define PAGE_LABEL_WIDGET_H - -#include - -class QLabel; -class QPropertyAnimation; - -class PageLabelWidget : public QWidget -{ -Q_OBJECT -private: - QLabel * textLabel; - QPropertyAnimation * animation; - -protected: - virtual void paintEvent(QPaintEvent *); - -public: - PageLabelWidget(QWidget * parent); - -public slots: - void show(); - void hide(); - void setText(const QString & text); - void updatePosition(); -}; - -#endif +#ifndef PAGE_LABEL_WIDGET_H +#define PAGE_LABEL_WIDGET_H + +#include + +class QLabel; +class QPropertyAnimation; + +class PageLabelWidget : public QWidget +{ +Q_OBJECT +private: + QLabel * textLabel; + QPropertyAnimation * animation; + +protected: + virtual void paintEvent(QPaintEvent *); + +public: + PageLabelWidget(QWidget * parent); + +public slots: + void show(); + void hide(); + void setText(const QString & text); + void updatePosition(); +}; + +#endif diff --git a/YACReader/render.cpp b/YACReader/render.cpp index e3f6cc44..f2d46255 100644 --- a/YACReader/render.cpp +++ b/YACReader/render.cpp @@ -1,1199 +1,1199 @@ -#include "render.h" -#include -#include -#include -#include -#include -#include -#include - -#include - -#include "comic_db.h" -#include "yacreader_global_gui.h" - -template -inline const T& kClamp( const T& x, const T& low, const T& high ) -{ - if ( x < low ) return low; - else if ( high < x ) return high; - else return x; -} - -inline -int changeBrightness( int value, int brightness ) - { - return kClamp( value + brightness * 255 / 100, 0, 255 ); - } - -inline -int changeContrast( int value, int contrast ) - { - return kClamp((( value - 127 ) * contrast / 100 ) + 127, 0, 255 ); - } - -inline -int changeGamma( int value, int gamma ) - { - return kClamp( int( pow( value / 255.0, 100.0 / gamma ) * 255 ), 0, 255 ); - } - -inline -int changeUsingTable( int value, const int table[] ) - { - return table[ value ]; - } - -template< int operation( int, int ) > -static -QImage changeImage( const QImage& image, int value ) - { - QImage im = image; - im.detach(); - if( im.colorCount() == 0 ) /* truecolor */ - { - if( im.format() != QImage::Format_RGB32 ) /* just in case */ - im = im.convertToFormat( QImage::Format_RGB32 ); - int table[ 256 ]; - for( int i = 0; - i < 256; - ++i ) - table[ i ] = operation( i, value ); - if( im.hasAlphaChannel() ) - { - for( int y = 0; - y < im.height(); - ++y ) - { - QRgb* line = reinterpret_cast< QRgb* >( im.scanLine( y )); - for( int x = 0; - x < im.width(); - ++x ) - line[ x ] = qRgba( changeUsingTable( qRed( line[ x ] ), table ), - changeUsingTable( qGreen( line[ x ] ), table ), - changeUsingTable( qBlue( line[ x ] ), table ), - changeUsingTable( qAlpha( line[ x ] ), table )); - } - } - else - { - for( int y = 0; - y < im.height(); - ++y ) - { - QRgb* line = reinterpret_cast< QRgb* >( im.scanLine( y )); - for( int x = 0; - x < im.width(); - ++x ) - line[ x ] = qRgb( changeUsingTable( qRed( line[ x ] ), table ), - changeUsingTable( qGreen( line[ x ] ), table ), - changeUsingTable( qBlue( line[ x ] ), table )); - } - } - } - else - { - QVector colors = im.colorTable(); - for( int i = 0; - i < im.colorCount(); - ++i ) - colors[ i ] = qRgb( operation( qRed( colors[ i ] ), value ), - operation( qGreen( colors[ i ] ), value ), - operation( qBlue( colors[ i ] ), value )); - im.setColorTable(colors); - } - return im; - } - - -// brightness is multiplied by 100 in order to avoid floating point numbers -QImage changeBrightness( const QImage& image, int brightness ) - { - if( brightness == 0 ) // no change - return image; - return changeImage< changeBrightness >( image, brightness ); - } - - -// contrast is multiplied by 100 in order to avoid floating point numbers -QImage changeContrast( const QImage& image, int contrast ) - { - if( contrast == 100 ) // no change - return image; - return changeImage< changeContrast >( image, contrast ); - } - -// gamma is multiplied by 100 in order to avoid floating point numbers -QImage changeGamma( const QImage& image, int gamma ) - { - if( gamma == 100 ) // no change - return image; - return changeImage< changeGamma >( image, gamma ); - } - - - -//----------------------------------------------------------------------------- -// MeanNoiseReductionFilter -//----------------------------------------------------------------------------- - -MeanNoiseReductionFilter::MeanNoiseReductionFilter(enum NeighborghoodSize ns) -:neighborghoodSize(ns) -{ - -} - -QImage MeanNoiseReductionFilter::setFilter(const QImage & image) -{ - int width = image.width(); - int height = image.height(); - QImage result(width,height,image.format()); - int filterSize = sqrt((float)neighborghoodSize); - int bound = filterSize/2; - QRgb pix; - int r,g,b; - for(int j=bound;j redChannel; - QList greenChannel; - QList blueChannel; - for(int j=bound;j hist(256,0); - - for(int j=0;j 1; i--) - { - new_count += hist[i]; - percentage = new_count/count; - next_percentage = (new_count+hist[i-1])/count; - if(fabs (percentage - 0.006) < fabs (next_percentage - 0.006)) - { - max = i-1; - break; - } - } - QColor c; - int range = max - min; - for(int j=0;j f) -:QThread(), -render(r), -numPage(np), -data(rd), -page(p), -degrees(d), -filters(f) -{ -} - -void PageRender::run() -{ - QMutexLocker locker(&(render->mutex)); - - QImage img; - img.loadFromData(data); - if(degrees > 0) - { - QMatrix m; - m.rotate(degrees); - img = img.transformed(m,Qt::SmoothTransformation); - } - for(int i=0;isetFilter(img); - } - - - *page = img; - - emit pageReady(numPage); -} - -//----------------------------------------------------------------------------- -// Render -//----------------------------------------------------------------------------- - -Render::Render() -:currentIndex(0),doublePage(false),doubleMangaPage(false),comic(0),loadedComic(false),imageRotation(0),numLeftPages(4),numRightPages(4) -{ - int size = numLeftPages+numRightPages+1; - currentPageBufferedIndex = numLeftPages; - for(int i = 0; imoveToThread(QApplication::instance()->thread()); - comic->deleteLater(); - } - - foreach(PageRender * pr,pageRenders) - if(pr !=0) - { - if(pr->wait()) - delete pr; - } - - //TODO move to share_ptr - foreach(ImageFilter * filter, filters) - delete filter; -} -//Este método se encarga de forzar el renderizado de las páginas. -//Actualiza el buffer según es necesario. -//si la pagina actual no está renderizada, se lanza un hilo que la renderize (double or single page mode) y se emite una señal que indica que se está renderizando. -void Render::render() -{ - updateBuffer(); - if(buffer[currentPageBufferedIndex]->isNull()) - { - if(pagesReady.size()>0) - { - if(pagesReady[currentIndex]) - { - pageRenders[currentPageBufferedIndex] = new PageRender(this,currentIndex,comic->getRawData()->at(currentIndex),buffer[currentPageBufferedIndex],imageRotation,filters); - } - else - //las páginas no están listas, y se están cargando en el cómic - emit processingPage(); //para evitar confusiones esta señal debería llamarse de otra forma - - //si se ha creado un hilo para renderizar la página actual, se arranca - if(pageRenders[currentPageBufferedIndex]!=0) - { - //se conecta la señal pageReady del hilo, con el SLOT prepareAvailablePage - connect(pageRenders[currentPageBufferedIndex],SIGNAL(pageReady(int)),this,SLOT(prepareAvailablePage(int))); - //se emite la señal de procesando, debido a que los hilos se arrancan aquí - if(filters.size()>0) - emit processingPage(); - pageRenders[currentPageBufferedIndex]->start(); - pageRenders[currentPageBufferedIndex]->setPriority(QThread::TimeCriticalPriority); - } - else - //en qué caso sería necesario hacer esto??? //TODO: IMPORTANTE, puede que no sea necesario. - emit processingPage(); - } - else - //no hay ninguna página lista para ser renderizada, es necesario esperar. - emit processingPage(); - } - else - // la página actual está lista - { - //emit currentPageReady(); - //make prepareAvailablePage the only function that emits currentPageReady() - prepareAvailablePage(currentIndex); - } - fillBuffer(); -} - -QPixmap * Render::getCurrentPage() -{ - QPixmap * page = new QPixmap(); - *page = page->fromImage(*buffer[currentPageBufferedIndex]); - return page; -} - -QPixmap * Render::getCurrentDoublePage() -{ - if (currentPageIsDoublePage()) - { - QPoint leftpage(0,0); - QPoint rightpage(0,0); - QSize leftsize = buffer[currentPageBufferedIndex]->size(); - QSize rightsize = buffer[currentPageBufferedIndex+1]->size(); - int totalWidth,totalHeight; - switch (imageRotation) - { - case 0: - totalHeight = qMax(leftsize.rheight(),rightsize.rheight()); - leftsize.scale(leftsize.rwidth(), totalHeight, Qt::KeepAspectRatioByExpanding); - rightsize.scale(rightsize.rwidth(), totalHeight, Qt::KeepAspectRatioByExpanding); - totalWidth = leftsize.rwidth() + rightsize.rwidth(); - rightpage.setX(leftsize.rwidth()); - break; - case 90: - totalWidth = qMax(leftsize.rwidth(), rightsize.rwidth()); - leftsize.scale(totalWidth, leftsize.rheight(), Qt::KeepAspectRatioByExpanding); - rightsize.scale(totalWidth, rightsize.rheight(), Qt::KeepAspectRatioByExpanding); - totalHeight = leftsize.rheight() + rightsize.rheight(); - rightpage.setY(leftsize.rheight()); - break; - case 180: - totalHeight = qMax(leftsize.rheight(),rightsize.rheight()); - leftsize.scale(leftsize.rwidth(), totalHeight, Qt::KeepAspectRatioByExpanding); - rightsize.scale(rightsize.rwidth(), totalHeight, Qt::KeepAspectRatioByExpanding); - totalWidth = leftsize.rwidth() + rightsize.rwidth(); - leftpage.setX(rightsize.rwidth()); - break; - case 270: - totalWidth = qMax(leftsize.rwidth(), rightsize.rwidth()); - leftsize.scale(totalWidth, leftsize.rheight(), Qt::KeepAspectRatioByExpanding); - rightsize.scale(totalWidth, rightsize.rheight(), Qt::KeepAspectRatioByExpanding); - totalHeight = leftsize.rheight() + rightsize.rheight(); - leftpage.setY(rightsize.rheight()); - break; - default: - return NULL; - } - QPixmap * page = new QPixmap(totalWidth, totalHeight); - QPainter painter(page); - painter.drawImage(QRect(leftpage,leftsize), *buffer[currentPageBufferedIndex]); - painter.drawImage(QRect(rightpage,rightsize), *buffer[currentPageBufferedIndex+1]); - return page; - } - else - { - return NULL; - } -} - -QPixmap * Render::getCurrentDoubleMangaPage() -{ - if (currentPageIsDoublePage()) - { - QPoint leftpage(0,0); - QPoint rightpage(0,0); - QSize leftsize = buffer[currentPageBufferedIndex+1]->size(); - QSize rightsize = buffer[currentPageBufferedIndex]->size(); - int totalWidth,totalHeight; - switch (imageRotation) - { - case 0: - totalHeight = qMax(leftsize.rheight(),rightsize.rheight()); - leftsize.scale(leftsize.rwidth(), totalHeight, Qt::KeepAspectRatioByExpanding); - rightsize.scale(rightsize.rwidth(), totalHeight, Qt::KeepAspectRatioByExpanding); - totalWidth = leftsize.rwidth() + rightsize.rwidth(); - rightpage.setX(leftsize.rwidth()); - break; - case 90: - totalWidth = qMax(leftsize.rwidth(), rightsize.rwidth()); - leftsize.scale(totalWidth, leftsize.rheight(), Qt::KeepAspectRatioByExpanding); - rightsize.scale(totalWidth, rightsize.rheight(), Qt::KeepAspectRatioByExpanding); - totalHeight = leftsize.rheight() + rightsize.rheight(); - rightpage.setY(leftsize.rheight()); - break; - case 180: - totalHeight = qMax(leftsize.rheight(),rightsize.rheight()); - leftsize.scale(leftsize.rwidth(), totalHeight, Qt::KeepAspectRatioByExpanding); - rightsize.scale(rightsize.rwidth(), totalHeight, Qt::KeepAspectRatioByExpanding); - totalWidth = leftsize.rwidth() + rightsize.rwidth(); - leftpage.setX(rightsize.rwidth()); - break; - case 270: - totalWidth = qMax(leftsize.rwidth(), rightsize.rwidth()); - leftsize.scale(totalWidth, leftsize.rheight(), Qt::KeepAspectRatioByExpanding); - rightsize.scale(totalWidth, rightsize.rheight(), Qt::KeepAspectRatioByExpanding); - totalHeight = leftsize.rheight() + rightsize.rheight(); - leftpage.setY(rightsize.rheight()); - break; - default: - return NULL; - } - QPixmap * page = new QPixmap(totalWidth, totalHeight); - QPainter painter(page); - painter.drawImage(QRect(rightpage, rightsize), *buffer[currentPageBufferedIndex]); - painter.drawImage(QRect(leftpage, leftsize), *buffer[currentPageBufferedIndex+1]); - return page; - } - else - { - return NULL; - } -} - -bool Render::currentPageIsDoublePage() -{ - if (buffer[currentPageBufferedIndex]->isNull() || buffer[currentPageBufferedIndex+1]->isNull()) - { - return false; - } - if (imageRotation == 0 || imageRotation == 180) - { - if (buffer[currentPageBufferedIndex]->height() > buffer[currentPageBufferedIndex]->width() && - buffer[currentPageBufferedIndex+1]->height() > buffer[currentPageBufferedIndex+1]->width()) - { - return true; - } - } - else if (imageRotation == 90 || imageRotation == 270) - { - if (buffer[currentPageBufferedIndex]->width() > buffer[currentPageBufferedIndex]->height() && - buffer[currentPageBufferedIndex+1]->width() > buffer[currentPageBufferedIndex+1]->height()) - { - return true; - } - } - return false; -} - -bool Render::nextPageIsDoublePage() -{ - //this function is not used right now - if (buffer[currentPageBufferedIndex+2]->isNull() || buffer[currentPageBufferedIndex+3]->isNull()) - { - return false; - } - if (imageRotation == 0 || imageRotation == 180) - { - if (buffer[currentPageBufferedIndex+2]->height() > buffer[currentPageBufferedIndex+2]->width() && - buffer[currentPageBufferedIndex+3]->height() > buffer[currentPageBufferedIndex+3]->width()) - { - return true; - } - } - else if (imageRotation == 90 || imageRotation == 270) - { - if (buffer[currentPageBufferedIndex]->width() > buffer[currentPageBufferedIndex]->height() && - buffer[currentPageBufferedIndex+1]->width() > buffer[currentPageBufferedIndex+1]->height()) - { - return true; - } - } - return false; -} - -bool Render::previousPageIsDoublePage() -{ - if (buffer[currentPageBufferedIndex-1]->isNull() || buffer[currentPageBufferedIndex-2]->isNull()) - { - return false; - } - if (imageRotation == 0 || imageRotation == 180) - { - if (buffer[currentPageBufferedIndex-1]->height() > buffer[currentPageBufferedIndex-1]->width() && - buffer[currentPageBufferedIndex-2]->height() > buffer[currentPageBufferedIndex-2]->width()) - { - return true; - } - } - else if (imageRotation == 90 || imageRotation == 270) - { - if (buffer[currentPageBufferedIndex-1]->width() > buffer[currentPageBufferedIndex-1]->height() && - buffer[currentPageBufferedIndex-2]->width() > buffer[currentPageBufferedIndex-2]->height()) - { - return true; - } - } - return false; -} - -void Render::setRotation(int degrees) -{ - Q_UNUSED(degrees) -} - -void Render::setComic(Comic * c) -{ - if(comic !=0) - { - comic->moveToThread(QApplication::instance()->thread()); - comic->disconnect(); - comic->deleteLater(); - } - comic = c; -} - -void Render::prepareAvailablePage(int page) -{ - if(!doublePage) - { - if (currentIndex == page) - { - emit currentPageReady(); - } - } - else - { - //check for last page in double page mode - if ((currentIndex == page) && (currentIndex + 1) >= (int)comic->numPages()) - { - emit currentPageReady(); - } - else if ((currentIndex == page && !buffer[currentPageBufferedIndex+1]->isNull()) || - (currentIndex+1 == page && !buffer[currentPageBufferedIndex]->isNull())) - { - emit currentPageReady(); - } - } -} - -void Render::update() -{ - render(); -} -//----------------------------------------------------------------------------- -// Comic interface -//----------------------------------------------------------------------------- -void Render::load(const QString & path, int atPage) -{ - createComic(path); - if (comic !=0) - { - loadComic(path,atPage); - startLoad(); - } -} - -//----------------------------------------------------------------------------- -void Render::load(const QString & path, const ComicDB & comicDB) -{ - //TODO prepare filters - for(int i = 0; i < filters.count(); i++) - { - if(typeid(*filters[i]) == typeid(BrightnessFilter)) - if(comicDB.info.brightness == -1) - filters[i]->setLevel(0); - else - filters[i]->setLevel(comicDB.info.brightness); - if(typeid(*filters[i]) == typeid(ContrastFilter)) - if(comicDB.info.contrast == -1) - filters[i]->setLevel(100); - else - filters[i]->setLevel(comicDB.info.contrast); - if(typeid(*filters[i]) == typeid(GammaFilter)) - if(comicDB.info.gamma == -1) - filters[i]->setLevel(100); - else - filters[i]->setLevel(comicDB.info.gamma); - } - createComic(path); - if (comic!=0) - { - loadComic(path,comicDB); - startLoad(); - } -} - -void Render::createComic(const QString & path) -{ - previousIndex = currentIndex = 0; - pagesEmited.clear(); - - if(comic!=0) - { - //comic->moveToThread(QApplication::instance()->thread()); - comic->invalidate(); - - comic->disconnect(); - comic->deleteLater(); - } - //comic->moveToThread(QApplication::instance()->thread()); - comic = FactoryComic::newComic(path); - - if(comic == NULL)//archivo no encontrado o no válido - { - emit errorOpening(); - reset(); - return; - } - - connect(comic,SIGNAL(errorOpening()),this,SIGNAL(errorOpening()), Qt::QueuedConnection); - connect(comic,SIGNAL(errorOpening(QString)),this,SIGNAL(errorOpening(QString)), Qt::QueuedConnection); - connect(comic,SIGNAL(crcErrorFound(QString)),this,SIGNAL(crcError(QString)), Qt::QueuedConnection); - connect(comic,SIGNAL(errorOpening()),this,SLOT(reset()), Qt::QueuedConnection); - connect(comic,SIGNAL(imageLoaded(int)),this,SLOT(pageRawDataReady(int)), Qt::QueuedConnection); - connect(comic,SIGNAL(imageLoaded(int)),this,SIGNAL(imageLoaded(int)), Qt::QueuedConnection); - connect(comic,SIGNAL(openAt(int)),this,SLOT(renderAt(int)), Qt::QueuedConnection); - connect(comic,SIGNAL(numPages(unsigned int)),this,SIGNAL(numPages(unsigned int)), Qt::QueuedConnection); - connect(comic,SIGNAL(numPages(unsigned int)),this,SLOT(setNumPages(unsigned int)), Qt::QueuedConnection); - connect(comic,SIGNAL(imageLoaded(int,QByteArray)),this,SIGNAL(imageLoaded(int,QByteArray)), Qt::QueuedConnection); - connect(comic,SIGNAL(isBookmark(bool)),this,SIGNAL(currentPageIsBookmark(bool)), Qt::QueuedConnection); - - connect(comic,SIGNAL(bookmarksUpdated()),this,SIGNAL(bookmarksUpdated()), Qt::QueuedConnection); - - //connect(comic,SIGNAL(isLast()),this,SIGNAL(isLast())); - //connect(comic,SIGNAL(isCover()),this,SIGNAL(isCover())); - - pagesReady.clear(); -} -void Render::loadComic(const QString & path,const ComicDB & comicDB) -{ - comic->load(path,comicDB); -} -void Render::loadComic(const QString & path, int atPage) -{ - comic->load(path,atPage); -} - -void Render::startLoad() -{ - QThread * thread = nullptr; - - thread = new QThread(); - - comic->moveToThread(thread); - - connect(comic, SIGNAL(errorOpening()), thread, SLOT(quit()), Qt::QueuedConnection); - connect(comic, SIGNAL(errorOpening(QString)), thread, SLOT(quit()), Qt::QueuedConnection); - connect(comic, SIGNAL(imagesLoaded()), thread, SLOT(quit()), Qt::QueuedConnection); - connect(comic, SIGNAL(destroyed()), thread, SLOT(quit()), Qt::QueuedConnection); - connect(comic, SIGNAL(invalidated()), thread, SLOT(quit()), Qt::QueuedConnection); - connect(thread, SIGNAL(started()), comic, SLOT(process())); - connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater())); - - if(thread != nullptr) - thread->start(); - - invalidate(); - loadedComic = true; - update(); -} - -void Render::renderAt(int page) -{ - previousIndex = currentIndex = page; - emit pageChanged(page); -} - -void Render::reset() -{ - loadedComic = false; - invalidate(); -} -//si se solicita la siguiente página, se calcula cuál debe ser en función de si se lee en modo a doble página o no. -//la página sólo se renderiza, si realmente ha cambiado. -void Render::nextPage() -{ - int nextPage; //indica cuál será la próxima página - nextPage = comic->nextPage(); - //se fuerza renderizado si la página ha cambiado - if(currentIndex != nextPage) - { - previousIndex = currentIndex; - currentIndex = nextPage; - update(); - emit pageChanged(currentIndex); - } - else if (hasLoadedComic() && (currentIndex == numPages()-1)) - { - emit isLast(); - } -} -void Render::nextDoublePage() -{ - int nextPage; - if (currentIndex +2 < (int)comic->numPages()) - { - nextPage = currentIndex+2; - } - else - { - nextPage = currentIndex; - } - if(currentIndex != nextPage) - { - comic->setIndex(nextPage); - previousIndex = currentIndex; - currentIndex = nextPage; - update(); - emit pageChanged(currentIndex); - } - else if (hasLoadedComic() && ((unsigned int)currentIndex >= numPages()-2)) - { - emit isLast(); - } -} - -//si se solicita la página anterior, se calcula cuál debe ser en función de si se lee en modo a doble página o no. -//la página sólo se renderiza, si realmente ha cambiado. -void Render::previousPage() -{ - int previousPage; //indica cuál será la próxima página - previousPage = comic->previousPage(); - - //se fuerza renderizado si la página ha cambiado - if(currentIndex != previousPage) - { - previousIndex = currentIndex; - currentIndex = previousPage; - update(); - emit pageChanged(currentIndex); - } - else if (hasLoadedComic() && (currentIndex == 0)) - { - emit isCover(); - } -} - -void Render::previousDoublePage() -{ - int previousPage; //indica cuál será la próxima página - previousPage = qMax(currentIndex-2,0); - if(currentIndex != previousPage) - { - comic->setIndex(previousPage); - previousIndex = currentIndex; - currentIndex = previousPage; - update(); - emit pageChanged(currentIndex); - } -} - -unsigned int Render::getIndex() -{ - return comic->getIndex(); -} -unsigned int Render::numPages() -{ - return comic->numPages(); -} - -bool Render::hasLoadedComic() -{ - if(comic!=0) - return comic->loaded(); - return false; -} - -void Render::setNumPages(unsigned int numPages) -{ - pagesReady.fill(false,numPages); -} - -void Render::pageRawDataReady(int page) -{ - if (!hasLoadedComic()) - return; - - pagesEmited.push_back(page); - if(pageRenders.size()>0) - { - for(int i=0;i= pagesReady.size()) - { - pagesEmited.clear(); - return; //Oooops, something went wrong - } - - pagesReady[pagesEmited.at(i)] = true; - if(pagesEmited.at(i) == currentIndex) - update(); - else - { - if ( ((pagesEmited.at(i) < currentIndex) && (pagesEmited.at(i) > currentIndex-numLeftPages)) || - ((pagesEmited.at(i) > currentIndex) && (pagesEmited.at(i) < currentIndex+numRightPages)) ) - { - fillBuffer(); - } - } - } - pagesEmited.clear(); - } -} - -//sólo se renderiza la página, si ha habido un cambio de página -void Render::goTo(int index) -{ - - if(currentIndex != index) - { - comic->setIndex(index); - previousIndex = currentIndex; - currentIndex = index; - update(); - emit pageChanged(currentIndex); - } -} - -void Render::rotateRight() -{ - imageRotation = (imageRotation+90) % 360; - reload(); -} -void Render::rotateLeft() -{ - if(imageRotation == 0) - imageRotation = 270; - else - imageRotation = imageRotation - 90; - reload(); -} - -//Actualiza el buffer, añadiendo las imágenes (vacías) necesarias para su posterior renderizado y -//eliminado aquellas que ya no sean necesarias. También libera los hilos (no estoy seguro de que sea responsabilidad suya) -//Calcula el número de nuevas páginas que hay que buferear y si debe hacerlo por la izquierda o la derecha (según sea el sentido de la lectura) -void Render::updateBuffer() -{ - QMutexLocker locker(&mutex); - int windowSize = currentIndex - previousIndex; - - if(windowSize > 0)//add pages to right pages and remove on the left - { - windowSize = qMin(windowSize,buffer.size()); - for(int i = 0; i < windowSize; i++) - { - //renders - PageRender * pr = pageRenders.front(); - pageRenders.pop_front(); - if(pr !=0) - { - if(pr->wait()) - delete pr; - } - pageRenders.push_back(0); - - //images - - if(buffer.front()!=0) - delete buffer.front(); - buffer.pop_front(); - buffer.push_back(new QImage()); - } - } - else //add pages to left pages and remove on the right - if(windowSize<0) - { - windowSize = -windowSize; - windowSize = qMin(windowSize,buffer.size()); - for(int i = 0; i < windowSize; i++) - { - //renders - PageRender * pr = pageRenders.back(); - pageRenders.pop_back(); - if(pr !=0) - { - if(pr->wait()) - delete pr; - } - pageRenders.push_front(0); - - //images - buffer.push_front(new QImage()); - QImage * p = buffer.back(); - if(p!=0) - delete p; - buffer.pop_back(); - } - } - previousIndex = currentIndex; -} - -void Render::fillBuffer() -{ - if (pagesReady.size() < 1) - { - return; - } - - for(int i = 1; i <= qMax(numLeftPages,numRightPages); i++) - { - if ((currentIndex+i < (int)comic->numPages()) && - buffer[currentPageBufferedIndex+i]->isNull() && - i <= numRightPages && - pageRenders[currentPageBufferedIndex+i]==0 && - pagesReady[currentIndex+i]) //preload next pages - { - pageRenders[currentPageBufferedIndex+i] = new PageRender(this,currentIndex+i,comic->getRawData()->at(currentIndex+i),buffer[currentPageBufferedIndex+i],imageRotation,filters); - connect(pageRenders[currentPageBufferedIndex+i],SIGNAL(pageReady(int)),this,SLOT(prepareAvailablePage(int))); - pageRenders[currentPageBufferedIndex+i]->start(); - } - - if ((currentIndex-i > 0) && - buffer[currentPageBufferedIndex-i]->isNull() && - i <= numLeftPages && - pageRenders[currentPageBufferedIndex-i]==0 && - pagesReady[currentIndex-i]) //preload previous pages - { - pageRenders[currentPageBufferedIndex-i] = new PageRender(this,currentIndex-i,comic->getRawData()->at(currentIndex-i),buffer[currentPageBufferedIndex-i],imageRotation,filters); - connect(pageRenders[currentPageBufferedIndex-i],SIGNAL(pageReady(int)),this,SLOT(prepareAvailablePage(int))); - pageRenders[currentPageBufferedIndex-i]->start(); - } - } -} - - -//Método que debe ser llamado cada vez que la estructura del buffer se vuelve inconsistente con el modo de lectura actual. -//se terminan todos los hilos en ejecución y se libera la memoria (de hilos e imágenes) -void Render::invalidate() -{ - for(int i=0;iwait(); - delete pageRenders[i]; - pageRenders[i] = 0; - } - } - - for(int i=0;inumPages())) - { - if (currentPageIsDoublePage()) - { - if (doubleMangaPage) - s = QString::number(currentIndex+2) + "-" + s; - else - s += "-"+QString::number(currentIndex+2); - } - } - s += "/"+QString::number(comic->numPages()); - return s; -} - -void Render::setBookmark() -{ - comic->setBookmark(); -} - -void Render::removeBookmark() -{ - comic->removeBookmark(); -} - -void Render::save() -{ - comic->saveBookmarks(); -} - -Bookmarks * Render::getBookmarks() -{ - return comic->bm; -} - -void Render::reload() -{ - if(comic) - { - invalidate(); - update(); - } -} - -void Render::updateFilters(int brightness, int contrast, int gamma) -{ - for(int i = 0; i < filters.count(); i++) - { - if(typeid(*filters[i]) == typeid(BrightnessFilter)) - filters[i]->setLevel(brightness); - if(typeid(*filters[i]) == typeid(ContrastFilter)) - filters[i]->setLevel(contrast); - if(typeid(*filters[i]) == typeid(GammaFilter)) - filters[i]->setLevel(gamma); - } - - reload(); -} +#include "render.h" +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "comic_db.h" +#include "yacreader_global_gui.h" + +template +inline const T& kClamp( const T& x, const T& low, const T& high ) +{ + if ( x < low ) return low; + else if ( high < x ) return high; + else return x; +} + +inline +int changeBrightness( int value, int brightness ) + { + return kClamp( value + brightness * 255 / 100, 0, 255 ); + } + +inline +int changeContrast( int value, int contrast ) + { + return kClamp((( value - 127 ) * contrast / 100 ) + 127, 0, 255 ); + } + +inline +int changeGamma( int value, int gamma ) + { + return kClamp( int( pow( value / 255.0, 100.0 / gamma ) * 255 ), 0, 255 ); + } + +inline +int changeUsingTable( int value, const int table[] ) + { + return table[ value ]; + } + +template< int operation( int, int ) > +static +QImage changeImage( const QImage& image, int value ) + { + QImage im = image; + im.detach(); + if( im.colorCount() == 0 ) /* truecolor */ + { + if( im.format() != QImage::Format_RGB32 ) /* just in case */ + im = im.convertToFormat( QImage::Format_RGB32 ); + int table[ 256 ]; + for( int i = 0; + i < 256; + ++i ) + table[ i ] = operation( i, value ); + if( im.hasAlphaChannel() ) + { + for( int y = 0; + y < im.height(); + ++y ) + { + QRgb* line = reinterpret_cast< QRgb* >( im.scanLine( y )); + for( int x = 0; + x < im.width(); + ++x ) + line[ x ] = qRgba( changeUsingTable( qRed( line[ x ] ), table ), + changeUsingTable( qGreen( line[ x ] ), table ), + changeUsingTable( qBlue( line[ x ] ), table ), + changeUsingTable( qAlpha( line[ x ] ), table )); + } + } + else + { + for( int y = 0; + y < im.height(); + ++y ) + { + QRgb* line = reinterpret_cast< QRgb* >( im.scanLine( y )); + for( int x = 0; + x < im.width(); + ++x ) + line[ x ] = qRgb( changeUsingTable( qRed( line[ x ] ), table ), + changeUsingTable( qGreen( line[ x ] ), table ), + changeUsingTable( qBlue( line[ x ] ), table )); + } + } + } + else + { + QVector colors = im.colorTable(); + for( int i = 0; + i < im.colorCount(); + ++i ) + colors[ i ] = qRgb( operation( qRed( colors[ i ] ), value ), + operation( qGreen( colors[ i ] ), value ), + operation( qBlue( colors[ i ] ), value )); + im.setColorTable(colors); + } + return im; + } + + +// brightness is multiplied by 100 in order to avoid floating point numbers +QImage changeBrightness( const QImage& image, int brightness ) + { + if( brightness == 0 ) // no change + return image; + return changeImage< changeBrightness >( image, brightness ); + } + + +// contrast is multiplied by 100 in order to avoid floating point numbers +QImage changeContrast( const QImage& image, int contrast ) + { + if( contrast == 100 ) // no change + return image; + return changeImage< changeContrast >( image, contrast ); + } + +// gamma is multiplied by 100 in order to avoid floating point numbers +QImage changeGamma( const QImage& image, int gamma ) + { + if( gamma == 100 ) // no change + return image; + return changeImage< changeGamma >( image, gamma ); + } + + + +//----------------------------------------------------------------------------- +// MeanNoiseReductionFilter +//----------------------------------------------------------------------------- + +MeanNoiseReductionFilter::MeanNoiseReductionFilter(enum NeighborghoodSize ns) +:neighborghoodSize(ns) +{ + +} + +QImage MeanNoiseReductionFilter::setFilter(const QImage & image) +{ + int width = image.width(); + int height = image.height(); + QImage result(width,height,image.format()); + int filterSize = sqrt((float)neighborghoodSize); + int bound = filterSize/2; + QRgb pix; + int r,g,b; + for(int j=bound;j redChannel; + QList greenChannel; + QList blueChannel; + for(int j=bound;j hist(256,0); + + for(int j=0;j 1; i--) + { + new_count += hist[i]; + percentage = new_count/count; + next_percentage = (new_count+hist[i-1])/count; + if(fabs (percentage - 0.006) < fabs (next_percentage - 0.006)) + { + max = i-1; + break; + } + } + QColor c; + int range = max - min; + for(int j=0;j f) +:QThread(), +render(r), +numPage(np), +data(rd), +page(p), +degrees(d), +filters(f) +{ +} + +void PageRender::run() +{ + QMutexLocker locker(&(render->mutex)); + + QImage img; + img.loadFromData(data); + if(degrees > 0) + { + QMatrix m; + m.rotate(degrees); + img = img.transformed(m,Qt::SmoothTransformation); + } + for(int i=0;isetFilter(img); + } + + + *page = img; + + emit pageReady(numPage); +} + +//----------------------------------------------------------------------------- +// Render +//----------------------------------------------------------------------------- + +Render::Render() +:currentIndex(0),doublePage(false),doubleMangaPage(false),comic(0),loadedComic(false),imageRotation(0),numLeftPages(4),numRightPages(4) +{ + int size = numLeftPages+numRightPages+1; + currentPageBufferedIndex = numLeftPages; + for(int i = 0; imoveToThread(QApplication::instance()->thread()); + comic->deleteLater(); + } + + foreach(PageRender * pr,pageRenders) + if(pr !=0) + { + if(pr->wait()) + delete pr; + } + + //TODO move to share_ptr + foreach(ImageFilter * filter, filters) + delete filter; +} +//Este método se encarga de forzar el renderizado de las páginas. +//Actualiza el buffer según es necesario. +//si la pagina actual no está renderizada, se lanza un hilo que la renderize (double or single page mode) y se emite una señal que indica que se está renderizando. +void Render::render() +{ + updateBuffer(); + if(buffer[currentPageBufferedIndex]->isNull()) + { + if(pagesReady.size()>0) + { + if(pagesReady[currentIndex]) + { + pageRenders[currentPageBufferedIndex] = new PageRender(this,currentIndex,comic->getRawData()->at(currentIndex),buffer[currentPageBufferedIndex],imageRotation,filters); + } + else + //las páginas no están listas, y se están cargando en el cómic + emit processingPage(); //para evitar confusiones esta señal debería llamarse de otra forma + + //si se ha creado un hilo para renderizar la página actual, se arranca + if(pageRenders[currentPageBufferedIndex]!=0) + { + //se conecta la señal pageReady del hilo, con el SLOT prepareAvailablePage + connect(pageRenders[currentPageBufferedIndex],SIGNAL(pageReady(int)),this,SLOT(prepareAvailablePage(int))); + //se emite la señal de procesando, debido a que los hilos se arrancan aquí + if(filters.size()>0) + emit processingPage(); + pageRenders[currentPageBufferedIndex]->start(); + pageRenders[currentPageBufferedIndex]->setPriority(QThread::TimeCriticalPriority); + } + else + //en qué caso sería necesario hacer esto??? //TODO: IMPORTANTE, puede que no sea necesario. + emit processingPage(); + } + else + //no hay ninguna página lista para ser renderizada, es necesario esperar. + emit processingPage(); + } + else + // la página actual está lista + { + //emit currentPageReady(); + //make prepareAvailablePage the only function that emits currentPageReady() + prepareAvailablePage(currentIndex); + } + fillBuffer(); +} + +QPixmap * Render::getCurrentPage() +{ + QPixmap * page = new QPixmap(); + *page = page->fromImage(*buffer[currentPageBufferedIndex]); + return page; +} + +QPixmap * Render::getCurrentDoublePage() +{ + if (currentPageIsDoublePage()) + { + QPoint leftpage(0,0); + QPoint rightpage(0,0); + QSize leftsize = buffer[currentPageBufferedIndex]->size(); + QSize rightsize = buffer[currentPageBufferedIndex+1]->size(); + int totalWidth,totalHeight; + switch (imageRotation) + { + case 0: + totalHeight = qMax(leftsize.rheight(),rightsize.rheight()); + leftsize.scale(leftsize.rwidth(), totalHeight, Qt::KeepAspectRatioByExpanding); + rightsize.scale(rightsize.rwidth(), totalHeight, Qt::KeepAspectRatioByExpanding); + totalWidth = leftsize.rwidth() + rightsize.rwidth(); + rightpage.setX(leftsize.rwidth()); + break; + case 90: + totalWidth = qMax(leftsize.rwidth(), rightsize.rwidth()); + leftsize.scale(totalWidth, leftsize.rheight(), Qt::KeepAspectRatioByExpanding); + rightsize.scale(totalWidth, rightsize.rheight(), Qt::KeepAspectRatioByExpanding); + totalHeight = leftsize.rheight() + rightsize.rheight(); + rightpage.setY(leftsize.rheight()); + break; + case 180: + totalHeight = qMax(leftsize.rheight(),rightsize.rheight()); + leftsize.scale(leftsize.rwidth(), totalHeight, Qt::KeepAspectRatioByExpanding); + rightsize.scale(rightsize.rwidth(), totalHeight, Qt::KeepAspectRatioByExpanding); + totalWidth = leftsize.rwidth() + rightsize.rwidth(); + leftpage.setX(rightsize.rwidth()); + break; + case 270: + totalWidth = qMax(leftsize.rwidth(), rightsize.rwidth()); + leftsize.scale(totalWidth, leftsize.rheight(), Qt::KeepAspectRatioByExpanding); + rightsize.scale(totalWidth, rightsize.rheight(), Qt::KeepAspectRatioByExpanding); + totalHeight = leftsize.rheight() + rightsize.rheight(); + leftpage.setY(rightsize.rheight()); + break; + default: + return NULL; + } + QPixmap * page = new QPixmap(totalWidth, totalHeight); + QPainter painter(page); + painter.drawImage(QRect(leftpage,leftsize), *buffer[currentPageBufferedIndex]); + painter.drawImage(QRect(rightpage,rightsize), *buffer[currentPageBufferedIndex+1]); + return page; + } + else + { + return NULL; + } +} + +QPixmap * Render::getCurrentDoubleMangaPage() +{ + if (currentPageIsDoublePage()) + { + QPoint leftpage(0,0); + QPoint rightpage(0,0); + QSize leftsize = buffer[currentPageBufferedIndex+1]->size(); + QSize rightsize = buffer[currentPageBufferedIndex]->size(); + int totalWidth,totalHeight; + switch (imageRotation) + { + case 0: + totalHeight = qMax(leftsize.rheight(),rightsize.rheight()); + leftsize.scale(leftsize.rwidth(), totalHeight, Qt::KeepAspectRatioByExpanding); + rightsize.scale(rightsize.rwidth(), totalHeight, Qt::KeepAspectRatioByExpanding); + totalWidth = leftsize.rwidth() + rightsize.rwidth(); + rightpage.setX(leftsize.rwidth()); + break; + case 90: + totalWidth = qMax(leftsize.rwidth(), rightsize.rwidth()); + leftsize.scale(totalWidth, leftsize.rheight(), Qt::KeepAspectRatioByExpanding); + rightsize.scale(totalWidth, rightsize.rheight(), Qt::KeepAspectRatioByExpanding); + totalHeight = leftsize.rheight() + rightsize.rheight(); + rightpage.setY(leftsize.rheight()); + break; + case 180: + totalHeight = qMax(leftsize.rheight(),rightsize.rheight()); + leftsize.scale(leftsize.rwidth(), totalHeight, Qt::KeepAspectRatioByExpanding); + rightsize.scale(rightsize.rwidth(), totalHeight, Qt::KeepAspectRatioByExpanding); + totalWidth = leftsize.rwidth() + rightsize.rwidth(); + leftpage.setX(rightsize.rwidth()); + break; + case 270: + totalWidth = qMax(leftsize.rwidth(), rightsize.rwidth()); + leftsize.scale(totalWidth, leftsize.rheight(), Qt::KeepAspectRatioByExpanding); + rightsize.scale(totalWidth, rightsize.rheight(), Qt::KeepAspectRatioByExpanding); + totalHeight = leftsize.rheight() + rightsize.rheight(); + leftpage.setY(rightsize.rheight()); + break; + default: + return NULL; + } + QPixmap * page = new QPixmap(totalWidth, totalHeight); + QPainter painter(page); + painter.drawImage(QRect(rightpage, rightsize), *buffer[currentPageBufferedIndex]); + painter.drawImage(QRect(leftpage, leftsize), *buffer[currentPageBufferedIndex+1]); + return page; + } + else + { + return NULL; + } +} + +bool Render::currentPageIsDoublePage() +{ + if (buffer[currentPageBufferedIndex]->isNull() || buffer[currentPageBufferedIndex+1]->isNull()) + { + return false; + } + if (imageRotation == 0 || imageRotation == 180) + { + if (buffer[currentPageBufferedIndex]->height() > buffer[currentPageBufferedIndex]->width() && + buffer[currentPageBufferedIndex+1]->height() > buffer[currentPageBufferedIndex+1]->width()) + { + return true; + } + } + else if (imageRotation == 90 || imageRotation == 270) + { + if (buffer[currentPageBufferedIndex]->width() > buffer[currentPageBufferedIndex]->height() && + buffer[currentPageBufferedIndex+1]->width() > buffer[currentPageBufferedIndex+1]->height()) + { + return true; + } + } + return false; +} + +bool Render::nextPageIsDoublePage() +{ + //this function is not used right now + if (buffer[currentPageBufferedIndex+2]->isNull() || buffer[currentPageBufferedIndex+3]->isNull()) + { + return false; + } + if (imageRotation == 0 || imageRotation == 180) + { + if (buffer[currentPageBufferedIndex+2]->height() > buffer[currentPageBufferedIndex+2]->width() && + buffer[currentPageBufferedIndex+3]->height() > buffer[currentPageBufferedIndex+3]->width()) + { + return true; + } + } + else if (imageRotation == 90 || imageRotation == 270) + { + if (buffer[currentPageBufferedIndex]->width() > buffer[currentPageBufferedIndex]->height() && + buffer[currentPageBufferedIndex+1]->width() > buffer[currentPageBufferedIndex+1]->height()) + { + return true; + } + } + return false; +} + +bool Render::previousPageIsDoublePage() +{ + if (buffer[currentPageBufferedIndex-1]->isNull() || buffer[currentPageBufferedIndex-2]->isNull()) + { + return false; + } + if (imageRotation == 0 || imageRotation == 180) + { + if (buffer[currentPageBufferedIndex-1]->height() > buffer[currentPageBufferedIndex-1]->width() && + buffer[currentPageBufferedIndex-2]->height() > buffer[currentPageBufferedIndex-2]->width()) + { + return true; + } + } + else if (imageRotation == 90 || imageRotation == 270) + { + if (buffer[currentPageBufferedIndex-1]->width() > buffer[currentPageBufferedIndex-1]->height() && + buffer[currentPageBufferedIndex-2]->width() > buffer[currentPageBufferedIndex-2]->height()) + { + return true; + } + } + return false; +} + +void Render::setRotation(int degrees) +{ + Q_UNUSED(degrees) +} + +void Render::setComic(Comic * c) +{ + if(comic !=0) + { + comic->moveToThread(QApplication::instance()->thread()); + comic->disconnect(); + comic->deleteLater(); + } + comic = c; +} + +void Render::prepareAvailablePage(int page) +{ + if(!doublePage) + { + if (currentIndex == page) + { + emit currentPageReady(); + } + } + else + { + //check for last page in double page mode + if ((currentIndex == page) && (currentIndex + 1) >= (int)comic->numPages()) + { + emit currentPageReady(); + } + else if ((currentIndex == page && !buffer[currentPageBufferedIndex+1]->isNull()) || + (currentIndex+1 == page && !buffer[currentPageBufferedIndex]->isNull())) + { + emit currentPageReady(); + } + } +} + +void Render::update() +{ + render(); +} +//----------------------------------------------------------------------------- +// Comic interface +//----------------------------------------------------------------------------- +void Render::load(const QString & path, int atPage) +{ + createComic(path); + if (comic !=0) + { + loadComic(path,atPage); + startLoad(); + } +} + +//----------------------------------------------------------------------------- +void Render::load(const QString & path, const ComicDB & comicDB) +{ + //TODO prepare filters + for(int i = 0; i < filters.count(); i++) + { + if(typeid(*filters[i]) == typeid(BrightnessFilter)) + if(comicDB.info.brightness == -1) + filters[i]->setLevel(0); + else + filters[i]->setLevel(comicDB.info.brightness); + if(typeid(*filters[i]) == typeid(ContrastFilter)) + if(comicDB.info.contrast == -1) + filters[i]->setLevel(100); + else + filters[i]->setLevel(comicDB.info.contrast); + if(typeid(*filters[i]) == typeid(GammaFilter)) + if(comicDB.info.gamma == -1) + filters[i]->setLevel(100); + else + filters[i]->setLevel(comicDB.info.gamma); + } + createComic(path); + if (comic!=0) + { + loadComic(path,comicDB); + startLoad(); + } +} + +void Render::createComic(const QString & path) +{ + previousIndex = currentIndex = 0; + pagesEmited.clear(); + + if(comic!=0) + { + //comic->moveToThread(QApplication::instance()->thread()); + comic->invalidate(); + + comic->disconnect(); + comic->deleteLater(); + } + //comic->moveToThread(QApplication::instance()->thread()); + comic = FactoryComic::newComic(path); + + if(comic == NULL)//archivo no encontrado o no válido + { + emit errorOpening(); + reset(); + return; + } + + connect(comic,SIGNAL(errorOpening()),this,SIGNAL(errorOpening()), Qt::QueuedConnection); + connect(comic,SIGNAL(errorOpening(QString)),this,SIGNAL(errorOpening(QString)), Qt::QueuedConnection); + connect(comic,SIGNAL(crcErrorFound(QString)),this,SIGNAL(crcError(QString)), Qt::QueuedConnection); + connect(comic,SIGNAL(errorOpening()),this,SLOT(reset()), Qt::QueuedConnection); + connect(comic,SIGNAL(imageLoaded(int)),this,SLOT(pageRawDataReady(int)), Qt::QueuedConnection); + connect(comic,SIGNAL(imageLoaded(int)),this,SIGNAL(imageLoaded(int)), Qt::QueuedConnection); + connect(comic,SIGNAL(openAt(int)),this,SLOT(renderAt(int)), Qt::QueuedConnection); + connect(comic,SIGNAL(numPages(unsigned int)),this,SIGNAL(numPages(unsigned int)), Qt::QueuedConnection); + connect(comic,SIGNAL(numPages(unsigned int)),this,SLOT(setNumPages(unsigned int)), Qt::QueuedConnection); + connect(comic,SIGNAL(imageLoaded(int,QByteArray)),this,SIGNAL(imageLoaded(int,QByteArray)), Qt::QueuedConnection); + connect(comic,SIGNAL(isBookmark(bool)),this,SIGNAL(currentPageIsBookmark(bool)), Qt::QueuedConnection); + + connect(comic,SIGNAL(bookmarksUpdated()),this,SIGNAL(bookmarksUpdated()), Qt::QueuedConnection); + + //connect(comic,SIGNAL(isLast()),this,SIGNAL(isLast())); + //connect(comic,SIGNAL(isCover()),this,SIGNAL(isCover())); + + pagesReady.clear(); +} +void Render::loadComic(const QString & path,const ComicDB & comicDB) +{ + comic->load(path,comicDB); +} +void Render::loadComic(const QString & path, int atPage) +{ + comic->load(path,atPage); +} + +void Render::startLoad() +{ + QThread * thread = nullptr; + + thread = new QThread(); + + comic->moveToThread(thread); + + connect(comic, SIGNAL(errorOpening()), thread, SLOT(quit()), Qt::QueuedConnection); + connect(comic, SIGNAL(errorOpening(QString)), thread, SLOT(quit()), Qt::QueuedConnection); + connect(comic, SIGNAL(imagesLoaded()), thread, SLOT(quit()), Qt::QueuedConnection); + connect(comic, SIGNAL(destroyed()), thread, SLOT(quit()), Qt::QueuedConnection); + connect(comic, SIGNAL(invalidated()), thread, SLOT(quit()), Qt::QueuedConnection); + connect(thread, SIGNAL(started()), comic, SLOT(process())); + connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater())); + + if(thread != nullptr) + thread->start(); + + invalidate(); + loadedComic = true; + update(); +} + +void Render::renderAt(int page) +{ + previousIndex = currentIndex = page; + emit pageChanged(page); +} + +void Render::reset() +{ + loadedComic = false; + invalidate(); +} +//si se solicita la siguiente página, se calcula cuál debe ser en función de si se lee en modo a doble página o no. +//la página sólo se renderiza, si realmente ha cambiado. +void Render::nextPage() +{ + int nextPage; //indica cuál será la próxima página + nextPage = comic->nextPage(); + //se fuerza renderizado si la página ha cambiado + if(currentIndex != nextPage) + { + previousIndex = currentIndex; + currentIndex = nextPage; + update(); + emit pageChanged(currentIndex); + } + else if (hasLoadedComic() && (currentIndex == numPages()-1)) + { + emit isLast(); + } +} +void Render::nextDoublePage() +{ + int nextPage; + if (currentIndex +2 < (int)comic->numPages()) + { + nextPage = currentIndex+2; + } + else + { + nextPage = currentIndex; + } + if(currentIndex != nextPage) + { + comic->setIndex(nextPage); + previousIndex = currentIndex; + currentIndex = nextPage; + update(); + emit pageChanged(currentIndex); + } + else if (hasLoadedComic() && ((unsigned int)currentIndex >= numPages()-2)) + { + emit isLast(); + } +} + +//si se solicita la página anterior, se calcula cuál debe ser en función de si se lee en modo a doble página o no. +//la página sólo se renderiza, si realmente ha cambiado. +void Render::previousPage() +{ + int previousPage; //indica cuál será la próxima página + previousPage = comic->previousPage(); + + //se fuerza renderizado si la página ha cambiado + if(currentIndex != previousPage) + { + previousIndex = currentIndex; + currentIndex = previousPage; + update(); + emit pageChanged(currentIndex); + } + else if (hasLoadedComic() && (currentIndex == 0)) + { + emit isCover(); + } +} + +void Render::previousDoublePage() +{ + int previousPage; //indica cuál será la próxima página + previousPage = qMax(currentIndex-2,0); + if(currentIndex != previousPage) + { + comic->setIndex(previousPage); + previousIndex = currentIndex; + currentIndex = previousPage; + update(); + emit pageChanged(currentIndex); + } +} + +unsigned int Render::getIndex() +{ + return comic->getIndex(); +} +unsigned int Render::numPages() +{ + return comic->numPages(); +} + +bool Render::hasLoadedComic() +{ + if(comic!=0) + return comic->loaded(); + return false; +} + +void Render::setNumPages(unsigned int numPages) +{ + pagesReady.fill(false,numPages); +} + +void Render::pageRawDataReady(int page) +{ + if (!hasLoadedComic()) + return; + + pagesEmited.push_back(page); + if(pageRenders.size()>0) + { + for(int i=0;i= pagesReady.size()) + { + pagesEmited.clear(); + return; //Oooops, something went wrong + } + + pagesReady[pagesEmited.at(i)] = true; + if(pagesEmited.at(i) == currentIndex) + update(); + else + { + if ( ((pagesEmited.at(i) < currentIndex) && (pagesEmited.at(i) > currentIndex-numLeftPages)) || + ((pagesEmited.at(i) > currentIndex) && (pagesEmited.at(i) < currentIndex+numRightPages)) ) + { + fillBuffer(); + } + } + } + pagesEmited.clear(); + } +} + +//sólo se renderiza la página, si ha habido un cambio de página +void Render::goTo(int index) +{ + + if(currentIndex != index) + { + comic->setIndex(index); + previousIndex = currentIndex; + currentIndex = index; + update(); + emit pageChanged(currentIndex); + } +} + +void Render::rotateRight() +{ + imageRotation = (imageRotation+90) % 360; + reload(); +} +void Render::rotateLeft() +{ + if(imageRotation == 0) + imageRotation = 270; + else + imageRotation = imageRotation - 90; + reload(); +} + +//Actualiza el buffer, añadiendo las imágenes (vacías) necesarias para su posterior renderizado y +//eliminado aquellas que ya no sean necesarias. También libera los hilos (no estoy seguro de que sea responsabilidad suya) +//Calcula el número de nuevas páginas que hay que buferear y si debe hacerlo por la izquierda o la derecha (según sea el sentido de la lectura) +void Render::updateBuffer() +{ + QMutexLocker locker(&mutex); + int windowSize = currentIndex - previousIndex; + + if(windowSize > 0)//add pages to right pages and remove on the left + { + windowSize = qMin(windowSize,buffer.size()); + for(int i = 0; i < windowSize; i++) + { + //renders + PageRender * pr = pageRenders.front(); + pageRenders.pop_front(); + if(pr !=0) + { + if(pr->wait()) + delete pr; + } + pageRenders.push_back(0); + + //images + + if(buffer.front()!=0) + delete buffer.front(); + buffer.pop_front(); + buffer.push_back(new QImage()); + } + } + else //add pages to left pages and remove on the right + if(windowSize<0) + { + windowSize = -windowSize; + windowSize = qMin(windowSize,buffer.size()); + for(int i = 0; i < windowSize; i++) + { + //renders + PageRender * pr = pageRenders.back(); + pageRenders.pop_back(); + if(pr !=0) + { + if(pr->wait()) + delete pr; + } + pageRenders.push_front(0); + + //images + buffer.push_front(new QImage()); + QImage * p = buffer.back(); + if(p!=0) + delete p; + buffer.pop_back(); + } + } + previousIndex = currentIndex; +} + +void Render::fillBuffer() +{ + if (pagesReady.size() < 1) + { + return; + } + + for(int i = 1; i <= qMax(numLeftPages,numRightPages); i++) + { + if ((currentIndex+i < (int)comic->numPages()) && + buffer[currentPageBufferedIndex+i]->isNull() && + i <= numRightPages && + pageRenders[currentPageBufferedIndex+i]==0 && + pagesReady[currentIndex+i]) //preload next pages + { + pageRenders[currentPageBufferedIndex+i] = new PageRender(this,currentIndex+i,comic->getRawData()->at(currentIndex+i),buffer[currentPageBufferedIndex+i],imageRotation,filters); + connect(pageRenders[currentPageBufferedIndex+i],SIGNAL(pageReady(int)),this,SLOT(prepareAvailablePage(int))); + pageRenders[currentPageBufferedIndex+i]->start(); + } + + if ((currentIndex-i > 0) && + buffer[currentPageBufferedIndex-i]->isNull() && + i <= numLeftPages && + pageRenders[currentPageBufferedIndex-i]==0 && + pagesReady[currentIndex-i]) //preload previous pages + { + pageRenders[currentPageBufferedIndex-i] = new PageRender(this,currentIndex-i,comic->getRawData()->at(currentIndex-i),buffer[currentPageBufferedIndex-i],imageRotation,filters); + connect(pageRenders[currentPageBufferedIndex-i],SIGNAL(pageReady(int)),this,SLOT(prepareAvailablePage(int))); + pageRenders[currentPageBufferedIndex-i]->start(); + } + } +} + + +//Método que debe ser llamado cada vez que la estructura del buffer se vuelve inconsistente con el modo de lectura actual. +//se terminan todos los hilos en ejecución y se libera la memoria (de hilos e imágenes) +void Render::invalidate() +{ + for(int i=0;iwait(); + delete pageRenders[i]; + pageRenders[i] = 0; + } + } + + for(int i=0;inumPages())) + { + if (currentPageIsDoublePage()) + { + if (doubleMangaPage) + s = QString::number(currentIndex+2) + "-" + s; + else + s += "-"+QString::number(currentIndex+2); + } + } + s += "/"+QString::number(comic->numPages()); + return s; +} + +void Render::setBookmark() +{ + comic->setBookmark(); +} + +void Render::removeBookmark() +{ + comic->removeBookmark(); +} + +void Render::save() +{ + comic->saveBookmarks(); +} + +Bookmarks * Render::getBookmarks() +{ + return comic->bm; +} + +void Render::reload() +{ + if(comic) + { + invalidate(); + update(); + } +} + +void Render::updateFilters(int brightness, int contrast, int gamma) +{ + for(int i = 0; i < filters.count(); i++) + { + if(typeid(*filters[i]) == typeid(BrightnessFilter)) + filters[i]->setLevel(brightness); + if(typeid(*filters[i]) == typeid(ContrastFilter)) + filters[i]->setLevel(contrast); + if(typeid(*filters[i]) == typeid(GammaFilter)) + filters[i]->setLevel(gamma); + } + + reload(); +} diff --git a/YACReader/render.h b/YACReader/render.h index d231be38..786bcd49 100644 --- a/YACReader/render.h +++ b/YACReader/render.h @@ -1,216 +1,216 @@ - #ifndef RENDER_H -#define RENDER_H - -#include -#include -#include -#include -#include -#include -#include "comic.h" -//----------------------------------------------------------------------------- -// FILTERS -//----------------------------------------------------------------------------- - -#include - -class Comic; -class ComicDB; -class Render; - -class ImageFilter { -public: - ImageFilter(){}; - virtual ~ImageFilter() {}; - virtual QImage setFilter(const QImage & image) = 0; - inline int getLevel() {return level;}; - inline void setLevel(int l) {level = l;}; -protected: - int level; -}; - -class MeanNoiseReductionFilter : public ImageFilter { -public: - enum NeighborghoodSize{SMALL=9, LARGE=25 }; - MeanNoiseReductionFilter(enum NeighborghoodSize ns = SMALL); - virtual QImage setFilter(const QImage & image); -private: - enum NeighborghoodSize neighborghoodSize; -}; - -class MedianNoiseReductionFilter : public ImageFilter { -public: - enum NeighborghoodSize{SMALL=9, LARGE=25 }; - MedianNoiseReductionFilter(enum NeighborghoodSize ns = SMALL); - virtual QImage setFilter(const QImage & image); -private: - enum NeighborghoodSize neighborghoodSize; -}; - -class BrightnessFilter : public ImageFilter { -public: - BrightnessFilter(int l=-1); - virtual QImage setFilter(const QImage & image); -}; - -class ContrastFilter : public ImageFilter { -public: - ContrastFilter(int l=-1); - virtual QImage setFilter(const QImage & image); -}; - -class GammaFilter : public ImageFilter { -public: - GammaFilter(int l=-1); - virtual QImage setFilter(const QImage & image); -}; - -//----------------------------------------------------------------------------- -// RENDER -//----------------------------------------------------------------------------- - -class PageRender : public QThread -{ - Q_OBJECT -public: - PageRender(); - PageRender(Render * render,int numPage, const QByteArray & rawData, QImage * page,unsigned int degrees=0, QVector filters = QVector()); - int getNumPage(){return numPage;}; - void setData(const QByteArray & rawData){data = rawData;}; - void setPage(QImage * p){page = p;}; - void setRotation(unsigned int d){degrees = d;}; - void setFilters(QVector f){filters = f;}; -private: - int numPage; - QByteArray data; - QImage * page; - unsigned int degrees; - QVector filters; - void run(); - Render * render; -signals: - void pageReady(int); - -}; -//----------------------------------------------------------------------------- -// RENDER -//----------------------------------------------------------------------------- - -/*class DoublePageRender : public PageRender -{ - Q_OBJECT -public: - DoublePageRender(Render * render, int firstPage, const QByteArray & firstPageData,const QByteArray & secondPageData, QImage * page,unsigned int degrees=0, QVector filters = QVector()); -private: - int numPage; - QByteArray data; - QByteArray data2; - QImage * page; - unsigned int degrees; - QVector filters; - void run(); - Render * render; -signals: - void pageReady(int); - -}; -*/ - -class Render : public QObject { -Q_OBJECT -public: - Render(); - ~Render(); - -public slots: - void render(); - QPixmap * getCurrentPage(); - QPixmap * getCurrentDoublePage(); - QPixmap * getCurrentDoubleMangaPage(); - bool currentPageIsDoublePage(); - bool nextPageIsDoublePage(); - bool previousPageIsDoublePage(); - void goTo(int index); - void doublePageSwitch(); - void doubleMangaPageSwitch(); - void setRotation(int degrees); - void setComic(Comic * c); - void prepareAvailablePage(int page); - void update(); - void setNumPages(unsigned int numPages); - void pageRawDataReady(int page); - //--comic interface - void nextPage(); - void previousPage(); - void nextDoublePage(); - void previousDoublePage(); - void load(const QString & path, const ComicDB & comic); - void load(const QString & path, int atPage); - void createComic(const QString & path); - void loadComic(const QString & path,const ComicDB & comic); - void loadComic(const QString & path, int atPage); - void startLoad(); - void rotateRight(); - void rotateLeft(); - unsigned int getIndex(); - unsigned int numPages(); - bool hasLoadedComic(); - void updateBuffer(); - void fillBuffer(); - void invalidate(); - QString getCurrentPagesInformation(); - void setBookmark(); - void removeBookmark(); - void save(); - void reset(); - void reload(); - void updateFilters(int brightness, int contrast, int gamma); - Bookmarks * getBookmarks(); - //sets the firt page to render - void renderAt(int page); - -signals: - void currentPageReady(); - void processingPage(); - void imagesLoaded(); - void imageLoaded(int index); - void imageLoaded(int index,const QByteArray & image); - void pageChanged(int index); - void numPages(unsigned int numPages); - void errorOpening(); - void errorOpening(QString); - void crcError(QString); - void currentPageIsBookmark(bool); - void isLast(); - void isCover(); - - void bookmarksUpdated(); - - -private: - Comic * comic; - bool doublePage; - bool doubleMangaPage; - int previousIndex; - int currentIndex; - //QPixmap * currentPage; - int currentPageBufferedIndex; - int numLeftPages; - int numRightPages; - QList pageRenders; - QList buffer; - void loadAll(); - void updateRightPages(); - void updateLeftPages(); - bool loadedComic; - QList pagesEmited; - QVector pagesReady; - int imageRotation; - QVector filters; - QMutex mutex; - - friend class PageRender; -}; - - -#endif // RENDER_H + #ifndef RENDER_H +#define RENDER_H + +#include +#include +#include +#include +#include +#include +#include "comic.h" +//----------------------------------------------------------------------------- +// FILTERS +//----------------------------------------------------------------------------- + +#include + +class Comic; +class ComicDB; +class Render; + +class ImageFilter { +public: + ImageFilter(){}; + virtual ~ImageFilter() {}; + virtual QImage setFilter(const QImage & image) = 0; + inline int getLevel() {return level;}; + inline void setLevel(int l) {level = l;}; +protected: + int level; +}; + +class MeanNoiseReductionFilter : public ImageFilter { +public: + enum NeighborghoodSize{SMALL=9, LARGE=25 }; + MeanNoiseReductionFilter(enum NeighborghoodSize ns = SMALL); + virtual QImage setFilter(const QImage & image); +private: + enum NeighborghoodSize neighborghoodSize; +}; + +class MedianNoiseReductionFilter : public ImageFilter { +public: + enum NeighborghoodSize{SMALL=9, LARGE=25 }; + MedianNoiseReductionFilter(enum NeighborghoodSize ns = SMALL); + virtual QImage setFilter(const QImage & image); +private: + enum NeighborghoodSize neighborghoodSize; +}; + +class BrightnessFilter : public ImageFilter { +public: + BrightnessFilter(int l=-1); + virtual QImage setFilter(const QImage & image); +}; + +class ContrastFilter : public ImageFilter { +public: + ContrastFilter(int l=-1); + virtual QImage setFilter(const QImage & image); +}; + +class GammaFilter : public ImageFilter { +public: + GammaFilter(int l=-1); + virtual QImage setFilter(const QImage & image); +}; + +//----------------------------------------------------------------------------- +// RENDER +//----------------------------------------------------------------------------- + +class PageRender : public QThread +{ + Q_OBJECT +public: + PageRender(); + PageRender(Render * render,int numPage, const QByteArray & rawData, QImage * page,unsigned int degrees=0, QVector filters = QVector()); + int getNumPage(){return numPage;}; + void setData(const QByteArray & rawData){data = rawData;}; + void setPage(QImage * p){page = p;}; + void setRotation(unsigned int d){degrees = d;}; + void setFilters(QVector f){filters = f;}; +private: + int numPage; + QByteArray data; + QImage * page; + unsigned int degrees; + QVector filters; + void run(); + Render * render; +signals: + void pageReady(int); + +}; +//----------------------------------------------------------------------------- +// RENDER +//----------------------------------------------------------------------------- + +/*class DoublePageRender : public PageRender +{ + Q_OBJECT +public: + DoublePageRender(Render * render, int firstPage, const QByteArray & firstPageData,const QByteArray & secondPageData, QImage * page,unsigned int degrees=0, QVector filters = QVector()); +private: + int numPage; + QByteArray data; + QByteArray data2; + QImage * page; + unsigned int degrees; + QVector filters; + void run(); + Render * render; +signals: + void pageReady(int); + +}; +*/ + +class Render : public QObject { +Q_OBJECT +public: + Render(); + ~Render(); + +public slots: + void render(); + QPixmap * getCurrentPage(); + QPixmap * getCurrentDoublePage(); + QPixmap * getCurrentDoubleMangaPage(); + bool currentPageIsDoublePage(); + bool nextPageIsDoublePage(); + bool previousPageIsDoublePage(); + void goTo(int index); + void doublePageSwitch(); + void doubleMangaPageSwitch(); + void setRotation(int degrees); + void setComic(Comic * c); + void prepareAvailablePage(int page); + void update(); + void setNumPages(unsigned int numPages); + void pageRawDataReady(int page); + //--comic interface + void nextPage(); + void previousPage(); + void nextDoublePage(); + void previousDoublePage(); + void load(const QString & path, const ComicDB & comic); + void load(const QString & path, int atPage); + void createComic(const QString & path); + void loadComic(const QString & path,const ComicDB & comic); + void loadComic(const QString & path, int atPage); + void startLoad(); + void rotateRight(); + void rotateLeft(); + unsigned int getIndex(); + unsigned int numPages(); + bool hasLoadedComic(); + void updateBuffer(); + void fillBuffer(); + void invalidate(); + QString getCurrentPagesInformation(); + void setBookmark(); + void removeBookmark(); + void save(); + void reset(); + void reload(); + void updateFilters(int brightness, int contrast, int gamma); + Bookmarks * getBookmarks(); + //sets the firt page to render + void renderAt(int page); + +signals: + void currentPageReady(); + void processingPage(); + void imagesLoaded(); + void imageLoaded(int index); + void imageLoaded(int index,const QByteArray & image); + void pageChanged(int index); + void numPages(unsigned int numPages); + void errorOpening(); + void errorOpening(QString); + void crcError(QString); + void currentPageIsBookmark(bool); + void isLast(); + void isCover(); + + void bookmarksUpdated(); + + +private: + Comic * comic; + bool doublePage; + bool doubleMangaPage; + int previousIndex; + int currentIndex; + //QPixmap * currentPage; + int currentPageBufferedIndex; + int numLeftPages; + int numRightPages; + QList pageRenders; + QList buffer; + void loadAll(); + void updateRightPages(); + void updateLeftPages(); + bool loadedComic; + QList pagesEmited; + QVector pagesReady; + int imageRotation; + QVector filters; + QMutex mutex; + + friend class PageRender; +}; + + +#endif // RENDER_H diff --git a/YACReader/shortcuts_dialog.cpp b/YACReader/shortcuts_dialog.cpp index e88c91a0..2c66bef6 100644 --- a/YACReader/shortcuts_dialog.cpp +++ b/YACReader/shortcuts_dialog.cpp @@ -1,55 +1,55 @@ -#include "shortcuts_dialog.h" -#include -#include -#include -#include -#include -#include -#include -#include - -ShortcutsDialog::ShortcutsDialog(QWidget * parent) - :QDialog(parent)//,Qt::FramelessWindowHint) -{ - setModal(true); - setWindowIcon(QIcon(":/images/shortcuts.png")); - setWindowTitle(tr("YACReader keyboard shortcuts")); - - QVBoxLayout * mainLayout = new QVBoxLayout; - - close = new QPushButton(tr("Close")); - connect(close,SIGNAL(clicked()),this,SLOT(close())); - - QHBoxLayout *bottomLayout = new QHBoxLayout; - bottomLayout->addStretch(); - bottomLayout->addWidget(close); - - QHBoxLayout * shortcutsLayout = new QHBoxLayout; - - shortcuts = new QTextEdit(); - shortcuts->setFrameStyle(QFrame::NoFrame); - - //"

General functions:


O : Open comic
Esc : Exit

" - shortcuts->setReadOnly(true); - shortcutsLayout->addWidget(shortcuts); - //shortcutsLayout->addWidget(shortcuts2); - shortcutsLayout->setSpacing(0); - mainLayout->addLayout(shortcutsLayout); - mainLayout->addLayout(bottomLayout); - - setLayout(mainLayout); - - setFixedSize(QSize(700,500)); - - QFile f(":/files/shortcuts.html"); - f.open(QIODevice::ReadOnly); - QTextStream txtS(&f); - txtS.setCodec(QTextCodec::codecForName("UTF-8")); - QString content = txtS.readAll(); - - f.close(); - - shortcuts->setHtml(content); - - setWindowTitle(tr("Keyboard Shortcuts")); -} +#include "shortcuts_dialog.h" +#include +#include +#include +#include +#include +#include +#include +#include + +ShortcutsDialog::ShortcutsDialog(QWidget * parent) + :QDialog(parent)//,Qt::FramelessWindowHint) +{ + setModal(true); + setWindowIcon(QIcon(":/images/shortcuts.png")); + setWindowTitle(tr("YACReader keyboard shortcuts")); + + QVBoxLayout * mainLayout = new QVBoxLayout; + + close = new QPushButton(tr("Close")); + connect(close,SIGNAL(clicked()),this,SLOT(close())); + + QHBoxLayout *bottomLayout = new QHBoxLayout; + bottomLayout->addStretch(); + bottomLayout->addWidget(close); + + QHBoxLayout * shortcutsLayout = new QHBoxLayout; + + shortcuts = new QTextEdit(); + shortcuts->setFrameStyle(QFrame::NoFrame); + + //"

General functions:


O : Open comic
Esc : Exit

" + shortcuts->setReadOnly(true); + shortcutsLayout->addWidget(shortcuts); + //shortcutsLayout->addWidget(shortcuts2); + shortcutsLayout->setSpacing(0); + mainLayout->addLayout(shortcutsLayout); + mainLayout->addLayout(bottomLayout); + + setLayout(mainLayout); + + setFixedSize(QSize(700,500)); + + QFile f(":/files/shortcuts.html"); + f.open(QIODevice::ReadOnly); + QTextStream txtS(&f); + txtS.setCodec(QTextCodec::codecForName("UTF-8")); + QString content = txtS.readAll(); + + f.close(); + + shortcuts->setHtml(content); + + setWindowTitle(tr("Keyboard Shortcuts")); +} diff --git a/YACReader/shortcuts_dialog.h b/YACReader/shortcuts_dialog.h index 8f1b66b6..1d93c62e 100644 --- a/YACReader/shortcuts_dialog.h +++ b/YACReader/shortcuts_dialog.h @@ -1,19 +1,19 @@ -#ifndef SHORTCUTS_DIALOG_H -#define SHORTCUTS_DIALOG_H - -#include -#include -#include - -class ShortcutsDialog : public QDialog -{ -Q_OBJECT - public: - ShortcutsDialog(QWidget * parent = 0); - private: - QTextEdit * shortcuts; - QPushButton * close; - public slots: -}; - -#endif // SHORTCUTS_DIALOG_H +#ifndef SHORTCUTS_DIALOG_H +#define SHORTCUTS_DIALOG_H + +#include +#include +#include + +class ShortcutsDialog : public QDialog +{ +Q_OBJECT + public: + ShortcutsDialog(QWidget * parent = 0); + private: + QTextEdit * shortcuts; + QPushButton * close; + public slots: +}; + +#endif // SHORTCUTS_DIALOG_H diff --git a/YACReader/translator.cpp b/YACReader/translator.cpp index bff51e85..af86d1ec 100644 --- a/YACReader/translator.cpp +++ b/YACReader/translator.cpp @@ -1,429 +1,429 @@ -#include - -#if QT_VERSION >= 0x050000 -#include -#else -#include -#include -#endif - -#include -#include -#include -#include -#include -#include "translator.h" - -#include "yacreader_busy_widget.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#define APPID "417CEAD93449502CC3C9B69FED26C54118E62BCC" - -YACReaderTranslator::YACReaderTranslator(QWidget * parent) -:QWidget(parent),drag(false) -{ - QString scrollBarStyle = "QScrollBar:vertical { border: none; background: #404040; width: 7px; margin: 0 3px 0 0; }" - "QScrollBar::handle:vertical { background: #DDDDDD; width: 7px; min-height: 20px; }" - "QScrollBar::add-line:vertical { border: none; background: #404040; height: 10px; subcontrol-position: bottom; subcontrol-origin: margin; margin: 0 3px 0 0;}" - - "QScrollBar::sub-line:vertical { border: none; background: #404040; height: 10px; subcontrol-position: top; subcontrol-origin: margin; margin: 0 3px 0 0;}" - "QScrollBar::up-arrow:vertical {border:none;width: 9px;height: 6px;background: url(':/images/folders_view/line-up.png') center top no-repeat;}" - "QScrollBar::down-arrow:vertical {border:none;width: 9px;height: 6px;background: url(':/images/folders_view/line-down.png') center top no-repeat;}" - - "QScrollBar::add-page:vertical, QScrollBar::sub-page:vertical {background: none; }"; - - this->setCursor(QCursor(Qt::ArrowCursor)); - this->setAutoFillBackground(true); - this->setBackgroundRole(QPalette::Window); - QPalette p(this->palette()); - p.setColor(QPalette::Window, QColor("#404040")); - this->setPalette(p); - - QVBoxLayout *layout = new QVBoxLayout(this); - - //TITLE BAR - QHBoxLayout * titleBar = new QHBoxLayout(); - QPushButton * close = new QPushButton(QIcon(QPixmap(":/images/close.png")),""); - close->setFlat(true); - QLabel * title = new QLabel(tr("YACReader translator")); - title->setStyleSheet("QLabel {font-size:18px; font-family:Arial; color:white;}"); - titleBar->addWidget(title); - titleBar->addStretch(); - close->resize(14,14); - close->setStyleSheet("QPushButton {margin:0;padding:0;border:none;}"); - titleBar->addWidget(close); - titleBar->setContentsMargins(0,0,0,0); - titleBar->setSpacing(0); - connect(close,SIGNAL(clicked()),this->parent(),SLOT(animateHideTranslator())); - - layout->addLayout(titleBar); - - //INPUT TEXT - text = new QTextEdit(this); - text->setMinimumHeight(110); - text->setMaximumHeight(110); - layout->addSpacing(12); - layout->addWidget(text); - text->setStyleSheet("QTextEdit{border:none;background:#2a2a2a;color:white; font-size:12px; padding:6px;}"+scrollBarStyle); - - //COMBOBOXES - QHBoxLayout * combos = new QHBoxLayout(); - from = new QComboBox(this); - to = new QComboBox(this); - QString comboBoxStyle = "QComboBox {border:none;background:#2a2a2a;color:white;font-size:12px;font-family:Arial;padding-left:8px;}" - "QComboBox::down-arrow {image: url(:/images/dropDownArrow.png);}" - "QComboBox::drop-down {border:none; padding-right:10px;}" - "QComboBox QAbstractItemView {border: none; background:#272727; color:white; selection-background-color: #202020; outline:none;}" - "QComboBox QAbstractItemView::item {padding-left:8px;}" + scrollBarStyle - ; - from->setStyleSheet(comboBoxStyle); - to->setStyleSheet(comboBoxStyle); - from->setFixedHeight(22); - to->setFixedHeight(22); - QLabel * arrow = new QLabel(this); - QPixmap arrowPixmap(":/images/fromTo.png"); - arrow->setPixmap(arrowPixmap); - QPushButton * searchButton = new QPushButton(this); - searchButton->setIcon(QIcon(":/images/translatorSearch.png")); - searchButton->setStyleSheet("QPushButton {border:none; background:#2a2a2a;}"); - searchButton->setFixedSize(22,22); - combos->addWidget(from,1); - combos->addSpacing(9); - combos->addWidget(arrow,0); - combos->addSpacing(9); - combos->addWidget(to,1); - combos->addSpacing(9); - combos->addWidget(searchButton,0); - layout->addSpacing(12); - layout->addLayout(combos); - - - //RESULTS - QHBoxLayout * resultsTitleLayout = new QHBoxLayout(); - resultsTitle = new QLabel(tr("Translation")); - resultsTitle->setStyleSheet("QLabel {font-family:Arial;font-size:14px;color:#e3e3e3;}"); - speakButton = new QPushButton(this); - speakButton->setStyleSheet("QPushButton {border:none;}"); - speakButton->setIcon(QIcon(":/images/speaker.png")); - resultsTitleLayout->addWidget(resultsTitle,0,Qt::AlignVCenter); - resultsTitleLayout->addSpacing(10); - resultsTitleLayout->addWidget(speakButton,0,Qt::AlignVCenter); - resultsTitleLayout->addStretch(); - - layout->addSpacing(15); - layout->addLayout(resultsTitleLayout); - layout->addSpacing(12); - - resultText = new QLabel(); - resultText->setWordWrap(true); - resultText->setStyleSheet("QLabel {color:white;font-size:12px;}"); - resultText->setText("ñlkas lakj dflkaj lasd jflie lkajd fie kljads ijef lasei afsliej ljse f"); - layout->addWidget(resultText); - - layout->addStretch(); - - //CLEAR BUTTON - clearButton = new QPushButton(tr("clear")); - layout->addWidget(clearButton,0,Qt::AlignRight); - clearButton->setMinimumWidth(95); - clearButton->setStyleSheet("QPushButton {border:1px solid #212121; background:#2a2a2a; color:white; font-family:Arial; font-size:12px; padding-top:5px; padding-bottom:5px;}"); - - resize(400,479); - - layout->setMargin(0); - layout->setContentsMargins(18,12,18,12); - setContentsMargins(0,0,0,0); - layout->setSpacing(0); - - hideResults(); - populateCombos(); - - busyIndicator = new YACReaderBusyWidget(this); - busyIndicator->move((this->width()-busyIndicator->width())/2,(this->height()-busyIndicator->height())*2/3); - busyIndicator->hide(); - - show(); - - connect(searchButton,SIGNAL(pressed()),this,SLOT(translate())); - connect(speakButton,SIGNAL(pressed()),this,SLOT(play())); - connect(clearButton,SIGNAL(pressed()),this,SLOT(clear())); - - //multimedia/phonon -#if QT_VERSION >= 0x050000 - player = new QMediaPlayer; -#else - music = createPlayer(MusicCategory); -#endif - -} - -void YACReaderTranslator::hideResults() -{ - resultsTitle->setHidden(true); - speakButton->setHidden(true); - resultText->setHidden(true); -} - -void YACReaderTranslator::clear() -{ - hideResults(); - text->clear(); -} - -void YACReaderTranslator::translate() -{ - QString text = this->text->toPlainText(); - if(text.isEmpty()) - return; - QString from = this->from->itemData(this->from->currentIndex()).toString(); - QString to = this->to->itemData(this->to->currentIndex()).toString(); - - TranslationLoader * translationLoader = new TranslationLoader(text,from,to); - connect(translationLoader,SIGNAL(requestFinished(QString)),this,SLOT(setTranslation(QString))); - connect(translationLoader,SIGNAL(error()),this,SLOT(error())); - connect(translationLoader,SIGNAL(timeOut()),this,SLOT(error())); - connect(translationLoader,SIGNAL(finished()),translationLoader,SLOT(deleteLater())); - - TextToSpeachLoader * tts = new TextToSpeachLoader(text,from); - connect(tts,SIGNAL(requestFinished(QUrl)),this,SLOT(setSpeak(QUrl))); - connect(tts,SIGNAL(error()),this,SLOT(error())); - connect(tts,SIGNAL(timeOut()),this,SLOT(error())); - connect(tts,SIGNAL(finished()),tts,SLOT(deleteLater())); - - translationLoader->start(); - tts->start(); - - resultsTitle->setText(tr("Translation")); - - hideResults(); - - busyIndicator->show(); -} - -void YACReaderTranslator::error() -{ - resultsTitle->setText(tr("Service not available")); - resultsTitle->setHidden(false); - busyIndicator->hide(); -} - -void YACReaderTranslator::setSpeak(const QUrl & url) -{ - resultsTitle->setHidden(false); - speakButton->setHidden(false); - - ttsSource = url; -} - -void YACReaderTranslator::setTranslation(const QString & string) -{ - resultText->setText(string); - - resultsTitle->setHidden(false); - resultText->setHidden(false); - busyIndicator->hide(); -} - -void YACReaderTranslator::populateCombos() -{ - QList combos; - combos.append(from); - combos.append(to); - - for(int i=0;iaddItem("Arabic","ar"); - combo->addItem("Bulgarian","bg"); - combo->addItem("Catalan","ca"); - combo->addItem("Chinese Simplified","zh-CHS"); - combo->addItem("Chinese Traditional","zh-CHT"); - combo->addItem("Czech","cs"); - combo->addItem("Danish","da"); - combo->addItem("Dutch","nl"); - combo->addItem("English","en"); - combo->addItem("Estonian","et"); - combo->addItem("Finnish","fi"); - combo->addItem("French","fr"); - combo->addItem("German","de"); - combo->addItem("Greek","el"); - combo->addItem("Haitian Creole","ht"); - combo->addItem("Hebrew","he"); - combo->addItem("Hindi","hi"); - combo->addItem("Hungarian","hu"); - combo->addItem("Indonesian","id"); - combo->addItem("Italian","it"); - combo->addItem("Japanese","ja"); - combo->addItem("Korean","ko"); - combo->addItem("Latvian","lv"); - combo->addItem("Lithuanian","lt"); - combo->addItem("Norwegian","no"); - combo->addItem("Polish","pl"); - combo->addItem("Portuguese","pt"); - combo->addItem("Romanian","ro"); - combo->addItem("Russian","ru"); - combo->addItem("Slovak","sk"); - combo->addItem("Slovenian","sl"); - combo->addItem("Spanish","es"); - combo->addItem("Swedish","sv"); - combo->addItem("Thai","th"); - combo->addItem("Turkish","tr"); - combo->addItem("Ukrainian","uk"); - combo->addItem("Vietnamese","vi"); - } - from->setCurrentIndex(from->findText("English")); - to->setCurrentIndex(from->findText("Spanish")); -} - -void YACReaderTranslator::play() -{ - //QMessageBox::question(this,"xxx",ttsSource.toString()); -#if QT_VERSION >= 0x050000 - - player->setMedia(ttsSource); - player->play(); - -#else - MediaSource src(ttsSource); - src.setAutoDelete(true); - music->setCurrentSource(src); - music->play(); -#endif -} - -YACReaderTranslator::~YACReaderTranslator() -{ -#if QT_VERSION >= 0x050000 -#else - delete music; -#endif -} - -void YACReaderTranslator::mousePressEvent(QMouseEvent *event) -{ - QPoint p = mapTo(this,event->pos()); - if(p.y() < 40) - { - drag = true; - click = event->pos(); - } -} - -void YACReaderTranslator::mouseReleaseEvent(QMouseEvent *event) -{ - drag = false; - event->accept(); -} - -void YACReaderTranslator::mouseMoveEvent(QMouseEvent * event) -{ - if(drag) - this->move(QPoint(mapToParent(event->pos())-click)); - event->accept(); -} - -//--------------------------------------------------------------------------- -//--------------------------------------------------------------------------- -//--------------------------------------------------------------------------- - -TranslationLoader::TranslationLoader(QString text, QString from, QString to) - :QThread(),text(text),from(from),to(to) -{ -} - -void TranslationLoader::run() -{ - QNetworkAccessManager manager; - QEventLoop q; - QTimer tT; - - tT.setSingleShot(true); - connect(&tT, SIGNAL(timeout()), &q, SLOT(quit())); - connect(&manager, SIGNAL(finished(QNetworkReply*)),&q, SLOT(quit())); - - QString url = "http://api.microsofttranslator.com/V2/Ajax.svc/Translate?appid=%1&from=%2&to=%3&text=%4&contentType=text/plain"; - url = url.arg(APPID).arg(from).arg(to).arg(text); - - QNetworkReply *reply = manager.get(QNetworkRequest(QUrl(url))); - - tT.start(5000); // 5s timeout - q.exec(); - - if(tT.isActive()){ - // download complete - if(reply->error() == QNetworkReply::NoError) - { - QString utf8 = QString::fromUtf8(reply->readAll()); - utf8 = utf8.remove(0,1); - utf8 = utf8.remove(utf8.count()-1,1); - - QString translated(utf8); - emit(requestFinished(translated)); - } - else - emit(error()); - } else { - emit(timeOut()); - } -} - -//--------------------------------------------------------------------------- -//--------------------------------------------------------------------------- -//--------------------------------------------------------------------------- - - -TextToSpeachLoader::TextToSpeachLoader(QString text, QString language) - :QThread(),text(text),language(language) -{ -} - - -void TextToSpeachLoader::run() -{ - QNetworkAccessManager manager; - QEventLoop q; - QTimer tT; - - tT.setSingleShot(true); - connect(&tT, SIGNAL(timeout()), &q, SLOT(quit())); - connect(&manager, SIGNAL(finished(QNetworkReply*)),&q, SLOT(quit())); - - QString url = "http://api.microsofttranslator.com/V2/Ajax.svc/Speak?appid=%1&language=%2&text=%3&contentType=text/plain"; - url = url.arg(APPID).arg(language).arg(text); - - QNetworkReply *reply = manager.get(QNetworkRequest(QUrl(url))); - - tT.start(5000); // 5s timeout - q.exec(); - - if(tT.isActive()){ - // download complete - if(reply->error() == QNetworkReply::NoError) - { - QString utf8 = QString::fromUtf8(reply->readAll()); - utf8 = utf8.remove(0,1); - utf8 = utf8.remove(utf8.count()-1,1); - utf8 = utf8.replace("\\",""); - - emit(requestFinished(QUrl(utf8))); - } - else - emit(error()); - } else { - emit(timeOut()); - } -} +#include + +#if QT_VERSION >= 0x050000 +#include +#else +#include +#include +#endif + +#include +#include +#include +#include +#include +#include "translator.h" + +#include "yacreader_busy_widget.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#define APPID "417CEAD93449502CC3C9B69FED26C54118E62BCC" + +YACReaderTranslator::YACReaderTranslator(QWidget * parent) +:QWidget(parent),drag(false) +{ + QString scrollBarStyle = "QScrollBar:vertical { border: none; background: #404040; width: 7px; margin: 0 3px 0 0; }" + "QScrollBar::handle:vertical { background: #DDDDDD; width: 7px; min-height: 20px; }" + "QScrollBar::add-line:vertical { border: none; background: #404040; height: 10px; subcontrol-position: bottom; subcontrol-origin: margin; margin: 0 3px 0 0;}" + + "QScrollBar::sub-line:vertical { border: none; background: #404040; height: 10px; subcontrol-position: top; subcontrol-origin: margin; margin: 0 3px 0 0;}" + "QScrollBar::up-arrow:vertical {border:none;width: 9px;height: 6px;background: url(':/images/folders_view/line-up.png') center top no-repeat;}" + "QScrollBar::down-arrow:vertical {border:none;width: 9px;height: 6px;background: url(':/images/folders_view/line-down.png') center top no-repeat;}" + + "QScrollBar::add-page:vertical, QScrollBar::sub-page:vertical {background: none; }"; + + this->setCursor(QCursor(Qt::ArrowCursor)); + this->setAutoFillBackground(true); + this->setBackgroundRole(QPalette::Window); + QPalette p(this->palette()); + p.setColor(QPalette::Window, QColor("#404040")); + this->setPalette(p); + + QVBoxLayout *layout = new QVBoxLayout(this); + + //TITLE BAR + QHBoxLayout * titleBar = new QHBoxLayout(); + QPushButton * close = new QPushButton(QIcon(QPixmap(":/images/close.png")),""); + close->setFlat(true); + QLabel * title = new QLabel(tr("YACReader translator")); + title->setStyleSheet("QLabel {font-size:18px; font-family:Arial; color:white;}"); + titleBar->addWidget(title); + titleBar->addStretch(); + close->resize(14,14); + close->setStyleSheet("QPushButton {margin:0;padding:0;border:none;}"); + titleBar->addWidget(close); + titleBar->setContentsMargins(0,0,0,0); + titleBar->setSpacing(0); + connect(close,SIGNAL(clicked()),this->parent(),SLOT(animateHideTranslator())); + + layout->addLayout(titleBar); + + //INPUT TEXT + text = new QTextEdit(this); + text->setMinimumHeight(110); + text->setMaximumHeight(110); + layout->addSpacing(12); + layout->addWidget(text); + text->setStyleSheet("QTextEdit{border:none;background:#2a2a2a;color:white; font-size:12px; padding:6px;}"+scrollBarStyle); + + //COMBOBOXES + QHBoxLayout * combos = new QHBoxLayout(); + from = new QComboBox(this); + to = new QComboBox(this); + QString comboBoxStyle = "QComboBox {border:none;background:#2a2a2a;color:white;font-size:12px;font-family:Arial;padding-left:8px;}" + "QComboBox::down-arrow {image: url(:/images/dropDownArrow.png);}" + "QComboBox::drop-down {border:none; padding-right:10px;}" + "QComboBox QAbstractItemView {border: none; background:#272727; color:white; selection-background-color: #202020; outline:none;}" + "QComboBox QAbstractItemView::item {padding-left:8px;}" + scrollBarStyle + ; + from->setStyleSheet(comboBoxStyle); + to->setStyleSheet(comboBoxStyle); + from->setFixedHeight(22); + to->setFixedHeight(22); + QLabel * arrow = new QLabel(this); + QPixmap arrowPixmap(":/images/fromTo.png"); + arrow->setPixmap(arrowPixmap); + QPushButton * searchButton = new QPushButton(this); + searchButton->setIcon(QIcon(":/images/translatorSearch.png")); + searchButton->setStyleSheet("QPushButton {border:none; background:#2a2a2a;}"); + searchButton->setFixedSize(22,22); + combos->addWidget(from,1); + combos->addSpacing(9); + combos->addWidget(arrow,0); + combos->addSpacing(9); + combos->addWidget(to,1); + combos->addSpacing(9); + combos->addWidget(searchButton,0); + layout->addSpacing(12); + layout->addLayout(combos); + + + //RESULTS + QHBoxLayout * resultsTitleLayout = new QHBoxLayout(); + resultsTitle = new QLabel(tr("Translation")); + resultsTitle->setStyleSheet("QLabel {font-family:Arial;font-size:14px;color:#e3e3e3;}"); + speakButton = new QPushButton(this); + speakButton->setStyleSheet("QPushButton {border:none;}"); + speakButton->setIcon(QIcon(":/images/speaker.png")); + resultsTitleLayout->addWidget(resultsTitle,0,Qt::AlignVCenter); + resultsTitleLayout->addSpacing(10); + resultsTitleLayout->addWidget(speakButton,0,Qt::AlignVCenter); + resultsTitleLayout->addStretch(); + + layout->addSpacing(15); + layout->addLayout(resultsTitleLayout); + layout->addSpacing(12); + + resultText = new QLabel(); + resultText->setWordWrap(true); + resultText->setStyleSheet("QLabel {color:white;font-size:12px;}"); + resultText->setText("ñlkas lakj dflkaj lasd jflie lkajd fie kljads ijef lasei afsliej ljse f"); + layout->addWidget(resultText); + + layout->addStretch(); + + //CLEAR BUTTON + clearButton = new QPushButton(tr("clear")); + layout->addWidget(clearButton,0,Qt::AlignRight); + clearButton->setMinimumWidth(95); + clearButton->setStyleSheet("QPushButton {border:1px solid #212121; background:#2a2a2a; color:white; font-family:Arial; font-size:12px; padding-top:5px; padding-bottom:5px;}"); + + resize(400,479); + + layout->setMargin(0); + layout->setContentsMargins(18,12,18,12); + setContentsMargins(0,0,0,0); + layout->setSpacing(0); + + hideResults(); + populateCombos(); + + busyIndicator = new YACReaderBusyWidget(this); + busyIndicator->move((this->width()-busyIndicator->width())/2,(this->height()-busyIndicator->height())*2/3); + busyIndicator->hide(); + + show(); + + connect(searchButton,SIGNAL(pressed()),this,SLOT(translate())); + connect(speakButton,SIGNAL(pressed()),this,SLOT(play())); + connect(clearButton,SIGNAL(pressed()),this,SLOT(clear())); + + //multimedia/phonon +#if QT_VERSION >= 0x050000 + player = new QMediaPlayer; +#else + music = createPlayer(MusicCategory); +#endif + +} + +void YACReaderTranslator::hideResults() +{ + resultsTitle->setHidden(true); + speakButton->setHidden(true); + resultText->setHidden(true); +} + +void YACReaderTranslator::clear() +{ + hideResults(); + text->clear(); +} + +void YACReaderTranslator::translate() +{ + QString text = this->text->toPlainText(); + if(text.isEmpty()) + return; + QString from = this->from->itemData(this->from->currentIndex()).toString(); + QString to = this->to->itemData(this->to->currentIndex()).toString(); + + TranslationLoader * translationLoader = new TranslationLoader(text,from,to); + connect(translationLoader,SIGNAL(requestFinished(QString)),this,SLOT(setTranslation(QString))); + connect(translationLoader,SIGNAL(error()),this,SLOT(error())); + connect(translationLoader,SIGNAL(timeOut()),this,SLOT(error())); + connect(translationLoader,SIGNAL(finished()),translationLoader,SLOT(deleteLater())); + + TextToSpeachLoader * tts = new TextToSpeachLoader(text,from); + connect(tts,SIGNAL(requestFinished(QUrl)),this,SLOT(setSpeak(QUrl))); + connect(tts,SIGNAL(error()),this,SLOT(error())); + connect(tts,SIGNAL(timeOut()),this,SLOT(error())); + connect(tts,SIGNAL(finished()),tts,SLOT(deleteLater())); + + translationLoader->start(); + tts->start(); + + resultsTitle->setText(tr("Translation")); + + hideResults(); + + busyIndicator->show(); +} + +void YACReaderTranslator::error() +{ + resultsTitle->setText(tr("Service not available")); + resultsTitle->setHidden(false); + busyIndicator->hide(); +} + +void YACReaderTranslator::setSpeak(const QUrl & url) +{ + resultsTitle->setHidden(false); + speakButton->setHidden(false); + + ttsSource = url; +} + +void YACReaderTranslator::setTranslation(const QString & string) +{ + resultText->setText(string); + + resultsTitle->setHidden(false); + resultText->setHidden(false); + busyIndicator->hide(); +} + +void YACReaderTranslator::populateCombos() +{ + QList combos; + combos.append(from); + combos.append(to); + + for(int i=0;iaddItem("Arabic","ar"); + combo->addItem("Bulgarian","bg"); + combo->addItem("Catalan","ca"); + combo->addItem("Chinese Simplified","zh-CHS"); + combo->addItem("Chinese Traditional","zh-CHT"); + combo->addItem("Czech","cs"); + combo->addItem("Danish","da"); + combo->addItem("Dutch","nl"); + combo->addItem("English","en"); + combo->addItem("Estonian","et"); + combo->addItem("Finnish","fi"); + combo->addItem("French","fr"); + combo->addItem("German","de"); + combo->addItem("Greek","el"); + combo->addItem("Haitian Creole","ht"); + combo->addItem("Hebrew","he"); + combo->addItem("Hindi","hi"); + combo->addItem("Hungarian","hu"); + combo->addItem("Indonesian","id"); + combo->addItem("Italian","it"); + combo->addItem("Japanese","ja"); + combo->addItem("Korean","ko"); + combo->addItem("Latvian","lv"); + combo->addItem("Lithuanian","lt"); + combo->addItem("Norwegian","no"); + combo->addItem("Polish","pl"); + combo->addItem("Portuguese","pt"); + combo->addItem("Romanian","ro"); + combo->addItem("Russian","ru"); + combo->addItem("Slovak","sk"); + combo->addItem("Slovenian","sl"); + combo->addItem("Spanish","es"); + combo->addItem("Swedish","sv"); + combo->addItem("Thai","th"); + combo->addItem("Turkish","tr"); + combo->addItem("Ukrainian","uk"); + combo->addItem("Vietnamese","vi"); + } + from->setCurrentIndex(from->findText("English")); + to->setCurrentIndex(from->findText("Spanish")); +} + +void YACReaderTranslator::play() +{ + //QMessageBox::question(this,"xxx",ttsSource.toString()); +#if QT_VERSION >= 0x050000 + + player->setMedia(ttsSource); + player->play(); + +#else + MediaSource src(ttsSource); + src.setAutoDelete(true); + music->setCurrentSource(src); + music->play(); +#endif +} + +YACReaderTranslator::~YACReaderTranslator() +{ +#if QT_VERSION >= 0x050000 +#else + delete music; +#endif +} + +void YACReaderTranslator::mousePressEvent(QMouseEvent *event) +{ + QPoint p = mapTo(this,event->pos()); + if(p.y() < 40) + { + drag = true; + click = event->pos(); + } +} + +void YACReaderTranslator::mouseReleaseEvent(QMouseEvent *event) +{ + drag = false; + event->accept(); +} + +void YACReaderTranslator::mouseMoveEvent(QMouseEvent * event) +{ + if(drag) + this->move(QPoint(mapToParent(event->pos())-click)); + event->accept(); +} + +//--------------------------------------------------------------------------- +//--------------------------------------------------------------------------- +//--------------------------------------------------------------------------- + +TranslationLoader::TranslationLoader(QString text, QString from, QString to) + :QThread(),text(text),from(from),to(to) +{ +} + +void TranslationLoader::run() +{ + QNetworkAccessManager manager; + QEventLoop q; + QTimer tT; + + tT.setSingleShot(true); + connect(&tT, SIGNAL(timeout()), &q, SLOT(quit())); + connect(&manager, SIGNAL(finished(QNetworkReply*)),&q, SLOT(quit())); + + QString url = "http://api.microsofttranslator.com/V2/Ajax.svc/Translate?appid=%1&from=%2&to=%3&text=%4&contentType=text/plain"; + url = url.arg(APPID).arg(from).arg(to).arg(text); + + QNetworkReply *reply = manager.get(QNetworkRequest(QUrl(url))); + + tT.start(5000); // 5s timeout + q.exec(); + + if(tT.isActive()){ + // download complete + if(reply->error() == QNetworkReply::NoError) + { + QString utf8 = QString::fromUtf8(reply->readAll()); + utf8 = utf8.remove(0,1); + utf8 = utf8.remove(utf8.count()-1,1); + + QString translated(utf8); + emit(requestFinished(translated)); + } + else + emit(error()); + } else { + emit(timeOut()); + } +} + +//--------------------------------------------------------------------------- +//--------------------------------------------------------------------------- +//--------------------------------------------------------------------------- + + +TextToSpeachLoader::TextToSpeachLoader(QString text, QString language) + :QThread(),text(text),language(language) +{ +} + + +void TextToSpeachLoader::run() +{ + QNetworkAccessManager manager; + QEventLoop q; + QTimer tT; + + tT.setSingleShot(true); + connect(&tT, SIGNAL(timeout()), &q, SLOT(quit())); + connect(&manager, SIGNAL(finished(QNetworkReply*)),&q, SLOT(quit())); + + QString url = "http://api.microsofttranslator.com/V2/Ajax.svc/Speak?appid=%1&language=%2&text=%3&contentType=text/plain"; + url = url.arg(APPID).arg(language).arg(text); + + QNetworkReply *reply = manager.get(QNetworkRequest(QUrl(url))); + + tT.start(5000); // 5s timeout + q.exec(); + + if(tT.isActive()){ + // download complete + if(reply->error() == QNetworkReply::NoError) + { + QString utf8 = QString::fromUtf8(reply->readAll()); + utf8 = utf8.remove(0,1); + utf8 = utf8.remove(utf8.count()-1,1); + utf8 = utf8.replace("\\",""); + + emit(requestFinished(QUrl(utf8))); + } + else + emit(error()); + } else { + emit(timeOut()); + } +} diff --git a/YACReader/translator.h b/YACReader/translator.h index 1ce1bee0..c6acaea5 100644 --- a/YACReader/translator.h +++ b/YACReader/translator.h @@ -1,102 +1,102 @@ -#ifndef __TRANSLATOR_H -#define __TRANSLATOR_H - -class QUrl; -class QMouseEvent; -class QPoint; -class QTextEdit; -class QComboBox; -class QLabel; -class QPushButton; -class YACReaderBusyWidget; - -#include -#include -#include - -#if QT_VERSION >= 0x050000 - class QMediaPlayer; -#else - #include - using namespace Phonon; -#endif - - - -class YACReaderTranslator : public QWidget -{ - Q_OBJECT - public: - YACReaderTranslator(QWidget * parent = 0); - ~YACReaderTranslator(); - - public slots: - void play(); - - protected slots: - void translate(); - void setSpeak(const QUrl & url); - void setTranslation(const QString & string); - void error(); - void clear(); - -protected: - void mousePressEvent(QMouseEvent *event); - void mouseReleaseEvent(QMouseEvent *event); - void mouseMoveEvent ( QMouseEvent * event ); - void hideResults(); - - void populateCombos(); - bool drag; - QPoint click; -private: - -#if QT_VERSION >= 0x050000 - QMediaPlayer *player; -#else - MediaObject * music; -#endif - - QTextEdit * text; - QComboBox * from; - QComboBox * to; - QLabel * resultsTitle; - QPushButton * speakButton; - QLabel * resultText; - YACReaderBusyWidget * busyIndicator; - QUrl ttsSource; - QPushButton * clearButton; - -}; - -class TranslationLoader : public QThread -{ - Q_OBJECT -public: - TranslationLoader(QString text, QString from, QString to); -signals: - void requestFinished(QString); - void timeOut(); - void error(); -private: - QString text; - QString from; - QString to; - void run(); -}; - -class TextToSpeachLoader : public QThread -{ - Q_OBJECT -public: - TextToSpeachLoader(QString text, QString language); -signals: - void requestFinished(QUrl); - void timeOut(); - void error(); -private: - QString text; - QString language; - void run(); -}; -#endif +#ifndef __TRANSLATOR_H +#define __TRANSLATOR_H + +class QUrl; +class QMouseEvent; +class QPoint; +class QTextEdit; +class QComboBox; +class QLabel; +class QPushButton; +class YACReaderBusyWidget; + +#include +#include +#include + +#if QT_VERSION >= 0x050000 + class QMediaPlayer; +#else + #include + using namespace Phonon; +#endif + + + +class YACReaderTranslator : public QWidget +{ + Q_OBJECT + public: + YACReaderTranslator(QWidget * parent = 0); + ~YACReaderTranslator(); + + public slots: + void play(); + + protected slots: + void translate(); + void setSpeak(const QUrl & url); + void setTranslation(const QString & string); + void error(); + void clear(); + +protected: + void mousePressEvent(QMouseEvent *event); + void mouseReleaseEvent(QMouseEvent *event); + void mouseMoveEvent ( QMouseEvent * event ); + void hideResults(); + + void populateCombos(); + bool drag; + QPoint click; +private: + +#if QT_VERSION >= 0x050000 + QMediaPlayer *player; +#else + MediaObject * music; +#endif + + QTextEdit * text; + QComboBox * from; + QComboBox * to; + QLabel * resultsTitle; + QPushButton * speakButton; + QLabel * resultText; + YACReaderBusyWidget * busyIndicator; + QUrl ttsSource; + QPushButton * clearButton; + +}; + +class TranslationLoader : public QThread +{ + Q_OBJECT +public: + TranslationLoader(QString text, QString from, QString to); +signals: + void requestFinished(QString); + void timeOut(); + void error(); +private: + QString text; + QString from; + QString to; + void run(); +}; + +class TextToSpeachLoader : public QThread +{ + Q_OBJECT +public: + TextToSpeachLoader(QString text, QString language); +signals: + void requestFinished(QUrl); + void timeOut(); + void error(); +private: + QString text; + QString language; + void run(); +}; +#endif diff --git a/YACReader/viewer.cpp b/YACReader/viewer.cpp index 41b2121c..93c5e5c9 100644 --- a/YACReader/viewer.cpp +++ b/YACReader/viewer.cpp @@ -1,1224 +1,1224 @@ -#include "viewer.h" -#include "magnifying_glass.h" -#include "configuration.h" -#include "magnifying_glass.h" -#include "goto_flow.h" -#ifndef NO_OPENGL -#include "goto_flow_gl.h" -#else -#include -#endif -#include "bookmarks_dialog.h" -#include "render.h" -#include "goto_dialog.h" -#include "translator.h" -#include "onstart_flow_selection_dialog.h" -#include "page_label_widget.h" -#include "notifications_label_widget.h" -#include "comic_db.h" -#include "shortcuts_manager.h" - -#include "opengl_checker.h" - -#include - -Viewer::Viewer(QWidget * parent) - :QScrollArea(parent), - currentPage(0), - magnifyingGlassShowed(false), - fullscreen(false), - information(false), - doublePage(false), - doubleMangaPage(false), - wheelStop(false), - direction(1), - restoreMagnifyingGlass(false), - drag(false), - numScrollSteps(22), - shouldOpenNext(false), - shouldOpenPrevious(false), - zoom(100) -{ - translator = new YACReaderTranslator(this); - translator->hide(); - translatorAnimation = new QPropertyAnimation(translator,"pos"); - translatorAnimation->setDuration(150); - translatorXPos = -10000; - translator->move(-translator->width(),10); - //current comic page - content = new QLabel(this); - configureContent(tr("Press 'O' to open comic.")); - //scroll area configuration - setBackgroundRole(QPalette::Dark); - setWidget(content); - setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); - setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); - setFrameStyle(QFrame::NoFrame); - setAlignment(Qt::AlignCenter); - - QPalette palette; - palette.setColor(backgroundRole(), Configuration::getConfiguration().getBackgroundColor()); - setPalette(palette); - //--------------------------------------- - mglass = new MagnifyingGlass(Configuration::getConfiguration().getMagnifyingGlassSize(),this); - mglass->hide(); - content->setMouseTracking(true); - setMouseTracking(true); - - showCursor(); - - goToDialog = new GoToDialog(this); - - QSettings * settings = new QSettings(YACReader::getSettingsPath()+"/YACReader.ini",QSettings::IniFormat); - - //CONFIG GOTO_FLOW-------------------------------------------------------- -#ifndef NO_OPENGL - - OpenGLChecker openGLChecker; - bool openGLAvailable = openGLChecker.hasCompatibleOpenGLVersion(); - - if(openGLAvailable && !settings->contains(USE_OPEN_GL)) - settings->setValue(USE_OPEN_GL,2); - else - if(!openGLAvailable) - settings->setValue(USE_OPEN_GL,0); - - if((settings->value(USE_OPEN_GL).toBool() == true)) - goToFlow = new GoToFlowGL(this,Configuration::getConfiguration().getFlowType()); - else - goToFlow = new GoToFlow(this,Configuration::getConfiguration().getFlowType()); -#else - goToFlow = new GoToFlow(this,Configuration::getConfiguration().getFlowType()); -#endif - goToFlow->setFocusPolicy(Qt::StrongFocus); - goToFlow->hide(); - showGoToFlowAnimation = new QPropertyAnimation(goToFlow,"pos"); - showGoToFlowAnimation->setDuration(150); - - bd = new BookmarksDialog(this->parentWidget()); - - render = new Render(); - - hideCursorTimer = new QTimer(); - hideCursorTimer->setSingleShot(true); - - if(Configuration::getConfiguration().getDoublePage()) - doublePageSwitch(); - - if(Configuration::getConfiguration().getDoubleMangaPage()) - doubleMangaPageSwitch(); - - createConnections(); - - hideCursorTimer->start(2500); - - setMouseTracking(true); - - //animations - verticalScroller = new QPropertyAnimation(verticalScrollBar(), "sliderPosition"); - connect(verticalScroller,SIGNAL(valueChanged (const QVariant &)),this,SIGNAL(backgroundChanges())); - horizontalScroller = new QPropertyAnimation(horizontalScrollBar(), "sliderPosition"); - connect(horizontalScroller,SIGNAL(valueChanged (const QVariant &)),this,SIGNAL(backgroundChanges())); - groupScroller = new QParallelAnimationGroup(); - groupScroller->addAnimation(verticalScroller); - groupScroller->addAnimation(horizontalScroller); - - notificationsLabel = new NotificationsLabelWidget(this); - notificationsLabel->hide(); - - informationLabel = new PageLabelWidget(this); - - setAcceptDrops(true); -} - -Viewer::~Viewer() -{ - delete render; - delete goToFlow; - delete translator; - delete translatorAnimation; - delete content; - delete hideCursorTimer; - delete informationLabel; - delete verticalScroller; - delete horizontalScroller; - delete groupScroller; - delete bd; - delete notificationsLabel; - delete mglass; - if(currentPage != 0) - delete currentPage; -} - -void Viewer::createConnections() -{ - //magnifyingGlass (update mg after a background change - connect(this,SIGNAL(backgroundChanges()),mglass,SLOT(updateImage())); - - //goToDialog - connect(goToDialog,SIGNAL(goToPage(unsigned int)),this,SLOT(goTo(unsigned int))); - - //goToFlow goTo - connect(goToFlow,SIGNAL(goToPage(unsigned int)),this,SLOT(goTo(unsigned int))); - - //current time - QTimer * t = new QTimer(); - connect(t,SIGNAL(timeout()),this,SLOT(updateInformation())); - t->start(1000); - - //hide cursor - connect(hideCursorTimer,SIGNAL(timeout()),this,SLOT(hideCursor())); - - //bookmarks - connect(bd,SIGNAL(goToPage(unsigned int)),this,SLOT(goTo(unsigned int))); - - //render - connect(render,SIGNAL(errorOpening()),this,SLOT(resetContent())); - connect(render,SIGNAL(errorOpening()),this,SLOT(showMessageErrorOpening())); - connect(render,SIGNAL(errorOpening(QString)),this,SLOT(showMessageErrorOpening(QString))); - connect(render,SIGNAL(crcError(QString)),this,SLOT(processCRCError(QString))); - connect(render,SIGNAL(numPages(unsigned int)),goToFlow,SLOT(setNumSlides(unsigned int))); - connect(render,SIGNAL(numPages(unsigned int)),goToDialog,SLOT(setNumPages(unsigned int))); - //connect(render,SIGNAL(numPages(unsigned int)),this,SLOT(updateInformation())); - connect(render,SIGNAL(imageLoaded(int,QByteArray)),goToFlow,SLOT(setImageReady(int,QByteArray))); - connect(render,SIGNAL(currentPageReady()),this,SLOT(updatePage())); - connect(render,SIGNAL(processingPage()),this,SLOT(setLoadingMessage())); - connect(render,SIGNAL(currentPageIsBookmark(bool)),this,SIGNAL(pageIsBookmark(bool))); - connect(render,SIGNAL(pageChanged(int)),this,SLOT(updateInformation())); - //connect(render,SIGNAL(bookmarksLoaded(Bookmarks)),this,SLOT(setBookmarks(Bookmarks))); - - connect(render,SIGNAL(isLast()),this,SLOT(showIsLastMessage())); - connect(render,SIGNAL(isCover()),this,SLOT(showIsCoverMessage())); - - connect(render,SIGNAL(bookmarksUpdated()),this,SLOT(setBookmarks())); -} - -//Deprecated -void Viewer::prepareForOpening() -{ - if(render->hasLoadedComic()) - save(); - //bd->setBookmarks(*bm); - - goToFlow->reset(); - - //render->update(); - - verticalScrollBar()->setSliderPosition(verticalScrollBar()->minimum()); - - if(Configuration::getConfiguration().getShowInformation() && !information) - { - QTimer * timer = new QTimer(); - connect(timer,SIGNAL(timeout()),this,SLOT(informationSwitch())); - connect(timer,SIGNAL(timeout()),timer,SLOT(deleteLater())); - timer->start(); - } - - informationLabel->setText("..."); -} - -void Viewer::open(QString pathFile, int atPage) -{ - prepareForOpening(); - render->load(pathFile, atPage); -} - -void Viewer::open(QString pathFile, const ComicDB & comic) -{ - prepareForOpening(); - render->load(pathFile, comic); -} - -void Viewer::showMessageErrorOpening() -{ - QMessageBox::critical(this,tr("Not found"),tr("Comic not found")); - //resetContent(); --> not needed -} - -void Viewer::showMessageErrorOpening(QString message) -{ - QMessageBox::critical(this,tr("Error opening comic"),message); - resetContent(); -} - -void Viewer::processCRCError(QString message) -{ - QMessageBox::critical(this,tr("CRC Error"),message); -} - -void Viewer::next() -{ - direction = 1; - if (doublePage && render->currentPageIsDoublePage()) - { - render->nextDoublePage(); - } - else - { - render->nextPage(); - } - updateInformation(); - shouldOpenPrevious = false; -} - -void Viewer::prev() -{ - direction = -1; - if (doublePage && render->previousPageIsDoublePage()) - { - render->previousDoublePage(); - } - else - { - render->previousPage(); - } - updateInformation(); - shouldOpenNext = false; -} -void Viewer::showGoToDialog() -{ - goToDialog->open(); -} -void Viewer::goTo(unsigned int page) -{ - direction = 1; //in "go to" direction is always fordward - render->goTo(page); -} - -void Viewer::updatePage() -{ - QPixmap * previousPage = currentPage; - if (doublePage) - { - if (!doubleMangaPage) - currentPage = render->getCurrentDoublePage(); - else - { - currentPage = render->getCurrentDoubleMangaPage(); - } - if (currentPage == NULL) - { - currentPage = render->getCurrentPage(); - } - } - else - { - currentPage = render->getCurrentPage(); - } - content->setPixmap(*currentPage); - updateContentSize(); - updateVerticalScrollBar(); - - if(goToFlow->isHidden()) - setFocus(Qt::ShortcutFocusReason); - else - goToFlow->setFocus(Qt::OtherFocusReason); - delete previousPage; - - if(currentPage->isNull()) - setPageUnavailableMessage(); - else - emit(pageAvailable(true)); - - emit backgroundChanges(); - - if(restoreMagnifyingGlass) - { - restoreMagnifyingGlass = false; - showMagnifyingGlass(); - } - -} - -void Viewer::updateContentSize() -{ - //there is an image to resize - if(currentPage !=0 && !currentPage->isNull()) - { - QSize pagefit; - YACReader::FitMode fitmode = Configuration::getConfiguration().getFitMode(); - switch (fitmode) - { - case YACReader::FitMode::FullRes: - pagefit=currentPage->size(); - break; - case YACReader::FitMode::ToWidth: - pagefit=currentPage->size(); - pagefit.scale(width(), 0, Qt::KeepAspectRatioByExpanding); - break; - case YACReader::FitMode::ToHeight: - pagefit=currentPage->size(); - pagefit.scale(0, height(), Qt::KeepAspectRatioByExpanding); - break; - //if everything fails showing the full page is a good idea - case YACReader::FitMode::FullPage: - default: - pagefit=currentPage->size(); - pagefit.scale(size(), Qt::KeepAspectRatio); - break; - } - - if(zoom != 100) - { - pagefit.scale(floor(pagefit.width()*zoom/100.0f), 0, Qt::KeepAspectRatioByExpanding); - } - //apply scaling - content->resize(pagefit); - - //TODO: updtateContentSize should only scale the pixmap once - if(devicePixelRatio()>1)//only in retina display - { - QPixmap page = currentPage->scaled(content->width()*devicePixelRatio(), content->height()*devicePixelRatio(), Qt::KeepAspectRatio, Qt::SmoothTransformation); - page.setDevicePixelRatio(devicePixelRatio()); - content->setPixmap(page); - } - - emit backgroundChanges(); - } - content->update(); //TODO, it shouldn't be neccesary -} - -void Viewer::increaseZoomFactor() -{ - zoom = std::min(zoom + 10, 500); - - updateContentSize(); - notificationsLabel->setText(QString::number(getZoomFactor())+"%"); - notificationsLabel->flash(); - - emit zoomUpdated(zoom); -} -void Viewer::decreaseZoomFactor() -{ - zoom = std::max(zoom - 10, 30); - - updateContentSize(); - notificationsLabel->setText(QString::number(getZoomFactor())+"%"); - notificationsLabel->flash(); - - emit zoomUpdated(zoom); -} - -int Viewer::getZoomFactor() -{ - //this function is a placeholder for future refactoring work - return zoom; -} - -void Viewer::setZoomFactor(int z) -{ - //this function is mostly used to reset the zoom after a fitmode switch - if (z > 500) - zoom = 500; - else if (z < 30) - zoom = 30; - else - zoom = z; - - emit zoomUpdated(zoom); -} - -void Viewer::updateVerticalScrollBar() -{ - if(direction > 0) - verticalScrollBar()->setSliderPosition(verticalScrollBar()->minimum()); - else - verticalScrollBar()->setSliderPosition(verticalScrollBar()->maximum()); -} - -void Viewer::scrollDown() -{ - if(verticalScrollBar()->sliderPosition()==verticalScrollBar()->maximum()) - { - next(); - } - else - { - int currentPos = verticalScrollBar()->sliderPosition(); - verticalScroller->setDuration(250); - verticalScroller->setStartValue(currentPos); - verticalScroller->setEndValue(nextPos); - - verticalScroller->start(); - - emit backgroundChanges(); - } -} - -void Viewer::scrollUp() -{ - if(verticalScrollBar()->sliderPosition()==verticalScrollBar()->minimum()) - { - prev(); - } - else - { - int currentPos = verticalScrollBar()->sliderPosition(); - verticalScroller->setDuration(250); - verticalScroller->setStartValue(currentPos); - verticalScroller->setEndValue(nextPos); - - verticalScroller->start(); - - emit backgroundChanges(); - } -} - -void Viewer::scrollForwardHorizontalFirst() -{ - if (!doubleMangaPage) - { - scrollZigzag(RIGHT, DOWN, true); // right->right->lower left->right->...->next page - } - else - { - scrollZigzag(LEFT, DOWN, true); // left->left->lower right->left->...->next page - } -} - -void Viewer::scrollBackwardHorizontalFirst() -{ - if (!doubleMangaPage) - { - scrollZigzag(LEFT, UP, false); // left->left->upper right->left->...->prev page - } - else - { - scrollZigzag(RIGHT, UP, false); // right->right->upper left->right->...->prev page - } -} - -void Viewer::scrollForwardVerticalFirst() -{ - if (!doubleMangaPage) - { - scrollZigzag(DOWN, RIGHT, true); // down->down->upper right->down->...->next page - } - else - { - scrollZigzag(DOWN, LEFT, true); // down->down->upper left->down->...->next page - } -} - -void Viewer::scrollBackwardVerticalFirst() -{ - if (!doubleMangaPage) - { - scrollZigzag(UP, LEFT, false); // up->up->lower left->up->...->prev page - } - else - { - scrollZigzag(UP, RIGHT, false); // up->up->lower right->up->...->prev page - } -} - -bool Viewer::isEdge(scrollDirection d) -{ - if(d == UP) - return verticalScrollBar()->sliderPosition() == verticalScrollBar()->minimum(); - else if(d == DOWN) - return verticalScrollBar()->sliderPosition() == verticalScrollBar()->maximum(); - else if(d == LEFT) - return horizontalScrollBar()->sliderPosition() == horizontalScrollBar()->minimum(); - else // d == RIGHT - return horizontalScrollBar()->sliderPosition() == horizontalScrollBar()->maximum(); -} - -void Viewer::scrollZigzag(scrollDirection d1, scrollDirection d2, bool forward) -{ - if(!isEdge(d1)) - { - if(d1 == UP) - scrollTo(horizontalScrollBar()->sliderPosition(), - verticalScrollBar()->sliderPosition()-static_cast((height()*0.80))); - else if(d1 == DOWN) - scrollTo(horizontalScrollBar()->sliderPosition(), - verticalScrollBar()->sliderPosition()+static_cast((height()*0.80))); - else if(d1 == LEFT) - scrollTo(horizontalScrollBar()->sliderPosition()-static_cast((width()*0.80)), - verticalScrollBar()->sliderPosition()); - else // d1 == RIGHT - scrollTo(horizontalScrollBar()->sliderPosition()+static_cast((width()*0.80)), - verticalScrollBar()->sliderPosition()); - } - else if(!isEdge(d2)) - { - int x = 0; - int y = 0; - - if(d1 == UP) - y = verticalScrollBar()->maximum(); - else if(d1 == DOWN) - y = verticalScrollBar()->minimum(); - else if(d1 == LEFT) - x = horizontalScrollBar()->maximum(); - else // d1 == RIGHT - x = horizontalScrollBar()->minimum(); - - if(d2 == UP) - y = std::max(verticalScrollBar()->sliderPosition()-static_cast((height()*0.80)), verticalScrollBar()->minimum()); - else if(d2 == DOWN) - y = std::min(verticalScrollBar()->sliderPosition()+static_cast((height()*0.80)), verticalScrollBar()->maximum()); - else if(d2 == LEFT) - x = std::max(horizontalScrollBar()->sliderPosition()-static_cast((width()*0.80)), horizontalScrollBar()->minimum()); - else // d2 == RIGHT - x = std::min(horizontalScrollBar()->sliderPosition()+static_cast((width()*0.80)), horizontalScrollBar()->maximum()); - - scrollTo(x, y); - } - else - { - // next or prev page's corner - int savedPageNumber = getCurrentPageNumber(); - - if(forward) - next(); - else - prev(); - - if(savedPageNumber != getCurrentPageNumber()){ - if(d1 == LEFT || d2 == LEFT) - horizontalScrollBar()->setSliderPosition(horizontalScrollBar()->maximum()); - else - horizontalScrollBar()->setSliderPosition(horizontalScrollBar()->minimum()); - emit backgroundChanges(); - } - } -} - -void Viewer::scrollTo(int x, int y) -{ - if(groupScroller->state() == QAbstractAnimation::Running) - return; - horizontalScroller->setDuration(250); - horizontalScroller->setStartValue(horizontalScrollBar()->sliderPosition()); - horizontalScroller->setEndValue(x); - verticalScroller->setDuration(250); - verticalScroller->setStartValue(verticalScrollBar()->sliderPosition()); - verticalScroller->setEndValue(y); - groupScroller->start(); - emit backgroundChanges(); -} - -void Viewer::keyPressEvent(QKeyEvent *event) -{ - if(render->hasLoadedComic()) - { - int _key = event->key(); - Qt::KeyboardModifiers modifiers = event->modifiers(); - - if(modifiers & Qt::ShiftModifier) - _key |= Qt::SHIFT; - if (modifiers & Qt::ControlModifier) - _key |= Qt::CTRL; - if (modifiers & Qt::MetaModifier) - _key |= Qt::META; - if (modifiers & Qt::AltModifier) - _key |= Qt::ALT; - - QKeySequence key(_key); - /*if(goToFlow->isVisible() && event->key()!=Qt::Key_S) - QCoreApplication::sendEvent(goToFlow,event); - else*/ - - if (key == ShortcutsManager::getShortcutsManager().getShortcut(AUTO_SCROLL_FORWARD_ACTION_Y)) - { - posByStep = height()/numScrollSteps; - nextPos=verticalScrollBar()->sliderPosition()+static_cast((height()*0.80)); - scrollDown(); - } - - else if (key == ShortcutsManager::getShortcutsManager().getShortcut(AUTO_SCROLL_BACKWARD_ACTION_Y)) - { - posByStep = height()/numScrollSteps; - nextPos=verticalScrollBar()->sliderPosition()-static_cast((height()*0.80)); - scrollUp(); - } - - else if (key == ShortcutsManager::getShortcutsManager().getShortcut(AUTO_SCROLL_FORWARD_HORIZONTAL_FIRST_ACTION_Y)) - { - scrollForwardHorizontalFirst(); - } - - else if (key == ShortcutsManager::getShortcutsManager().getShortcut(AUTO_SCROLL_BACKWARD_HORIZONTAL_FIRST_ACTION_Y)) - { - scrollBackwardHorizontalFirst(); - } - - else if (key == ShortcutsManager::getShortcutsManager().getShortcut(AUTO_SCROLL_FORWARD_VERTICAL_FIRST_ACTION_Y)) - { - scrollForwardVerticalFirst(); - } - - else if (key == ShortcutsManager::getShortcutsManager().getShortcut(AUTO_SCROLL_BACKWARD_VERTICAL_FIRST_ACTION_Y)) - { - scrollBackwardVerticalFirst(); - } - - else if (key == ShortcutsManager::getShortcutsManager().getShortcut(MOVE_DOWN_ACTION_Y) || - key == ShortcutsManager::getShortcutsManager().getShortcut(MOVE_UP_ACTION_Y) || - key == ShortcutsManager::getShortcutsManager().getShortcut(MOVE_LEFT_ACTION_Y) || - key == ShortcutsManager::getShortcutsManager().getShortcut(MOVE_RIGHT_ACTION_Y)) - { - QAbstractScrollArea::keyPressEvent(event); - emit backgroundChanges(); - } - - else if (key == ShortcutsManager::getShortcutsManager().getShortcut(GO_TO_FIRST_PAGE_ACTION_Y)) - { - goTo(0); - } - - else if (key == ShortcutsManager::getShortcutsManager().getShortcut(GO_TO_LAST_PAGE_ACTION_Y)) - { - goTo(this->render->numPages()-1); - } - - else - QAbstractScrollArea::keyPressEvent(event); - - if(mglass->isVisible() && (key == ShortcutsManager::getShortcutsManager().getShortcut(SIZE_UP_MGLASS_ACTION_Y) || - key == ShortcutsManager::getShortcutsManager().getShortcut(SIZE_DOWN_MGLASS_ACTION_Y) || - key == ShortcutsManager::getShortcutsManager().getShortcut(ZOOM_IN_MGLASS_ACTION_Y) || - key == ShortcutsManager::getShortcutsManager().getShortcut(ZOOM_OUT_MGLASS_ACTION_Y))) - { - QCoreApplication::sendEvent(mglass,event); - } - - } - else - QAbstractScrollArea::keyPressEvent(event); -} - -void Viewer::wheelEvent(QWheelEvent * event) -{ - if(render->hasLoadedComic()) - { - if((event->delta()<0)&&(verticalScrollBar()->sliderPosition()==verticalScrollBar()->maximum())) - { - if(wheelStop) - { - if(getMovement(event) == Forward) - { - next(); - verticalScroller->stop(); - event->accept(); - wheelStop = false; - } - return; - } - else - wheelStop = true; - } - else - { - if((event->delta()>0)&&(verticalScrollBar()->sliderPosition()==verticalScrollBar()->minimum())) - { - if(wheelStop) - { - if(getMovement(event) == Backward) - { - prev(); - verticalScroller->stop(); - event->accept(); - wheelStop = false; - } - return; - } - else - wheelStop = true; - } - } - - int deltaNotFinished = 0; - if(verticalScroller->state() == QAbstractAnimation::Running) - { - deltaNotFinished = verticalScroller->startValue().toInt() - verticalScroller->endValue().toInt(); - verticalScroller->stop(); - } - - - int currentPos = verticalScrollBar()->sliderPosition(); - verticalScroller->setDuration(250); - verticalScroller->setStartValue(currentPos); - verticalScroller->setEndValue(currentPos - event->delta() - deltaNotFinished); - - verticalScroller->start(); - - //QAbstractScrollArea::wheelEvent(event); - } -} - -void Viewer::resizeEvent(QResizeEvent * event) -{ - updateContentSize(); - goToFlow->updateSize(); - goToFlow->move((width()-goToFlow->width())/2,height()-goToFlow->height()); - informationLabel->updatePosition(); - QScrollArea::resizeEvent(event); -} - -void Viewer::mouseMoveEvent(QMouseEvent * event) -{ - showCursor(); - hideCursorTimer->start(2500); - - if(magnifyingGlassShowed) - mglass->move(static_cast(event->x()-float(mglass->width())/2),static_cast(event->y()-float(mglass->height())/2)); - - if(render->hasLoadedComic()) - { - if(showGoToFlowAnimation->state()!=QPropertyAnimation::Running) - { - if(Configuration::getConfiguration().getDisableShowOnMouseOver() == false) - { - if(goToFlow->isVisible()) - { - QPoint gtfPos = goToFlow->mapFrom(this,event->pos()); - if(gtfPos.y() < 0 || gtfPos.x()<0 || gtfPos.x()>goToFlow->width())//TODO this extra check is for Mavericks (mouseMove over goToFlowGL seems to be broken) - animateHideGoToFlow(); - //goToFlow->hide(); - } - else - { - int umbral = (width()-goToFlow->width())/2; - if((event->y()>height()-15)&&(event->x()>umbral)&&(event->x()stop(); - } - } - } - } - - if(drag) - { - int currentPosY = verticalScrollBar()->sliderPosition(); - int currentPosX = horizontalScrollBar()->sliderPosition(); - verticalScrollBar()->setSliderPosition(currentPosY=currentPosY+(yDragOrigin-event->y())); - horizontalScrollBar()->setSliderPosition(currentPosX=currentPosX+(xDragOrigin-event->x())); - yDragOrigin = event->y(); - xDragOrigin = event->x(); - } - } - - -} - -const QPixmap * Viewer::pixmap() -{ - return content->pixmap(); -} - -void Viewer::magnifyingGlassSwitch() -{ - magnifyingGlassShowed?hideMagnifyingGlass():showMagnifyingGlass(); -} - -void Viewer::showMagnifyingGlass() -{ - if(render->hasLoadedComic()) - { - QPoint p = QPoint(cursor().pos().x(),cursor().pos().y()); - p = this->parentWidget()->mapFromGlobal(p); - mglass->move(static_cast(p.x()-float(mglass->width())/2) - ,static_cast(p.y()-float(mglass->height())/2)); - mglass->show(); - mglass->updateImage(mglass->x()+mglass->width()/2,mglass->y()+mglass->height()/2); - magnifyingGlassShowed = true; - } -} - -void Viewer::hideMagnifyingGlass() -{ - mglass->hide(); - magnifyingGlassShowed = false; -} - -void Viewer::informationSwitch() -{ - information?informationLabel->hide():informationLabel->show(); - //informationLabel->move(QPoint((width()-informationLabel->width())/2,0)); - information=!information; - Configuration::getConfiguration().setShowInformation(information); - //TODO it shouldn't be neccesary - informationLabel->adjustSize(); - informationLabel->update(); -} - -void Viewer::updateInformation() -{ - if(render->hasLoadedComic()) - { - informationLabel->setText(render->getCurrentPagesInformation()+" - "+QTime::currentTime().toString("HH:mm")); - informationLabel->adjustSize(); - informationLabel->update(); //TODO it shouldn't be neccesary - } -} - -void Viewer::goToFlowSwitch() -{ - goToFlow->isVisible()?animateHideGoToFlow():showGoToFlow(); -} - -void Viewer::translatorSwitch() -{ - translator->isVisible()?animateHideTranslator():animateShowTranslator(); -} - -void Viewer::showGoToFlow() -{ - if(render->hasLoadedComic()) - { - animateShowGoToFlow(); - } -} - -void Viewer::animateShowGoToFlow() -{ - if(goToFlow->isHidden() && showGoToFlowAnimation->state()!=QPropertyAnimation::Running) - { - disconnect(showGoToFlowAnimation,SIGNAL(finished()),goToFlow,SLOT(hide())); - connect(showGoToFlowAnimation,SIGNAL(finished()),this,SLOT(moveCursoToGoToFlow())); - showGoToFlowAnimation->setStartValue(QPoint((width()-goToFlow->width())/2,height()-10)); - showGoToFlowAnimation->setEndValue(QPoint((width()-goToFlow->width())/2,height()-goToFlow->height())); - showGoToFlowAnimation->start(); - goToFlow->centerSlide(render->getIndex()); - goToFlow->setPageNumber(render->getIndex()); - goToFlow->show(); - goToFlow->setFocus(Qt::OtherFocusReason); - } -} - -void Viewer::animateHideGoToFlow() -{ - if(goToFlow->isVisible() && showGoToFlowAnimation->state()!=QPropertyAnimation::Running) - { - connect(showGoToFlowAnimation,SIGNAL(finished()),goToFlow,SLOT(hide())); - disconnect(showGoToFlowAnimation,SIGNAL(finished()),this,SLOT(moveCursoToGoToFlow())); - showGoToFlowAnimation->setStartValue(QPoint((width()-goToFlow->width())/2,height()-goToFlow->height())); - showGoToFlowAnimation->setEndValue(QPoint((width()-goToFlow->width())/2,height())); - showGoToFlowAnimation->start(); - goToFlow->centerSlide(render->getIndex()); - goToFlow->setPageNumber(render->getIndex()); - this->setFocus(Qt::OtherFocusReason); - } -} - -void Viewer::moveCursoToGoToFlow() -{ - if(Configuration::getConfiguration().getDisableShowOnMouseOver()) - { - return; - } - - //Move cursor to goToFlow widget on show (this avoid hide when mouse is moved) - int y = goToFlow->pos().y(); - int x1 = goToFlow->pos().x(); - int x2 = x1 + goToFlow->width(); - QPoint cursorPos = mapFromGlobal(cursor().pos()); - int cursorX = cursorPos.x(); - int cursorY = cursorPos.y(); - - if(cursorY <= y) - cursorY = y + 10; - if(cursorX <= x1) - cursorX = x1 + 10; - if(cursorX >= x2) - cursorX = x2 - 10; - cursor().setPos(mapToGlobal(QPoint(cursorX,cursorY))); - hideCursorTimer->stop(); - showCursor(); -} - -void Viewer::rotateLeft() -{ - render->rotateLeft(); -} -void Viewer::rotateRight() -{ - render->rotateRight(); -} - -//TODO -void Viewer::setBookmark(bool set) -{ - render->setBookmark(); - if(set) //add bookmark - { - render->setBookmark(); - } - else //remove bookmark - { - render->removeBookmark(); - } -} - -void Viewer::save () -{ - if(render->hasLoadedComic()) - render->save(); -} - -void Viewer::doublePageSwitch() -{ - doublePage = !doublePage; - render->doublePageSwitch(); - Configuration::getConfiguration().setDoublePage(doublePage); -} - -void Viewer::doubleMangaPageSwitch() -{ - doubleMangaPage = !doubleMangaPage; - render->doubleMangaPageSwitch(); - Configuration &config = Configuration::getConfiguration(); - config.setDoubleMangaPage(doubleMangaPage); - goToFlow->setFlowRightToLeft(doubleMangaPage); - goToFlow->updateConfig(config.getSettings()); -} - -void Viewer::resetContent() -{ - configureContent(tr("Press 'O' to open comic.")); - goToFlow->reset(); - emit reset(); -} - -void Viewer::setLoadingMessage() -{ - if(magnifyingGlassShowed) - { - hideMagnifyingGlass(); - restoreMagnifyingGlass = true; - } - emit(pageAvailable(false)); - configureContent(tr("Loading...please wait!")); -} - -void Viewer::setPageUnavailableMessage() -{ - if(magnifyingGlassShowed) - { - hideMagnifyingGlass(); - restoreMagnifyingGlass = true; - } - emit(pageAvailable(false)); - configureContent(tr("Page not available!")); -} - -void Viewer::configureContent(QString msg) -{ - content->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Ignored); - if(!(devicePixelRatio()>1)) - content->setScaledContents(true); - content->setAlignment(Qt::AlignTop|Qt::AlignHCenter); - content->setText(msg); - content->setFont(QFont("courier new", 12)); - content->adjustSize(); - setFocus(Qt::ShortcutFocusReason); - //emit showingText(); -} - -void Viewer::hideCursor() -{ -#ifdef Q_OS_MAC - setCursor(QCursor(QBitmap(1,1),QBitmap(1,1))); -#else - setCursor(Qt::BlankCursor); -#endif -} -void Viewer::showCursor() -{ - if(drag) - setCursor(Qt::ClosedHandCursor); - else - setCursor(Qt::OpenHandCursor); -} - -void Viewer::updateOptions() -{ - - goToFlow->setFlowType(Configuration::getConfiguration().getFlowType()); - updateBackgroundColor(Configuration::getConfiguration().getBackgroundColor()); - updateContentSize(); -} - -void Viewer::updateBackgroundColor(const QColor & color) -{ - QPalette palette; - palette.setColor(backgroundRole(), color); - setPalette(palette); -} - -void Viewer::animateShowTranslator() -{ - if(translator->isHidden() && translatorAnimation->state()!=QPropertyAnimation::Running) - { - disconnect(translatorAnimation,SIGNAL(finished()),translator,SLOT(hide())); - if(translatorXPos == -10000) - translatorXPos = (width()-translator->width())/2; - int x = qMax(0,qMin(translatorXPos,width()-translator->width())); - if(translator->pos().x()<0) - { - translatorAnimation->setStartValue(QPoint(-translator->width(),translator->pos().y())); - } - else - { - translatorAnimation->setStartValue(QPoint(width()+translator->width(),translator->pos().y())); - } - translatorAnimation->setEndValue(QPoint(x,translator->pos().y())); - translatorAnimation->start(); - translator->show(); - translator->setFocus(Qt::OtherFocusReason); - } -} -void Viewer::animateHideTranslator() -{ - if(translator->isVisible() && translatorAnimation->state()!=QPropertyAnimation::Running) - { - connect(translatorAnimation,SIGNAL(finished()),translator,SLOT(hide())); - translatorAnimation->setStartValue(QPoint(translatorXPos = translator->pos().x(),translator->pos().y())); - if((translator->width()/2)+translator->pos().x() <= width()/2) - translatorAnimation->setEndValue(QPoint(-translator->width(),translator->pos().y())); - else - translatorAnimation->setEndValue(QPoint(width()+translator->width(),translator->pos().y())); - translatorAnimation->start(); - this->setFocus(Qt::OtherFocusReason); - } -} - -void Viewer::mousePressEvent ( QMouseEvent * event ) -{ - if (event->button() == Qt::LeftButton) - { - drag = true; - yDragOrigin = event->y(); - xDragOrigin = event->x(); - setCursor(Qt::ClosedHandCursor); - event->accept(); - } -} - -void Viewer::mouseReleaseEvent ( QMouseEvent * event ) -{ - drag = false; - setCursor(Qt::OpenHandCursor); - event->accept(); -} - -void Viewer::updateZoomRatio(int ratio) -{ - zoom = ratio; - updateContentSize(); -} - -void Viewer::updateConfig(QSettings * settings) -{ - goToFlow->updateConfig(settings); - - QPalette palette; - palette.setColor(backgroundRole(), Configuration::getConfiguration().getBackgroundColor()); - setPalette(palette); -} - -//deprecated -void Viewer::updateImageOptions() -{ - render->reload(); -} - -void Viewer::updateFilters(int brightness, int contrast,int gamma) -{ - render->updateFilters(brightness,contrast,gamma); -} - -void Viewer::setBookmarks() -{ - bd->setBookmarks(*render->getBookmarks()); -} - -void Viewer::showIsCoverMessage() -{ - if(!shouldOpenPrevious) - { - notificationsLabel->setText(tr("Cover!")); - notificationsLabel->flash(); - shouldOpenPrevious = true; - } - else - { - shouldOpenPrevious = false; - emit (openPreviousComic()); - } - - shouldOpenNext = false; //single page comic -} - -void Viewer::showIsLastMessage() -{ - if(!shouldOpenNext) - { - notificationsLabel->setText(tr("Last page!")); - notificationsLabel->flash(); - shouldOpenNext = true; - } - else - { - shouldOpenNext = false; - emit (openNextComic()); - } - - shouldOpenPrevious = false; //single page comic -} - -unsigned int Viewer::getIndex() -{ - return render->getIndex()+1; -} - -int Viewer::getCurrentPageNumber() -{ - return render->getIndex(); -} - -void Viewer::updateComic(ComicDB & comic) -{ - if(render->hasLoadedComic()) - { - //set currentPage - if(!doublePage || (doublePage && render->currentPageIsDoublePage() == false)) - { - comic.info.currentPage = render->getIndex()+1; - } - else - { - comic.info.currentPage = std::min(render->numPages(), render->getIndex()+2); - } - //set bookmarks - Bookmarks * boomarks = render->getBookmarks(); - QList boomarksList = boomarks->getBookmarkPages(); - int numBookmarks = boomarksList.size(); - if(numBookmarks > 0) - comic.info.bookmark1 = boomarksList[0]; - if(numBookmarks > 1) - comic.info.bookmark2 = boomarksList[1]; - if(numBookmarks > 2) - comic.info.bookmark3 = boomarksList[2]; - //set filters - //TODO: avoid use settings for this... - QSettings settings(YACReader::getSettingsPath()+"/YACReader.ini",QSettings::IniFormat); - int brightness = settings.value(BRIGHTNESS,0).toInt(); - int contrast = settings.value(CONTRAST,100).toInt(); - int gamma = settings.value(GAMMA,100).toInt(); - - if(brightness != 0 || comic.info.brightness!=-1) - comic.info.brightness = brightness; - if(contrast != 100 || comic.info.contrast!=-1) - comic.info.contrast = contrast; - if(gamma != 100 || comic.info.gamma!=-1) - comic.info.gamma = gamma; - } - - -} +#include "viewer.h" +#include "magnifying_glass.h" +#include "configuration.h" +#include "magnifying_glass.h" +#include "goto_flow.h" +#ifndef NO_OPENGL +#include "goto_flow_gl.h" +#else +#include +#endif +#include "bookmarks_dialog.h" +#include "render.h" +#include "goto_dialog.h" +#include "translator.h" +#include "onstart_flow_selection_dialog.h" +#include "page_label_widget.h" +#include "notifications_label_widget.h" +#include "comic_db.h" +#include "shortcuts_manager.h" + +#include "opengl_checker.h" + +#include + +Viewer::Viewer(QWidget * parent) + :QScrollArea(parent), + currentPage(0), + magnifyingGlassShowed(false), + fullscreen(false), + information(false), + doublePage(false), + doubleMangaPage(false), + wheelStop(false), + direction(1), + restoreMagnifyingGlass(false), + drag(false), + numScrollSteps(22), + shouldOpenNext(false), + shouldOpenPrevious(false), + zoom(100) +{ + translator = new YACReaderTranslator(this); + translator->hide(); + translatorAnimation = new QPropertyAnimation(translator,"pos"); + translatorAnimation->setDuration(150); + translatorXPos = -10000; + translator->move(-translator->width(),10); + //current comic page + content = new QLabel(this); + configureContent(tr("Press 'O' to open comic.")); + //scroll area configuration + setBackgroundRole(QPalette::Dark); + setWidget(content); + setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); + setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); + setFrameStyle(QFrame::NoFrame); + setAlignment(Qt::AlignCenter); + + QPalette palette; + palette.setColor(backgroundRole(), Configuration::getConfiguration().getBackgroundColor()); + setPalette(palette); + //--------------------------------------- + mglass = new MagnifyingGlass(Configuration::getConfiguration().getMagnifyingGlassSize(),this); + mglass->hide(); + content->setMouseTracking(true); + setMouseTracking(true); + + showCursor(); + + goToDialog = new GoToDialog(this); + + QSettings * settings = new QSettings(YACReader::getSettingsPath()+"/YACReader.ini",QSettings::IniFormat); + + //CONFIG GOTO_FLOW-------------------------------------------------------- +#ifndef NO_OPENGL + + OpenGLChecker openGLChecker; + bool openGLAvailable = openGLChecker.hasCompatibleOpenGLVersion(); + + if(openGLAvailable && !settings->contains(USE_OPEN_GL)) + settings->setValue(USE_OPEN_GL,2); + else + if(!openGLAvailable) + settings->setValue(USE_OPEN_GL,0); + + if((settings->value(USE_OPEN_GL).toBool() == true)) + goToFlow = new GoToFlowGL(this,Configuration::getConfiguration().getFlowType()); + else + goToFlow = new GoToFlow(this,Configuration::getConfiguration().getFlowType()); +#else + goToFlow = new GoToFlow(this,Configuration::getConfiguration().getFlowType()); +#endif + goToFlow->setFocusPolicy(Qt::StrongFocus); + goToFlow->hide(); + showGoToFlowAnimation = new QPropertyAnimation(goToFlow,"pos"); + showGoToFlowAnimation->setDuration(150); + + bd = new BookmarksDialog(this->parentWidget()); + + render = new Render(); + + hideCursorTimer = new QTimer(); + hideCursorTimer->setSingleShot(true); + + if(Configuration::getConfiguration().getDoublePage()) + doublePageSwitch(); + + if(Configuration::getConfiguration().getDoubleMangaPage()) + doubleMangaPageSwitch(); + + createConnections(); + + hideCursorTimer->start(2500); + + setMouseTracking(true); + + //animations + verticalScroller = new QPropertyAnimation(verticalScrollBar(), "sliderPosition"); + connect(verticalScroller,SIGNAL(valueChanged (const QVariant &)),this,SIGNAL(backgroundChanges())); + horizontalScroller = new QPropertyAnimation(horizontalScrollBar(), "sliderPosition"); + connect(horizontalScroller,SIGNAL(valueChanged (const QVariant &)),this,SIGNAL(backgroundChanges())); + groupScroller = new QParallelAnimationGroup(); + groupScroller->addAnimation(verticalScroller); + groupScroller->addAnimation(horizontalScroller); + + notificationsLabel = new NotificationsLabelWidget(this); + notificationsLabel->hide(); + + informationLabel = new PageLabelWidget(this); + + setAcceptDrops(true); +} + +Viewer::~Viewer() +{ + delete render; + delete goToFlow; + delete translator; + delete translatorAnimation; + delete content; + delete hideCursorTimer; + delete informationLabel; + delete verticalScroller; + delete horizontalScroller; + delete groupScroller; + delete bd; + delete notificationsLabel; + delete mglass; + if(currentPage != 0) + delete currentPage; +} + +void Viewer::createConnections() +{ + //magnifyingGlass (update mg after a background change + connect(this,SIGNAL(backgroundChanges()),mglass,SLOT(updateImage())); + + //goToDialog + connect(goToDialog,SIGNAL(goToPage(unsigned int)),this,SLOT(goTo(unsigned int))); + + //goToFlow goTo + connect(goToFlow,SIGNAL(goToPage(unsigned int)),this,SLOT(goTo(unsigned int))); + + //current time + QTimer * t = new QTimer(); + connect(t,SIGNAL(timeout()),this,SLOT(updateInformation())); + t->start(1000); + + //hide cursor + connect(hideCursorTimer,SIGNAL(timeout()),this,SLOT(hideCursor())); + + //bookmarks + connect(bd,SIGNAL(goToPage(unsigned int)),this,SLOT(goTo(unsigned int))); + + //render + connect(render,SIGNAL(errorOpening()),this,SLOT(resetContent())); + connect(render,SIGNAL(errorOpening()),this,SLOT(showMessageErrorOpening())); + connect(render,SIGNAL(errorOpening(QString)),this,SLOT(showMessageErrorOpening(QString))); + connect(render,SIGNAL(crcError(QString)),this,SLOT(processCRCError(QString))); + connect(render,SIGNAL(numPages(unsigned int)),goToFlow,SLOT(setNumSlides(unsigned int))); + connect(render,SIGNAL(numPages(unsigned int)),goToDialog,SLOT(setNumPages(unsigned int))); + //connect(render,SIGNAL(numPages(unsigned int)),this,SLOT(updateInformation())); + connect(render,SIGNAL(imageLoaded(int,QByteArray)),goToFlow,SLOT(setImageReady(int,QByteArray))); + connect(render,SIGNAL(currentPageReady()),this,SLOT(updatePage())); + connect(render,SIGNAL(processingPage()),this,SLOT(setLoadingMessage())); + connect(render,SIGNAL(currentPageIsBookmark(bool)),this,SIGNAL(pageIsBookmark(bool))); + connect(render,SIGNAL(pageChanged(int)),this,SLOT(updateInformation())); + //connect(render,SIGNAL(bookmarksLoaded(Bookmarks)),this,SLOT(setBookmarks(Bookmarks))); + + connect(render,SIGNAL(isLast()),this,SLOT(showIsLastMessage())); + connect(render,SIGNAL(isCover()),this,SLOT(showIsCoverMessage())); + + connect(render,SIGNAL(bookmarksUpdated()),this,SLOT(setBookmarks())); +} + +//Deprecated +void Viewer::prepareForOpening() +{ + if(render->hasLoadedComic()) + save(); + //bd->setBookmarks(*bm); + + goToFlow->reset(); + + //render->update(); + + verticalScrollBar()->setSliderPosition(verticalScrollBar()->minimum()); + + if(Configuration::getConfiguration().getShowInformation() && !information) + { + QTimer * timer = new QTimer(); + connect(timer,SIGNAL(timeout()),this,SLOT(informationSwitch())); + connect(timer,SIGNAL(timeout()),timer,SLOT(deleteLater())); + timer->start(); + } + + informationLabel->setText("..."); +} + +void Viewer::open(QString pathFile, int atPage) +{ + prepareForOpening(); + render->load(pathFile, atPage); +} + +void Viewer::open(QString pathFile, const ComicDB & comic) +{ + prepareForOpening(); + render->load(pathFile, comic); +} + +void Viewer::showMessageErrorOpening() +{ + QMessageBox::critical(this,tr("Not found"),tr("Comic not found")); + //resetContent(); --> not needed +} + +void Viewer::showMessageErrorOpening(QString message) +{ + QMessageBox::critical(this,tr("Error opening comic"),message); + resetContent(); +} + +void Viewer::processCRCError(QString message) +{ + QMessageBox::critical(this,tr("CRC Error"),message); +} + +void Viewer::next() +{ + direction = 1; + if (doublePage && render->currentPageIsDoublePage()) + { + render->nextDoublePage(); + } + else + { + render->nextPage(); + } + updateInformation(); + shouldOpenPrevious = false; +} + +void Viewer::prev() +{ + direction = -1; + if (doublePage && render->previousPageIsDoublePage()) + { + render->previousDoublePage(); + } + else + { + render->previousPage(); + } + updateInformation(); + shouldOpenNext = false; +} +void Viewer::showGoToDialog() +{ + goToDialog->open(); +} +void Viewer::goTo(unsigned int page) +{ + direction = 1; //in "go to" direction is always fordward + render->goTo(page); +} + +void Viewer::updatePage() +{ + QPixmap * previousPage = currentPage; + if (doublePage) + { + if (!doubleMangaPage) + currentPage = render->getCurrentDoublePage(); + else + { + currentPage = render->getCurrentDoubleMangaPage(); + } + if (currentPage == NULL) + { + currentPage = render->getCurrentPage(); + } + } + else + { + currentPage = render->getCurrentPage(); + } + content->setPixmap(*currentPage); + updateContentSize(); + updateVerticalScrollBar(); + + if(goToFlow->isHidden()) + setFocus(Qt::ShortcutFocusReason); + else + goToFlow->setFocus(Qt::OtherFocusReason); + delete previousPage; + + if(currentPage->isNull()) + setPageUnavailableMessage(); + else + emit(pageAvailable(true)); + + emit backgroundChanges(); + + if(restoreMagnifyingGlass) + { + restoreMagnifyingGlass = false; + showMagnifyingGlass(); + } + +} + +void Viewer::updateContentSize() +{ + //there is an image to resize + if(currentPage !=0 && !currentPage->isNull()) + { + QSize pagefit; + YACReader::FitMode fitmode = Configuration::getConfiguration().getFitMode(); + switch (fitmode) + { + case YACReader::FitMode::FullRes: + pagefit=currentPage->size(); + break; + case YACReader::FitMode::ToWidth: + pagefit=currentPage->size(); + pagefit.scale(width(), 0, Qt::KeepAspectRatioByExpanding); + break; + case YACReader::FitMode::ToHeight: + pagefit=currentPage->size(); + pagefit.scale(0, height(), Qt::KeepAspectRatioByExpanding); + break; + //if everything fails showing the full page is a good idea + case YACReader::FitMode::FullPage: + default: + pagefit=currentPage->size(); + pagefit.scale(size(), Qt::KeepAspectRatio); + break; + } + + if(zoom != 100) + { + pagefit.scale(floor(pagefit.width()*zoom/100.0f), 0, Qt::KeepAspectRatioByExpanding); + } + //apply scaling + content->resize(pagefit); + + //TODO: updtateContentSize should only scale the pixmap once + if(devicePixelRatio()>1)//only in retina display + { + QPixmap page = currentPage->scaled(content->width()*devicePixelRatio(), content->height()*devicePixelRatio(), Qt::KeepAspectRatio, Qt::SmoothTransformation); + page.setDevicePixelRatio(devicePixelRatio()); + content->setPixmap(page); + } + + emit backgroundChanges(); + } + content->update(); //TODO, it shouldn't be neccesary +} + +void Viewer::increaseZoomFactor() +{ + zoom = std::min(zoom + 10, 500); + + updateContentSize(); + notificationsLabel->setText(QString::number(getZoomFactor())+"%"); + notificationsLabel->flash(); + + emit zoomUpdated(zoom); +} +void Viewer::decreaseZoomFactor() +{ + zoom = std::max(zoom - 10, 30); + + updateContentSize(); + notificationsLabel->setText(QString::number(getZoomFactor())+"%"); + notificationsLabel->flash(); + + emit zoomUpdated(zoom); +} + +int Viewer::getZoomFactor() +{ + //this function is a placeholder for future refactoring work + return zoom; +} + +void Viewer::setZoomFactor(int z) +{ + //this function is mostly used to reset the zoom after a fitmode switch + if (z > 500) + zoom = 500; + else if (z < 30) + zoom = 30; + else + zoom = z; + + emit zoomUpdated(zoom); +} + +void Viewer::updateVerticalScrollBar() +{ + if(direction > 0) + verticalScrollBar()->setSliderPosition(verticalScrollBar()->minimum()); + else + verticalScrollBar()->setSliderPosition(verticalScrollBar()->maximum()); +} + +void Viewer::scrollDown() +{ + if(verticalScrollBar()->sliderPosition()==verticalScrollBar()->maximum()) + { + next(); + } + else + { + int currentPos = verticalScrollBar()->sliderPosition(); + verticalScroller->setDuration(250); + verticalScroller->setStartValue(currentPos); + verticalScroller->setEndValue(nextPos); + + verticalScroller->start(); + + emit backgroundChanges(); + } +} + +void Viewer::scrollUp() +{ + if(verticalScrollBar()->sliderPosition()==verticalScrollBar()->minimum()) + { + prev(); + } + else + { + int currentPos = verticalScrollBar()->sliderPosition(); + verticalScroller->setDuration(250); + verticalScroller->setStartValue(currentPos); + verticalScroller->setEndValue(nextPos); + + verticalScroller->start(); + + emit backgroundChanges(); + } +} + +void Viewer::scrollForwardHorizontalFirst() +{ + if (!doubleMangaPage) + { + scrollZigzag(RIGHT, DOWN, true); // right->right->lower left->right->...->next page + } + else + { + scrollZigzag(LEFT, DOWN, true); // left->left->lower right->left->...->next page + } +} + +void Viewer::scrollBackwardHorizontalFirst() +{ + if (!doubleMangaPage) + { + scrollZigzag(LEFT, UP, false); // left->left->upper right->left->...->prev page + } + else + { + scrollZigzag(RIGHT, UP, false); // right->right->upper left->right->...->prev page + } +} + +void Viewer::scrollForwardVerticalFirst() +{ + if (!doubleMangaPage) + { + scrollZigzag(DOWN, RIGHT, true); // down->down->upper right->down->...->next page + } + else + { + scrollZigzag(DOWN, LEFT, true); // down->down->upper left->down->...->next page + } +} + +void Viewer::scrollBackwardVerticalFirst() +{ + if (!doubleMangaPage) + { + scrollZigzag(UP, LEFT, false); // up->up->lower left->up->...->prev page + } + else + { + scrollZigzag(UP, RIGHT, false); // up->up->lower right->up->...->prev page + } +} + +bool Viewer::isEdge(scrollDirection d) +{ + if(d == UP) + return verticalScrollBar()->sliderPosition() == verticalScrollBar()->minimum(); + else if(d == DOWN) + return verticalScrollBar()->sliderPosition() == verticalScrollBar()->maximum(); + else if(d == LEFT) + return horizontalScrollBar()->sliderPosition() == horizontalScrollBar()->minimum(); + else // d == RIGHT + return horizontalScrollBar()->sliderPosition() == horizontalScrollBar()->maximum(); +} + +void Viewer::scrollZigzag(scrollDirection d1, scrollDirection d2, bool forward) +{ + if(!isEdge(d1)) + { + if(d1 == UP) + scrollTo(horizontalScrollBar()->sliderPosition(), + verticalScrollBar()->sliderPosition()-static_cast((height()*0.80))); + else if(d1 == DOWN) + scrollTo(horizontalScrollBar()->sliderPosition(), + verticalScrollBar()->sliderPosition()+static_cast((height()*0.80))); + else if(d1 == LEFT) + scrollTo(horizontalScrollBar()->sliderPosition()-static_cast((width()*0.80)), + verticalScrollBar()->sliderPosition()); + else // d1 == RIGHT + scrollTo(horizontalScrollBar()->sliderPosition()+static_cast((width()*0.80)), + verticalScrollBar()->sliderPosition()); + } + else if(!isEdge(d2)) + { + int x = 0; + int y = 0; + + if(d1 == UP) + y = verticalScrollBar()->maximum(); + else if(d1 == DOWN) + y = verticalScrollBar()->minimum(); + else if(d1 == LEFT) + x = horizontalScrollBar()->maximum(); + else // d1 == RIGHT + x = horizontalScrollBar()->minimum(); + + if(d2 == UP) + y = std::max(verticalScrollBar()->sliderPosition()-static_cast((height()*0.80)), verticalScrollBar()->minimum()); + else if(d2 == DOWN) + y = std::min(verticalScrollBar()->sliderPosition()+static_cast((height()*0.80)), verticalScrollBar()->maximum()); + else if(d2 == LEFT) + x = std::max(horizontalScrollBar()->sliderPosition()-static_cast((width()*0.80)), horizontalScrollBar()->minimum()); + else // d2 == RIGHT + x = std::min(horizontalScrollBar()->sliderPosition()+static_cast((width()*0.80)), horizontalScrollBar()->maximum()); + + scrollTo(x, y); + } + else + { + // next or prev page's corner + int savedPageNumber = getCurrentPageNumber(); + + if(forward) + next(); + else + prev(); + + if(savedPageNumber != getCurrentPageNumber()){ + if(d1 == LEFT || d2 == LEFT) + horizontalScrollBar()->setSliderPosition(horizontalScrollBar()->maximum()); + else + horizontalScrollBar()->setSliderPosition(horizontalScrollBar()->minimum()); + emit backgroundChanges(); + } + } +} + +void Viewer::scrollTo(int x, int y) +{ + if(groupScroller->state() == QAbstractAnimation::Running) + return; + horizontalScroller->setDuration(250); + horizontalScroller->setStartValue(horizontalScrollBar()->sliderPosition()); + horizontalScroller->setEndValue(x); + verticalScroller->setDuration(250); + verticalScroller->setStartValue(verticalScrollBar()->sliderPosition()); + verticalScroller->setEndValue(y); + groupScroller->start(); + emit backgroundChanges(); +} + +void Viewer::keyPressEvent(QKeyEvent *event) +{ + if(render->hasLoadedComic()) + { + int _key = event->key(); + Qt::KeyboardModifiers modifiers = event->modifiers(); + + if(modifiers & Qt::ShiftModifier) + _key |= Qt::SHIFT; + if (modifiers & Qt::ControlModifier) + _key |= Qt::CTRL; + if (modifiers & Qt::MetaModifier) + _key |= Qt::META; + if (modifiers & Qt::AltModifier) + _key |= Qt::ALT; + + QKeySequence key(_key); + /*if(goToFlow->isVisible() && event->key()!=Qt::Key_S) + QCoreApplication::sendEvent(goToFlow,event); + else*/ + + if (key == ShortcutsManager::getShortcutsManager().getShortcut(AUTO_SCROLL_FORWARD_ACTION_Y)) + { + posByStep = height()/numScrollSteps; + nextPos=verticalScrollBar()->sliderPosition()+static_cast((height()*0.80)); + scrollDown(); + } + + else if (key == ShortcutsManager::getShortcutsManager().getShortcut(AUTO_SCROLL_BACKWARD_ACTION_Y)) + { + posByStep = height()/numScrollSteps; + nextPos=verticalScrollBar()->sliderPosition()-static_cast((height()*0.80)); + scrollUp(); + } + + else if (key == ShortcutsManager::getShortcutsManager().getShortcut(AUTO_SCROLL_FORWARD_HORIZONTAL_FIRST_ACTION_Y)) + { + scrollForwardHorizontalFirst(); + } + + else if (key == ShortcutsManager::getShortcutsManager().getShortcut(AUTO_SCROLL_BACKWARD_HORIZONTAL_FIRST_ACTION_Y)) + { + scrollBackwardHorizontalFirst(); + } + + else if (key == ShortcutsManager::getShortcutsManager().getShortcut(AUTO_SCROLL_FORWARD_VERTICAL_FIRST_ACTION_Y)) + { + scrollForwardVerticalFirst(); + } + + else if (key == ShortcutsManager::getShortcutsManager().getShortcut(AUTO_SCROLL_BACKWARD_VERTICAL_FIRST_ACTION_Y)) + { + scrollBackwardVerticalFirst(); + } + + else if (key == ShortcutsManager::getShortcutsManager().getShortcut(MOVE_DOWN_ACTION_Y) || + key == ShortcutsManager::getShortcutsManager().getShortcut(MOVE_UP_ACTION_Y) || + key == ShortcutsManager::getShortcutsManager().getShortcut(MOVE_LEFT_ACTION_Y) || + key == ShortcutsManager::getShortcutsManager().getShortcut(MOVE_RIGHT_ACTION_Y)) + { + QAbstractScrollArea::keyPressEvent(event); + emit backgroundChanges(); + } + + else if (key == ShortcutsManager::getShortcutsManager().getShortcut(GO_TO_FIRST_PAGE_ACTION_Y)) + { + goTo(0); + } + + else if (key == ShortcutsManager::getShortcutsManager().getShortcut(GO_TO_LAST_PAGE_ACTION_Y)) + { + goTo(this->render->numPages()-1); + } + + else + QAbstractScrollArea::keyPressEvent(event); + + if(mglass->isVisible() && (key == ShortcutsManager::getShortcutsManager().getShortcut(SIZE_UP_MGLASS_ACTION_Y) || + key == ShortcutsManager::getShortcutsManager().getShortcut(SIZE_DOWN_MGLASS_ACTION_Y) || + key == ShortcutsManager::getShortcutsManager().getShortcut(ZOOM_IN_MGLASS_ACTION_Y) || + key == ShortcutsManager::getShortcutsManager().getShortcut(ZOOM_OUT_MGLASS_ACTION_Y))) + { + QCoreApplication::sendEvent(mglass,event); + } + + } + else + QAbstractScrollArea::keyPressEvent(event); +} + +void Viewer::wheelEvent(QWheelEvent * event) +{ + if(render->hasLoadedComic()) + { + if((event->delta()<0)&&(verticalScrollBar()->sliderPosition()==verticalScrollBar()->maximum())) + { + if(wheelStop) + { + if(getMovement(event) == Forward) + { + next(); + verticalScroller->stop(); + event->accept(); + wheelStop = false; + } + return; + } + else + wheelStop = true; + } + else + { + if((event->delta()>0)&&(verticalScrollBar()->sliderPosition()==verticalScrollBar()->minimum())) + { + if(wheelStop) + { + if(getMovement(event) == Backward) + { + prev(); + verticalScroller->stop(); + event->accept(); + wheelStop = false; + } + return; + } + else + wheelStop = true; + } + } + + int deltaNotFinished = 0; + if(verticalScroller->state() == QAbstractAnimation::Running) + { + deltaNotFinished = verticalScroller->startValue().toInt() - verticalScroller->endValue().toInt(); + verticalScroller->stop(); + } + + + int currentPos = verticalScrollBar()->sliderPosition(); + verticalScroller->setDuration(250); + verticalScroller->setStartValue(currentPos); + verticalScroller->setEndValue(currentPos - event->delta() - deltaNotFinished); + + verticalScroller->start(); + + //QAbstractScrollArea::wheelEvent(event); + } +} + +void Viewer::resizeEvent(QResizeEvent * event) +{ + updateContentSize(); + goToFlow->updateSize(); + goToFlow->move((width()-goToFlow->width())/2,height()-goToFlow->height()); + informationLabel->updatePosition(); + QScrollArea::resizeEvent(event); +} + +void Viewer::mouseMoveEvent(QMouseEvent * event) +{ + showCursor(); + hideCursorTimer->start(2500); + + if(magnifyingGlassShowed) + mglass->move(static_cast(event->x()-float(mglass->width())/2),static_cast(event->y()-float(mglass->height())/2)); + + if(render->hasLoadedComic()) + { + if(showGoToFlowAnimation->state()!=QPropertyAnimation::Running) + { + if(Configuration::getConfiguration().getDisableShowOnMouseOver() == false) + { + if(goToFlow->isVisible()) + { + QPoint gtfPos = goToFlow->mapFrom(this,event->pos()); + if(gtfPos.y() < 0 || gtfPos.x()<0 || gtfPos.x()>goToFlow->width())//TODO this extra check is for Mavericks (mouseMove over goToFlowGL seems to be broken) + animateHideGoToFlow(); + //goToFlow->hide(); + } + else + { + int umbral = (width()-goToFlow->width())/2; + if((event->y()>height()-15)&&(event->x()>umbral)&&(event->x()stop(); + } + } + } + } + + if(drag) + { + int currentPosY = verticalScrollBar()->sliderPosition(); + int currentPosX = horizontalScrollBar()->sliderPosition(); + verticalScrollBar()->setSliderPosition(currentPosY=currentPosY+(yDragOrigin-event->y())); + horizontalScrollBar()->setSliderPosition(currentPosX=currentPosX+(xDragOrigin-event->x())); + yDragOrigin = event->y(); + xDragOrigin = event->x(); + } + } + + +} + +const QPixmap * Viewer::pixmap() +{ + return content->pixmap(); +} + +void Viewer::magnifyingGlassSwitch() +{ + magnifyingGlassShowed?hideMagnifyingGlass():showMagnifyingGlass(); +} + +void Viewer::showMagnifyingGlass() +{ + if(render->hasLoadedComic()) + { + QPoint p = QPoint(cursor().pos().x(),cursor().pos().y()); + p = this->parentWidget()->mapFromGlobal(p); + mglass->move(static_cast(p.x()-float(mglass->width())/2) + ,static_cast(p.y()-float(mglass->height())/2)); + mglass->show(); + mglass->updateImage(mglass->x()+mglass->width()/2,mglass->y()+mglass->height()/2); + magnifyingGlassShowed = true; + } +} + +void Viewer::hideMagnifyingGlass() +{ + mglass->hide(); + magnifyingGlassShowed = false; +} + +void Viewer::informationSwitch() +{ + information?informationLabel->hide():informationLabel->show(); + //informationLabel->move(QPoint((width()-informationLabel->width())/2,0)); + information=!information; + Configuration::getConfiguration().setShowInformation(information); + //TODO it shouldn't be neccesary + informationLabel->adjustSize(); + informationLabel->update(); +} + +void Viewer::updateInformation() +{ + if(render->hasLoadedComic()) + { + informationLabel->setText(render->getCurrentPagesInformation()+" - "+QTime::currentTime().toString("HH:mm")); + informationLabel->adjustSize(); + informationLabel->update(); //TODO it shouldn't be neccesary + } +} + +void Viewer::goToFlowSwitch() +{ + goToFlow->isVisible()?animateHideGoToFlow():showGoToFlow(); +} + +void Viewer::translatorSwitch() +{ + translator->isVisible()?animateHideTranslator():animateShowTranslator(); +} + +void Viewer::showGoToFlow() +{ + if(render->hasLoadedComic()) + { + animateShowGoToFlow(); + } +} + +void Viewer::animateShowGoToFlow() +{ + if(goToFlow->isHidden() && showGoToFlowAnimation->state()!=QPropertyAnimation::Running) + { + disconnect(showGoToFlowAnimation,SIGNAL(finished()),goToFlow,SLOT(hide())); + connect(showGoToFlowAnimation,SIGNAL(finished()),this,SLOT(moveCursoToGoToFlow())); + showGoToFlowAnimation->setStartValue(QPoint((width()-goToFlow->width())/2,height()-10)); + showGoToFlowAnimation->setEndValue(QPoint((width()-goToFlow->width())/2,height()-goToFlow->height())); + showGoToFlowAnimation->start(); + goToFlow->centerSlide(render->getIndex()); + goToFlow->setPageNumber(render->getIndex()); + goToFlow->show(); + goToFlow->setFocus(Qt::OtherFocusReason); + } +} + +void Viewer::animateHideGoToFlow() +{ + if(goToFlow->isVisible() && showGoToFlowAnimation->state()!=QPropertyAnimation::Running) + { + connect(showGoToFlowAnimation,SIGNAL(finished()),goToFlow,SLOT(hide())); + disconnect(showGoToFlowAnimation,SIGNAL(finished()),this,SLOT(moveCursoToGoToFlow())); + showGoToFlowAnimation->setStartValue(QPoint((width()-goToFlow->width())/2,height()-goToFlow->height())); + showGoToFlowAnimation->setEndValue(QPoint((width()-goToFlow->width())/2,height())); + showGoToFlowAnimation->start(); + goToFlow->centerSlide(render->getIndex()); + goToFlow->setPageNumber(render->getIndex()); + this->setFocus(Qt::OtherFocusReason); + } +} + +void Viewer::moveCursoToGoToFlow() +{ + if(Configuration::getConfiguration().getDisableShowOnMouseOver()) + { + return; + } + + //Move cursor to goToFlow widget on show (this avoid hide when mouse is moved) + int y = goToFlow->pos().y(); + int x1 = goToFlow->pos().x(); + int x2 = x1 + goToFlow->width(); + QPoint cursorPos = mapFromGlobal(cursor().pos()); + int cursorX = cursorPos.x(); + int cursorY = cursorPos.y(); + + if(cursorY <= y) + cursorY = y + 10; + if(cursorX <= x1) + cursorX = x1 + 10; + if(cursorX >= x2) + cursorX = x2 - 10; + cursor().setPos(mapToGlobal(QPoint(cursorX,cursorY))); + hideCursorTimer->stop(); + showCursor(); +} + +void Viewer::rotateLeft() +{ + render->rotateLeft(); +} +void Viewer::rotateRight() +{ + render->rotateRight(); +} + +//TODO +void Viewer::setBookmark(bool set) +{ + render->setBookmark(); + if(set) //add bookmark + { + render->setBookmark(); + } + else //remove bookmark + { + render->removeBookmark(); + } +} + +void Viewer::save () +{ + if(render->hasLoadedComic()) + render->save(); +} + +void Viewer::doublePageSwitch() +{ + doublePage = !doublePage; + render->doublePageSwitch(); + Configuration::getConfiguration().setDoublePage(doublePage); +} + +void Viewer::doubleMangaPageSwitch() +{ + doubleMangaPage = !doubleMangaPage; + render->doubleMangaPageSwitch(); + Configuration &config = Configuration::getConfiguration(); + config.setDoubleMangaPage(doubleMangaPage); + goToFlow->setFlowRightToLeft(doubleMangaPage); + goToFlow->updateConfig(config.getSettings()); +} + +void Viewer::resetContent() +{ + configureContent(tr("Press 'O' to open comic.")); + goToFlow->reset(); + emit reset(); +} + +void Viewer::setLoadingMessage() +{ + if(magnifyingGlassShowed) + { + hideMagnifyingGlass(); + restoreMagnifyingGlass = true; + } + emit(pageAvailable(false)); + configureContent(tr("Loading...please wait!")); +} + +void Viewer::setPageUnavailableMessage() +{ + if(magnifyingGlassShowed) + { + hideMagnifyingGlass(); + restoreMagnifyingGlass = true; + } + emit(pageAvailable(false)); + configureContent(tr("Page not available!")); +} + +void Viewer::configureContent(QString msg) +{ + content->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Ignored); + if(!(devicePixelRatio()>1)) + content->setScaledContents(true); + content->setAlignment(Qt::AlignTop|Qt::AlignHCenter); + content->setText(msg); + content->setFont(QFont("courier new", 12)); + content->adjustSize(); + setFocus(Qt::ShortcutFocusReason); + //emit showingText(); +} + +void Viewer::hideCursor() +{ +#ifdef Q_OS_MAC + setCursor(QCursor(QBitmap(1,1),QBitmap(1,1))); +#else + setCursor(Qt::BlankCursor); +#endif +} +void Viewer::showCursor() +{ + if(drag) + setCursor(Qt::ClosedHandCursor); + else + setCursor(Qt::OpenHandCursor); +} + +void Viewer::updateOptions() +{ + + goToFlow->setFlowType(Configuration::getConfiguration().getFlowType()); + updateBackgroundColor(Configuration::getConfiguration().getBackgroundColor()); + updateContentSize(); +} + +void Viewer::updateBackgroundColor(const QColor & color) +{ + QPalette palette; + palette.setColor(backgroundRole(), color); + setPalette(palette); +} + +void Viewer::animateShowTranslator() +{ + if(translator->isHidden() && translatorAnimation->state()!=QPropertyAnimation::Running) + { + disconnect(translatorAnimation,SIGNAL(finished()),translator,SLOT(hide())); + if(translatorXPos == -10000) + translatorXPos = (width()-translator->width())/2; + int x = qMax(0,qMin(translatorXPos,width()-translator->width())); + if(translator->pos().x()<0) + { + translatorAnimation->setStartValue(QPoint(-translator->width(),translator->pos().y())); + } + else + { + translatorAnimation->setStartValue(QPoint(width()+translator->width(),translator->pos().y())); + } + translatorAnimation->setEndValue(QPoint(x,translator->pos().y())); + translatorAnimation->start(); + translator->show(); + translator->setFocus(Qt::OtherFocusReason); + } +} +void Viewer::animateHideTranslator() +{ + if(translator->isVisible() && translatorAnimation->state()!=QPropertyAnimation::Running) + { + connect(translatorAnimation,SIGNAL(finished()),translator,SLOT(hide())); + translatorAnimation->setStartValue(QPoint(translatorXPos = translator->pos().x(),translator->pos().y())); + if((translator->width()/2)+translator->pos().x() <= width()/2) + translatorAnimation->setEndValue(QPoint(-translator->width(),translator->pos().y())); + else + translatorAnimation->setEndValue(QPoint(width()+translator->width(),translator->pos().y())); + translatorAnimation->start(); + this->setFocus(Qt::OtherFocusReason); + } +} + +void Viewer::mousePressEvent ( QMouseEvent * event ) +{ + if (event->button() == Qt::LeftButton) + { + drag = true; + yDragOrigin = event->y(); + xDragOrigin = event->x(); + setCursor(Qt::ClosedHandCursor); + event->accept(); + } +} + +void Viewer::mouseReleaseEvent ( QMouseEvent * event ) +{ + drag = false; + setCursor(Qt::OpenHandCursor); + event->accept(); +} + +void Viewer::updateZoomRatio(int ratio) +{ + zoom = ratio; + updateContentSize(); +} + +void Viewer::updateConfig(QSettings * settings) +{ + goToFlow->updateConfig(settings); + + QPalette palette; + palette.setColor(backgroundRole(), Configuration::getConfiguration().getBackgroundColor()); + setPalette(palette); +} + +//deprecated +void Viewer::updateImageOptions() +{ + render->reload(); +} + +void Viewer::updateFilters(int brightness, int contrast,int gamma) +{ + render->updateFilters(brightness,contrast,gamma); +} + +void Viewer::setBookmarks() +{ + bd->setBookmarks(*render->getBookmarks()); +} + +void Viewer::showIsCoverMessage() +{ + if(!shouldOpenPrevious) + { + notificationsLabel->setText(tr("Cover!")); + notificationsLabel->flash(); + shouldOpenPrevious = true; + } + else + { + shouldOpenPrevious = false; + emit (openPreviousComic()); + } + + shouldOpenNext = false; //single page comic +} + +void Viewer::showIsLastMessage() +{ + if(!shouldOpenNext) + { + notificationsLabel->setText(tr("Last page!")); + notificationsLabel->flash(); + shouldOpenNext = true; + } + else + { + shouldOpenNext = false; + emit (openNextComic()); + } + + shouldOpenPrevious = false; //single page comic +} + +unsigned int Viewer::getIndex() +{ + return render->getIndex()+1; +} + +int Viewer::getCurrentPageNumber() +{ + return render->getIndex(); +} + +void Viewer::updateComic(ComicDB & comic) +{ + if(render->hasLoadedComic()) + { + //set currentPage + if(!doublePage || (doublePage && render->currentPageIsDoublePage() == false)) + { + comic.info.currentPage = render->getIndex()+1; + } + else + { + comic.info.currentPage = std::min(render->numPages(), render->getIndex()+2); + } + //set bookmarks + Bookmarks * boomarks = render->getBookmarks(); + QList boomarksList = boomarks->getBookmarkPages(); + int numBookmarks = boomarksList.size(); + if(numBookmarks > 0) + comic.info.bookmark1 = boomarksList[0]; + if(numBookmarks > 1) + comic.info.bookmark2 = boomarksList[1]; + if(numBookmarks > 2) + comic.info.bookmark3 = boomarksList[2]; + //set filters + //TODO: avoid use settings for this... + QSettings settings(YACReader::getSettingsPath()+"/YACReader.ini",QSettings::IniFormat); + int brightness = settings.value(BRIGHTNESS,0).toInt(); + int contrast = settings.value(CONTRAST,100).toInt(); + int gamma = settings.value(GAMMA,100).toInt(); + + if(brightness != 0 || comic.info.brightness!=-1) + comic.info.brightness = brightness; + if(contrast != 100 || comic.info.contrast!=-1) + comic.info.contrast = contrast; + if(gamma != 100 || comic.info.gamma!=-1) + comic.info.gamma = gamma; + } + + +} diff --git a/YACReader/viewer.h b/YACReader/viewer.h index e22bfb93..a6bd315b 100644 --- a/YACReader/viewer.h +++ b/YACReader/viewer.h @@ -1,189 +1,189 @@ -#ifndef __VIEWER_H -#define __VIEWER_H - -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "scroll_management.h" - -class ComicDB; -class Comic; -class MagnifyingGlass; -class GoToFlow; -class BookmarksDialog; -class Render; -class GoToDialog; -class YACReaderTranslator; -class GoToFlowWidget; -class Bookmarks; -class PageLabelWidget; -class NotificationsLabelWidget; - - class Viewer : public QScrollArea, public ScrollManagement - { - Q_OBJECT - public: - bool fullscreen; //TODO, change by the right use of windowState(); - public slots: - void increaseZoomFactor(); - void decreaseZoomFactor(); - void setZoomFactor(int); - int getZoomFactor(); - - void prepareForOpening(); - void open(QString pathFile, int atPage = -1); - void open(QString pathFile, const ComicDB & comic); - void prev(); - void next(); - void showGoToDialog(); - void goTo(unsigned int page); - void updatePage(); - void updateContentSize(); - void updateVerticalScrollBar(); - void updateOptions(); - void scrollDown(); - void scrollUp(); - void scrollForwardHorizontalFirst(); - void scrollBackwardHorizontalFirst(); - void scrollForwardVerticalFirst(); - void scrollBackwardVerticalFirst(); - void magnifyingGlassSwitch(); - void showMagnifyingGlass(); - void hideMagnifyingGlass(); - void informationSwitch(); - void updateInformation(); - void goToFlowSwitch(); - void showGoToFlow(); - void moveCursoToGoToFlow(); - void animateShowGoToFlow(); - void animateHideGoToFlow(); - void rotateLeft(); - void rotateRight(); - bool magnifyingGlassIsVisible() {return magnifyingGlassShowed;} - void setBookmark(bool); - void save(); - void doublePageSwitch(); - void doubleMangaPageSwitch(); - void resetContent(); - void setLoadingMessage(); - void setPageUnavailableMessage(); - void configureContent(QString msg); - void hideCursor(); - void showCursor(); - void createConnections(); - void translatorSwitch(); - void animateShowTranslator(); - void animateHideTranslator(); -virtual void mousePressEvent ( QMouseEvent * event ); -virtual void mouseReleaseEvent ( QMouseEvent * event ); - void updateBackgroundColor(const QColor & color); - void updateConfig(QSettings * settings); - void showMessageErrorOpening(); - void showMessageErrorOpening(QString); - void processCRCError(QString message); - void setBookmarks(); - //deprecated - void updateImageOptions(); - void updateFilters(int brightness, int contrast,int gamma); - void showIsCoverMessage(); - void showIsLastMessage(); - int getCurrentPageNumber(); - void updateZoomRatio(int ratio); - - private: - bool information; - bool doublePage; - bool doubleMangaPage; - - int zoom; - - PageLabelWidget * informationLabel; - //QTimer * scroller; - QPropertyAnimation * verticalScroller; - QPropertyAnimation * horizontalScroller; - QParallelAnimationGroup * groupScroller; - int posByStep; - int nextPos; - GoToFlowWidget * goToFlow; - QPropertyAnimation * showGoToFlowAnimation; - GoToDialog * goToDialog; - //!Image properties - //! Comic - //Comic * comic; - int index; - QPixmap *currentPage; - BookmarksDialog * bd; - bool wheelStop; - Render * render; - QTimer * hideCursorTimer; - int direction; - bool drag; - int numScrollSteps; - - //!Widgets - QLabel *content; - - YACReaderTranslator * translator; - int translatorXPos; - QPropertyAnimation * translatorAnimation; - - int yDragOrigin; - int xDragOrigin; - - NotificationsLabelWidget * notificationsLabel; - - bool shouldOpenNext; - bool shouldOpenPrevious; - - private: - //!Magnifying glass - MagnifyingGlass *mglass; - bool magnifyingGlassShowed; - bool restoreMagnifyingGlass; - - //! Manejadores de evento: - void keyPressEvent(QKeyEvent * event); - void resizeEvent(QResizeEvent * event); - void wheelEvent(QWheelEvent * event); - void mouseMoveEvent(QMouseEvent * event); - - //!ZigzagScroll - enum scrollDirection{ UP, DOWN, LEFT, RIGHT }; - bool isEdge(scrollDirection d); - void scrollZigzag(scrollDirection d1, scrollDirection d2, bool forward); - void scrollTo(int x, int y); - - public: - Viewer(QWidget * parent = 0); - ~Viewer(); - void toggleFullScreen(); - const QPixmap * pixmap(); - //Comic * getComic(){return comic;} - const BookmarksDialog * getBookmarksDialog(){return bd;} - //returns the current index starting in 1 [1,nPages] - unsigned int getIndex(); - void updateComic(ComicDB & comic); - signals: - void backgroundChanges(); - void pageAvailable(bool); - void pageIsBookmark(bool); - void reset(); - void openNextComic(); - void openPreviousComic(); - void zoomUpdated(int); - }; - -#endif +#ifndef __VIEWER_H +#define __VIEWER_H + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "scroll_management.h" + +class ComicDB; +class Comic; +class MagnifyingGlass; +class GoToFlow; +class BookmarksDialog; +class Render; +class GoToDialog; +class YACReaderTranslator; +class GoToFlowWidget; +class Bookmarks; +class PageLabelWidget; +class NotificationsLabelWidget; + + class Viewer : public QScrollArea, public ScrollManagement + { + Q_OBJECT + public: + bool fullscreen; //TODO, change by the right use of windowState(); + public slots: + void increaseZoomFactor(); + void decreaseZoomFactor(); + void setZoomFactor(int); + int getZoomFactor(); + + void prepareForOpening(); + void open(QString pathFile, int atPage = -1); + void open(QString pathFile, const ComicDB & comic); + void prev(); + void next(); + void showGoToDialog(); + void goTo(unsigned int page); + void updatePage(); + void updateContentSize(); + void updateVerticalScrollBar(); + void updateOptions(); + void scrollDown(); + void scrollUp(); + void scrollForwardHorizontalFirst(); + void scrollBackwardHorizontalFirst(); + void scrollForwardVerticalFirst(); + void scrollBackwardVerticalFirst(); + void magnifyingGlassSwitch(); + void showMagnifyingGlass(); + void hideMagnifyingGlass(); + void informationSwitch(); + void updateInformation(); + void goToFlowSwitch(); + void showGoToFlow(); + void moveCursoToGoToFlow(); + void animateShowGoToFlow(); + void animateHideGoToFlow(); + void rotateLeft(); + void rotateRight(); + bool magnifyingGlassIsVisible() {return magnifyingGlassShowed;} + void setBookmark(bool); + void save(); + void doublePageSwitch(); + void doubleMangaPageSwitch(); + void resetContent(); + void setLoadingMessage(); + void setPageUnavailableMessage(); + void configureContent(QString msg); + void hideCursor(); + void showCursor(); + void createConnections(); + void translatorSwitch(); + void animateShowTranslator(); + void animateHideTranslator(); +virtual void mousePressEvent ( QMouseEvent * event ); +virtual void mouseReleaseEvent ( QMouseEvent * event ); + void updateBackgroundColor(const QColor & color); + void updateConfig(QSettings * settings); + void showMessageErrorOpening(); + void showMessageErrorOpening(QString); + void processCRCError(QString message); + void setBookmarks(); + //deprecated + void updateImageOptions(); + void updateFilters(int brightness, int contrast,int gamma); + void showIsCoverMessage(); + void showIsLastMessage(); + int getCurrentPageNumber(); + void updateZoomRatio(int ratio); + + private: + bool information; + bool doublePage; + bool doubleMangaPage; + + int zoom; + + PageLabelWidget * informationLabel; + //QTimer * scroller; + QPropertyAnimation * verticalScroller; + QPropertyAnimation * horizontalScroller; + QParallelAnimationGroup * groupScroller; + int posByStep; + int nextPos; + GoToFlowWidget * goToFlow; + QPropertyAnimation * showGoToFlowAnimation; + GoToDialog * goToDialog; + //!Image properties + //! Comic + //Comic * comic; + int index; + QPixmap *currentPage; + BookmarksDialog * bd; + bool wheelStop; + Render * render; + QTimer * hideCursorTimer; + int direction; + bool drag; + int numScrollSteps; + + //!Widgets + QLabel *content; + + YACReaderTranslator * translator; + int translatorXPos; + QPropertyAnimation * translatorAnimation; + + int yDragOrigin; + int xDragOrigin; + + NotificationsLabelWidget * notificationsLabel; + + bool shouldOpenNext; + bool shouldOpenPrevious; + + private: + //!Magnifying glass + MagnifyingGlass *mglass; + bool magnifyingGlassShowed; + bool restoreMagnifyingGlass; + + //! Manejadores de evento: + void keyPressEvent(QKeyEvent * event); + void resizeEvent(QResizeEvent * event); + void wheelEvent(QWheelEvent * event); + void mouseMoveEvent(QMouseEvent * event); + + //!ZigzagScroll + enum scrollDirection{ UP, DOWN, LEFT, RIGHT }; + bool isEdge(scrollDirection d); + void scrollZigzag(scrollDirection d1, scrollDirection d2, bool forward); + void scrollTo(int x, int y); + + public: + Viewer(QWidget * parent = 0); + ~Viewer(); + void toggleFullScreen(); + const QPixmap * pixmap(); + //Comic * getComic(){return comic;} + const BookmarksDialog * getBookmarksDialog(){return bd;} + //returns the current index starting in 1 [1,nPages] + unsigned int getIndex(); + void updateComic(ComicDB & comic); + signals: + void backgroundChanges(); + void pageAvailable(bool); + void pageIsBookmark(bool); + void reset(); + void openNextComic(); + void openPreviousComic(); + void zoomUpdated(int); + }; + +#endif diff --git a/YACReader/width_slider.cpp b/YACReader/width_slider.cpp index ec9c0c63..dcbd3c87 100644 --- a/YACReader/width_slider.cpp +++ b/YACReader/width_slider.cpp @@ -1,111 +1,111 @@ -#include "width_slider.h" - -#include - -#include "configuration.h" - -YACReaderSliderAction::YACReaderSliderAction (QWidget * parent) - :QWidgetAction (parent) { - - widget = new YACReaderSlider(); - setDefaultWidget(widget); - - connect(widget,SIGNAL(zoomRatioChanged(int)),this,SIGNAL(zoomRatioChanged(int))); -} - -void YACReaderSliderAction::updateText(int value) -{ - widget->updateText(value); -} - -void YACReaderSliderAction::updateZoomRatio(int value) -{ - widget->updateZoomRatio(value); -} - -YACReaderSlider::YACReaderSlider(QWidget *parent) - :QWidget(parent) -{ - const int sliderWidth = 200; - const int contentsMargin = 10; - const int elementsSpacing = 10; - const int percentageLabelWidth = 30; - - setFocusPolicy(Qt::StrongFocus); - - QHBoxLayout* pLayout = new QHBoxLayout(); - - pLayout->addStretch(); - - percentageLabel = new QLabel(); - percentageLabel->setStyleSheet("QLabel { color : white; }"); - percentageLabel->setAlignment(Qt::AlignHCenter | Qt::AlignVCenter); - slider = new QSlider(); - slider->setOrientation(Qt::Horizontal); - - slider->setMinimumWidth(sliderWidth); - - QPushButton *resetButton = new QPushButton(tr("Reset")); - resetButton->setStyleSheet("QPushButton {border: 1px solid #BB242424; background: #BB2E2E2E; color:white; padding: 3px 5px 5px 5px;}"); - connect(resetButton, &QPushButton::clicked, this, &YACReaderSlider::resetValueToDefault); - - pLayout->addWidget(percentageLabel, 1, Qt::AlignHCenter); - pLayout->addWidget(slider, 0, Qt::AlignHCenter | Qt::AlignBottom); - pLayout->addWidget(resetButton, 1, Qt::AlignHCenter | Qt::AlignBottom); - pLayout->setSpacing(elementsSpacing); - - pLayout->setMargin(0); - - setLayout (pLayout); - setAutoFillBackground(false); - - setContentsMargins(contentsMargin,contentsMargin,contentsMargin,contentsMargin); - setFixedSize(sliderWidth + 2 * contentsMargin + 2 * elementsSpacing + percentageLabelWidth + resetButton->sizeHint().width(), 45); - - slider->setMinimum(30); - slider->setMaximum(500); - slider->setPageStep(5); - - slider->setFocusPolicy(Qt::NoFocus); - resetButton->setFocusPolicy(Qt::NoFocus); - - slider->setValue(100); - percentageLabel->setText(QString("%1%").arg(100)); - connect(slider, &QSlider::valueChanged, this, &YACReaderSlider::updateText); -} - -void YACReaderSlider::paintEvent(QPaintEvent *) -{ - QPainter painter(this); - - painter.fillRect(0,0,width(),height(),QColor("#BB000000")); -} - -void YACReaderSlider::show() -{ - QWidget::show(); - setFocus(); -} - -void YACReaderSlider::focusOutEvent(QFocusEvent * event) -{ - QWidget::focusOutEvent(event); - hide(); -} - -void YACReaderSlider::updateText(int value) -{ - percentageLabel->setText(QString("%1%").arg(value)); - emit zoomRatioChanged(value); -} - -void YACReaderSlider::updateZoomRatio(int value) -{ - slider->setValue(value); - percentageLabel->setText(QString("%1%").arg(value)); -} - -void YACReaderSlider::resetValueToDefault() -{ - slider->setValue(100); -} +#include "width_slider.h" + +#include + +#include "configuration.h" + +YACReaderSliderAction::YACReaderSliderAction (QWidget * parent) + :QWidgetAction (parent) { + + widget = new YACReaderSlider(); + setDefaultWidget(widget); + + connect(widget,SIGNAL(zoomRatioChanged(int)),this,SIGNAL(zoomRatioChanged(int))); +} + +void YACReaderSliderAction::updateText(int value) +{ + widget->updateText(value); +} + +void YACReaderSliderAction::updateZoomRatio(int value) +{ + widget->updateZoomRatio(value); +} + +YACReaderSlider::YACReaderSlider(QWidget *parent) + :QWidget(parent) +{ + const int sliderWidth = 200; + const int contentsMargin = 10; + const int elementsSpacing = 10; + const int percentageLabelWidth = 30; + + setFocusPolicy(Qt::StrongFocus); + + QHBoxLayout* pLayout = new QHBoxLayout(); + + pLayout->addStretch(); + + percentageLabel = new QLabel(); + percentageLabel->setStyleSheet("QLabel { color : white; }"); + percentageLabel->setAlignment(Qt::AlignHCenter | Qt::AlignVCenter); + slider = new QSlider(); + slider->setOrientation(Qt::Horizontal); + + slider->setMinimumWidth(sliderWidth); + + QPushButton *resetButton = new QPushButton(tr("Reset")); + resetButton->setStyleSheet("QPushButton {border: 1px solid #BB242424; background: #BB2E2E2E; color:white; padding: 3px 5px 5px 5px;}"); + connect(resetButton, &QPushButton::clicked, this, &YACReaderSlider::resetValueToDefault); + + pLayout->addWidget(percentageLabel, 1, Qt::AlignHCenter); + pLayout->addWidget(slider, 0, Qt::AlignHCenter | Qt::AlignBottom); + pLayout->addWidget(resetButton, 1, Qt::AlignHCenter | Qt::AlignBottom); + pLayout->setSpacing(elementsSpacing); + + pLayout->setMargin(0); + + setLayout (pLayout); + setAutoFillBackground(false); + + setContentsMargins(contentsMargin,contentsMargin,contentsMargin,contentsMargin); + setFixedSize(sliderWidth + 2 * contentsMargin + 2 * elementsSpacing + percentageLabelWidth + resetButton->sizeHint().width(), 45); + + slider->setMinimum(30); + slider->setMaximum(500); + slider->setPageStep(5); + + slider->setFocusPolicy(Qt::NoFocus); + resetButton->setFocusPolicy(Qt::NoFocus); + + slider->setValue(100); + percentageLabel->setText(QString("%1%").arg(100)); + connect(slider, &QSlider::valueChanged, this, &YACReaderSlider::updateText); +} + +void YACReaderSlider::paintEvent(QPaintEvent *) +{ + QPainter painter(this); + + painter.fillRect(0,0,width(),height(),QColor("#BB000000")); +} + +void YACReaderSlider::show() +{ + QWidget::show(); + setFocus(); +} + +void YACReaderSlider::focusOutEvent(QFocusEvent * event) +{ + QWidget::focusOutEvent(event); + hide(); +} + +void YACReaderSlider::updateText(int value) +{ + percentageLabel->setText(QString("%1%").arg(value)); + emit zoomRatioChanged(value); +} + +void YACReaderSlider::updateZoomRatio(int value) +{ + slider->setValue(value); + percentageLabel->setText(QString("%1%").arg(value)); +} + +void YACReaderSlider::resetValueToDefault() +{ + slider->setValue(100); +} diff --git a/YACReader/width_slider.h b/YACReader/width_slider.h index 2ac4deeb..7eed67b6 100644 --- a/YACReader/width_slider.h +++ b/YACReader/width_slider.h @@ -1,53 +1,53 @@ -#ifndef WIDTH_SLIDER_H -#define WIDTH_SLIDER_H - -#include - -class QLabel; -class QSlider; - -class YACReaderSlider : public QWidget -{ - Q_OBJECT -private: - QLabel * percentageLabel; - QSlider * slider; - -public: - YACReaderSlider (QWidget * parent = 0); - void show(); - -protected: - virtual void focusOutEvent(QFocusEvent * event); - virtual void paintEvent(QPaintEvent *); - -public slots: - void updateText(int value); - void updateZoomRatio(int value); - void resetValueToDefault(); - - -signals: - void zoomRatioChanged(int value); -}; - -class YACReaderSliderAction : public QWidgetAction -{ - Q_OBJECT -private: - YACReaderSlider * widget; - -public: - - YACReaderSliderAction (QWidget * parent = 0); - -public slots: - void updateText(int value); - void updateZoomRatio(int value); - - -signals: - void zoomRatioChanged(int value); -}; - -#endif +#ifndef WIDTH_SLIDER_H +#define WIDTH_SLIDER_H + +#include + +class QLabel; +class QSlider; + +class YACReaderSlider : public QWidget +{ + Q_OBJECT +private: + QLabel * percentageLabel; + QSlider * slider; + +public: + YACReaderSlider (QWidget * parent = 0); + void show(); + +protected: + virtual void focusOutEvent(QFocusEvent * event); + virtual void paintEvent(QPaintEvent *); + +public slots: + void updateText(int value); + void updateZoomRatio(int value); + void resetValueToDefault(); + + +signals: + void zoomRatioChanged(int value); +}; + +class YACReaderSliderAction : public QWidgetAction +{ + Q_OBJECT +private: + YACReaderSlider * widget; + +public: + + YACReaderSliderAction (QWidget * parent = 0); + +public slots: + void updateText(int value); + void updateZoomRatio(int value); + + +signals: + void zoomRatioChanged(int value); +}; + +#endif diff --git a/YACReader/yacreader_local_client.cpp b/YACReader/yacreader_local_client.cpp index 85b235fb..23ca326d 100644 --- a/YACReader/yacreader_local_client.cpp +++ b/YACReader/yacreader_local_client.cpp @@ -1,216 +1,216 @@ -#include "yacreader_local_client.h" -#include "comic_db.h" -#include "yacreader_global.h" - -#include - -#include "QsLog.h" - -using namespace YACReader; - -YACReaderLocalClient::YACReaderLocalClient(QObject *parent) : - QObject(parent) -{ - localSocket = new QLocalSocket(this); - - //connect(localSocket, SIGNAL(readyRead()), this, SLOT(readMessage())); - - /*connect(socket, SIGNAL(error(QLocalSocket::LocalSocketError)), - this, SLOT(displayError(QLocalSocket::LocalSocketError)));*/ -} -YACReaderLocalClient::~YACReaderLocalClient() -{ - delete localSocket; -} -//información de comic recibida... -void YACReaderLocalClient::readMessage() -{ - -} -#include - -bool YACReaderLocalClient::requestComicInfo(quint64 libraryId, ComicDB & comic, QList & siblings) -{ - localSocket->connectToServer(YACREADERLIBRARY_GUID); - if(localSocket->isOpen()) - { - QByteArray block; - QDataStream out(&block, QIODevice::WriteOnly); - out.setVersion(QDataStream::Qt_4_8); - out << (quint32)0; - out << (quint8)YACReader::RequestComicInfo; - out << libraryId; - out << comic; - out.device()->seek(0); - out << (quint32)(block.size() - sizeof(quint32)); - - int written = 0; - int previousWritten = 0; - quint16 tries = 0; - while(written != block.size() && tries < 200) - { - written += localSocket->write(block); - localSocket->flush(); - if(written == previousWritten) //no bytes were written - tries++; - previousWritten = written; - } - if(tries == 200) - { - localSocket->close(); - QLOG_ERROR() << "Requesting Comic Info : unable to send request"; - return false; - } - - localSocket->waitForBytesWritten(2000); - - //QByteArray data; - tries = 0; - int dataAvailable = 0; - QByteArray packageSize; - localSocket->waitForReadyRead(1000); - while(packageSize.size() < sizeof(quint32) && tries < 20) - { - packageSize.append(localSocket->read(sizeof(quint32) - packageSize.size())); - localSocket->waitForReadyRead(100); - if(dataAvailable == packageSize.size()) - { - tries++; //TODO apply 'tries' fix - } - dataAvailable = packageSize.size(); - } - if(tries == 20) - { - localSocket->close(); - QLOG_ERROR() << "Requesting Comic Info : unable to read package size"; - return false; - } - QDataStream sizeStream(packageSize);//localSocket->read(sizeof(quint32))); - sizeStream.setVersion(QDataStream::Qt_4_8); - quint32 totalSize = 0; - sizeStream >> totalSize; - - QByteArray data; - - tries = 0; - int dataRead = 0; - localSocket->waitForReadyRead(1000); - while((unsigned int)data.length() < totalSize && tries < 20 ) - { - data.append(localSocket->readAll()); - if((unsigned int)data.length() < totalSize) - localSocket->waitForReadyRead(100); - if(data.length() == dataRead) - tries++; - dataRead = data.length(); - } - - if(tries == 20) - { - localSocket->close(); - QLOG_ERROR() << "Requesting Comic Info : unable to read data (" << data.length() << "," << totalSize << ")"; - return false; - } - - QDataStream dataStream(data); - dataStream >> comic; - dataStream >> siblings; - localSocket->close(); - return true; - } - else - { - QLOG_ERROR() << "Requesting Comic Info : unable to connect to the server"; - return false; - } -} - - -bool YACReaderLocalClient::sendComicInfo(quint64 libraryId, ComicDB & comic) -{ - localSocket->connectToServer(YACREADERLIBRARY_GUID); - if(localSocket->isOpen()) - { - //QLOG_INFO() << "Connection opened for sending ComicInfo"; - QByteArray block; - QDataStream out(&block, QIODevice::WriteOnly); - out.setVersion(QDataStream::Qt_4_8); - out << (quint32)0; - out << (quint8)YACReader::SendComicInfo; - out << libraryId; - out << comic; - out.device()->seek(0); - out << (quint32)(block.size() - sizeof(quint32)); - - int written, previousWritten; - written = previousWritten = 0; - int tries = 0; - while(written != block.size() && tries < 100) - { - written += localSocket->write(block); - if(written == previousWritten) - tries++; - previousWritten = written; - } - localSocket->waitForBytesWritten(2000); - localSocket->close(); - //QLOG_INFO() << QString("Sending Comic Info : writen data (%1,%2)").arg(written).arg(block.size()); - if(tries == 100 && written != block.size()) - { - emit finished(); - QLOG_ERROR() << QString("Sending Comic Info : unable to write data (%1,%2)").arg(written).arg(block.size()); - return false; - } - emit finished(); - return true; - } - - emit finished(); - QLOG_ERROR() << "Sending Comic Info : unable to connect to the server"; - return false; -} - -bool YACReaderLocalClient::sendComicInfo(quint64 libraryId, ComicDB & comic, qulonglong nextComicId) -{ - localSocket->connectToServer(YACREADERLIBRARY_GUID); - if(localSocket->isOpen()) - { - //QLOG_INFO() << "Connection opened for sending ComicInfo"; - QByteArray block; - QDataStream out(&block, QIODevice::WriteOnly); - out.setVersion(QDataStream::Qt_4_8); - out << (quint32)0; - out << (quint8)YACReader::SendComicInfo; - out << libraryId; - out << comic; - out << nextComicId; - out.device()->seek(0); - out << (quint32)(block.size() - sizeof(quint32)); - - int written, previousWritten; - written = previousWritten = 0; - int tries = 0; - while(written != block.size() && tries < 100) - { - written += localSocket->write(block); - if(written == previousWritten) - tries++; - previousWritten = written; - } - localSocket->waitForBytesWritten(2000); - localSocket->close(); - //QLOG_INFO() << QString("Sending Comic Info : writen data (%1,%2)").arg(written).arg(block.size()); - if(tries == 100 && written != block.size()) - { - emit finished(); - QLOG_ERROR() << QString("Sending Comic Info : unable to write data (%1,%2)").arg(written).arg(block.size()); - return false; - } - emit finished(); - return true; - } - - emit finished(); - QLOG_ERROR() << "Sending Comic Info : unable to connect to the server"; - return false; -} +#include "yacreader_local_client.h" +#include "comic_db.h" +#include "yacreader_global.h" + +#include + +#include "QsLog.h" + +using namespace YACReader; + +YACReaderLocalClient::YACReaderLocalClient(QObject *parent) : + QObject(parent) +{ + localSocket = new QLocalSocket(this); + + //connect(localSocket, SIGNAL(readyRead()), this, SLOT(readMessage())); + + /*connect(socket, SIGNAL(error(QLocalSocket::LocalSocketError)), + this, SLOT(displayError(QLocalSocket::LocalSocketError)));*/ +} +YACReaderLocalClient::~YACReaderLocalClient() +{ + delete localSocket; +} +//información de comic recibida... +void YACReaderLocalClient::readMessage() +{ + +} +#include + +bool YACReaderLocalClient::requestComicInfo(quint64 libraryId, ComicDB & comic, QList & siblings) +{ + localSocket->connectToServer(YACREADERLIBRARY_GUID); + if(localSocket->isOpen()) + { + QByteArray block; + QDataStream out(&block, QIODevice::WriteOnly); + out.setVersion(QDataStream::Qt_4_8); + out << (quint32)0; + out << (quint8)YACReader::RequestComicInfo; + out << libraryId; + out << comic; + out.device()->seek(0); + out << (quint32)(block.size() - sizeof(quint32)); + + int written = 0; + int previousWritten = 0; + quint16 tries = 0; + while(written != block.size() && tries < 200) + { + written += localSocket->write(block); + localSocket->flush(); + if(written == previousWritten) //no bytes were written + tries++; + previousWritten = written; + } + if(tries == 200) + { + localSocket->close(); + QLOG_ERROR() << "Requesting Comic Info : unable to send request"; + return false; + } + + localSocket->waitForBytesWritten(2000); + + //QByteArray data; + tries = 0; + int dataAvailable = 0; + QByteArray packageSize; + localSocket->waitForReadyRead(1000); + while(packageSize.size() < sizeof(quint32) && tries < 20) + { + packageSize.append(localSocket->read(sizeof(quint32) - packageSize.size())); + localSocket->waitForReadyRead(100); + if(dataAvailable == packageSize.size()) + { + tries++; //TODO apply 'tries' fix + } + dataAvailable = packageSize.size(); + } + if(tries == 20) + { + localSocket->close(); + QLOG_ERROR() << "Requesting Comic Info : unable to read package size"; + return false; + } + QDataStream sizeStream(packageSize);//localSocket->read(sizeof(quint32))); + sizeStream.setVersion(QDataStream::Qt_4_8); + quint32 totalSize = 0; + sizeStream >> totalSize; + + QByteArray data; + + tries = 0; + int dataRead = 0; + localSocket->waitForReadyRead(1000); + while((unsigned int)data.length() < totalSize && tries < 20 ) + { + data.append(localSocket->readAll()); + if((unsigned int)data.length() < totalSize) + localSocket->waitForReadyRead(100); + if(data.length() == dataRead) + tries++; + dataRead = data.length(); + } + + if(tries == 20) + { + localSocket->close(); + QLOG_ERROR() << "Requesting Comic Info : unable to read data (" << data.length() << "," << totalSize << ")"; + return false; + } + + QDataStream dataStream(data); + dataStream >> comic; + dataStream >> siblings; + localSocket->close(); + return true; + } + else + { + QLOG_ERROR() << "Requesting Comic Info : unable to connect to the server"; + return false; + } +} + + +bool YACReaderLocalClient::sendComicInfo(quint64 libraryId, ComicDB & comic) +{ + localSocket->connectToServer(YACREADERLIBRARY_GUID); + if(localSocket->isOpen()) + { + //QLOG_INFO() << "Connection opened for sending ComicInfo"; + QByteArray block; + QDataStream out(&block, QIODevice::WriteOnly); + out.setVersion(QDataStream::Qt_4_8); + out << (quint32)0; + out << (quint8)YACReader::SendComicInfo; + out << libraryId; + out << comic; + out.device()->seek(0); + out << (quint32)(block.size() - sizeof(quint32)); + + int written, previousWritten; + written = previousWritten = 0; + int tries = 0; + while(written != block.size() && tries < 100) + { + written += localSocket->write(block); + if(written == previousWritten) + tries++; + previousWritten = written; + } + localSocket->waitForBytesWritten(2000); + localSocket->close(); + //QLOG_INFO() << QString("Sending Comic Info : writen data (%1,%2)").arg(written).arg(block.size()); + if(tries == 100 && written != block.size()) + { + emit finished(); + QLOG_ERROR() << QString("Sending Comic Info : unable to write data (%1,%2)").arg(written).arg(block.size()); + return false; + } + emit finished(); + return true; + } + + emit finished(); + QLOG_ERROR() << "Sending Comic Info : unable to connect to the server"; + return false; +} + +bool YACReaderLocalClient::sendComicInfo(quint64 libraryId, ComicDB & comic, qulonglong nextComicId) +{ + localSocket->connectToServer(YACREADERLIBRARY_GUID); + if(localSocket->isOpen()) + { + //QLOG_INFO() << "Connection opened for sending ComicInfo"; + QByteArray block; + QDataStream out(&block, QIODevice::WriteOnly); + out.setVersion(QDataStream::Qt_4_8); + out << (quint32)0; + out << (quint8)YACReader::SendComicInfo; + out << libraryId; + out << comic; + out << nextComicId; + out.device()->seek(0); + out << (quint32)(block.size() - sizeof(quint32)); + + int written, previousWritten; + written = previousWritten = 0; + int tries = 0; + while(written != block.size() && tries < 100) + { + written += localSocket->write(block); + if(written == previousWritten) + tries++; + previousWritten = written; + } + localSocket->waitForBytesWritten(2000); + localSocket->close(); + //QLOG_INFO() << QString("Sending Comic Info : writen data (%1,%2)").arg(written).arg(block.size()); + if(tries == 100 && written != block.size()) + { + emit finished(); + QLOG_ERROR() << QString("Sending Comic Info : unable to write data (%1,%2)").arg(written).arg(block.size()); + return false; + } + emit finished(); + return true; + } + + emit finished(); + QLOG_ERROR() << "Sending Comic Info : unable to connect to the server"; + return false; +} diff --git a/YACReader/yacreader_local_client.h b/YACReader/yacreader_local_client.h index 2f08825b..840c1047 100644 --- a/YACReader/yacreader_local_client.h +++ b/YACReader/yacreader_local_client.h @@ -1,29 +1,29 @@ -#ifndef YACREADER_LOCAL_CLIENT_H -#define YACREADER_LOCAL_CLIENT_H - -#include - -class QLocalSocket; -class ComicDB; - -class YACReaderLocalClient : public QObject -{ - Q_OBJECT -public: - explicit YACReaderLocalClient(QObject *parent = 0); - ~YACReaderLocalClient(); -signals: - void finished(); -public slots: - void readMessage(); - bool requestComicInfo(quint64 libraryId, ComicDB & comic,QList & siblings); - bool sendComicInfo(quint64 libraryId, ComicDB & comic); - bool sendComicInfo(quint64 libraryId, ComicDB & comic, qulonglong nextComicId); - - -private: - QLocalSocket * localSocket; - -}; - -#endif // YACREADER_LOCAL_CLIENT_H +#ifndef YACREADER_LOCAL_CLIENT_H +#define YACREADER_LOCAL_CLIENT_H + +#include + +class QLocalSocket; +class ComicDB; + +class YACReaderLocalClient : public QObject +{ + Q_OBJECT +public: + explicit YACReaderLocalClient(QObject *parent = 0); + ~YACReaderLocalClient(); +signals: + void finished(); +public slots: + void readMessage(); + bool requestComicInfo(quint64 libraryId, ComicDB & comic,QList & siblings); + bool sendComicInfo(quint64 libraryId, ComicDB & comic); + bool sendComicInfo(quint64 libraryId, ComicDB & comic, qulonglong nextComicId); + + +private: + QLocalSocket * localSocket; + +}; + +#endif // YACREADER_LOCAL_CLIENT_H diff --git a/YACReaderLibrary/add_label_dialog.cpp b/YACReaderLibrary/add_label_dialog.cpp index 6d9d73b7..f1b91fb0 100644 --- a/YACReaderLibrary/add_label_dialog.cpp +++ b/YACReaderLibrary/add_label_dialog.cpp @@ -1,84 +1,84 @@ -#include "add_label_dialog.h" - -AddLabelDialog::AddLabelDialog(QWidget *parent) : - QDialog(parent) -{ - QVBoxLayout * layout = new QVBoxLayout; - - layout->addWidget(new QLabel(tr("Label name:"))); - layout->addWidget(edit = new QLineEdit()); - - 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"))); - - QColor backgroundColor = this->palette().background().color(); - list->setStyleSheet(QString("QListWidget {border : none; background-color: rgb(%1,%2,%3);}").arg(backgroundColor.red()).arg(backgroundColor.green()).arg(backgroundColor.blue())); - list->setMinimumHeight(225); - - setModal(true); - - setMinimumHeight(340); - - //buttons - acceptButton = new QPushButton(tr("accept"),this); - cancelButton = new QPushButton(tr("cancel"),this); - - QHBoxLayout * buttons = new QHBoxLayout; - buttons->addStretch(); - buttons->addWidget(acceptButton); - buttons->addWidget(cancelButton); - - layout->addStretch(); - layout->addLayout(buttons); - - setLayout(layout); - - //connections - connect(edit,SIGNAL(textChanged(QString)),this,SLOT(validateName(QString))); - connect(cancelButton,SIGNAL(clicked()),this,SLOT(close())); - connect(acceptButton,SIGNAL(clicked()),this,SLOT(accept())); - -} - -YACReader::LabelColors AddLabelDialog::selectedColor() -{ - return YACReader::LabelColors(list->currentRow()+1); -} - -QString AddLabelDialog::name() -{ - return edit->text(); -} - -int AddLabelDialog::exec() -{ - edit->clear(); - list->clearSelection(); - - acceptButton->setDisabled(true); - - list->setCurrentRow(0); - - return QDialog::exec(); -} - -void AddLabelDialog::validateName(const QString &name) -{ - if(name.isEmpty()) - acceptButton->setDisabled(true); - else - acceptButton->setEnabled(true); -} +#include "add_label_dialog.h" + +AddLabelDialog::AddLabelDialog(QWidget *parent) : + QDialog(parent) +{ + QVBoxLayout * layout = new QVBoxLayout; + + layout->addWidget(new QLabel(tr("Label name:"))); + layout->addWidget(edit = new QLineEdit()); + + 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"))); + + QColor backgroundColor = this->palette().background().color(); + list->setStyleSheet(QString("QListWidget {border : none; background-color: rgb(%1,%2,%3);}").arg(backgroundColor.red()).arg(backgroundColor.green()).arg(backgroundColor.blue())); + list->setMinimumHeight(225); + + setModal(true); + + setMinimumHeight(340); + + //buttons + acceptButton = new QPushButton(tr("accept"),this); + cancelButton = new QPushButton(tr("cancel"),this); + + QHBoxLayout * buttons = new QHBoxLayout; + buttons->addStretch(); + buttons->addWidget(acceptButton); + buttons->addWidget(cancelButton); + + layout->addStretch(); + layout->addLayout(buttons); + + setLayout(layout); + + //connections + connect(edit,SIGNAL(textChanged(QString)),this,SLOT(validateName(QString))); + connect(cancelButton,SIGNAL(clicked()),this,SLOT(close())); + connect(acceptButton,SIGNAL(clicked()),this,SLOT(accept())); + +} + +YACReader::LabelColors AddLabelDialog::selectedColor() +{ + return YACReader::LabelColors(list->currentRow()+1); +} + +QString AddLabelDialog::name() +{ + return edit->text(); +} + +int AddLabelDialog::exec() +{ + edit->clear(); + list->clearSelection(); + + acceptButton->setDisabled(true); + + list->setCurrentRow(0); + + return QDialog::exec(); +} + +void AddLabelDialog::validateName(const QString &name) +{ + if(name.isEmpty()) + acceptButton->setDisabled(true); + else + acceptButton->setEnabled(true); +} diff --git a/YACReaderLibrary/add_label_dialog.h b/YACReaderLibrary/add_label_dialog.h index 1f5de48b..da11befa 100644 --- a/YACReaderLibrary/add_label_dialog.h +++ b/YACReaderLibrary/add_label_dialog.h @@ -1,31 +1,31 @@ -#ifndef ADD_LABEL_DIALOG_H -#define ADD_LABEL_DIALOG_H - -#include - -#include "yacreader_global.h" - -class AddLabelDialog : public QDialog -{ - Q_OBJECT -public: - explicit AddLabelDialog(QWidget *parent = 0); - YACReader::LabelColors selectedColor(); - QString name(); -signals: - -public slots: - int exec(); - -protected slots: - void validateName(const QString & name); - -protected: - QLineEdit * edit; - QListWidget * list; - - QPushButton * acceptButton; - QPushButton * cancelButton; -}; - -#endif // ADD_LABEL_DIALOG_H +#ifndef ADD_LABEL_DIALOG_H +#define ADD_LABEL_DIALOG_H + +#include + +#include "yacreader_global.h" + +class AddLabelDialog : public QDialog +{ + Q_OBJECT +public: + explicit AddLabelDialog(QWidget *parent = 0); + YACReader::LabelColors selectedColor(); + QString name(); +signals: + +public slots: + int exec(); + +protected slots: + void validateName(const QString & name); + +protected: + QLineEdit * edit; + QListWidget * list; + + QPushButton * acceptButton; + QPushButton * cancelButton; +}; + +#endif // ADD_LABEL_DIALOG_H diff --git a/YACReaderLibrary/add_library_dialog.cpp b/YACReaderLibrary/add_library_dialog.cpp index 4af23218..a7bcb152 100644 --- a/YACReaderLibrary/add_library_dialog.cpp +++ b/YACReaderLibrary/add_library_dialog.cpp @@ -1,124 +1,124 @@ -#include "add_library_dialog.h" - -#include -#include -#include -#include - - -AddLibraryDialog::AddLibraryDialog(QWidget * parent) -:QDialog(parent) -{ - setupUI(); -} - -void AddLibraryDialog::setupUI() -{ - textLabel = new QLabel(tr("Comics folder : ")); - path = new QLineEdit; - textLabel->setBuddy(path); - connect(path,SIGNAL(textChanged(QString)),this,SLOT(pathSetted(QString))); - - nameLabel = new QLabel(tr("Library name : ")); - nameEdit = new QLineEdit; - nameLabel->setBuddy(nameEdit); - connect(nameEdit,SIGNAL(textChanged(QString)),this,SLOT(nameSetted(QString))); - - accept = new QPushButton(tr("Add")); - accept->setDisabled(true); - connect(accept,SIGNAL(clicked()),this,SLOT(add())); - - cancel = new QPushButton(tr("Cancel")); - connect(cancel,SIGNAL(clicked()),this,SLOT(close())); - - find = new QPushButton(QIcon(":/images/find_folder.png"),""); - connect(find,SIGNAL(clicked()),this,SLOT(findPath())); - - QGridLayout * content = new QGridLayout; - - content->addWidget(nameLabel,0,0); - content->addWidget(nameEdit,0,1); - - content->addWidget(textLabel,1,0); - content->addWidget(path,1,1); - content->addWidget(find,1,2); - content->setColumnStretch(2,0); - - QHBoxLayout *bottomLayout = new QHBoxLayout; - bottomLayout->addStretch(); - bottomLayout->addWidget(accept); - bottomLayout->addWidget(cancel); - - QVBoxLayout *mainLayout = new QVBoxLayout; - mainLayout->addLayout(content); - mainLayout->addStretch(); - mainLayout->addLayout(bottomLayout); - - QHBoxLayout * imgMainLayout = new QHBoxLayout; - QLabel * imgLabel = new QLabel(this); - QPixmap p(":/images/openLibrary.png"); - imgLabel->setPixmap(p); - imgMainLayout->addWidget(imgLabel);//,0,Qt::AlignTop); - imgMainLayout->addLayout(mainLayout); - - setLayout(imgMainLayout); - - setModal(true); - setWindowTitle(tr("Add an existing library")); -} - -void AddLibraryDialog::add() -{ - //accept->setEnabled(false); - emit(addLibrary(QDir::cleanPath(path->text()),nameEdit->text())); -} - -void AddLibraryDialog::nameSetted(const QString & text) -{ - if(!text.isEmpty()) - { - if(!path->text().isEmpty()) - { - QFileInfo fi(path->text()); - if(fi.isDir()) - accept->setEnabled(true); - else - accept->setEnabled(false); - } - } - else - accept->setEnabled(false); -} - -void AddLibraryDialog::pathSetted(const QString & text) -{ - QFileInfo fi(text); - if(fi.isDir()) - { - if(!nameEdit->text().isEmpty()) - accept->setEnabled(true); - } - else - accept->setEnabled(false); -} - -void AddLibraryDialog::findPath() -{ - QString s = QFileDialog::getExistingDirectory(0,"Comics directory","."); - if(!s.isEmpty()) - { - path->setText(s); - if(!nameEdit->text().isEmpty()) - accept->setEnabled(true); - } - else - accept->setEnabled(false); -} - -void AddLibraryDialog::close() -{ - path->clear(); - nameEdit->clear(); - accept->setEnabled(false); - QDialog::close(); -} +#include "add_library_dialog.h" + +#include +#include +#include +#include + + +AddLibraryDialog::AddLibraryDialog(QWidget * parent) +:QDialog(parent) +{ + setupUI(); +} + +void AddLibraryDialog::setupUI() +{ + textLabel = new QLabel(tr("Comics folder : ")); + path = new QLineEdit; + textLabel->setBuddy(path); + connect(path,SIGNAL(textChanged(QString)),this,SLOT(pathSetted(QString))); + + nameLabel = new QLabel(tr("Library name : ")); + nameEdit = new QLineEdit; + nameLabel->setBuddy(nameEdit); + connect(nameEdit,SIGNAL(textChanged(QString)),this,SLOT(nameSetted(QString))); + + accept = new QPushButton(tr("Add")); + accept->setDisabled(true); + connect(accept,SIGNAL(clicked()),this,SLOT(add())); + + cancel = new QPushButton(tr("Cancel")); + connect(cancel,SIGNAL(clicked()),this,SLOT(close())); + + find = new QPushButton(QIcon(":/images/find_folder.png"),""); + connect(find,SIGNAL(clicked()),this,SLOT(findPath())); + + QGridLayout * content = new QGridLayout; + + content->addWidget(nameLabel,0,0); + content->addWidget(nameEdit,0,1); + + content->addWidget(textLabel,1,0); + content->addWidget(path,1,1); + content->addWidget(find,1,2); + content->setColumnStretch(2,0); + + QHBoxLayout *bottomLayout = new QHBoxLayout; + bottomLayout->addStretch(); + bottomLayout->addWidget(accept); + bottomLayout->addWidget(cancel); + + QVBoxLayout *mainLayout = new QVBoxLayout; + mainLayout->addLayout(content); + mainLayout->addStretch(); + mainLayout->addLayout(bottomLayout); + + QHBoxLayout * imgMainLayout = new QHBoxLayout; + QLabel * imgLabel = new QLabel(this); + QPixmap p(":/images/openLibrary.png"); + imgLabel->setPixmap(p); + imgMainLayout->addWidget(imgLabel);//,0,Qt::AlignTop); + imgMainLayout->addLayout(mainLayout); + + setLayout(imgMainLayout); + + setModal(true); + setWindowTitle(tr("Add an existing library")); +} + +void AddLibraryDialog::add() +{ + //accept->setEnabled(false); + emit(addLibrary(QDir::cleanPath(path->text()),nameEdit->text())); +} + +void AddLibraryDialog::nameSetted(const QString & text) +{ + if(!text.isEmpty()) + { + if(!path->text().isEmpty()) + { + QFileInfo fi(path->text()); + if(fi.isDir()) + accept->setEnabled(true); + else + accept->setEnabled(false); + } + } + else + accept->setEnabled(false); +} + +void AddLibraryDialog::pathSetted(const QString & text) +{ + QFileInfo fi(text); + if(fi.isDir()) + { + if(!nameEdit->text().isEmpty()) + accept->setEnabled(true); + } + else + accept->setEnabled(false); +} + +void AddLibraryDialog::findPath() +{ + QString s = QFileDialog::getExistingDirectory(0,"Comics directory","."); + if(!s.isEmpty()) + { + path->setText(s); + if(!nameEdit->text().isEmpty()) + accept->setEnabled(true); + } + else + accept->setEnabled(false); +} + +void AddLibraryDialog::close() +{ + path->clear(); + nameEdit->clear(); + accept->setEnabled(false); + QDialog::close(); +} diff --git a/YACReaderLibrary/bundle_creator.cpp b/YACReaderLibrary/bundle_creator.cpp index 8ea6eef2..ea2ff602 100644 --- a/YACReaderLibrary/bundle_creator.cpp +++ b/YACReaderLibrary/bundle_creator.cpp @@ -1,13 +1,13 @@ -#include "bundle_creator.h" - - -BundleCreator::BundleCreator(void) - :QObject() -{ - -} - - -BundleCreator::~BundleCreator(void) -{ -} +#include "bundle_creator.h" + + +BundleCreator::BundleCreator(void) + :QObject() +{ + +} + + +BundleCreator::~BundleCreator(void) +{ +} diff --git a/YACReaderLibrary/bundle_creator.h b/YACReaderLibrary/bundle_creator.h index ff4dbd08..2a6159a0 100644 --- a/YACReaderLibrary/bundle_creator.h +++ b/YACReaderLibrary/bundle_creator.h @@ -1,14 +1,14 @@ -#ifndef __BUNDLE_CREATOR_H -#define __BUNDLE_CREATOR_H - -#include - -class BundleCreator : public QObject -{ -Q_OBJECT -public: - BundleCreator(void); - ~BundleCreator(void); -}; - +#ifndef __BUNDLE_CREATOR_H +#define __BUNDLE_CREATOR_H + +#include + +class BundleCreator : public QObject +{ +Q_OBJECT +public: + BundleCreator(void); + ~BundleCreator(void); +}; + #endif \ No newline at end of file diff --git a/YACReaderLibrary/classic_comics_view.cpp b/YACReaderLibrary/classic_comics_view.cpp index f65d2bdc..e17fe3f1 100644 --- a/YACReaderLibrary/classic_comics_view.cpp +++ b/YACReaderLibrary/classic_comics_view.cpp @@ -1,382 +1,382 @@ -#include "classic_comics_view.h" - -#include "QStackedWidget" - -#include "comic_flow_widget.h" -#include "QsLog.h" -#include "shortcuts_manager.h" -#include "yacreader_table_view.h" -#include "yacreader_tool_bar_stretch.h" - -ClassicComicsView::ClassicComicsView(QWidget *parent) - :ComicsView(parent),searching(false) -{ - QHBoxLayout * layout = new QHBoxLayout; - - settings = new QSettings(YACReader::getSettingsPath()+"/YACReaderLibrary.ini",QSettings::IniFormat); //TODO unificar la creación del fichero de config con el servidor - settings->beginGroup("libraryConfig"); - //FLOW----------------------------------------------------------------------- - //--------------------------------------------------------------------------- -//FORCE_ANGLE is not used here, because ComicFlowWidgetGL will use OpenGL ES in the future -#ifndef NO_OPENGL - if((settings->value(USE_OPEN_GL).toBool() == true)) - comicFlow = new ComicFlowWidgetGL(0); - else - comicFlow = new ComicFlowWidgetSW(0); -#else - comicFlow = new ComicFlowWidgetSW(0); -#endif - comicFlow->updateConfig(settings); - comicFlow->setFocusPolicy(Qt::StrongFocus); - comicFlow->setShowMarks(true); - setFocusProxy(comicFlow); - - comicFlow->setFocus(Qt::OtherFocusReason); - - comicFlow->setContextMenuPolicy(Qt::CustomContextMenu); - - - //layout----------------------------------------------- - sVertical = new QSplitter(Qt::Vertical); //spliter derecha - - stack = new QStackedWidget; - stack->addWidget(comicFlow); - setupSearchingIcon(); - stack->addWidget(searchingIcon); - - - sVertical->addWidget(stack); - comics = new QWidget; - QVBoxLayout * comicsLayout = new QVBoxLayout; - comicsLayout->setSpacing(0); - comicsLayout->setContentsMargins(0,0,0,0); - //TODO ComicsView:(set toolbar) comicsLayout->addWidget(editInfoToolBar); - - tableView = new YACReaderTableView; - tableView->verticalHeader()->hide(); - tableView->setFocusPolicy(Qt::StrongFocus); - comicsLayout->addWidget(tableView); - comics->setLayout(comicsLayout); - sVertical->addWidget(comics); - - tableView->setContextMenuPolicy(Qt::CustomContextMenu); - - //config-------------------------------------------------- - if(settings->contains(COMICS_VIEW_HEADERS)) - tableView->horizontalHeader()->restoreState(settings->value(COMICS_VIEW_HEADERS).toByteArray()); - - //connections--------------------------------------------- - connect(tableView, SIGNAL(clicked(QModelIndex)), this, SLOT(centerComicFlow(QModelIndex))); - connect(tableView, SIGNAL(doubleClicked(QModelIndex)), this, SLOT(selectedComicForOpening(QModelIndex))); - connect(comicFlow, SIGNAL(centerIndexChanged(int)), this, SLOT(updateTableView(int))); - connect(tableView, SIGNAL(comicRated(int,QModelIndex)), this, SIGNAL(comicRated(int,QModelIndex))); - connect(comicFlow, SIGNAL(selected(uint)), this, SIGNAL(selected(uint))); - connect(tableView->horizontalHeader(), SIGNAL(sectionMoved(int,int,int)), this, SLOT(saveTableHeadersStatus())); - connect(tableView->horizontalHeader(), SIGNAL(sectionResized(int,int,int)), this, SLOT(saveTableHeadersStatus())); - connect(comicFlow, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(requestedViewContextMenu(QPoint))); - connect(tableView, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(requestedItemContextMenu(QPoint))); - layout->addWidget(sVertical); - setLayout(layout); - - layout->setMargin(0); - -#ifdef Q_OS_MAC - sVertical->setCollapsible(1,false); -#endif - - if(settings->contains(COMICS_VIEW_FLOW_SPLITTER_STATUS)) - sVertical->restoreState(settings->value(COMICS_VIEW_FLOW_SPLITTER_STATUS).toByteArray()); - - //hide flow widgets - hideFlowViewAction = new QAction(this); - hideFlowViewAction->setText(tr("Hide comic flow")); - hideFlowViewAction->setData(HIDE_COMIC_VIEW_ACTION_YL); - hideFlowViewAction->setShortcut(ShortcutsManager::getShortcutsManager().getShortcut(HIDE_COMIC_VIEW_ACTION_YL)); - hideFlowViewAction->setIcon(QIcon(":/images/comics_view_toolbar/hideComicFlow.png")); - hideFlowViewAction->setCheckable(true); - hideFlowViewAction->setChecked(false); - - connect(hideFlowViewAction, SIGNAL(toggled(bool)),this, SLOT(hideComicFlow(bool))); -} - -void ClassicComicsView::hideComicFlow(bool hide) -{ - if(hide) - { - QList sizes; - sizes.append(0); - int total = sVertical->sizes().at(0) + sVertical->sizes().at(1); - sizes.append(total); - sVertical->setSizes(sizes); - } - else - { - QList sizes; - int total = sVertical->sizes().at(0) + sVertical->sizes().at(1); - sizes.append(2*total/3); - sizes.append(total/3); - sVertical->setSizes(sizes); - } -} - -//the toolbar has to be populated -void ClassicComicsView::setToolBar(QToolBar *toolBar) -{ - static_cast(comics->layout())->insertWidget(0,toolBar); - this->toolbar = toolBar; - - toolBarStretch = new YACReaderToolBarStretch(this); - - toolBarStretchAction = toolBar->addWidget(toolBarStretch); - toolBar->addAction(hideFlowViewAction); -} - -void ClassicComicsView::setModel(ComicModel *model) -{ - ComicsView::setModel(model); - - if(model == NULL) - { - comicFlow->clear(); - } - else - { - connect(model, SIGNAL(dataChanged(QModelIndex,QModelIndex,QVector)), this, SLOT(applyModelChanges(QModelIndex,QModelIndex,QVector)),Qt::UniqueConnection); - connect(model, SIGNAL(rowsRemoved(QModelIndex,int,int)), this, SLOT(removeItemsFromFlow(QModelIndex,int,int)),Qt::UniqueConnection); - connect(model, SIGNAL(resortedIndexes(QList)),comicFlow,SLOT(resortCovers(QList)),Qt::UniqueConnection); - connect(model, SIGNAL(newSelectedIndex(QModelIndex)),this,SLOT(setCurrentIndex(QModelIndex)),Qt::UniqueConnection); - - tableView->setModel(model); - if(model->rowCount()>0) - tableView->setCurrentIndex(model->index(0,0)); - - tableView->horizontalHeader()->setDefaultAlignment(Qt::AlignLeft); - #if QT_VERSION >= 0x050000 - tableView->horizontalHeader()->setSectionsMovable(true); - #else - tableView->horizontalHeader()->setMovable(true); - #endif - //TODO parametrizar la configuración de las columnas - /*if(!settings->contains(COMICS_VIEW_HEADERS)) - {*/ - for(int i = 0;ihorizontalHeader()->count();i++) - tableView->horizontalHeader()->hideSection(i); - - tableView->horizontalHeader()->showSection(ComicModel::Number); - tableView->horizontalHeader()->showSection(ComicModel::Title); - tableView->horizontalHeader()->showSection(ComicModel::FileName); - tableView->horizontalHeader()->showSection(ComicModel::NumPages); - tableView->horizontalHeader()->showSection(ComicModel::Hash); //Size is part of the Hash...TODO add Columns::Size to Columns - tableView->horizontalHeader()->showSection(ComicModel::ReadColumn); - tableView->horizontalHeader()->showSection(ComicModel::CurrentPage); - tableView->horizontalHeader()->showSection(ComicModel::Rating); - //} - - //debido a un bug, qt4 no es capaz de ajustar el ancho teniendo en cuenta todas la filas (no sólo las visibles) - //así que se ecala la primera vez y después se deja el control al usuario. - //if(!settings->contains(COMICS_VIEW_HEADERS)) - - - QStringList paths = model->getPaths(model->getCurrentPath());//TODO ComicsView: get currentpath from somewhere currentPath()); - comicFlow->setImagePaths(paths); - comicFlow->setMarks(model->getReadList()); - //comicFlow->setFocus(Qt::OtherFocusReason); - - if(settings->contains(COMICS_VIEW_HEADERS)) - tableView->horizontalHeader()->restoreState(settings->value(COMICS_VIEW_HEADERS).toByteArray()); - - tableView->resizeColumnsToContents(); - - tableView->horizontalHeader()->setStretchLastSection(true); - } -} - -void ClassicComicsView::setCurrentIndex(const QModelIndex &index) -{ - tableView->setCurrentIndex(index); - centerComicFlow(index); -} - -QModelIndex ClassicComicsView::currentIndex() -{ - return tableView->currentIndex(); -} - -QItemSelectionModel *ClassicComicsView::selectionModel() -{ - return tableView->selectionModel(); -} - -void ClassicComicsView::scrollTo(const QModelIndex & mi, QAbstractItemView::ScrollHint hint) -{ - Q_UNUSED(hint); - - comicFlow->setCenterIndex(mi.row()); -} - -void ClassicComicsView::toFullScreen() -{ - comicFlow->hide(); - comicFlow->setCenterIndex(comicFlow->centerIndex()); - comics->hide(); - - //showFullScreen() //parent windows - - comicFlow->show(); - comicFlow->setFocus(Qt::OtherFocusReason); -} - -void ClassicComicsView::toNormal() -{ - comicFlow->hide(); - comicFlow->setCenterIndex(comicFlow->centerIndex()); - comicFlow->render(); - comics->show(); - comicFlow->show(); -} - -void ClassicComicsView::updateConfig(QSettings *settings) -{ - comicFlow->updateConfig(settings); -} - -void ClassicComicsView::enableFilterMode(bool enabled) -{ - if(enabled) - { - comicFlow->clear(); - if(previousSplitterStatus.isEmpty()) - previousSplitterStatus = sVertical->saveState(); - sVertical->setSizes(QList () << 100 << 10000000); - showSearchingIcon(); - }else - { - hideSearchingIcon(); - sVertical->restoreState(previousSplitterStatus); - previousSplitterStatus.clear(); - } - - //sVertical->setCollapsible(0,!enabled); - searching = enabled; -} - -void ClassicComicsView::selectIndex(int index) -{ - tableView->selectRow(index); -} - -void ClassicComicsView::updateCurrentComicView() -{ - -} - -void ClassicComicsView::selectAll() -{ - tableView->selectAll(); -} - -void ClassicComicsView::selectedComicForOpening(const QModelIndex &mi) -{ - emit selected(mi.row()); -} - -void ClassicComicsView::requestedViewContextMenu(const QPoint &point) -{ - emit customContextMenuViewRequested(comicFlow->mapTo(this, point)); -} - -void ClassicComicsView::requestedItemContextMenu(const QPoint &point) -{ - emit customContextMenuItemRequested(tableView->mapTo(this, point)); -} - -void ClassicComicsView::setShowMarks(bool show) -{ - comicFlow->setShowMarks(show); -} - -void ClassicComicsView::centerComicFlow(const QModelIndex & mi) -{ - comicFlow->showSlide(mi.row()); - comicFlow->setFocus(Qt::OtherFocusReason); -} - -void ClassicComicsView::updateTableView(int i) -{ - QModelIndex mi = model->index(i,2); - tableView->setCurrentIndex(mi); - tableView->scrollTo(mi,QAbstractItemView::EnsureVisible); -} - -void ClassicComicsView::saveTableHeadersStatus() -{ - settings->setValue(COMICS_VIEW_HEADERS,tableView->horizontalHeader()->saveState()); -} - -void ClassicComicsView::saveSplitterStatus() -{ - settingsMutex.lock(); - if(!searching) - settings->setValue(COMICS_VIEW_FLOW_SPLITTER_STATUS, sVertical->saveState()); - settingsMutex.unlock(); -} - -void ClassicComicsView::applyModelChanges(const QModelIndex &topLeft, const QModelIndex &bottomRight, const QVector &roles) -{ - Q_UNUSED(topLeft); - Q_UNUSED(bottomRight); - if(roles.contains(ComicModel::ReadColumnRole)) - { - comicFlow->setMarks(model->getReadList()); - comicFlow->updateMarks(); - } -} - -void ClassicComicsView::removeItemsFromFlow(const QModelIndex &parent, int from, int to) -{ - Q_UNUSED(parent); - for(int i = from; i<=to; i++) - comicFlow->remove(i); -} - -void ClassicComicsView::closeEvent(QCloseEvent *event) -{ - toolbar->removeAction(toolBarStretchAction); - toolbar->removeAction(hideFlowViewAction); - - saveTableHeadersStatus(); - saveSplitterStatus(); - ComicsView::closeEvent(event); -} - -void ClassicComicsView::setupSearchingIcon() -{ - searchingIcon = new QWidget(comicFlow); - - QHBoxLayout * h = new QHBoxLayout; - - QPixmap p(":/images/searching_icon.png"); - QLabel * l = new QLabel(searchingIcon); - l->setPixmap(p); - l->setFixedSize(p.size()); - h->addWidget(l,0,Qt::AlignCenter); - searchingIcon->setLayout(h); - - QPalette pal(searchingIcon->palette()); - pal.setColor(QPalette::Background, Qt::black); - searchingIcon->setAutoFillBackground(true); - searchingIcon->setPalette(pal); - - hideSearchingIcon(); -} - -void ClassicComicsView::showSearchingIcon() -{ - stack->setCurrentWidget(searchingIcon); -} - -void ClassicComicsView::hideSearchingIcon() -{ - stack->setCurrentWidget(comicFlow); -} - +#include "classic_comics_view.h" + +#include "QStackedWidget" + +#include "comic_flow_widget.h" +#include "QsLog.h" +#include "shortcuts_manager.h" +#include "yacreader_table_view.h" +#include "yacreader_tool_bar_stretch.h" + +ClassicComicsView::ClassicComicsView(QWidget *parent) + :ComicsView(parent),searching(false) +{ + QHBoxLayout * layout = new QHBoxLayout; + + settings = new QSettings(YACReader::getSettingsPath()+"/YACReaderLibrary.ini",QSettings::IniFormat); //TODO unificar la creación del fichero de config con el servidor + settings->beginGroup("libraryConfig"); + //FLOW----------------------------------------------------------------------- + //--------------------------------------------------------------------------- +//FORCE_ANGLE is not used here, because ComicFlowWidgetGL will use OpenGL ES in the future +#ifndef NO_OPENGL + if((settings->value(USE_OPEN_GL).toBool() == true)) + comicFlow = new ComicFlowWidgetGL(0); + else + comicFlow = new ComicFlowWidgetSW(0); +#else + comicFlow = new ComicFlowWidgetSW(0); +#endif + comicFlow->updateConfig(settings); + comicFlow->setFocusPolicy(Qt::StrongFocus); + comicFlow->setShowMarks(true); + setFocusProxy(comicFlow); + + comicFlow->setFocus(Qt::OtherFocusReason); + + comicFlow->setContextMenuPolicy(Qt::CustomContextMenu); + + + //layout----------------------------------------------- + sVertical = new QSplitter(Qt::Vertical); //spliter derecha + + stack = new QStackedWidget; + stack->addWidget(comicFlow); + setupSearchingIcon(); + stack->addWidget(searchingIcon); + + + sVertical->addWidget(stack); + comics = new QWidget; + QVBoxLayout * comicsLayout = new QVBoxLayout; + comicsLayout->setSpacing(0); + comicsLayout->setContentsMargins(0,0,0,0); + //TODO ComicsView:(set toolbar) comicsLayout->addWidget(editInfoToolBar); + + tableView = new YACReaderTableView; + tableView->verticalHeader()->hide(); + tableView->setFocusPolicy(Qt::StrongFocus); + comicsLayout->addWidget(tableView); + comics->setLayout(comicsLayout); + sVertical->addWidget(comics); + + tableView->setContextMenuPolicy(Qt::CustomContextMenu); + + //config-------------------------------------------------- + if(settings->contains(COMICS_VIEW_HEADERS)) + tableView->horizontalHeader()->restoreState(settings->value(COMICS_VIEW_HEADERS).toByteArray()); + + //connections--------------------------------------------- + connect(tableView, SIGNAL(clicked(QModelIndex)), this, SLOT(centerComicFlow(QModelIndex))); + connect(tableView, SIGNAL(doubleClicked(QModelIndex)), this, SLOT(selectedComicForOpening(QModelIndex))); + connect(comicFlow, SIGNAL(centerIndexChanged(int)), this, SLOT(updateTableView(int))); + connect(tableView, SIGNAL(comicRated(int,QModelIndex)), this, SIGNAL(comicRated(int,QModelIndex))); + connect(comicFlow, SIGNAL(selected(uint)), this, SIGNAL(selected(uint))); + connect(tableView->horizontalHeader(), SIGNAL(sectionMoved(int,int,int)), this, SLOT(saveTableHeadersStatus())); + connect(tableView->horizontalHeader(), SIGNAL(sectionResized(int,int,int)), this, SLOT(saveTableHeadersStatus())); + connect(comicFlow, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(requestedViewContextMenu(QPoint))); + connect(tableView, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(requestedItemContextMenu(QPoint))); + layout->addWidget(sVertical); + setLayout(layout); + + layout->setMargin(0); + +#ifdef Q_OS_MAC + sVertical->setCollapsible(1,false); +#endif + + if(settings->contains(COMICS_VIEW_FLOW_SPLITTER_STATUS)) + sVertical->restoreState(settings->value(COMICS_VIEW_FLOW_SPLITTER_STATUS).toByteArray()); + + //hide flow widgets + hideFlowViewAction = new QAction(this); + hideFlowViewAction->setText(tr("Hide comic flow")); + hideFlowViewAction->setData(HIDE_COMIC_VIEW_ACTION_YL); + hideFlowViewAction->setShortcut(ShortcutsManager::getShortcutsManager().getShortcut(HIDE_COMIC_VIEW_ACTION_YL)); + hideFlowViewAction->setIcon(QIcon(":/images/comics_view_toolbar/hideComicFlow.png")); + hideFlowViewAction->setCheckable(true); + hideFlowViewAction->setChecked(false); + + connect(hideFlowViewAction, SIGNAL(toggled(bool)),this, SLOT(hideComicFlow(bool))); +} + +void ClassicComicsView::hideComicFlow(bool hide) +{ + if(hide) + { + QList sizes; + sizes.append(0); + int total = sVertical->sizes().at(0) + sVertical->sizes().at(1); + sizes.append(total); + sVertical->setSizes(sizes); + } + else + { + QList sizes; + int total = sVertical->sizes().at(0) + sVertical->sizes().at(1); + sizes.append(2*total/3); + sizes.append(total/3); + sVertical->setSizes(sizes); + } +} + +//the toolbar has to be populated +void ClassicComicsView::setToolBar(QToolBar *toolBar) +{ + static_cast(comics->layout())->insertWidget(0,toolBar); + this->toolbar = toolBar; + + toolBarStretch = new YACReaderToolBarStretch(this); + + toolBarStretchAction = toolBar->addWidget(toolBarStretch); + toolBar->addAction(hideFlowViewAction); +} + +void ClassicComicsView::setModel(ComicModel *model) +{ + ComicsView::setModel(model); + + if(model == NULL) + { + comicFlow->clear(); + } + else + { + connect(model, SIGNAL(dataChanged(QModelIndex,QModelIndex,QVector)), this, SLOT(applyModelChanges(QModelIndex,QModelIndex,QVector)),Qt::UniqueConnection); + connect(model, SIGNAL(rowsRemoved(QModelIndex,int,int)), this, SLOT(removeItemsFromFlow(QModelIndex,int,int)),Qt::UniqueConnection); + connect(model, SIGNAL(resortedIndexes(QList)),comicFlow,SLOT(resortCovers(QList)),Qt::UniqueConnection); + connect(model, SIGNAL(newSelectedIndex(QModelIndex)),this,SLOT(setCurrentIndex(QModelIndex)),Qt::UniqueConnection); + + tableView->setModel(model); + if(model->rowCount()>0) + tableView->setCurrentIndex(model->index(0,0)); + + tableView->horizontalHeader()->setDefaultAlignment(Qt::AlignLeft); + #if QT_VERSION >= 0x050000 + tableView->horizontalHeader()->setSectionsMovable(true); + #else + tableView->horizontalHeader()->setMovable(true); + #endif + //TODO parametrizar la configuración de las columnas + /*if(!settings->contains(COMICS_VIEW_HEADERS)) + {*/ + for(int i = 0;ihorizontalHeader()->count();i++) + tableView->horizontalHeader()->hideSection(i); + + tableView->horizontalHeader()->showSection(ComicModel::Number); + tableView->horizontalHeader()->showSection(ComicModel::Title); + tableView->horizontalHeader()->showSection(ComicModel::FileName); + tableView->horizontalHeader()->showSection(ComicModel::NumPages); + tableView->horizontalHeader()->showSection(ComicModel::Hash); //Size is part of the Hash...TODO add Columns::Size to Columns + tableView->horizontalHeader()->showSection(ComicModel::ReadColumn); + tableView->horizontalHeader()->showSection(ComicModel::CurrentPage); + tableView->horizontalHeader()->showSection(ComicModel::Rating); + //} + + //debido a un bug, qt4 no es capaz de ajustar el ancho teniendo en cuenta todas la filas (no sólo las visibles) + //así que se ecala la primera vez y después se deja el control al usuario. + //if(!settings->contains(COMICS_VIEW_HEADERS)) + + + QStringList paths = model->getPaths(model->getCurrentPath());//TODO ComicsView: get currentpath from somewhere currentPath()); + comicFlow->setImagePaths(paths); + comicFlow->setMarks(model->getReadList()); + //comicFlow->setFocus(Qt::OtherFocusReason); + + if(settings->contains(COMICS_VIEW_HEADERS)) + tableView->horizontalHeader()->restoreState(settings->value(COMICS_VIEW_HEADERS).toByteArray()); + + tableView->resizeColumnsToContents(); + + tableView->horizontalHeader()->setStretchLastSection(true); + } +} + +void ClassicComicsView::setCurrentIndex(const QModelIndex &index) +{ + tableView->setCurrentIndex(index); + centerComicFlow(index); +} + +QModelIndex ClassicComicsView::currentIndex() +{ + return tableView->currentIndex(); +} + +QItemSelectionModel *ClassicComicsView::selectionModel() +{ + return tableView->selectionModel(); +} + +void ClassicComicsView::scrollTo(const QModelIndex & mi, QAbstractItemView::ScrollHint hint) +{ + Q_UNUSED(hint); + + comicFlow->setCenterIndex(mi.row()); +} + +void ClassicComicsView::toFullScreen() +{ + comicFlow->hide(); + comicFlow->setCenterIndex(comicFlow->centerIndex()); + comics->hide(); + + //showFullScreen() //parent windows + + comicFlow->show(); + comicFlow->setFocus(Qt::OtherFocusReason); +} + +void ClassicComicsView::toNormal() +{ + comicFlow->hide(); + comicFlow->setCenterIndex(comicFlow->centerIndex()); + comicFlow->render(); + comics->show(); + comicFlow->show(); +} + +void ClassicComicsView::updateConfig(QSettings *settings) +{ + comicFlow->updateConfig(settings); +} + +void ClassicComicsView::enableFilterMode(bool enabled) +{ + if(enabled) + { + comicFlow->clear(); + if(previousSplitterStatus.isEmpty()) + previousSplitterStatus = sVertical->saveState(); + sVertical->setSizes(QList () << 100 << 10000000); + showSearchingIcon(); + }else + { + hideSearchingIcon(); + sVertical->restoreState(previousSplitterStatus); + previousSplitterStatus.clear(); + } + + //sVertical->setCollapsible(0,!enabled); + searching = enabled; +} + +void ClassicComicsView::selectIndex(int index) +{ + tableView->selectRow(index); +} + +void ClassicComicsView::updateCurrentComicView() +{ + +} + +void ClassicComicsView::selectAll() +{ + tableView->selectAll(); +} + +void ClassicComicsView::selectedComicForOpening(const QModelIndex &mi) +{ + emit selected(mi.row()); +} + +void ClassicComicsView::requestedViewContextMenu(const QPoint &point) +{ + emit customContextMenuViewRequested(comicFlow->mapTo(this, point)); +} + +void ClassicComicsView::requestedItemContextMenu(const QPoint &point) +{ + emit customContextMenuItemRequested(tableView->mapTo(this, point)); +} + +void ClassicComicsView::setShowMarks(bool show) +{ + comicFlow->setShowMarks(show); +} + +void ClassicComicsView::centerComicFlow(const QModelIndex & mi) +{ + comicFlow->showSlide(mi.row()); + comicFlow->setFocus(Qt::OtherFocusReason); +} + +void ClassicComicsView::updateTableView(int i) +{ + QModelIndex mi = model->index(i,2); + tableView->setCurrentIndex(mi); + tableView->scrollTo(mi,QAbstractItemView::EnsureVisible); +} + +void ClassicComicsView::saveTableHeadersStatus() +{ + settings->setValue(COMICS_VIEW_HEADERS,tableView->horizontalHeader()->saveState()); +} + +void ClassicComicsView::saveSplitterStatus() +{ + settingsMutex.lock(); + if(!searching) + settings->setValue(COMICS_VIEW_FLOW_SPLITTER_STATUS, sVertical->saveState()); + settingsMutex.unlock(); +} + +void ClassicComicsView::applyModelChanges(const QModelIndex &topLeft, const QModelIndex &bottomRight, const QVector &roles) +{ + Q_UNUSED(topLeft); + Q_UNUSED(bottomRight); + if(roles.contains(ComicModel::ReadColumnRole)) + { + comicFlow->setMarks(model->getReadList()); + comicFlow->updateMarks(); + } +} + +void ClassicComicsView::removeItemsFromFlow(const QModelIndex &parent, int from, int to) +{ + Q_UNUSED(parent); + for(int i = from; i<=to; i++) + comicFlow->remove(i); +} + +void ClassicComicsView::closeEvent(QCloseEvent *event) +{ + toolbar->removeAction(toolBarStretchAction); + toolbar->removeAction(hideFlowViewAction); + + saveTableHeadersStatus(); + saveSplitterStatus(); + ComicsView::closeEvent(event); +} + +void ClassicComicsView::setupSearchingIcon() +{ + searchingIcon = new QWidget(comicFlow); + + QHBoxLayout * h = new QHBoxLayout; + + QPixmap p(":/images/searching_icon.png"); + QLabel * l = new QLabel(searchingIcon); + l->setPixmap(p); + l->setFixedSize(p.size()); + h->addWidget(l,0,Qt::AlignCenter); + searchingIcon->setLayout(h); + + QPalette pal(searchingIcon->palette()); + pal.setColor(QPalette::Background, Qt::black); + searchingIcon->setAutoFillBackground(true); + searchingIcon->setPalette(pal); + + hideSearchingIcon(); +} + +void ClassicComicsView::showSearchingIcon() +{ + stack->setCurrentWidget(searchingIcon); +} + +void ClassicComicsView::hideSearchingIcon() +{ + stack->setCurrentWidget(comicFlow); +} + diff --git a/YACReaderLibrary/classic_comics_view.h b/YACReaderLibrary/classic_comics_view.h index c06a9429..08af02e6 100644 --- a/YACReaderLibrary/classic_comics_view.h +++ b/YACReaderLibrary/classic_comics_view.h @@ -1,80 +1,80 @@ -#ifndef CLASSIC_COMICS_VIEW_H -#define CLASSIC_COMICS_VIEW_H - -#include "comics_view.h" - -#include -#include - -class QSplitter; -class QStackedWidget; -class QToolBar; - -class ComicFlowWidget; -class ComicModel; -class YACReaderTableView; -class YACReaderToolBarStretch; - -class ClassicComicsView : public ComicsView -{ - Q_OBJECT -public: - ClassicComicsView(QWidget *parent = 0); - void setToolBar(QToolBar * toolBar); - void setModel(ComicModel *model); - - QModelIndex currentIndex(); - QItemSelectionModel * selectionModel(); - void scrollTo(const QModelIndex & mi, QAbstractItemView::ScrollHint hint ); - void toFullScreen(); - void toNormal(); - void updateConfig(QSettings * settings); - void enableFilterMode(bool enabled); - void selectIndex(int index); - void updateCurrentComicView(); - -public slots: - void setCurrentIndex(const QModelIndex &index); - void centerComicFlow(const QModelIndex & mi); - void updateTableView(int i); - void saveTableHeadersStatus(); - void saveSplitterStatus(); - void applyModelChanges(const QModelIndex & topLeft,const QModelIndex & bottomRight,const QVector & roles); - void removeItemsFromFlow(const QModelIndex & parent, int from, int to); - //ComicsView - void setShowMarks(bool show); - void selectAll(); - void selectedComicForOpening(const QModelIndex & mi); - -protected slots: - void hideComicFlow(bool hide); - void requestedViewContextMenu(const QPoint & point); - void requestedItemContextMenu(const QPoint & point); - - -private: - YACReaderTableView * tableView; - YACReaderToolBarStretch * toolBarStretch; - QAction * toolBarStretchAction; - QToolBar * toolbar; - QWidget *comics; - QSplitter * sVertical; - ComicFlowWidget * comicFlow; - QSettings * settings; - void closeEvent ( QCloseEvent * event ); - QAction * hideFlowViewAction; - - QStackedWidget * stack; - - QByteArray previousSplitterStatus; - QWidget * searchingIcon; - bool searching; - void setupSearchingIcon(); - void showSearchingIcon(); - void hideSearchingIcon(); - void updateSearchingIconPosition(); - - QMutex settingsMutex; -}; - -#endif // CLASSIC_COMICS_VIEW_H +#ifndef CLASSIC_COMICS_VIEW_H +#define CLASSIC_COMICS_VIEW_H + +#include "comics_view.h" + +#include +#include + +class QSplitter; +class QStackedWidget; +class QToolBar; + +class ComicFlowWidget; +class ComicModel; +class YACReaderTableView; +class YACReaderToolBarStretch; + +class ClassicComicsView : public ComicsView +{ + Q_OBJECT +public: + ClassicComicsView(QWidget *parent = 0); + void setToolBar(QToolBar * toolBar); + void setModel(ComicModel *model); + + QModelIndex currentIndex(); + QItemSelectionModel * selectionModel(); + void scrollTo(const QModelIndex & mi, QAbstractItemView::ScrollHint hint ); + void toFullScreen(); + void toNormal(); + void updateConfig(QSettings * settings); + void enableFilterMode(bool enabled); + void selectIndex(int index); + void updateCurrentComicView(); + +public slots: + void setCurrentIndex(const QModelIndex &index); + void centerComicFlow(const QModelIndex & mi); + void updateTableView(int i); + void saveTableHeadersStatus(); + void saveSplitterStatus(); + void applyModelChanges(const QModelIndex & topLeft,const QModelIndex & bottomRight,const QVector & roles); + void removeItemsFromFlow(const QModelIndex & parent, int from, int to); + //ComicsView + void setShowMarks(bool show); + void selectAll(); + void selectedComicForOpening(const QModelIndex & mi); + +protected slots: + void hideComicFlow(bool hide); + void requestedViewContextMenu(const QPoint & point); + void requestedItemContextMenu(const QPoint & point); + + +private: + YACReaderTableView * tableView; + YACReaderToolBarStretch * toolBarStretch; + QAction * toolBarStretchAction; + QToolBar * toolbar; + QWidget *comics; + QSplitter * sVertical; + ComicFlowWidget * comicFlow; + QSettings * settings; + void closeEvent ( QCloseEvent * event ); + QAction * hideFlowViewAction; + + QStackedWidget * stack; + + QByteArray previousSplitterStatus; + QWidget * searchingIcon; + bool searching; + void setupSearchingIcon(); + void showSearchingIcon(); + void hideSearchingIcon(); + void updateSearchingIconPosition(); + + QMutex settingsMutex; +}; + +#endif // CLASSIC_COMICS_VIEW_H diff --git a/YACReaderLibrary/comic_files_manager.cpp b/YACReaderLibrary/comic_files_manager.cpp index 50f2b81d..43c5bcde 100644 --- a/YACReaderLibrary/comic_files_manager.cpp +++ b/YACReaderLibrary/comic_files_manager.cpp @@ -1,108 +1,108 @@ -#include "comic_files_manager.h" -#include -#include -#include - -#include - -#include "comic.h" - -ComicFilesManager::ComicFilesManager(QObject *parent) : - QObject(parent), canceled(false) -{ -} - -void ComicFilesManager::copyComicsTo(const QList > &sourceComics, const QString &folderDest, const QModelIndex & dest) -{ - comics = sourceComics; - folder = folderDest; - folderDestinationModelIndex = dest; - move = false; -} - -void ComicFilesManager::moveComicsTo(const QList > &sourceComics, const QString &folderDest, const QModelIndex &dest) -{ - comics = sourceComics; - folder = folderDest; - folderDestinationModelIndex = dest; - move = true; -} - -QList > ComicFilesManager::getDroppedFiles(const QList &urls) -{ - QList > dropedFiles; - - QString currentPath; - foreach(QUrl url, urls) - { - currentPath = url.toLocalFile(); - if(currentPath.endsWith('/')) - currentPath = currentPath.remove(currentPath.length()-1,1); //QTBUG-35896 QUrl.toLocalFile inconsistency. - if(Comic::fileIsComic(currentPath)) - dropedFiles << QPair(currentPath,"/"); - else - { - QLOG_DEBUG() << "XXXXXXXXXXXX :" << currentPath; - QFileInfo info(currentPath); - if(info.isDir()) - { - QLOG_DEBUG() << "origin path prior to absoluteFilePath : " << info.absolutePath(); - foreach(QString comicPath, Comic::findValidComicFilesInFolder(info.absoluteFilePath())) - { - QFileInfo comicInfo(comicPath); - QString path = comicInfo.absolutePath(); - QLOG_DEBUG() << "comic path : " << comicPath; - QLOG_DEBUG() << "full comic path : " << path; - QLOG_DEBUG() << "origin path : " << info.absolutePath(); - dropedFiles << QPair(comicPath, path.remove(info.absolutePath())); - } - } - } - } - - return dropedFiles; -} - -void ComicFilesManager::process() -{ - int i=0; - bool successProcesingFiles = false; - QPair source; - foreach (source, comics) { - - if(canceled) - { - if(successProcesingFiles) - emit success(folderDestinationModelIndex); - emit finished(); - - return; //TODO rollback? - } - - QFileInfo info(source.first); - QString destPath = QDir::cleanPath(folder+'/'+source.second); - QLOG_DEBUG() << "crear : " << destPath; - QDir().mkpath(destPath); - if(QFile::copy(source.first, QDir::cleanPath(destPath+'/'+info.fileName()))) - { - successProcesingFiles = true; - if(move) - { - QFile::remove(source.first); //TODO: remove the whole path.... - } - } - - i++; - emit progress(i); - } - - if(successProcesingFiles) - emit success(folderDestinationModelIndex); - emit finished(); -} - -void ComicFilesManager::cancel() -{ - QLOG_DEBUG() << "Operation canceled"; - canceled = true; -} +#include "comic_files_manager.h" +#include +#include +#include + +#include + +#include "comic.h" + +ComicFilesManager::ComicFilesManager(QObject *parent) : + QObject(parent), canceled(false) +{ +} + +void ComicFilesManager::copyComicsTo(const QList > &sourceComics, const QString &folderDest, const QModelIndex & dest) +{ + comics = sourceComics; + folder = folderDest; + folderDestinationModelIndex = dest; + move = false; +} + +void ComicFilesManager::moveComicsTo(const QList > &sourceComics, const QString &folderDest, const QModelIndex &dest) +{ + comics = sourceComics; + folder = folderDest; + folderDestinationModelIndex = dest; + move = true; +} + +QList > ComicFilesManager::getDroppedFiles(const QList &urls) +{ + QList > dropedFiles; + + QString currentPath; + foreach(QUrl url, urls) + { + currentPath = url.toLocalFile(); + if(currentPath.endsWith('/')) + currentPath = currentPath.remove(currentPath.length()-1,1); //QTBUG-35896 QUrl.toLocalFile inconsistency. + if(Comic::fileIsComic(currentPath)) + dropedFiles << QPair(currentPath,"/"); + else + { + QLOG_DEBUG() << "XXXXXXXXXXXX :" << currentPath; + QFileInfo info(currentPath); + if(info.isDir()) + { + QLOG_DEBUG() << "origin path prior to absoluteFilePath : " << info.absolutePath(); + foreach(QString comicPath, Comic::findValidComicFilesInFolder(info.absoluteFilePath())) + { + QFileInfo comicInfo(comicPath); + QString path = comicInfo.absolutePath(); + QLOG_DEBUG() << "comic path : " << comicPath; + QLOG_DEBUG() << "full comic path : " << path; + QLOG_DEBUG() << "origin path : " << info.absolutePath(); + dropedFiles << QPair(comicPath, path.remove(info.absolutePath())); + } + } + } + } + + return dropedFiles; +} + +void ComicFilesManager::process() +{ + int i=0; + bool successProcesingFiles = false; + QPair source; + foreach (source, comics) { + + if(canceled) + { + if(successProcesingFiles) + emit success(folderDestinationModelIndex); + emit finished(); + + return; //TODO rollback? + } + + QFileInfo info(source.first); + QString destPath = QDir::cleanPath(folder+'/'+source.second); + QLOG_DEBUG() << "crear : " << destPath; + QDir().mkpath(destPath); + if(QFile::copy(source.first, QDir::cleanPath(destPath+'/'+info.fileName()))) + { + successProcesingFiles = true; + if(move) + { + QFile::remove(source.first); //TODO: remove the whole path.... + } + } + + i++; + emit progress(i); + } + + if(successProcesingFiles) + emit success(folderDestinationModelIndex); + emit finished(); +} + +void ComicFilesManager::cancel() +{ + QLOG_DEBUG() << "Operation canceled"; + canceled = true; +} diff --git a/YACReaderLibrary/comic_files_manager.h b/YACReaderLibrary/comic_files_manager.h index a6b54060..7c2c202b 100644 --- a/YACReaderLibrary/comic_files_manager.h +++ b/YACReaderLibrary/comic_files_manager.h @@ -1,37 +1,37 @@ -#ifndef COMIC_FILES_MANAGER_H -#define COMIC_FILES_MANAGER_H - -#include -#include -#include -#include - - -//this class is intended to work in background, just use moveToThread and process to start working -class ComicFilesManager : public QObject -{ - Q_OBJECT -public: - explicit ComicFilesManager(QObject *parent = 0); - void copyComicsTo(const QList > & sourceComics, const QString & folderDest, const QModelIndex &dest); - void moveComicsTo(const QList > & comics, const QString & folderDest, const QModelIndex &dest); - static QList > getDroppedFiles(const QList & urls); -signals: - void currentComic(QString); - void progress(int); - void finished(); - void success(QModelIndex); //at least one comics has been copied or moved -public slots: - void process(); - void cancel(); - -protected: - bool move; - bool canceled; - QList > comics; - QString folder; - QModelIndex folderDestinationModelIndex; - -}; - -#endif // COMIC_FILES_MANAGER_H +#ifndef COMIC_FILES_MANAGER_H +#define COMIC_FILES_MANAGER_H + +#include +#include +#include +#include + + +//this class is intended to work in background, just use moveToThread and process to start working +class ComicFilesManager : public QObject +{ + Q_OBJECT +public: + explicit ComicFilesManager(QObject *parent = 0); + void copyComicsTo(const QList > & sourceComics, const QString & folderDest, const QModelIndex &dest); + void moveComicsTo(const QList > & comics, const QString & folderDest, const QModelIndex &dest); + static QList > getDroppedFiles(const QList & urls); +signals: + void currentComic(QString); + void progress(int); + void finished(); + void success(QModelIndex); //at least one comics has been copied or moved +public slots: + void process(); + void cancel(); + +protected: + bool move; + bool canceled; + QList > comics; + QString folder; + QModelIndex folderDestinationModelIndex; + +}; + +#endif // COMIC_FILES_MANAGER_H diff --git a/YACReaderLibrary/comic_flow.cpp b/YACReaderLibrary/comic_flow.cpp index 730687b4..375a645f 100644 --- a/YACReaderLibrary/comic_flow.cpp +++ b/YACReaderLibrary/comic_flow.cpp @@ -1,265 +1,265 @@ -#include "comic_flow.h" -#include "qnaturalsorting.h" - -#include "yacreader_global.h" - -#include - -#include -#include -#include - -ComicFlow::ComicFlow(QWidget* parent,FlowType flowType) -:YACReaderFlow(parent,flowType) -{ - updateTimer = new QTimer; - connect(updateTimer, SIGNAL(timeout()), this, SLOT(updateImageData())); - - worker = new ImageLoader; - connect(this, SIGNAL(centerIndexChanged(int)), this, SLOT(preload())); - connect(this, SIGNAL(centerIndexChangedSilent(int)), this, SLOT(preload())); - - setReflectionEffect(PlainReflection); -} - -ComicFlow::~ComicFlow() -{ - worker->terminate(); - delete worker; - delete updateTimer; -} - -void ComicFlow::setImagePaths(const QStringList& paths) -{ - clear(); - - //imagePath = path; - imageFiles = paths; - imagesLoaded.clear(); - imagesLoaded.fill(false,imageFiles.size()); - numImagesLoaded = 0; - - imagesSetted.clear(); - imagesSetted.fill(false,imageFiles.size()); - - // populate with empty images - QImage img; //TODO remove - QString s; - for(int i = 0; i < (int)imageFiles.size(); i++) - { - addSlide(img); - s = imageFiles.at(i); - s.remove(s.size()-4,4); - if(QFileInfo(s+".r").exists()) - markSlide(i); - } - - setCenterIndex(0); - worker->reset(); - preload(); -} - -void ComicFlow::preload() -{ - if(numImagesLoaded < imagesLoaded.size()) - updateTimer->start(30); //TODO comprobar rendimiento, originalmente era 70 -} - -void ComicFlow::updateImageData() -{ - // can't do anything, wait for the next possibility - if(worker->busy()) - return; - - // set image of last one - int idx = worker->index(); - if( idx >= 0 && !worker->result().isNull()) - { - if(!imagesSetted[idx]) - { - setSlide(idx, worker->result()); - imagesSetted[idx] = true; - numImagesLoaded++; - imagesLoaded[idx]=true; - } - } - - // try to load only few images on the left and right side - // i.e. all visible ones plus some extra -#define COUNT 8 - int indexes[2*COUNT+1]; - int center = centerIndex(); - indexes[0] = center; - for(int j = 0; j < COUNT; j++) - { - indexes[j*2+1] = center+j+1; - indexes[j*2+2] = center-j-1; - } - for(int c = 0; c < 2*COUNT+1; c++) - { - int i = indexes[c]; - if((i >= 0) && (i < slideCount())) - if(!imagesLoaded[i])//slide(i).isNull()) - { - // schedule thumbnail generation - QString fname = imageFiles[i]; - - - worker->generate(i, fname, slideSize()); - return; - } - } - - // no need to generate anything? stop polling... - updateTimer->stop(); -} - -void ComicFlow::keyPressEvent(QKeyEvent* event) -{ - PictureFlow::keyPressEvent(event); -} - -void ComicFlow::wheelEvent(QWheelEvent * event) -{ - if(event->delta()<0) - showNext(); - else - showPrevious(); - event->accept(); -} - -void ComicFlow::removeSlide(int cover) -{ - worker->lock(); - - worker->reset(); - - imageFiles.removeAt(cover); - if(imagesLoaded[cover]) - numImagesLoaded--; - imagesLoaded.remove(cover); - imagesSetted.remove(cover); - - YACReaderFlow::removeSlide(cover); - worker->unlock(); - - preload(); -} - -void ComicFlow::resortCovers(QList newOrder) -{ - worker->lock(); - worker->reset(); - - YACReaderFlow::resortCovers(newOrder); - - QStringList imageFilesNew; - QVector imagesLoadedNew; - QVector imagesSettedNew; - foreach(int index, newOrder) - { - imageFilesNew << imageFiles.at(index); - imagesLoadedNew << imagesLoaded.at(index); - imagesSettedNew << imagesSetted.at(index); - } - - - - imageFiles = imageFilesNew; - imagesLoaded = imagesLoadedNew; - imagesSetted = imagesSettedNew; - - worker->unlock(); -} -//----------------------------------------------------------------------------- -//ImageLoader -//----------------------------------------------------------------------------- -static QImage loadImage(const QString& fileName) -{ - QImage image; - bool result = image.load(fileName); - - if(!result) - return QImage(); - - return image; -} - -ImageLoader::ImageLoader(): -QThread(), restart(false), working(false), idx(-1) -{ -} - -ImageLoader::~ImageLoader() -{ - mutex.lock(); - condition.wakeOne(); - mutex.unlock(); - wait(); -} - -bool ImageLoader::busy() const -{ - return isRunning() ? working : false; -} - -void ImageLoader::generate(int index, const QString& fileName, QSize size) -{ - mutex.lock(); - this->idx = index; - this->fileName = fileName; - this->size = size; - this->img = QImage(); - mutex.unlock(); - - if (!isRunning()) - start(); - else - { - // already running, wake up whenever ready - restart = true; - condition.wakeOne(); - } -} - -void ImageLoader::lock() -{ - mutex.lock(); -} - -void ImageLoader::unlock() -{ - mutex.unlock(); -} - -void ImageLoader::run() -{ - for(;;) - { - // copy necessary data - mutex.lock(); - this->working = true; - QString fileName = this->fileName; - mutex.unlock(); - - QImage image = loadImage(fileName); - - // let everyone knows it is ready - mutex.lock(); - this->working = false; - this->img = image; - mutex.unlock(); - - // put to sleep - mutex.lock(); - if (!this->restart) - condition.wait(&mutex); - restart = false; - mutex.unlock(); - } -} - -QImage ImageLoader::result() -{ - return img; -} +#include "comic_flow.h" +#include "qnaturalsorting.h" + +#include "yacreader_global.h" + +#include + +#include +#include +#include + +ComicFlow::ComicFlow(QWidget* parent,FlowType flowType) +:YACReaderFlow(parent,flowType) +{ + updateTimer = new QTimer; + connect(updateTimer, SIGNAL(timeout()), this, SLOT(updateImageData())); + + worker = new ImageLoader; + connect(this, SIGNAL(centerIndexChanged(int)), this, SLOT(preload())); + connect(this, SIGNAL(centerIndexChangedSilent(int)), this, SLOT(preload())); + + setReflectionEffect(PlainReflection); +} + +ComicFlow::~ComicFlow() +{ + worker->terminate(); + delete worker; + delete updateTimer; +} + +void ComicFlow::setImagePaths(const QStringList& paths) +{ + clear(); + + //imagePath = path; + imageFiles = paths; + imagesLoaded.clear(); + imagesLoaded.fill(false,imageFiles.size()); + numImagesLoaded = 0; + + imagesSetted.clear(); + imagesSetted.fill(false,imageFiles.size()); + + // populate with empty images + QImage img; //TODO remove + QString s; + for(int i = 0; i < (int)imageFiles.size(); i++) + { + addSlide(img); + s = imageFiles.at(i); + s.remove(s.size()-4,4); + if(QFileInfo(s+".r").exists()) + markSlide(i); + } + + setCenterIndex(0); + worker->reset(); + preload(); +} + +void ComicFlow::preload() +{ + if(numImagesLoaded < imagesLoaded.size()) + updateTimer->start(30); //TODO comprobar rendimiento, originalmente era 70 +} + +void ComicFlow::updateImageData() +{ + // can't do anything, wait for the next possibility + if(worker->busy()) + return; + + // set image of last one + int idx = worker->index(); + if( idx >= 0 && !worker->result().isNull()) + { + if(!imagesSetted[idx]) + { + setSlide(idx, worker->result()); + imagesSetted[idx] = true; + numImagesLoaded++; + imagesLoaded[idx]=true; + } + } + + // try to load only few images on the left and right side + // i.e. all visible ones plus some extra +#define COUNT 8 + int indexes[2*COUNT+1]; + int center = centerIndex(); + indexes[0] = center; + for(int j = 0; j < COUNT; j++) + { + indexes[j*2+1] = center+j+1; + indexes[j*2+2] = center-j-1; + } + for(int c = 0; c < 2*COUNT+1; c++) + { + int i = indexes[c]; + if((i >= 0) && (i < slideCount())) + if(!imagesLoaded[i])//slide(i).isNull()) + { + // schedule thumbnail generation + QString fname = imageFiles[i]; + + + worker->generate(i, fname, slideSize()); + return; + } + } + + // no need to generate anything? stop polling... + updateTimer->stop(); +} + +void ComicFlow::keyPressEvent(QKeyEvent* event) +{ + PictureFlow::keyPressEvent(event); +} + +void ComicFlow::wheelEvent(QWheelEvent * event) +{ + if(event->delta()<0) + showNext(); + else + showPrevious(); + event->accept(); +} + +void ComicFlow::removeSlide(int cover) +{ + worker->lock(); + + worker->reset(); + + imageFiles.removeAt(cover); + if(imagesLoaded[cover]) + numImagesLoaded--; + imagesLoaded.remove(cover); + imagesSetted.remove(cover); + + YACReaderFlow::removeSlide(cover); + worker->unlock(); + + preload(); +} + +void ComicFlow::resortCovers(QList newOrder) +{ + worker->lock(); + worker->reset(); + + YACReaderFlow::resortCovers(newOrder); + + QStringList imageFilesNew; + QVector imagesLoadedNew; + QVector imagesSettedNew; + foreach(int index, newOrder) + { + imageFilesNew << imageFiles.at(index); + imagesLoadedNew << imagesLoaded.at(index); + imagesSettedNew << imagesSetted.at(index); + } + + + + imageFiles = imageFilesNew; + imagesLoaded = imagesLoadedNew; + imagesSetted = imagesSettedNew; + + worker->unlock(); +} +//----------------------------------------------------------------------------- +//ImageLoader +//----------------------------------------------------------------------------- +static QImage loadImage(const QString& fileName) +{ + QImage image; + bool result = image.load(fileName); + + if(!result) + return QImage(); + + return image; +} + +ImageLoader::ImageLoader(): +QThread(), restart(false), working(false), idx(-1) +{ +} + +ImageLoader::~ImageLoader() +{ + mutex.lock(); + condition.wakeOne(); + mutex.unlock(); + wait(); +} + +bool ImageLoader::busy() const +{ + return isRunning() ? working : false; +} + +void ImageLoader::generate(int index, const QString& fileName, QSize size) +{ + mutex.lock(); + this->idx = index; + this->fileName = fileName; + this->size = size; + this->img = QImage(); + mutex.unlock(); + + if (!isRunning()) + start(); + else + { + // already running, wake up whenever ready + restart = true; + condition.wakeOne(); + } +} + +void ImageLoader::lock() +{ + mutex.lock(); +} + +void ImageLoader::unlock() +{ + mutex.unlock(); +} + +void ImageLoader::run() +{ + for(;;) + { + // copy necessary data + mutex.lock(); + this->working = true; + QString fileName = this->fileName; + mutex.unlock(); + + QImage image = loadImage(fileName); + + // let everyone knows it is ready + mutex.lock(); + this->working = false; + this->img = image; + mutex.unlock(); + + // put to sleep + mutex.lock(); + if (!this->restart) + condition.wait(&mutex); + restart = false; + mutex.unlock(); + } +} + +QImage ImageLoader::result() +{ + return img; +} diff --git a/YACReaderLibrary/comic_flow.h b/YACReaderLibrary/comic_flow.h index c49543b3..ecb27916 100644 --- a/YACReaderLibrary/comic_flow.h +++ b/YACReaderLibrary/comic_flow.h @@ -1,78 +1,78 @@ -#ifndef __COMICFLOW_H -#define __COMICFLOW_H - -#include "yacreader_flow.h" - -#include -#include -#include -#include -#include -#include -#include -#include - -class ImageLoader; -class ComicFlow : public YACReaderFlow -{ - Q_OBJECT -public: - ComicFlow(QWidget* parent = 0,FlowType flowType = CoverFlowLike); - virtual ~ComicFlow(); - - void setImagePaths(const QStringList& paths); - //bool eventFilter(QObject *target, QEvent *event); - void keyPressEvent(QKeyEvent* event); - void removeSlide(int cover); - void resortCovers(QList newOrder); - -private slots: - void preload(); - void updateImageData(); - -private: - //QString imagePath; - QStringList imageFiles; - QVector imagesLoaded; - QVector imagesSetted; - int numImagesLoaded; - QTimer* updateTimer; - ImageLoader* worker; - virtual void wheelEvent(QWheelEvent * event); -}; - - -//----------------------------------------------------------------------------- -// Source code of ImageLoader class was modified from http://code.google.com/p/photoflow/ -//------------------------------------------------------------------------------ -class ImageLoader : public QThread -{ -public: - ImageLoader(); - ~ImageLoader(); - // returns FALSE if worker is still busy and can't take the task - bool busy() const; - void generate(int index, const QString& fileName, QSize size); - void reset(){idx = -1;}; - int index() const { return idx; }; - void lock(); - void unlock(); - QImage result(); - -protected: - void run(); - -private: - QMutex mutex; - QWaitCondition condition; - - bool restart; - bool working; - int idx; - QString fileName; - QSize size; - QImage img; -}; - - -#endif +#ifndef __COMICFLOW_H +#define __COMICFLOW_H + +#include "yacreader_flow.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +class ImageLoader; +class ComicFlow : public YACReaderFlow +{ + Q_OBJECT +public: + ComicFlow(QWidget* parent = 0,FlowType flowType = CoverFlowLike); + virtual ~ComicFlow(); + + void setImagePaths(const QStringList& paths); + //bool eventFilter(QObject *target, QEvent *event); + void keyPressEvent(QKeyEvent* event); + void removeSlide(int cover); + void resortCovers(QList newOrder); + +private slots: + void preload(); + void updateImageData(); + +private: + //QString imagePath; + QStringList imageFiles; + QVector imagesLoaded; + QVector imagesSetted; + int numImagesLoaded; + QTimer* updateTimer; + ImageLoader* worker; + virtual void wheelEvent(QWheelEvent * event); +}; + + +//----------------------------------------------------------------------------- +// Source code of ImageLoader class was modified from http://code.google.com/p/photoflow/ +//------------------------------------------------------------------------------ +class ImageLoader : public QThread +{ +public: + ImageLoader(); + ~ImageLoader(); + // returns FALSE if worker is still busy and can't take the task + bool busy() const; + void generate(int index, const QString& fileName, QSize size); + void reset(){idx = -1;}; + int index() const { return idx; }; + void lock(); + void unlock(); + QImage result(); + +protected: + void run(); + +private: + QMutex mutex; + QWaitCondition condition; + + bool restart; + bool working; + int idx; + QString fileName; + QSize size; + QImage img; +}; + + +#endif diff --git a/YACReaderLibrary/comic_flow_widget.cpp b/YACReaderLibrary/comic_flow_widget.cpp index e4326abc..e96dc684 100644 --- a/YACReaderLibrary/comic_flow_widget.cpp +++ b/YACReaderLibrary/comic_flow_widget.cpp @@ -1,355 +1,355 @@ -#include "comic_flow_widget.h" -#include -ComicFlowWidget::ComicFlowWidget(QWidget * parent) - :QWidget(parent) -{ - -} - -ComicFlowWidgetSW::ComicFlowWidgetSW(QWidget * parent) - :ComicFlowWidget(parent) -{ - flow = new ComicFlow(parent); - - connect(flow,SIGNAL(centerIndexChanged(int)),this,SIGNAL(centerIndexChanged(int))); - connect(flow,SIGNAL(selected(unsigned int)),this,SIGNAL(selected(unsigned int))); - - QVBoxLayout * l = new QVBoxLayout; - l->addWidget(flow); - setLayout(l); - - //TODO eleminar "padding" - QPalette Pal(palette()); - // set black background - Pal.setColor(QPalette::Background, Qt::black); - setAutoFillBackground(true); - setPalette(Pal); - - //config - QMatrix m; - m.rotate(-90); - m.scale(-1,1); - QImage image(":/images/setRead.png"); - QImage imageTransformed = image.transformed(m,Qt::SmoothTransformation); - setMarkImage(imageTransformed); -} - -QSize ComicFlowWidgetSW::minimumSizeHint() const -{ - return flow->minimumSizeHint(); -} -QSize ComicFlowWidgetSW::sizeHint() const -{ - return flow->sizeHint(); -} - -void ComicFlowWidgetSW::setShowMarks(bool value) -{ - flow->setShowMarks(value); -} -void ComicFlowWidgetSW::setMarks(QVector marks) -{ - flow->setMarks(marks); -} -void ComicFlowWidgetSW::setMarkImage(QImage & image) -{ - flow->setMarkImage(image); -} -void ComicFlowWidgetSW::markSlide(int index, YACReaderComicReadStatus status) -{ - flow->markSlide(index,status); -} -void ComicFlowWidgetSW::unmarkSlide(int index) -{ - flow->unmarkSlide(index); -} -void ComicFlowWidgetSW::setSlideSize(QSize size) -{ - flow->setSlideSize(size); -} -void ComicFlowWidgetSW::clear() -{ - flow->clear(); -} -void ComicFlowWidgetSW::setImagePaths(QStringList paths) -{ - flow->setImagePaths(paths); -} -void ComicFlowWidgetSW::setCenterIndex(int index) -{ - flow->setCenterIndex(index); -} -void ComicFlowWidgetSW::showSlide(int index) -{ - flow->showSlide(index); -} -int ComicFlowWidgetSW::centerIndex() -{ - return flow->centerIndex(); -} -void ComicFlowWidgetSW::updateMarks() -{ - flow->updateMarks(); -} -void ComicFlowWidgetSW::setFlowType(FlowType flowType) -{ - flow->setFlowType(flowType); -} -void ComicFlowWidgetSW::render() -{ - flow->render(); -} -void ComicFlowWidgetSW::keyPressEvent(QKeyEvent* event) -{ - flow->keyPressEvent(event); -} -void ComicFlowWidgetSW::paintEvent(QPaintEvent *event) -{ - flow->paintEvent(event); -} -void ComicFlowWidgetSW::mousePressEvent(QMouseEvent* event) -{ - flow->mousePressEvent(event); -} -void ComicFlowWidgetSW::resizeEvent(QResizeEvent* event) -{ - flow->resizeEvent(event); -} -void ComicFlowWidgetSW::mouseDoubleClickEvent(QMouseEvent* event) -{ - flow->mouseDoubleClickEvent(event); -} -void ComicFlowWidgetSW::updateConfig(QSettings * settings) -{ - switch (settings->value(FLOW_TYPE_SW).toInt()) - { - case CoverFlowLike: - flow->setFlowType(CoverFlowLike); - return; - case Strip: - flow->setFlowType(Strip); - return; - case StripOverlapped: - flow->setFlowType(StripOverlapped); - return; - } -} - -void ComicFlowWidgetSW::remove(int cover) -{ - flow->removeSlide(cover); -} - -void ComicFlowWidgetSW::resortCovers(QList newOrder) -{ - flow->resortCovers(newOrder); -} - -#ifndef NO_OPENGL -////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////// -///OpenGL ComicFlow -////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////// - -ComicFlowWidgetGL::ComicFlowWidgetGL(QWidget * parent) - :ComicFlowWidget(parent) -{ - flow = new YACReaderComicFlowGL(parent); - - connect(flow,SIGNAL(centerIndexChanged(int)),this,SIGNAL(centerIndexChanged(int))); - connect(flow,SIGNAL(selected(unsigned int)),this,SIGNAL(selected(unsigned int))); - - QVBoxLayout * l = new QVBoxLayout; - l->addWidget(flow); - l->setContentsMargins(0,0,0,0); - setLayout(l); - - //TODO eleminar "padding" - QPalette Pal(palette()); - // set black background - Pal.setColor(QPalette::Background, Qt::black); - setAutoFillBackground(true); - setPalette(Pal); -} - -QSize ComicFlowWidgetGL::minimumSizeHint() const -{ - return flow->minimumSizeHint(); -} -QSize ComicFlowWidgetGL::sizeHint() const -{ - return flow->sizeHint(); -} - -void ComicFlowWidgetGL::setShowMarks(bool value) -{ - flow->setShowMarks(value); -} -void ComicFlowWidgetGL::setMarks(QVector marks) -{ - flow->setMarks(marks); -} -void ComicFlowWidgetGL::setMarkImage(QImage & image) -{ - flow->setMarkImage(image); -} -void ComicFlowWidgetGL::markSlide(int index, YACReaderComicReadStatus status) -{ - flow->markSlide(index,status); -} -void ComicFlowWidgetGL::unmarkSlide(int index) -{ - flow->unmarkSlide(index); -} -void ComicFlowWidgetGL::setSlideSize(QSize size) -{ - flow->setSlideSize(size); -} -void ComicFlowWidgetGL::clear() -{ - flow->clear(); -} -void ComicFlowWidgetGL::setImagePaths(QStringList paths) -{ - flow->setImagePaths(paths); -} -void ComicFlowWidgetGL::setCenterIndex(int index) -{ - flow->setCenterIndex(index); -} -void ComicFlowWidgetGL::showSlide(int index) -{ - flow->showSlide(index); -} -int ComicFlowWidgetGL::centerIndex() -{ - return flow->centerIndex(); -} -void ComicFlowWidgetGL::updateMarks() -{ - flow->updateMarks(); -} -void ComicFlowWidgetGL::setFlowType(FlowType flowType) -{ - if(flowType == CoverFlowLike) - flow->setPreset(presetYACReaderFlowClassicConfig); - else if(flowType == Strip) - flow->setPreset(presetYACReaderFlowStripeConfig); - else if(flowType == StripOverlapped) - flow->setPreset(presetYACReaderFlowOverlappedStripeConfig); - else - flow->setPreset(defaultYACReaderFlowConfig); -} -void ComicFlowWidgetGL::render() -{ - flow->render(); -} -void ComicFlowWidgetGL::keyPressEvent(QKeyEvent* event) -{ - flow->keyPressEvent(event); -} -void ComicFlowWidgetGL::paintEvent(QPaintEvent *event) -{ - //flow->paintEvent(event); - ComicFlowWidget::paintEvent(event); -} -void ComicFlowWidgetGL::mousePressEvent(QMouseEvent* event) -{ - flow->mousePressEvent(event); -} -void ComicFlowWidgetGL::resizeEvent(QResizeEvent* event) -{ - flow->resizeGL(event->size().width(),event->size().height()); -} -void ComicFlowWidgetGL::mouseDoubleClickEvent(QMouseEvent* event) -{ - flow->mouseDoubleClickEvent(event); -} - -void ComicFlowWidgetGL::updateConfig(QSettings * settings) -{ - Performance performance = medium; - - switch (settings->value(PERFORMANCE).toInt()) - { - case 0: - performance = low; - break; - case 1: - performance = medium; - break; - case 2: - performance = high; - break; - case 3: - performance = ultraHigh; - break; - } - - flow->setPerformance(performance); - if(!settings->contains(V_SYNC)) - flow->useVSync(false); - else - flow->useVSync(settings->value(V_SYNC).toBool()); - - switch (settings->value(FLOW_TYPE_GL).toInt()) - { - case 0: - flow->setPreset(presetYACReaderFlowClassicConfig); - return; - case 1: - flow->setPreset(presetYACReaderFlowStripeConfig); - return; - case 2: - flow->setPreset(presetYACReaderFlowOverlappedStripeConfig); - return; - case 3: - flow->setPreset(defaultYACReaderFlowConfig); - return; - case 4: - flow->setPreset(pressetYACReaderFlowDownConfig); - return; - } - - - //custom config - - flow->setCF_RX(settings->value(X_ROTATION).toInt()); - flow->setCF_Y(settings->value(Y_POSITION).toInt()); - flow->setX_Distance(settings->value(COVER_DISTANCE).toInt()); - flow->setCenter_Distance(settings->value(CENTRAL_DISTANCE).toInt()); - flow->setCF_Z(settings->value(ZOOM_LEVEL).toInt()); - flow->setY_Distance(settings->value(Y_COVER_OFFSET).toInt()); - flow->setZ_Distance(settings->value(Z_COVER_OFFSET).toInt()); - flow->setRotation(settings->value(COVER_ROTATION).toInt()); - flow->setFadeOutDist(settings->value(FADE_OUT_DIST).toInt()); - flow->setLightStrenght(settings->value(LIGHT_STRENGTH).toInt()); - flow->setMaxAngle(settings->value(MAX_ANGLE).toInt()); - -/* flow->setVisibility(settings->value("visibilityDistance").toInt()); - flow->setLightStrenght(settings->value("lightStrength").toInt())*/; - -} - -void ComicFlowWidgetGL::remove(int cover) -{ - flow->remove(cover); -} - -void ComicFlowWidgetGL::resortCovers(QList newOrder) -{ - flow->resortCovers(newOrder); -} -#endif -//void ComicFlowWidgetGL::setCF_RX(int value){ flow->setCF_RX(value);} -//void ComicFlowWidgetGL::setCF_RY(int value){ flow->setCF_RY(value);} -//void ComicFlowWidgetGL::setCF_RZ(int value){ flow->setCF_RZ(value);} -//void ComicFlowWidgetGL::setZoom(int zoom){ flow->setZoom(zoom);} -//void ComicFlowWidgetGL::setRotation(int angle){ flow->setRotation(angle);} -//void ComicFlowWidgetGL::setX_Distance(int distance){ flow->setX_Distance(distance);} -//void ComicFlowWidgetGL::setCenter_Distance(int distance){ flow->setCenter_Distance(distance);} -//void ComicFlowWidgetGL::setZ_Distance(int distance){ flow->setZ_Distance(distance);} -//void ComicFlowWidgetGL::setCF_Y(int value){ flow->setCF_Y(value);} -//void ComicFlowWidgetGL::setY_Distance(int value){ flow->setY_Distance(value);} -//void ComicFlowWidgetGL::setPreset(const Preset & p){ flow->setPreset(p);} +#include "comic_flow_widget.h" +#include +ComicFlowWidget::ComicFlowWidget(QWidget * parent) + :QWidget(parent) +{ + +} + +ComicFlowWidgetSW::ComicFlowWidgetSW(QWidget * parent) + :ComicFlowWidget(parent) +{ + flow = new ComicFlow(parent); + + connect(flow,SIGNAL(centerIndexChanged(int)),this,SIGNAL(centerIndexChanged(int))); + connect(flow,SIGNAL(selected(unsigned int)),this,SIGNAL(selected(unsigned int))); + + QVBoxLayout * l = new QVBoxLayout; + l->addWidget(flow); + setLayout(l); + + //TODO eleminar "padding" + QPalette Pal(palette()); + // set black background + Pal.setColor(QPalette::Background, Qt::black); + setAutoFillBackground(true); + setPalette(Pal); + + //config + QMatrix m; + m.rotate(-90); + m.scale(-1,1); + QImage image(":/images/setRead.png"); + QImage imageTransformed = image.transformed(m,Qt::SmoothTransformation); + setMarkImage(imageTransformed); +} + +QSize ComicFlowWidgetSW::minimumSizeHint() const +{ + return flow->minimumSizeHint(); +} +QSize ComicFlowWidgetSW::sizeHint() const +{ + return flow->sizeHint(); +} + +void ComicFlowWidgetSW::setShowMarks(bool value) +{ + flow->setShowMarks(value); +} +void ComicFlowWidgetSW::setMarks(QVector marks) +{ + flow->setMarks(marks); +} +void ComicFlowWidgetSW::setMarkImage(QImage & image) +{ + flow->setMarkImage(image); +} +void ComicFlowWidgetSW::markSlide(int index, YACReaderComicReadStatus status) +{ + flow->markSlide(index,status); +} +void ComicFlowWidgetSW::unmarkSlide(int index) +{ + flow->unmarkSlide(index); +} +void ComicFlowWidgetSW::setSlideSize(QSize size) +{ + flow->setSlideSize(size); +} +void ComicFlowWidgetSW::clear() +{ + flow->clear(); +} +void ComicFlowWidgetSW::setImagePaths(QStringList paths) +{ + flow->setImagePaths(paths); +} +void ComicFlowWidgetSW::setCenterIndex(int index) +{ + flow->setCenterIndex(index); +} +void ComicFlowWidgetSW::showSlide(int index) +{ + flow->showSlide(index); +} +int ComicFlowWidgetSW::centerIndex() +{ + return flow->centerIndex(); +} +void ComicFlowWidgetSW::updateMarks() +{ + flow->updateMarks(); +} +void ComicFlowWidgetSW::setFlowType(FlowType flowType) +{ + flow->setFlowType(flowType); +} +void ComicFlowWidgetSW::render() +{ + flow->render(); +} +void ComicFlowWidgetSW::keyPressEvent(QKeyEvent* event) +{ + flow->keyPressEvent(event); +} +void ComicFlowWidgetSW::paintEvent(QPaintEvent *event) +{ + flow->paintEvent(event); +} +void ComicFlowWidgetSW::mousePressEvent(QMouseEvent* event) +{ + flow->mousePressEvent(event); +} +void ComicFlowWidgetSW::resizeEvent(QResizeEvent* event) +{ + flow->resizeEvent(event); +} +void ComicFlowWidgetSW::mouseDoubleClickEvent(QMouseEvent* event) +{ + flow->mouseDoubleClickEvent(event); +} +void ComicFlowWidgetSW::updateConfig(QSettings * settings) +{ + switch (settings->value(FLOW_TYPE_SW).toInt()) + { + case CoverFlowLike: + flow->setFlowType(CoverFlowLike); + return; + case Strip: + flow->setFlowType(Strip); + return; + case StripOverlapped: + flow->setFlowType(StripOverlapped); + return; + } +} + +void ComicFlowWidgetSW::remove(int cover) +{ + flow->removeSlide(cover); +} + +void ComicFlowWidgetSW::resortCovers(QList newOrder) +{ + flow->resortCovers(newOrder); +} + +#ifndef NO_OPENGL +////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// +///OpenGL ComicFlow +////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// + +ComicFlowWidgetGL::ComicFlowWidgetGL(QWidget * parent) + :ComicFlowWidget(parent) +{ + flow = new YACReaderComicFlowGL(parent); + + connect(flow,SIGNAL(centerIndexChanged(int)),this,SIGNAL(centerIndexChanged(int))); + connect(flow,SIGNAL(selected(unsigned int)),this,SIGNAL(selected(unsigned int))); + + QVBoxLayout * l = new QVBoxLayout; + l->addWidget(flow); + l->setContentsMargins(0,0,0,0); + setLayout(l); + + //TODO eleminar "padding" + QPalette Pal(palette()); + // set black background + Pal.setColor(QPalette::Background, Qt::black); + setAutoFillBackground(true); + setPalette(Pal); +} + +QSize ComicFlowWidgetGL::minimumSizeHint() const +{ + return flow->minimumSizeHint(); +} +QSize ComicFlowWidgetGL::sizeHint() const +{ + return flow->sizeHint(); +} + +void ComicFlowWidgetGL::setShowMarks(bool value) +{ + flow->setShowMarks(value); +} +void ComicFlowWidgetGL::setMarks(QVector marks) +{ + flow->setMarks(marks); +} +void ComicFlowWidgetGL::setMarkImage(QImage & image) +{ + flow->setMarkImage(image); +} +void ComicFlowWidgetGL::markSlide(int index, YACReaderComicReadStatus status) +{ + flow->markSlide(index,status); +} +void ComicFlowWidgetGL::unmarkSlide(int index) +{ + flow->unmarkSlide(index); +} +void ComicFlowWidgetGL::setSlideSize(QSize size) +{ + flow->setSlideSize(size); +} +void ComicFlowWidgetGL::clear() +{ + flow->clear(); +} +void ComicFlowWidgetGL::setImagePaths(QStringList paths) +{ + flow->setImagePaths(paths); +} +void ComicFlowWidgetGL::setCenterIndex(int index) +{ + flow->setCenterIndex(index); +} +void ComicFlowWidgetGL::showSlide(int index) +{ + flow->showSlide(index); +} +int ComicFlowWidgetGL::centerIndex() +{ + return flow->centerIndex(); +} +void ComicFlowWidgetGL::updateMarks() +{ + flow->updateMarks(); +} +void ComicFlowWidgetGL::setFlowType(FlowType flowType) +{ + if(flowType == CoverFlowLike) + flow->setPreset(presetYACReaderFlowClassicConfig); + else if(flowType == Strip) + flow->setPreset(presetYACReaderFlowStripeConfig); + else if(flowType == StripOverlapped) + flow->setPreset(presetYACReaderFlowOverlappedStripeConfig); + else + flow->setPreset(defaultYACReaderFlowConfig); +} +void ComicFlowWidgetGL::render() +{ + flow->render(); +} +void ComicFlowWidgetGL::keyPressEvent(QKeyEvent* event) +{ + flow->keyPressEvent(event); +} +void ComicFlowWidgetGL::paintEvent(QPaintEvent *event) +{ + //flow->paintEvent(event); + ComicFlowWidget::paintEvent(event); +} +void ComicFlowWidgetGL::mousePressEvent(QMouseEvent* event) +{ + flow->mousePressEvent(event); +} +void ComicFlowWidgetGL::resizeEvent(QResizeEvent* event) +{ + flow->resizeGL(event->size().width(),event->size().height()); +} +void ComicFlowWidgetGL::mouseDoubleClickEvent(QMouseEvent* event) +{ + flow->mouseDoubleClickEvent(event); +} + +void ComicFlowWidgetGL::updateConfig(QSettings * settings) +{ + Performance performance = medium; + + switch (settings->value(PERFORMANCE).toInt()) + { + case 0: + performance = low; + break; + case 1: + performance = medium; + break; + case 2: + performance = high; + break; + case 3: + performance = ultraHigh; + break; + } + + flow->setPerformance(performance); + if(!settings->contains(V_SYNC)) + flow->useVSync(false); + else + flow->useVSync(settings->value(V_SYNC).toBool()); + + switch (settings->value(FLOW_TYPE_GL).toInt()) + { + case 0: + flow->setPreset(presetYACReaderFlowClassicConfig); + return; + case 1: + flow->setPreset(presetYACReaderFlowStripeConfig); + return; + case 2: + flow->setPreset(presetYACReaderFlowOverlappedStripeConfig); + return; + case 3: + flow->setPreset(defaultYACReaderFlowConfig); + return; + case 4: + flow->setPreset(pressetYACReaderFlowDownConfig); + return; + } + + + //custom config + + flow->setCF_RX(settings->value(X_ROTATION).toInt()); + flow->setCF_Y(settings->value(Y_POSITION).toInt()); + flow->setX_Distance(settings->value(COVER_DISTANCE).toInt()); + flow->setCenter_Distance(settings->value(CENTRAL_DISTANCE).toInt()); + flow->setCF_Z(settings->value(ZOOM_LEVEL).toInt()); + flow->setY_Distance(settings->value(Y_COVER_OFFSET).toInt()); + flow->setZ_Distance(settings->value(Z_COVER_OFFSET).toInt()); + flow->setRotation(settings->value(COVER_ROTATION).toInt()); + flow->setFadeOutDist(settings->value(FADE_OUT_DIST).toInt()); + flow->setLightStrenght(settings->value(LIGHT_STRENGTH).toInt()); + flow->setMaxAngle(settings->value(MAX_ANGLE).toInt()); + +/* flow->setVisibility(settings->value("visibilityDistance").toInt()); + flow->setLightStrenght(settings->value("lightStrength").toInt())*/; + +} + +void ComicFlowWidgetGL::remove(int cover) +{ + flow->remove(cover); +} + +void ComicFlowWidgetGL::resortCovers(QList newOrder) +{ + flow->resortCovers(newOrder); +} +#endif +//void ComicFlowWidgetGL::setCF_RX(int value){ flow->setCF_RX(value);} +//void ComicFlowWidgetGL::setCF_RY(int value){ flow->setCF_RY(value);} +//void ComicFlowWidgetGL::setCF_RZ(int value){ flow->setCF_RZ(value);} +//void ComicFlowWidgetGL::setZoom(int zoom){ flow->setZoom(zoom);} +//void ComicFlowWidgetGL::setRotation(int angle){ flow->setRotation(angle);} +//void ComicFlowWidgetGL::setX_Distance(int distance){ flow->setX_Distance(distance);} +//void ComicFlowWidgetGL::setCenter_Distance(int distance){ flow->setCenter_Distance(distance);} +//void ComicFlowWidgetGL::setZ_Distance(int distance){ flow->setZ_Distance(distance);} +//void ComicFlowWidgetGL::setCF_Y(int value){ flow->setCF_Y(value);} +//void ComicFlowWidgetGL::setY_Distance(int value){ flow->setY_Distance(value);} +//void ComicFlowWidgetGL::setPreset(const Preset & p){ flow->setPreset(p);} diff --git a/YACReaderLibrary/comic_flow_widget.h b/YACReaderLibrary/comic_flow_widget.h index 10f68486..014c8ac0 100644 --- a/YACReaderLibrary/comic_flow_widget.h +++ b/YACReaderLibrary/comic_flow_widget.h @@ -1,133 +1,133 @@ -#ifndef __COMIC_FLOW_WIDGET_H -#define __COMIC_FLOW_WIDGET_H - - -#include - -#include "pictureflow.h" -#include "comic_flow.h" -#ifndef NO_OPENGL -#include "yacreader_flow_gl.h" -#endif -class ComicFlowWidget : public QWidget -{ - Q_OBJECT -public: - ComicFlowWidget(QWidget * paret = 0); - -public slots: - virtual void setShowMarks(bool value) = 0; - virtual void setMarks(QVector marks) = 0; - virtual void setMarkImage(QImage & image) = 0; - virtual void markSlide(int index, YACReaderComicReadStatus status) = 0; - virtual void unmarkSlide(int index) = 0; - virtual void setSlideSize(QSize size) = 0; - virtual void clear() = 0; - virtual void setImagePaths(QStringList paths) = 0; - virtual void setCenterIndex(int index) = 0; - virtual void showSlide(int index) = 0; - virtual int centerIndex() = 0; - virtual void updateMarks() = 0; - virtual void setFlowType(FlowType flowType) = 0; - virtual void render() = 0; - virtual void updateConfig(QSettings * settings) = 0; - virtual void remove(int cover) = 0; - virtual void resortCovers(QList newOrder) = 0; -signals: - void centerIndexChanged(int); - void selected(unsigned int); -}; - - -class ComicFlowWidgetSW : public ComicFlowWidget -{ - Q_OBJECT -private: - ComicFlow * flow; -public: - ComicFlowWidgetSW(QWidget * parent = 0); - - void setShowMarks(bool value); - void setMarks(QVector marks); - void setMarkImage(QImage & image); - void markSlide(int index, YACReaderComicReadStatus status); - void unmarkSlide(int index); - void setSlideSize(QSize size); - void clear(); - void setImagePaths(QStringList paths); - void setCenterIndex(int index); - void showSlide(int index); - int centerIndex(); - void updateMarks(); - void setFlowType(FlowType flowType); - void render(); - void updateConfig(QSettings * settings); - void remove(int cover); - void resortCovers(QList newOrder); -protected: - void keyPressEvent(QKeyEvent* event); - void paintEvent(QPaintEvent *event); - void mousePressEvent(QMouseEvent* event); - void resizeEvent(QResizeEvent* event); - void mouseDoubleClickEvent(QMouseEvent* event); - QSize minimumSizeHint() const; - QSize sizeHint() const; - QSize slideSizeW; - QSize slideSizeF; -}; - -#ifndef NO_OPENGL -class ComicFlowWidgetGL : public ComicFlowWidget -{ - Q_OBJECT -private: - YACReaderComicFlowGL * flow; -public: - ComicFlowWidgetGL(QWidget * parent = 0); - - void setShowMarks(bool value); - void setMarks(QVector marks); - void setMarkImage(QImage & image); - void markSlide(int index, YACReaderComicReadStatus status); - void unmarkSlide(int index); - void setSlideSize(QSize size); - void clear(); - void setImagePaths(QStringList paths); - void setCenterIndex(int index); - void showSlide(int index); - int centerIndex(); - void updateMarks(); - void setFlowType(FlowType flowType); - void render(); - void updateConfig(QSettings * settings); - void remove(int cover); - void resortCovers(QList newOrder); -//public slots: -// void setCF_RX(int value); -// //the Y Rotation of the Coverflow -// void setCF_RY(int value); -// //the Z Rotation of the Coverflow -// void setCF_RZ(int value); -// //perspective -// void setZoom(int zoom); -// void setRotation(int angle); -// //sets the distance between the covers -// void setX_Distance(int distance); -// //sets the distance between the centered and the non centered covers -// void setCenter_Distance(int distance); -// //sets the pushback amount -// void setZ_Distance(int distance); -// void setCF_Y(int value); -// void setY_Distance(int value); -// void setPreset(const Preset & p); -protected: - void keyPressEvent(QKeyEvent* event); - void paintEvent(QPaintEvent *event); - void mousePressEvent(QMouseEvent* event); - void resizeEvent(QResizeEvent* event); - void mouseDoubleClickEvent(QMouseEvent* event); - QSize minimumSizeHint() const; - QSize sizeHint() const; -}; -#endif -#endif +#ifndef __COMIC_FLOW_WIDGET_H +#define __COMIC_FLOW_WIDGET_H + + +#include + +#include "pictureflow.h" +#include "comic_flow.h" +#ifndef NO_OPENGL +#include "yacreader_flow_gl.h" +#endif +class ComicFlowWidget : public QWidget +{ + Q_OBJECT +public: + ComicFlowWidget(QWidget * paret = 0); + +public slots: + virtual void setShowMarks(bool value) = 0; + virtual void setMarks(QVector marks) = 0; + virtual void setMarkImage(QImage & image) = 0; + virtual void markSlide(int index, YACReaderComicReadStatus status) = 0; + virtual void unmarkSlide(int index) = 0; + virtual void setSlideSize(QSize size) = 0; + virtual void clear() = 0; + virtual void setImagePaths(QStringList paths) = 0; + virtual void setCenterIndex(int index) = 0; + virtual void showSlide(int index) = 0; + virtual int centerIndex() = 0; + virtual void updateMarks() = 0; + virtual void setFlowType(FlowType flowType) = 0; + virtual void render() = 0; + virtual void updateConfig(QSettings * settings) = 0; + virtual void remove(int cover) = 0; + virtual void resortCovers(QList newOrder) = 0; +signals: + void centerIndexChanged(int); + void selected(unsigned int); +}; + + +class ComicFlowWidgetSW : public ComicFlowWidget +{ + Q_OBJECT +private: + ComicFlow * flow; +public: + ComicFlowWidgetSW(QWidget * parent = 0); + + void setShowMarks(bool value); + void setMarks(QVector marks); + void setMarkImage(QImage & image); + void markSlide(int index, YACReaderComicReadStatus status); + void unmarkSlide(int index); + void setSlideSize(QSize size); + void clear(); + void setImagePaths(QStringList paths); + void setCenterIndex(int index); + void showSlide(int index); + int centerIndex(); + void updateMarks(); + void setFlowType(FlowType flowType); + void render(); + void updateConfig(QSettings * settings); + void remove(int cover); + void resortCovers(QList newOrder); +protected: + void keyPressEvent(QKeyEvent* event); + void paintEvent(QPaintEvent *event); + void mousePressEvent(QMouseEvent* event); + void resizeEvent(QResizeEvent* event); + void mouseDoubleClickEvent(QMouseEvent* event); + QSize minimumSizeHint() const; + QSize sizeHint() const; + QSize slideSizeW; + QSize slideSizeF; +}; + +#ifndef NO_OPENGL +class ComicFlowWidgetGL : public ComicFlowWidget +{ + Q_OBJECT +private: + YACReaderComicFlowGL * flow; +public: + ComicFlowWidgetGL(QWidget * parent = 0); + + void setShowMarks(bool value); + void setMarks(QVector marks); + void setMarkImage(QImage & image); + void markSlide(int index, YACReaderComicReadStatus status); + void unmarkSlide(int index); + void setSlideSize(QSize size); + void clear(); + void setImagePaths(QStringList paths); + void setCenterIndex(int index); + void showSlide(int index); + int centerIndex(); + void updateMarks(); + void setFlowType(FlowType flowType); + void render(); + void updateConfig(QSettings * settings); + void remove(int cover); + void resortCovers(QList newOrder); +//public slots: +// void setCF_RX(int value); +// //the Y Rotation of the Coverflow +// void setCF_RY(int value); +// //the Z Rotation of the Coverflow +// void setCF_RZ(int value); +// //perspective +// void setZoom(int zoom); +// void setRotation(int angle); +// //sets the distance between the covers +// void setX_Distance(int distance); +// //sets the distance between the centered and the non centered covers +// void setCenter_Distance(int distance); +// //sets the pushback amount +// void setZ_Distance(int distance); +// void setCF_Y(int value); +// void setY_Distance(int value); +// void setPreset(const Preset & p); +protected: + void keyPressEvent(QKeyEvent* event); + void paintEvent(QPaintEvent *event); + void mousePressEvent(QMouseEvent* event); + void resizeEvent(QResizeEvent* event); + void mouseDoubleClickEvent(QMouseEvent* event); + QSize minimumSizeHint() const; + QSize sizeHint() const; +}; +#endif +#endif diff --git a/YACReaderLibrary/comic_vine/api_key_dialog.cpp b/YACReaderLibrary/comic_vine/api_key_dialog.cpp index 81b99e0f..fd45af96 100644 --- a/YACReaderLibrary/comic_vine/api_key_dialog.cpp +++ b/YACReaderLibrary/comic_vine/api_key_dialog.cpp @@ -1,68 +1,68 @@ -#include "api_key_dialog.h" - -#include -#include -#include -#include -#include -#include - -#include "yacreader_global_gui.h" - -ApiKeyDialog::ApiKeyDialog(QWidget *parent) : - QDialog(parent) -{ - QVBoxLayout * layout = new QVBoxLayout; - QHBoxLayout * buttonsLayout = new QHBoxLayout; - - settings = new QSettings(YACReader::getSettingsPath()+"/YACReaderLibrary.ini",QSettings::IniFormat); //TODO unificar la creación del fichero de config con el servidor - settings->beginGroup("ComicVine"); - - QLabel * info = new QLabel(tr("Before you can connect to Comic Vine, you need your own API key. Please, get one free here")); - info->setWordWrap(true); - info->setOpenExternalLinks(true); - edit = new QLineEdit(); - edit->setPlaceholderText(tr("Paste here your Comic Vine API key")); - connect(edit,SIGNAL(textChanged(QString)),this,SLOT(enableAccept(QString))); - - acceptButton = new QPushButton(tr("Accept")); - acceptButton->setDisabled(true); - connect(acceptButton,SIGNAL(clicked()),this,SLOT(saveApiKey())); - - cancelButton = new QPushButton(tr("Cancel")); - connect(cancelButton,SIGNAL(clicked()),this,SLOT(reject())); - - layout->addWidget(info); - layout->addWidget(edit); - layout->addStretch(); - - buttonsLayout->addStretch(); - buttonsLayout->addWidget(acceptButton); - buttonsLayout->addWidget(cancelButton); - - layout->addLayout(buttonsLayout); - - setLayout(layout); - - resize(400,150); - - if(settings->contains(COMIC_VINE_API_KEY)) - edit->setText(settings->value(COMIC_VINE_API_KEY).toString()); -} - -ApiKeyDialog::~ApiKeyDialog() -{ - delete settings; -} - -void ApiKeyDialog::enableAccept(const QString &text) -{ - //TODO key validation - acceptButton->setEnabled(!text.isEmpty()); -} - -void ApiKeyDialog::saveApiKey() -{ - settings->setValue(COMIC_VINE_API_KEY,edit->text().trimmed()); - accept(); -} +#include "api_key_dialog.h" + +#include +#include +#include +#include +#include +#include + +#include "yacreader_global_gui.h" + +ApiKeyDialog::ApiKeyDialog(QWidget *parent) : + QDialog(parent) +{ + QVBoxLayout * layout = new QVBoxLayout; + QHBoxLayout * buttonsLayout = new QHBoxLayout; + + settings = new QSettings(YACReader::getSettingsPath()+"/YACReaderLibrary.ini",QSettings::IniFormat); //TODO unificar la creación del fichero de config con el servidor + settings->beginGroup("ComicVine"); + + QLabel * info = new QLabel(tr("Before you can connect to Comic Vine, you need your own API key. Please, get one free here")); + info->setWordWrap(true); + info->setOpenExternalLinks(true); + edit = new QLineEdit(); + edit->setPlaceholderText(tr("Paste here your Comic Vine API key")); + connect(edit,SIGNAL(textChanged(QString)),this,SLOT(enableAccept(QString))); + + acceptButton = new QPushButton(tr("Accept")); + acceptButton->setDisabled(true); + connect(acceptButton,SIGNAL(clicked()),this,SLOT(saveApiKey())); + + cancelButton = new QPushButton(tr("Cancel")); + connect(cancelButton,SIGNAL(clicked()),this,SLOT(reject())); + + layout->addWidget(info); + layout->addWidget(edit); + layout->addStretch(); + + buttonsLayout->addStretch(); + buttonsLayout->addWidget(acceptButton); + buttonsLayout->addWidget(cancelButton); + + layout->addLayout(buttonsLayout); + + setLayout(layout); + + resize(400,150); + + if(settings->contains(COMIC_VINE_API_KEY)) + edit->setText(settings->value(COMIC_VINE_API_KEY).toString()); +} + +ApiKeyDialog::~ApiKeyDialog() +{ + delete settings; +} + +void ApiKeyDialog::enableAccept(const QString &text) +{ + //TODO key validation + acceptButton->setEnabled(!text.isEmpty()); +} + +void ApiKeyDialog::saveApiKey() +{ + settings->setValue(COMIC_VINE_API_KEY,edit->text().trimmed()); + accept(); +} diff --git a/YACReaderLibrary/comic_vine/api_key_dialog.h b/YACReaderLibrary/comic_vine/api_key_dialog.h index 13ff5750..0d8fc153 100644 --- a/YACReaderLibrary/comic_vine/api_key_dialog.h +++ b/YACReaderLibrary/comic_vine/api_key_dialog.h @@ -1,31 +1,31 @@ -#ifndef API_KEY_DIALOG_H -#define API_KEY_DIALOG_H - -#include - -class QPushButton; -class QLineEdit; -class QSettings; - -class ApiKeyDialog : public QDialog -{ - Q_OBJECT -public: - explicit ApiKeyDialog(QWidget *parent = 0); - ~ApiKeyDialog(); -signals: - -public slots: - -protected slots: - void enableAccept(const QString & text); - void saveApiKey(); - -protected: - QPushButton * acceptButton; - QPushButton * cancelButton; - QLineEdit * edit; - QSettings * settings; -}; - -#endif // API_KEY_DIALOG_H +#ifndef API_KEY_DIALOG_H +#define API_KEY_DIALOG_H + +#include + +class QPushButton; +class QLineEdit; +class QSettings; + +class ApiKeyDialog : public QDialog +{ + Q_OBJECT +public: + explicit ApiKeyDialog(QWidget *parent = 0); + ~ApiKeyDialog(); +signals: + +public slots: + +protected slots: + void enableAccept(const QString & text); + void saveApiKey(); + +protected: + QPushButton * acceptButton; + QPushButton * cancelButton; + QLineEdit * edit; + QSettings * settings; +}; + +#endif // API_KEY_DIALOG_H diff --git a/YACReaderLibrary/comic_vine/comic_vine_all_volume_comics_retriever.cpp b/YACReaderLibrary/comic_vine/comic_vine_all_volume_comics_retriever.cpp index 9d6e463c..a6c79d98 100644 --- a/YACReaderLibrary/comic_vine/comic_vine_all_volume_comics_retriever.cpp +++ b/YACReaderLibrary/comic_vine/comic_vine_all_volume_comics_retriever.cpp @@ -1,97 +1,97 @@ -#include "comic_vine_all_volume_comics_retriever.h" - -#include "http_worker.h" -#include "response_parser.h" - -#include - -ComicVineAllVolumeComicsRetriever::ComicVineAllVolumeComicsRetriever(const QString &volumeURLString, QObject *parent) - : QObject(parent), volumeURLString(volumeURLString) -{ - -} - -void ComicVineAllVolumeComicsRetriever::getAllVolumeComics() -{ - getAllVolumeComics(0); -} - -void ComicVineAllVolumeComicsRetriever::getAllVolumeComics(int range) -{ - HttpWorker * search = new HttpWorker(volumeURLString.arg(range)); - connect(search,SIGNAL(dataReady(const QByteArray &)),this,SLOT(appendVolumeComicsInfo(const QByteArray &))); - connect(search,SIGNAL(timeout()),this,SIGNAL(timeOut())); - connect(search,SIGNAL(timeout()),this,SIGNAL(finished())); - connect(search,SIGNAL(finished()),search,SLOT(deleteLater())); - search->get(); -} - -void ComicVineAllVolumeComicsRetriever::appendVolumeComicsInfo(const QByteArray &data) -{ - QString json(data); - - jsonResponses.append(data); - - ResponseParser rp; - rp.loadJSONResponse(json); - - qint32 currentPage = rp.getCurrentPage(); - qint32 totalPages = rp.getTotalPages(); - - bool isLastResponse = currentPage == totalPages; - - if (!isLastResponse) { - getAllVolumeComics(currentPage * 100); - } - else - { - emit allVolumeComicsInfo(consolidateJSON()); - emit finished(); - } -} - -QString ComicVineAllVolumeComicsRetriever::consolidateJSON() -{ - QJsonObject consolidatedJSON; - QJsonArray comicsInfo; - - foreach (QByteArray json, jsonResponses) { - QJsonDocument doc = QJsonDocument::fromJson(json); - - if(doc.isNull() || !doc.isObject() || doc.isEmpty()) - { - continue; - } - - QJsonObject main = doc.object(); - QJsonValue error = main["error"]; - - if (error.isUndefined() || error.toString() != "OK") - { - continue; - } - else - { - QJsonValue results = main["results"]; - if (results.isUndefined() || !results.isArray()) - { - continue; - } - - QJsonArray resultsArray = results.toArray(); - foreach (const QJsonValue & v, resultsArray) - comicsInfo.append(v); - } - } - - consolidatedJSON["error"] = "OK"; - consolidatedJSON["status_code"] = 1; - consolidatedJSON["number_of_total_results"] = comicsInfo.size(); - consolidatedJSON["offset"] = 0; - consolidatedJSON["results"] = comicsInfo; - - QJsonDocument doc(consolidatedJSON); - return doc.toJson(QJsonDocument::Compact); -} - - +#include "comic_vine_all_volume_comics_retriever.h" + +#include "http_worker.h" +#include "response_parser.h" + +#include + +ComicVineAllVolumeComicsRetriever::ComicVineAllVolumeComicsRetriever(const QString &volumeURLString, QObject *parent) + : QObject(parent), volumeURLString(volumeURLString) +{ + +} + +void ComicVineAllVolumeComicsRetriever::getAllVolumeComics() +{ + getAllVolumeComics(0); +} + +void ComicVineAllVolumeComicsRetriever::getAllVolumeComics(int range) +{ + HttpWorker * search = new HttpWorker(volumeURLString.arg(range)); + connect(search,SIGNAL(dataReady(const QByteArray &)),this,SLOT(appendVolumeComicsInfo(const QByteArray &))); + connect(search,SIGNAL(timeout()),this,SIGNAL(timeOut())); + connect(search,SIGNAL(timeout()),this,SIGNAL(finished())); + connect(search,SIGNAL(finished()),search,SLOT(deleteLater())); + search->get(); +} + +void ComicVineAllVolumeComicsRetriever::appendVolumeComicsInfo(const QByteArray &data) +{ + QString json(data); + + jsonResponses.append(data); + + ResponseParser rp; + rp.loadJSONResponse(json); + + qint32 currentPage = rp.getCurrentPage(); + qint32 totalPages = rp.getTotalPages(); + + bool isLastResponse = currentPage == totalPages; + + if (!isLastResponse) { + getAllVolumeComics(currentPage * 100); + } + else + { + emit allVolumeComicsInfo(consolidateJSON()); + emit finished(); + } +} + +QString ComicVineAllVolumeComicsRetriever::consolidateJSON() +{ + QJsonObject consolidatedJSON; + QJsonArray comicsInfo; + + foreach (QByteArray json, jsonResponses) { + QJsonDocument doc = QJsonDocument::fromJson(json); + + if(doc.isNull() || !doc.isObject() || doc.isEmpty()) + { + continue; + } + + QJsonObject main = doc.object(); + QJsonValue error = main["error"]; + + if (error.isUndefined() || error.toString() != "OK") + { + continue; + } + else + { + QJsonValue results = main["results"]; + if (results.isUndefined() || !results.isArray()) + { + continue; + } + + QJsonArray resultsArray = results.toArray(); + foreach (const QJsonValue & v, resultsArray) + comicsInfo.append(v); + } + } + + consolidatedJSON["error"] = "OK"; + consolidatedJSON["status_code"] = 1; + consolidatedJSON["number_of_total_results"] = comicsInfo.size(); + consolidatedJSON["offset"] = 0; + consolidatedJSON["results"] = comicsInfo; + + QJsonDocument doc(consolidatedJSON); + return doc.toJson(QJsonDocument::Compact); +} + + diff --git a/YACReaderLibrary/comic_vine/comic_vine_all_volume_comics_retriever.h b/YACReaderLibrary/comic_vine/comic_vine_all_volume_comics_retriever.h index ea90d5bd..65e21a0d 100644 --- a/YACReaderLibrary/comic_vine/comic_vine_all_volume_comics_retriever.h +++ b/YACReaderLibrary/comic_vine/comic_vine_all_volume_comics_retriever.h @@ -1,28 +1,28 @@ -#ifndef COMIC_VINE_ALL_VOLUME_COMICS_RETRIEVER_H -#define COMIC_VINE_ALL_VOLUME_COMICS_RETRIEVER_H - -#include - -class ComicVineAllVolumeComicsRetriever : public QObject -{ - Q_OBJECT -public: - explicit ComicVineAllVolumeComicsRetriever(const QString &volumeURLString, QObject *parent = 0); - void getAllVolumeComics(); -protected: - void getAllVolumeComics(const int range); -signals: - void allVolumeComicsInfo(QString json); - void finished(); - void timeOut(); -protected slots: - void appendVolumeComicsInfo(const QByteArray &data); - -protected: - QString volumeURLString; - QList jsonResponses; - - QString consolidateJSON(); -}; - -#endif // COMIC_VINE_ALL_VOLUME_COMICS_RETRIEVER_H +#ifndef COMIC_VINE_ALL_VOLUME_COMICS_RETRIEVER_H +#define COMIC_VINE_ALL_VOLUME_COMICS_RETRIEVER_H + +#include + +class ComicVineAllVolumeComicsRetriever : public QObject +{ + Q_OBJECT +public: + explicit ComicVineAllVolumeComicsRetriever(const QString &volumeURLString, QObject *parent = 0); + void getAllVolumeComics(); +protected: + void getAllVolumeComics(const int range); +signals: + void allVolumeComicsInfo(QString json); + void finished(); + void timeOut(); +protected slots: + void appendVolumeComicsInfo(const QByteArray &data); + +protected: + QString volumeURLString; + QList jsonResponses; + + QString consolidateJSON(); +}; + +#endif // COMIC_VINE_ALL_VOLUME_COMICS_RETRIEVER_H diff --git a/YACReaderLibrary/comic_vine/comic_vine_client.cpp b/YACReaderLibrary/comic_vine/comic_vine_client.cpp index 0f2616ee..c8d1d13b 100644 --- a/YACReaderLibrary/comic_vine/comic_vine_client.cpp +++ b/YACReaderLibrary/comic_vine/comic_vine_client.cpp @@ -1,189 +1,189 @@ -#include "comic_vine_client.h" -#include "yacreader_global_gui.h" - -#include "comic_vine_all_volume_comics_retriever.h" - -//this is the API key used by YACReader to access Comic Vine -//please, do not use it in your own software, get one for free at Comic Vine -static const QString CV_API_KEY = "%CV_API_KEY%"; //get from settings -static const QString CV_API_KEY_DEFAULT = "46680bebb358f1de690a5a365e15d325f9649f91"; - -static const QString CV_WEB_ADDRESS = "%CV_WEB_ADDRESS%"; //get from settings - -//gets any volumen containing any comic matching 'query' -static const QString CV_SEARCH = CV_WEB_ADDRESS + "/search/?api_key=" + CV_API_KEY + - "&format=json&limit=100&resources=volume" - "&field_list=name,start_year,publisher,id,image,count_of_issues,deck" - "&sort=name:asc" - "&query=%1&page=%2"; -//http://www.comicvine.com/api/search/?api_key=46680bebb358f1de690a5a365e15d325f9649f91&format=json&limit=100&resources=volume&field_list=name,start_year,publisher,id,image,count_of_issues,deck&query=superman - -//gets the detail for a volume %1 -static const QString CV_SERIES_DETAIL = CV_WEB_ADDRESS + "/volume/4050-%1/?api_key=" + CV_API_KEY + - "&format=json&field_list=name,start_year,publisher,image,count_of_issues,id,description"; - -//gets info for comics in a volume id %1 -static const QString CV_COMICS_INFO = CV_WEB_ADDRESS + "/issues/?api_key=" + CV_API_KEY + - "&limit=1000&format=json&field_list=name,issue_number,id,image&filter=volume:%1" - "&sort=cover_date:asc" //sorting by cover_date, because comic vine doesn't use natural sorting (issue_number -> 1 10 11 ... 100 2 20 21....) - "&offset=%2"; - -//"http://www.comicvine.com/api/issues/?api_key=46680bebb358f1de690a5a365e15d325f9649f91&format=json&field_list=name,issue_number,id,image&filter=volume:%1&page=%2 - -//gets id for comic number %2 in a volume id %1 -static const QString CV_COMIC_ID = CV_WEB_ADDRESS + "/issues/?api_key=" + CV_API_KEY + - "&format=json&field_list=name,issue_number,id,image" - "&filter=volume:%1,issue_number:%2"; -//gets comic detail -static const QString CV_COMIC_DETAIL = CV_WEB_ADDRESS + "/issue/4000-%1/?api_key=" + CV_API_KEY + "&format=json"; -//http://www.comicvine.com/api/issue/4000-%1/?api_key=46680bebb358f1de690a5a365e15d325f9649f91&format=json - -//gets comic cover URL -static const QString CV_COVER_URL = CV_WEB_ADDRESS + "/issue/4000-%1/?api_key=" + CV_API_KEY + "&format=json&field_list=image"; - -//gets comics matching name %1 and number %2 -//http://comicvine.com/api/issues/?api_key=46680bebb358f1de690a5a365e15d325f9649f91&limit=20&filter=name:super,issue_number:15 - -ComicVineClient::ComicVineClient(QObject *parent) : - QObject(parent) -{ - settings = new QSettings(YACReader::getSettingsPath()+"/YACReaderLibrary.ini",QSettings::IniFormat); //TODO unificar la creación del fichero de config con el servidor - settings->beginGroup("ComicVine"); - baseURL = settings->value(COMIC_VINE_BASE_URL, "https://comicvine.gamespot.com/api").toString(); -} - -ComicVineClient::~ComicVineClient() -{ - delete settings; -} - -//CV_SEARCH -void ComicVineClient::search(const QString & query, int page) -{ - HttpWorker * search = new HttpWorker(QString(CV_SEARCH).replace(CV_WEB_ADDRESS, baseURL).replace(CV_API_KEY,settings->value(COMIC_VINE_API_KEY,CV_API_KEY_DEFAULT).toString()).arg(query).arg(page)); - connect(search,SIGNAL(dataReady(const QByteArray &)),this,SLOT(proccessVolumesSearchData(const QByteArray &))); - connect(search,SIGNAL(timeout()),this,SIGNAL(timeOut())); - connect(search,SIGNAL(finished()),search,SLOT(deleteLater())); - search->get(); -} -//CV_SEARCH result -void ComicVineClient::proccessVolumesSearchData(const QByteArray & data) -{ - QString json(data); - emit searchResult(json); - emit finished(); -} - -void ComicVineClient::proccessSeriesDetailData(const QByteArray &data) -{ - QString json(data); - emit seriesDetail(json); - emit finished(); -} - -void ComicVineClient::processVolumeComicsInfo(const QByteArray &data) -{ - QString json(data); - emit volumeComicsInfo(json); - emit finished(); -} - -void ComicVineClient::proccessComicDetailData(const QByteArray &data) -{ - QString json(data); - emit comicDetail(json); - emit finished(); -} - -//CV_SERIES_DETAIL -void ComicVineClient::getSeriesDetail(const QString & id) -{ - HttpWorker * search = new HttpWorker(QString(CV_SERIES_DETAIL).replace(CV_WEB_ADDRESS, baseURL).replace(CV_API_KEY,settings->value(COMIC_VINE_API_KEY,CV_API_KEY_DEFAULT).toString()).arg(id)); - connect(search,SIGNAL(dataReady(const QByteArray &)),this,SLOT(proccessSeriesDetailData(const QByteArray &))); - connect(search,SIGNAL(timeout()),this,SIGNAL(timeOut())); - connect(search,SIGNAL(finished()),search,SLOT(deleteLater())); - search->get(); -} - -void ComicVineClient::getSeriesCover(const QString & url) -{ - HttpWorker * search = new HttpWorker(url); - connect(search,SIGNAL(dataReady(const QByteArray &)),this,SIGNAL(seriesCover(const QByteArray &))); - connect(search,SIGNAL(timeout()),this,SIGNAL(timeOut())); //TODO - connect(search,SIGNAL(finished()),search,SLOT(deleteLater())); - search->get(); -} - -//CV_COMIC_IDS -void ComicVineClient::getVolumeComicsInfo(const QString & idVolume, int page) -{ - HttpWorker * search = new HttpWorker(QString(CV_COMICS_INFO).replace(CV_WEB_ADDRESS, baseURL).replace(CV_API_KEY,settings->value(COMIC_VINE_API_KEY,CV_API_KEY_DEFAULT).toString()).arg(idVolume).arg((page-1)*100)); //page doesn't work for search, using offset instead - connect(search,SIGNAL(dataReady(const QByteArray &)),this,SLOT(processVolumeComicsInfo(const QByteArray &))); - connect(search,SIGNAL(timeout()),this,SIGNAL(timeOut())); //TODO - connect(search,SIGNAL(finished()),search,SLOT(deleteLater())); - search->get(); -} - -void ComicVineClient::getAllVolumeComicsInfo(const QString &idVolume) -{ - QString url = QString(CV_COMICS_INFO).replace(CV_WEB_ADDRESS, baseURL).replace(CV_API_KEY,settings->value(COMIC_VINE_API_KEY,CV_API_KEY_DEFAULT).toString()).arg(idVolume); - ComicVineAllVolumeComicsRetriever * comicsRetriever = new ComicVineAllVolumeComicsRetriever(url); - - connect(comicsRetriever, &ComicVineAllVolumeComicsRetriever::allVolumeComicsInfo, this, &ComicVineClient::volumeComicsInfo); - connect(comicsRetriever, &ComicVineAllVolumeComicsRetriever::finished, this, &ComicVineClient::finished); - connect(comicsRetriever, &ComicVineAllVolumeComicsRetriever::finished, this, &ComicVineAllVolumeComicsRetriever::deleteLater); - connect(comicsRetriever, &ComicVineAllVolumeComicsRetriever::timeOut, this, &ComicVineClient::timeOut); - - comicsRetriever->getAllVolumeComics(); -} - -//CV_COMIC_ID -void ComicVineClient::getComicId(const QString & id, int comicNumber) -{ - Q_UNUSED(id); - Q_UNUSED(comicNumber); -} - -//CV_COMIC_DETAIL -QByteArray ComicVineClient::getComicDetail(const QString & id, bool & outError, bool & outTimeout) -{ - HttpWorker * search = new HttpWorker(QString(CV_COMIC_DETAIL).replace(CV_WEB_ADDRESS, baseURL).replace(CV_API_KEY,settings->value(COMIC_VINE_API_KEY,CV_API_KEY_DEFAULT).toString()).arg(id)); - - //connect(search,SIGNAL(dataReady(const QByteArray &)),this,SLOT(proccessComicDetailData(const QByteArray &))); - //connect(search,SIGNAL(timeout()),this,SIGNAL(timeOut())); - //connect(search,SIGNAL(finished()),search,SLOT(deleteLater())); - search->get(); - search->wait(); - outError = !(search->wasValid()); - outTimeout = search->wasTimeout(); - QByteArray result = search->getResult(); - delete search; - - return result; -} - -//CV_COMIC_DETAIL -void ComicVineClient::getComicDetailAsync(const QString & id) -{ - HttpWorker * search = new HttpWorker(QString(CV_COMIC_DETAIL).replace(CV_WEB_ADDRESS, baseURL).replace(CV_API_KEY,settings->value(COMIC_VINE_API_KEY,CV_API_KEY_DEFAULT).toString()).arg(id)); - - connect(search,SIGNAL(dataReady(const QByteArray &)),this,SLOT(proccessComicDetailData(const QByteArray &))); - connect(search,SIGNAL(timeout()),this,SIGNAL(timeOut())); - connect(search,SIGNAL(finished()),search,SLOT(deleteLater())); - search->get(); -} - -void ComicVineClient::getComicCover(const QString &url) -{ - HttpWorker * search = new HttpWorker(url); - connect(search,SIGNAL(dataReady(const QByteArray &)),this,SIGNAL(comicCover(QByteArray))); - connect(search,SIGNAL(timeout()),this,SIGNAL(timeOut())); //TODO - connect(search,SIGNAL(finished()),search,SLOT(deleteLater())); - search->get(); -} - -//CV_COVER_DETAIL -void ComicVineClient::getCoverURL(const QString & id) -{ - Q_UNUSED(id); -} +#include "comic_vine_client.h" +#include "yacreader_global_gui.h" + +#include "comic_vine_all_volume_comics_retriever.h" + +//this is the API key used by YACReader to access Comic Vine +//please, do not use it in your own software, get one for free at Comic Vine +static const QString CV_API_KEY = "%CV_API_KEY%"; //get from settings +static const QString CV_API_KEY_DEFAULT = "46680bebb358f1de690a5a365e15d325f9649f91"; + +static const QString CV_WEB_ADDRESS = "%CV_WEB_ADDRESS%"; //get from settings + +//gets any volumen containing any comic matching 'query' +static const QString CV_SEARCH = CV_WEB_ADDRESS + "/search/?api_key=" + CV_API_KEY + + "&format=json&limit=100&resources=volume" + "&field_list=name,start_year,publisher,id,image,count_of_issues,deck" + "&sort=name:asc" + "&query=%1&page=%2"; +//http://www.comicvine.com/api/search/?api_key=46680bebb358f1de690a5a365e15d325f9649f91&format=json&limit=100&resources=volume&field_list=name,start_year,publisher,id,image,count_of_issues,deck&query=superman + +//gets the detail for a volume %1 +static const QString CV_SERIES_DETAIL = CV_WEB_ADDRESS + "/volume/4050-%1/?api_key=" + CV_API_KEY + + "&format=json&field_list=name,start_year,publisher,image,count_of_issues,id,description"; + +//gets info for comics in a volume id %1 +static const QString CV_COMICS_INFO = CV_WEB_ADDRESS + "/issues/?api_key=" + CV_API_KEY + + "&limit=1000&format=json&field_list=name,issue_number,id,image&filter=volume:%1" + "&sort=cover_date:asc" //sorting by cover_date, because comic vine doesn't use natural sorting (issue_number -> 1 10 11 ... 100 2 20 21....) + "&offset=%2"; + +//"http://www.comicvine.com/api/issues/?api_key=46680bebb358f1de690a5a365e15d325f9649f91&format=json&field_list=name,issue_number,id,image&filter=volume:%1&page=%2 + +//gets id for comic number %2 in a volume id %1 +static const QString CV_COMIC_ID = CV_WEB_ADDRESS + "/issues/?api_key=" + CV_API_KEY + + "&format=json&field_list=name,issue_number,id,image" + "&filter=volume:%1,issue_number:%2"; +//gets comic detail +static const QString CV_COMIC_DETAIL = CV_WEB_ADDRESS + "/issue/4000-%1/?api_key=" + CV_API_KEY + "&format=json"; +//http://www.comicvine.com/api/issue/4000-%1/?api_key=46680bebb358f1de690a5a365e15d325f9649f91&format=json + +//gets comic cover URL +static const QString CV_COVER_URL = CV_WEB_ADDRESS + "/issue/4000-%1/?api_key=" + CV_API_KEY + "&format=json&field_list=image"; + +//gets comics matching name %1 and number %2 +//http://comicvine.com/api/issues/?api_key=46680bebb358f1de690a5a365e15d325f9649f91&limit=20&filter=name:super,issue_number:15 + +ComicVineClient::ComicVineClient(QObject *parent) : + QObject(parent) +{ + settings = new QSettings(YACReader::getSettingsPath()+"/YACReaderLibrary.ini",QSettings::IniFormat); //TODO unificar la creación del fichero de config con el servidor + settings->beginGroup("ComicVine"); + baseURL = settings->value(COMIC_VINE_BASE_URL, "https://comicvine.gamespot.com/api").toString(); +} + +ComicVineClient::~ComicVineClient() +{ + delete settings; +} + +//CV_SEARCH +void ComicVineClient::search(const QString & query, int page) +{ + HttpWorker * search = new HttpWorker(QString(CV_SEARCH).replace(CV_WEB_ADDRESS, baseURL).replace(CV_API_KEY,settings->value(COMIC_VINE_API_KEY,CV_API_KEY_DEFAULT).toString()).arg(query).arg(page)); + connect(search,SIGNAL(dataReady(const QByteArray &)),this,SLOT(proccessVolumesSearchData(const QByteArray &))); + connect(search,SIGNAL(timeout()),this,SIGNAL(timeOut())); + connect(search,SIGNAL(finished()),search,SLOT(deleteLater())); + search->get(); +} +//CV_SEARCH result +void ComicVineClient::proccessVolumesSearchData(const QByteArray & data) +{ + QString json(data); + emit searchResult(json); + emit finished(); +} + +void ComicVineClient::proccessSeriesDetailData(const QByteArray &data) +{ + QString json(data); + emit seriesDetail(json); + emit finished(); +} + +void ComicVineClient::processVolumeComicsInfo(const QByteArray &data) +{ + QString json(data); + emit volumeComicsInfo(json); + emit finished(); +} + +void ComicVineClient::proccessComicDetailData(const QByteArray &data) +{ + QString json(data); + emit comicDetail(json); + emit finished(); +} + +//CV_SERIES_DETAIL +void ComicVineClient::getSeriesDetail(const QString & id) +{ + HttpWorker * search = new HttpWorker(QString(CV_SERIES_DETAIL).replace(CV_WEB_ADDRESS, baseURL).replace(CV_API_KEY,settings->value(COMIC_VINE_API_KEY,CV_API_KEY_DEFAULT).toString()).arg(id)); + connect(search,SIGNAL(dataReady(const QByteArray &)),this,SLOT(proccessSeriesDetailData(const QByteArray &))); + connect(search,SIGNAL(timeout()),this,SIGNAL(timeOut())); + connect(search,SIGNAL(finished()),search,SLOT(deleteLater())); + search->get(); +} + +void ComicVineClient::getSeriesCover(const QString & url) +{ + HttpWorker * search = new HttpWorker(url); + connect(search,SIGNAL(dataReady(const QByteArray &)),this,SIGNAL(seriesCover(const QByteArray &))); + connect(search,SIGNAL(timeout()),this,SIGNAL(timeOut())); //TODO + connect(search,SIGNAL(finished()),search,SLOT(deleteLater())); + search->get(); +} + +//CV_COMIC_IDS +void ComicVineClient::getVolumeComicsInfo(const QString & idVolume, int page) +{ + HttpWorker * search = new HttpWorker(QString(CV_COMICS_INFO).replace(CV_WEB_ADDRESS, baseURL).replace(CV_API_KEY,settings->value(COMIC_VINE_API_KEY,CV_API_KEY_DEFAULT).toString()).arg(idVolume).arg((page-1)*100)); //page doesn't work for search, using offset instead + connect(search,SIGNAL(dataReady(const QByteArray &)),this,SLOT(processVolumeComicsInfo(const QByteArray &))); + connect(search,SIGNAL(timeout()),this,SIGNAL(timeOut())); //TODO + connect(search,SIGNAL(finished()),search,SLOT(deleteLater())); + search->get(); +} + +void ComicVineClient::getAllVolumeComicsInfo(const QString &idVolume) +{ + QString url = QString(CV_COMICS_INFO).replace(CV_WEB_ADDRESS, baseURL).replace(CV_API_KEY,settings->value(COMIC_VINE_API_KEY,CV_API_KEY_DEFAULT).toString()).arg(idVolume); + ComicVineAllVolumeComicsRetriever * comicsRetriever = new ComicVineAllVolumeComicsRetriever(url); + + connect(comicsRetriever, &ComicVineAllVolumeComicsRetriever::allVolumeComicsInfo, this, &ComicVineClient::volumeComicsInfo); + connect(comicsRetriever, &ComicVineAllVolumeComicsRetriever::finished, this, &ComicVineClient::finished); + connect(comicsRetriever, &ComicVineAllVolumeComicsRetriever::finished, this, &ComicVineAllVolumeComicsRetriever::deleteLater); + connect(comicsRetriever, &ComicVineAllVolumeComicsRetriever::timeOut, this, &ComicVineClient::timeOut); + + comicsRetriever->getAllVolumeComics(); +} + +//CV_COMIC_ID +void ComicVineClient::getComicId(const QString & id, int comicNumber) +{ + Q_UNUSED(id); + Q_UNUSED(comicNumber); +} + +//CV_COMIC_DETAIL +QByteArray ComicVineClient::getComicDetail(const QString & id, bool & outError, bool & outTimeout) +{ + HttpWorker * search = new HttpWorker(QString(CV_COMIC_DETAIL).replace(CV_WEB_ADDRESS, baseURL).replace(CV_API_KEY,settings->value(COMIC_VINE_API_KEY,CV_API_KEY_DEFAULT).toString()).arg(id)); + + //connect(search,SIGNAL(dataReady(const QByteArray &)),this,SLOT(proccessComicDetailData(const QByteArray &))); + //connect(search,SIGNAL(timeout()),this,SIGNAL(timeOut())); + //connect(search,SIGNAL(finished()),search,SLOT(deleteLater())); + search->get(); + search->wait(); + outError = !(search->wasValid()); + outTimeout = search->wasTimeout(); + QByteArray result = search->getResult(); + delete search; + + return result; +} + +//CV_COMIC_DETAIL +void ComicVineClient::getComicDetailAsync(const QString & id) +{ + HttpWorker * search = new HttpWorker(QString(CV_COMIC_DETAIL).replace(CV_WEB_ADDRESS, baseURL).replace(CV_API_KEY,settings->value(COMIC_VINE_API_KEY,CV_API_KEY_DEFAULT).toString()).arg(id)); + + connect(search,SIGNAL(dataReady(const QByteArray &)),this,SLOT(proccessComicDetailData(const QByteArray &))); + connect(search,SIGNAL(timeout()),this,SIGNAL(timeOut())); + connect(search,SIGNAL(finished()),search,SLOT(deleteLater())); + search->get(); +} + +void ComicVineClient::getComicCover(const QString &url) +{ + HttpWorker * search = new HttpWorker(url); + connect(search,SIGNAL(dataReady(const QByteArray &)),this,SIGNAL(comicCover(QByteArray))); + connect(search,SIGNAL(timeout()),this,SIGNAL(timeOut())); //TODO + connect(search,SIGNAL(finished()),search,SLOT(deleteLater())); + search->get(); +} + +//CV_COVER_DETAIL +void ComicVineClient::getCoverURL(const QString & id) +{ + Q_UNUSED(id); +} diff --git a/YACReaderLibrary/comic_vine/comic_vine_client.h b/YACReaderLibrary/comic_vine/comic_vine_client.h index 2208c6a7..c7e6b6f7 100644 --- a/YACReaderLibrary/comic_vine/comic_vine_client.h +++ b/YACReaderLibrary/comic_vine/comic_vine_client.h @@ -1,48 +1,48 @@ -#ifndef COMIC_VINE_CLIENT_H -#define COMIC_VINE_CLIENT_H - -#include "http_worker.h" - -#include -#include - -class ComicVineClient : public QObject -{ - Q_OBJECT -public: - explicit ComicVineClient(QObject *parent = 0); - ~ComicVineClient(); - -signals: - void searchResult(QString); - void seriesDetail(QString);//JSON - void comicDetail(QString);//JSON - void seriesCover(const QByteArray &); - void comicCover(const QByteArray &); - void volumeComicsInfo(QString); - void timeOut(); - void finished(); -public slots: - void search(const QString & query, int page = 1); - void getSeriesDetail(const QString & id); - void getSeriesCover(const QString & url); - void getVolumeComicsInfo(const QString & idVolume, int page=1); - void getAllVolumeComicsInfo(const QString & idVolume); - QByteArray getComicDetail(const QString & id, bool &outError, bool &outTimeout); - void getComicCover(const QString & url); - - void getComicId(const QString & id, int comicNumber); - void getCoverURL(const QString & id); - void getComicDetailAsync(const QString &id); -protected slots: - void proccessVolumesSearchData(const QByteArray & data); - void proccessSeriesDetailData(const QByteArray & data); - void processVolumeComicsInfo(const QByteArray & data); - void proccessComicDetailData(const QByteArray & data); - -protected: - QSettings * settings; - QString baseURL; - -}; -#endif // COMIC_VINE_CLIENT_H +#ifndef COMIC_VINE_CLIENT_H +#define COMIC_VINE_CLIENT_H + +#include "http_worker.h" + +#include +#include + +class ComicVineClient : public QObject +{ + Q_OBJECT +public: + explicit ComicVineClient(QObject *parent = 0); + ~ComicVineClient(); + +signals: + void searchResult(QString); + void seriesDetail(QString);//JSON + void comicDetail(QString);//JSON + void seriesCover(const QByteArray &); + void comicCover(const QByteArray &); + void volumeComicsInfo(QString); + void timeOut(); + void finished(); +public slots: + void search(const QString & query, int page = 1); + void getSeriesDetail(const QString & id); + void getSeriesCover(const QString & url); + void getVolumeComicsInfo(const QString & idVolume, int page=1); + void getAllVolumeComicsInfo(const QString & idVolume); + QByteArray getComicDetail(const QString & id, bool &outError, bool &outTimeout); + void getComicCover(const QString & url); + + void getComicId(const QString & id, int comicNumber); + void getCoverURL(const QString & id); + void getComicDetailAsync(const QString &id); +protected slots: + void proccessVolumesSearchData(const QByteArray & data); + void proccessSeriesDetailData(const QByteArray & data); + void processVolumeComicsInfo(const QByteArray & data); + void proccessComicDetailData(const QByteArray & data); + +protected: + QSettings * settings; + QString baseURL; + +}; +#endif // COMIC_VINE_CLIENT_H diff --git a/YACReaderLibrary/comic_vine/comic_vine_dialog.cpp b/YACReaderLibrary/comic_vine/comic_vine_dialog.cpp index 5f869105..b65ce6fb 100644 --- a/YACReaderLibrary/comic_vine/comic_vine_dialog.cpp +++ b/YACReaderLibrary/comic_vine/comic_vine_dialog.cpp @@ -1,742 +1,742 @@ -#include "comic_vine_dialog.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#if QT_VERSION >= 0x050000 - #include -#else - #include -#endif -#include -#include -#include "data_base_management.h" - -#include "yacreader_busy_widget.h" -#include "comic_vine_client.h" -#include "scraper_lineedit.h" -#include "title_header.h" -#include "series_question.h" -#include "search_single_comic.h" -#include "search_volume.h" -#include "select_comic.h" -#include "select_volume.h" -#include "sort_volume_comics.h" -#include "db_helper.h" -#include "response_parser.h" - -#include "QsLog.h" - - - -ComicVineDialog::ComicVineDialog(QWidget *parent) : - QDialog(parent) -{ - setWindowFlags(Qt::Window); - - doLayout(); - doStackedWidgets(); - doConnections(); -} - -void ComicVineDialog::doLayout() -{ - setStyleSheet("" - "QDialog {background-color: #404040; }" - ""); - - QString dialogButtonsStyleSheet = "QPushButton {border: 1px solid #242424; background: #2e2e2e; color:white; padding: 5px 26px 5px 26px; font-size:12px;font-family:Arial; font-weight:bold;}"; - - skipButton = new QPushButton(tr("skip")); - backButton = new QPushButton(tr("back")); - nextButton = new QPushButton(tr("next")); - searchButton = new QPushButton(tr("search")); - closeButton = new QPushButton(tr("close")); - - skipButton->setStyleSheet(dialogButtonsStyleSheet); - backButton->setStyleSheet(dialogButtonsStyleSheet); - nextButton->setStyleSheet(dialogButtonsStyleSheet); - searchButton->setStyleSheet(dialogButtonsStyleSheet); - closeButton->setStyleSheet(dialogButtonsStyleSheet); - - content = new QStackedWidget(this); - - QVBoxLayout * mainLayout = new QVBoxLayout; - - QHBoxLayout * buttonLayout = new QHBoxLayout; - - buttonLayout->addStretch(); - buttonLayout->addWidget(skipButton); - buttonLayout->addWidget(backButton); - buttonLayout->addWidget(nextButton); - buttonLayout->addWidget(searchButton); - buttonLayout->addWidget(closeButton); - buttonLayout->setContentsMargins(0,0,0,0); - - mainLayout->addWidget(titleHeader = new TitleHeader, 0); - mainLayout->addWidget(content, 1); - mainLayout->addLayout(buttonLayout, 0); - - mainLayout->setContentsMargins(26,16,26,11); - - setLayout(mainLayout); - - setWindowTitle("Comic Vine Scraper (beta)"); -} - -void ComicVineDialog::doStackedWidgets() -{ - doLoading(); - content->addWidget(seriesQuestionWidget = new SeriesQuestion); - content->addWidget(searchSingleComicWidget = new SearchSingleComic); - content->addWidget(searchVolumeWidget = new SearchVolume); - content->addWidget(selectVolumeWidget = new SelectVolume); - content->addWidget(selectComicWidget = new SelectComic); - content->addWidget(sortVolumeComicsWidget = new SortVolumeComics); -} - -void ComicVineDialog::doConnections() -{ - connect(closeButton,SIGNAL(clicked()),this,SLOT(close())); - connect(nextButton,SIGNAL(clicked()),this,SLOT(goNext())); - connect(backButton,SIGNAL(clicked()),this,SLOT(goBack())); - connect(searchButton,SIGNAL(clicked()),this,SLOT(search())); - connect(skipButton,SIGNAL(clicked()),this,SLOT(goToNextComic())); - - connect(selectVolumeWidget,SIGNAL(loadPage(QString,int)),this,SLOT(searchVolume(QString,int))); - connect(selectComicWidget,SIGNAL(loadPage(QString,int)),this,SLOT(getVolumeComicsInfo(QString,int))); - connect(sortVolumeComicsWidget,SIGNAL(loadPage(QString,int)),this,SLOT(getVolumeComicsInfo(QString,int))); - - connect(this, SIGNAL(accepted()), this, SLOT(close()), Qt::QueuedConnection); -} - -void ComicVineDialog::goNext() -{ - // - if(content->currentWidget() == seriesQuestionWidget) - { - if(seriesQuestionWidget->getYes()) - { - QString volumeSearchString = comics[0].getParentFolderName(); - mode = Volume; - - if(volumeSearchString.isEmpty()) - showSearchVolume(); - else - { - status = AutoSearching; - showLoading(tr("Looking for volume...")); - searchVolume(volumeSearchString); - } - } - else - { - status = AutoSearching; - mode = SingleComicInList; - ComicDB comic = comics[currentIndex]; - QString title = comic.getTitleOrFileName(); - titleHeader->setSubTitle(tr("comic %1 of %2 - %3").arg(currentIndex+1).arg(comics.length()).arg(title)); - - showLoading(tr("Looking for volume...")); - searchVolume(title); - } - } - else if (content->currentWidget() == selectVolumeWidget) { - currentVolumeId = selectVolumeWidget->getSelectedVolumeId(); - getVolumeComicsInfo(currentVolumeId); - - } else if (content->currentWidget() == sortVolumeComicsWidget) { - showLoading(); - - //ComicDB-ComicVineID - QList > matchingInfo = sortVolumeComicsWidget->getMatchingInfo(); - int count = selectVolumeWidget->getSelectedVolumeNumIssues(); - QString publisher = selectVolumeWidget->getSelectedVolumePublisher(); - QtConcurrent::run(this, &ComicVineDialog::getComicsInfo,matchingInfo,count,publisher); - } else if (content->currentWidget() == selectComicWidget) - { - showLoading(); - QString comicId = selectComicWidget->getSelectedComicId(); - int count = selectVolumeWidget->getSelectedVolumeNumIssues(); - QString publisher = selectVolumeWidget->getSelectedVolumePublisher(); - QtConcurrent::run(this, &ComicVineDialog::getComicInfo,comicId,count,publisher); - } -} - -void ComicVineDialog::goBack() -{ - switch (status) { - case SelectingSeries: - if(mode == Volume) - showSearchVolume(); - else - showSearchSingleComic(); - break; - case SortingComics: - showSelectVolume(); - break; - case SelectingComic: - if(mode == SingleComic) - showSelectVolume(); - break; - case AutoSearching: - if(mode == Volume) - showSearchVolume(); - else - showSearchSingleComic(); - default: - if(mode == Volume) - showSearchVolume(); - else - showSearchSingleComic(); - break; - } -} - -void ComicVineDialog::setComics(const QList & comics) -{ - this->comics = comics; -} - -QSize ComicVineDialog::sizeHint() const -{ - int heightDesktopResolution = QApplication::desktop()->screenGeometry().height(); - int widthDesktopResolution = QApplication::desktop()->screenGeometry().width(); - int height,width; - height = qMax(529, static_cast(heightDesktopResolution*0.5)); - width = height * 1.65; - - if (width > widthDesktopResolution) - return minimumSizeHint(); - - return QSize(width, height); -} - -QSize ComicVineDialog::minimumSizeHint() const -{ - return QSize(872, 529); -} - -void ComicVineDialog::show() -{ - QDialog::show(); - - currentIndex = 0; - - seriesQuestionWidget->setYes(true); - searchSingleComicWidget->clean(); - searchVolumeWidget->clean(); - - if(comics.length() == 1) - { - status = AutoSearching; - mode = SingleComic; - - ComicDB singleComic = comics[0]; - QString title = singleComic.getTitleOrFileName(); - titleHeader->setSubTitle(title); - showLoading(tr("Looking for volume...")); - - searchVolume(singleComic.getParentFolderName()); - QLOG_TRACE() << singleComic.getParentFolderName(); - }else if(comics.length()>1) - { - titleHeader->setSubTitle(tr("%1 comics selected").arg(comics.length())); - showSeriesQuestion(); - } -} - -void ComicVineDialog::doLoading() -{ - QWidget * w = new QWidget; - QVBoxLayout * l = new QVBoxLayout; - - YACReaderBusyWidget * bw = new YACReaderBusyWidget; - loadingMessage = new QLabel; - - loadingMessage->setStyleSheet("QLabel {color:white; font-size:12px;font-family:Arial;}"); - - l->addStretch(); - l->addWidget(bw,0,Qt::AlignHCenter); - l->addStretch(); - l->addWidget(loadingMessage); - - - l->setContentsMargins(0,0,0,0); - w->setLayout(l); - w->setContentsMargins(0,0,0,0); - - content->addWidget(w); -} - -void ComicVineDialog::debugClientResults(const QString & string) -{ - ResponseParser p; - p.loadJSONResponse(string); - //QMessageBox::information(0,"Result", QString("Number of results : %1").arg(p.getNumResults())); - if(p.responseError()) - { - QMessageBox::critical(0,tr("Error connecting to ComicVine"), p.errorDescription()); - goBack(); - } - else - { - switch(mode) - { - case SingleComic: case SingleComicInList: - if(p.getNumResults() == 0) - showSearchSingleComic(); - else - if(status == SearchingVolume) - showSelectVolume(string); - else - showSelectComic(string); - break; - case Volume: - if(p.getNumResults() == 0) - showSearchVolume(); - else - showSelectVolume(string); - break; - } - } -} - -void ComicVineDialog::showSeriesQuestion() -{ - status = AskingForInfo; - content->setCurrentWidget(seriesQuestionWidget); - backButton->setHidden(true); - skipButton->setHidden(true); - nextButton->setVisible(true); - searchButton->setHidden(true); - closeButton->setVisible(true); - - if(mode == SingleComicInList) - skipButton->setVisible(true); - else - skipButton->setHidden(true); -} - -void ComicVineDialog::showSearchSingleComic() -{ - status = AskingForInfo; - content->setCurrentWidget(searchSingleComicWidget); - backButton->setHidden(true); - skipButton->setHidden(true); - nextButton->setHidden(true); - searchButton->setVisible(true); - closeButton->setVisible(true); - - if(mode == SingleComicInList) - skipButton->setVisible(true); - else - skipButton->setHidden(true); -} - -void ComicVineDialog::showSearchVolume() -{ - status = AskingForInfo; - content->setCurrentWidget(searchVolumeWidget); - backButton->setHidden(true); - nextButton->setHidden(true); - searchButton->setVisible(true); - closeButton->setVisible(true); - toggleSkipButton(); -} - -void ComicVineDialog::showSelectVolume(const QString & json) -{ - showSelectVolume(); - selectVolumeWidget->load(json,currentVolumeSearchString); -} - -void ComicVineDialog::showSelectVolume() -{ - status = SelectingSeries; - - content->setCurrentWidget(selectVolumeWidget); - - backButton->setVisible(true); - nextButton->setVisible(true); - searchButton->setHidden(true); - closeButton->setVisible(true); - toggleSkipButton(); -} - -void ComicVineDialog::showSelectComic(const QString &json) -{ - status = SelectingComic; - - content->setCurrentWidget(selectComicWidget); - selectComicWidget->load(json,currentVolumeId); - - backButton->setVisible(true); - nextButton->setVisible(true); - searchButton->setHidden(true); - closeButton->setVisible(true); - toggleSkipButton(); -} - -void ComicVineDialog::showSortVolumeComics(const QString &json) -{ - status = SortingComics; - - content->setCurrentWidget(sortVolumeComicsWidget); - - sortVolumeComicsWidget->setData(comics, json, currentVolumeId); - - backButton->setVisible(true); - nextButton->setVisible(true); - searchButton->setHidden(true); - closeButton->setVisible(true); - toggleSkipButton(); -} - -void ComicVineDialog::queryTimeOut() -{ - QMessageBox::warning(this,"Comic Vine error", "Time out connecting to Comic Vine"); - - switch (status) { - case AutoSearching: - if(mode == Volume) - showSearchVolume(); - else - showSearchSingleComic(); - break; - case SearchingVolume: - if(mode == Volume) - showSearchVolume(); - else - showSearchSingleComic(); - break; - case SearchingSingleComic: - showSearchSingleComic(); - break; - case GettingVolumeComics: - showSelectVolume(); - break; - default: - break; - } -} - -void ComicVineDialog::getComicsInfo(QList > & matchingInfo, int count,const QString & publisher) -{ - QPair p; - QList comics; - foreach (p, matchingInfo) { - ComicVineClient * comicVineClient = new ComicVineClient; - //connect(comicVineClient,SIGNAL(searchResult(QString)),this,SLOT(debugClientResults(QString))); - //connect(comicVineClient,SIGNAL(timeOut()),this,SLOT(queryTimeOut())); - //connect(comicVineClient,SIGNAL(finished()),comicVineClient,SLOT(deleteLater())); - bool error; - bool timeout; - QByteArray result = comicVineClient->getComicDetail(p.second,error,timeout); //TODO check timeOut or Connection error - if(error || timeout) - continue; //TODO - ComicDB comic = parseComicInfo(p.first,result,count,publisher);//TODO check result error - comic.info.comicVineID = p.second; - comics.push_back(comic); - - setLoadingMessage(tr("Retrieving tags for : %1").arg(p.first.getFileName())); - } - - QSqlDatabase db = DataBaseManagement::loadDatabase(databasePath); - db.open(); - db.transaction(); - foreach(ComicDB comic, comics) - { - DBHelper::update(&(comic.info),db); - } - db.commit(); - db.close(); - QSqlDatabase::removeDatabase(db.connectionName()); - - emit accepted(); -} - -void ComicVineDialog::getComicInfo(const QString &comicId, int count, const QString &publisher) -{ - - ComicVineClient * comicVineClient = new ComicVineClient; - bool error; - bool timeout; - QByteArray result = comicVineClient->getComicDetail(comicId,error,timeout); //TODO check timeOut or Connection error - if(error || timeout) - { - //TODO - if(mode == SingleComic || currentIndex == (comics.count()-1)) - { - emit accepted(); - } else - { - goToNextComic(); - } - } - - ComicDB comic = parseComicInfo(comics[currentIndex],result,count,publisher); //TODO check result error - comic.info.comicVineID = comicId; - setLoadingMessage(tr("Retrieving tags for : %1").arg(comics[currentIndex].getFileName())); - - QSqlDatabase db = DataBaseManagement::loadDatabase(databasePath); - db.open(); - db.transaction(); - - DBHelper::update(&(comic.info),db); - - db.commit(); - db.close(); - QSqlDatabase::removeDatabase(db.connectionName()); - - if(mode == SingleComic || currentIndex == (comics.count()-1)) - { - emit accepted(); - } else - { - goToNextComic(); - } -} - -ComicDB ComicVineDialog::parseComicInfo(ComicDB & comic, const QString & json, int count, const QString & publisher) -{ - QScriptEngine engine; - QScriptValue sc; - sc = engine.evaluate("(" + json + ")"); - - if (!sc.property("error").isValid() && sc.property("error").toString() != "OK") - { - qDebug("Error detected"); - } - else - { - int numResults = sc.property("number_of_total_results").toString().toInt(); //fix to weird behaviour using hasNext - - if(numResults > 0) - { - QScriptValue result = sc.property("results"); - - QString title = result.property("name").toString(); - - QString number = result.property("issue_number").toString(); - //QString count; //get from select volume - - - QString volume = result.property("volume").property("name").toString(); - // QString storyArc; //story_arc - // QString arcNumber; //?? - // QString arcCount; //count_of_issue_appearances -> NO - - // QString genere; //no - - QMap authors = getAuthors(result.property("person_credits")); - - QString writer = QStringList(authors.values("writer")).join("\n"); - QString penciller = QStringList(authors.values("penciller")).join("\n"); - QString inker = QStringList(authors.values("inker")).join("\n"); - QString colorist = QStringList(authors.values("colorist")).join("\n"); - QString letterer = QStringList(authors.values("letterer")).join("\n"); - QString coverArtist = QStringList(authors.values("cover")).join("\n"); - - QString date = result.property("cover_date").toString(); - - //QString publisher; //get from select volume - // QString format; //no - // bool color; //no - // QString ageRating; //no - - QString synopsis = result.property("description").toString().remove(QRegExp("<[^>]*>")); //description - QString characters = getCharacters(result.property("character_credits")); - - if (title != "null") { - comic.info.title = title; - } - - comic.info.number = number; - comic.info.count = count; - - comic.info.writer = writer; - comic.info.penciller = penciller; - comic.info.inker = inker; - comic.info.colorist = colorist; - comic.info.letterer = letterer; - comic.info.coverArtist = coverArtist; - - QStringList tempList = date.split("-"); - std::reverse(tempList.begin(),tempList.end()); - comic.info.date = tempList.join("/"); - comic.info.volume = volume; - - comic.info.publisher = publisher; - - comic.info.synopsis = synopsis; - comic.info.characters = characters; - } - } - return comic; -} - -QString ComicVineDialog::getCharacters(const QScriptValue &json_characters) -{ - QString characters; - - QScriptValueIterator it(json_characters); - QScriptValue resultsValue; - while (it.hasNext()) { - it.next(); - if(it.flags() & QScriptValue::SkipInEnumeration) - continue; - resultsValue = it.value(); - - characters += resultsValue.property("name").toString() + "\n"; - } - - return characters; -} - -QMap ComicVineDialog::getAuthors(const QScriptValue &json_authors) -{ - QMap authors; - - QScriptValueIterator it(json_authors); - QScriptValue resultsValue; - while (it.hasNext()) { - it.next(); - if(it.flags() & QScriptValue::SkipInEnumeration) - continue; - resultsValue = it.value(); - - QString authorName = resultsValue.property("name").toString(); - - QStringList roles = resultsValue.property("role").toString().split(","); - foreach(QString role, roles) - { - if(role.trimmed() == "writer") - authors.insertMulti("writer",authorName); - else if(role.trimmed() == "inker") - authors.insertMulti("inker",authorName); - else if(role.trimmed() == "penciler" || role.trimmed() == "penciller") - authors.insertMulti("penciller",authorName); - else if(role.trimmed() == "colorist") - authors.insertMulti("colorist",authorName); - else if(role.trimmed() == "letterer") - authors.insertMulti("letterer",authorName); - else if(role.trimmed() == "cover") - authors.insertMulti("cover",authorName); - } - } - - return authors; -} - -void ComicVineDialog::toggleSkipButton() -{ - if (mode == SingleComicInList) - skipButton->setVisible(true); - else - skipButton->setHidden(true); -} - -void ComicVineDialog::goToNextComic() -{ - if(mode == SingleComic || currentIndex == (comics.count()-1)) - { - emit accepted(); - return; - } - - currentIndex++; - - showSearchSingleComic(); - - ComicDB comic = comics[currentIndex]; - QString title = comic.getTitleOrFileName(); - titleHeader->setSubTitle(tr("comic %1 of %2 - %3").arg(currentIndex+1).arg(comics.length()).arg(title)); -} - -void ComicVineDialog::showLoading(const QString &message) -{ - content->setCurrentIndex(0); - loadingMessage->setText(message); - backButton->setHidden(true); - skipButton->setHidden(true); - nextButton->setHidden(true); - searchButton->setHidden(true); - closeButton->setVisible(true); -} - -void ComicVineDialog::setLoadingMessage(const QString &message) -{ - loadingMessage->setText(message); -} - -void ComicVineDialog::search() -{ - switch (mode) { - case Volume: - launchSearchVolume(); - break; - default: - launchSearchComic(); - break; - } -} - -void ComicVineDialog::searchVolume(const QString &v, int page) -{ - showLoading(tr("Looking for volume...")); - - currentVolumeSearchString = v; - - ComicVineClient * comicVineClient = new ComicVineClient; - connect(comicVineClient,SIGNAL(searchResult(QString)),this,SLOT(debugClientResults(QString))); - connect(comicVineClient,SIGNAL(timeOut()),this,SLOT(queryTimeOut())); - connect(comicVineClient,SIGNAL(finished()),comicVineClient,SLOT(deleteLater())); - comicVineClient->search(v,page); - - status = SearchingVolume; -} - -void ComicVineDialog::getVolumeComicsInfo(const QString &vID, int page) -{ - showLoading(tr("Retrieving volume info...")); - - status = GettingVolumeComics; - - ComicVineClient * comicVineClient = new ComicVineClient; - if(mode == Volume) - connect(comicVineClient,SIGNAL(volumeComicsInfo(QString)),this,SLOT(showSortVolumeComics(QString))); - else - connect(comicVineClient,SIGNAL(volumeComicsInfo(QString)),this,SLOT(showSelectComic(QString))); - connect(comicVineClient,SIGNAL(timeOut()),this,SLOT(queryTimeOut())); - connect(comicVineClient,SIGNAL(finished()),comicVineClient,SLOT(deleteLater())); - - QLOG_TRACE() << vID; - - comicVineClient->getAllVolumeComicsInfo(vID); -} - -void ComicVineDialog::launchSearchVolume() -{ - showLoading(tr("Looking for volume...")); - //TODO: check if volume info is empty. - searchVolume(searchVolumeWidget->getVolumeInfo()); -} - -void ComicVineDialog::launchSearchComic() -{ - showLoading(tr("Looking for comic...")); - - QString volumeInfo = searchSingleComicWidget->getVolumeInfo(); - //QString comicInfo = searchSingleComicWidget->getComicInfo(); - //int comicNumber = searchSingleComicWidget->getComicNumber(); - - //if(comicInfo.isEmpty() && comicNumber == -1) - searchVolume(volumeInfo); -} - +#include "comic_vine_dialog.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#if QT_VERSION >= 0x050000 + #include +#else + #include +#endif +#include +#include +#include "data_base_management.h" + +#include "yacreader_busy_widget.h" +#include "comic_vine_client.h" +#include "scraper_lineedit.h" +#include "title_header.h" +#include "series_question.h" +#include "search_single_comic.h" +#include "search_volume.h" +#include "select_comic.h" +#include "select_volume.h" +#include "sort_volume_comics.h" +#include "db_helper.h" +#include "response_parser.h" + +#include "QsLog.h" + + + +ComicVineDialog::ComicVineDialog(QWidget *parent) : + QDialog(parent) +{ + setWindowFlags(Qt::Window); + + doLayout(); + doStackedWidgets(); + doConnections(); +} + +void ComicVineDialog::doLayout() +{ + setStyleSheet("" + "QDialog {background-color: #404040; }" + ""); + + QString dialogButtonsStyleSheet = "QPushButton {border: 1px solid #242424; background: #2e2e2e; color:white; padding: 5px 26px 5px 26px; font-size:12px;font-family:Arial; font-weight:bold;}"; + + skipButton = new QPushButton(tr("skip")); + backButton = new QPushButton(tr("back")); + nextButton = new QPushButton(tr("next")); + searchButton = new QPushButton(tr("search")); + closeButton = new QPushButton(tr("close")); + + skipButton->setStyleSheet(dialogButtonsStyleSheet); + backButton->setStyleSheet(dialogButtonsStyleSheet); + nextButton->setStyleSheet(dialogButtonsStyleSheet); + searchButton->setStyleSheet(dialogButtonsStyleSheet); + closeButton->setStyleSheet(dialogButtonsStyleSheet); + + content = new QStackedWidget(this); + + QVBoxLayout * mainLayout = new QVBoxLayout; + + QHBoxLayout * buttonLayout = new QHBoxLayout; + + buttonLayout->addStretch(); + buttonLayout->addWidget(skipButton); + buttonLayout->addWidget(backButton); + buttonLayout->addWidget(nextButton); + buttonLayout->addWidget(searchButton); + buttonLayout->addWidget(closeButton); + buttonLayout->setContentsMargins(0,0,0,0); + + mainLayout->addWidget(titleHeader = new TitleHeader, 0); + mainLayout->addWidget(content, 1); + mainLayout->addLayout(buttonLayout, 0); + + mainLayout->setContentsMargins(26,16,26,11); + + setLayout(mainLayout); + + setWindowTitle("Comic Vine Scraper (beta)"); +} + +void ComicVineDialog::doStackedWidgets() +{ + doLoading(); + content->addWidget(seriesQuestionWidget = new SeriesQuestion); + content->addWidget(searchSingleComicWidget = new SearchSingleComic); + content->addWidget(searchVolumeWidget = new SearchVolume); + content->addWidget(selectVolumeWidget = new SelectVolume); + content->addWidget(selectComicWidget = new SelectComic); + content->addWidget(sortVolumeComicsWidget = new SortVolumeComics); +} + +void ComicVineDialog::doConnections() +{ + connect(closeButton,SIGNAL(clicked()),this,SLOT(close())); + connect(nextButton,SIGNAL(clicked()),this,SLOT(goNext())); + connect(backButton,SIGNAL(clicked()),this,SLOT(goBack())); + connect(searchButton,SIGNAL(clicked()),this,SLOT(search())); + connect(skipButton,SIGNAL(clicked()),this,SLOT(goToNextComic())); + + connect(selectVolumeWidget,SIGNAL(loadPage(QString,int)),this,SLOT(searchVolume(QString,int))); + connect(selectComicWidget,SIGNAL(loadPage(QString,int)),this,SLOT(getVolumeComicsInfo(QString,int))); + connect(sortVolumeComicsWidget,SIGNAL(loadPage(QString,int)),this,SLOT(getVolumeComicsInfo(QString,int))); + + connect(this, SIGNAL(accepted()), this, SLOT(close()), Qt::QueuedConnection); +} + +void ComicVineDialog::goNext() +{ + // + if(content->currentWidget() == seriesQuestionWidget) + { + if(seriesQuestionWidget->getYes()) + { + QString volumeSearchString = comics[0].getParentFolderName(); + mode = Volume; + + if(volumeSearchString.isEmpty()) + showSearchVolume(); + else + { + status = AutoSearching; + showLoading(tr("Looking for volume...")); + searchVolume(volumeSearchString); + } + } + else + { + status = AutoSearching; + mode = SingleComicInList; + ComicDB comic = comics[currentIndex]; + QString title = comic.getTitleOrFileName(); + titleHeader->setSubTitle(tr("comic %1 of %2 - %3").arg(currentIndex+1).arg(comics.length()).arg(title)); + + showLoading(tr("Looking for volume...")); + searchVolume(title); + } + } + else if (content->currentWidget() == selectVolumeWidget) { + currentVolumeId = selectVolumeWidget->getSelectedVolumeId(); + getVolumeComicsInfo(currentVolumeId); + + } else if (content->currentWidget() == sortVolumeComicsWidget) { + showLoading(); + + //ComicDB-ComicVineID + QList > matchingInfo = sortVolumeComicsWidget->getMatchingInfo(); + int count = selectVolumeWidget->getSelectedVolumeNumIssues(); + QString publisher = selectVolumeWidget->getSelectedVolumePublisher(); + QtConcurrent::run(this, &ComicVineDialog::getComicsInfo,matchingInfo,count,publisher); + } else if (content->currentWidget() == selectComicWidget) + { + showLoading(); + QString comicId = selectComicWidget->getSelectedComicId(); + int count = selectVolumeWidget->getSelectedVolumeNumIssues(); + QString publisher = selectVolumeWidget->getSelectedVolumePublisher(); + QtConcurrent::run(this, &ComicVineDialog::getComicInfo,comicId,count,publisher); + } +} + +void ComicVineDialog::goBack() +{ + switch (status) { + case SelectingSeries: + if(mode == Volume) + showSearchVolume(); + else + showSearchSingleComic(); + break; + case SortingComics: + showSelectVolume(); + break; + case SelectingComic: + if(mode == SingleComic) + showSelectVolume(); + break; + case AutoSearching: + if(mode == Volume) + showSearchVolume(); + else + showSearchSingleComic(); + default: + if(mode == Volume) + showSearchVolume(); + else + showSearchSingleComic(); + break; + } +} + +void ComicVineDialog::setComics(const QList & comics) +{ + this->comics = comics; +} + +QSize ComicVineDialog::sizeHint() const +{ + int heightDesktopResolution = QApplication::desktop()->screenGeometry().height(); + int widthDesktopResolution = QApplication::desktop()->screenGeometry().width(); + int height,width; + height = qMax(529, static_cast(heightDesktopResolution*0.5)); + width = height * 1.65; + + if (width > widthDesktopResolution) + return minimumSizeHint(); + + return QSize(width, height); +} + +QSize ComicVineDialog::minimumSizeHint() const +{ + return QSize(872, 529); +} + +void ComicVineDialog::show() +{ + QDialog::show(); + + currentIndex = 0; + + seriesQuestionWidget->setYes(true); + searchSingleComicWidget->clean(); + searchVolumeWidget->clean(); + + if(comics.length() == 1) + { + status = AutoSearching; + mode = SingleComic; + + ComicDB singleComic = comics[0]; + QString title = singleComic.getTitleOrFileName(); + titleHeader->setSubTitle(title); + showLoading(tr("Looking for volume...")); + + searchVolume(singleComic.getParentFolderName()); + QLOG_TRACE() << singleComic.getParentFolderName(); + }else if(comics.length()>1) + { + titleHeader->setSubTitle(tr("%1 comics selected").arg(comics.length())); + showSeriesQuestion(); + } +} + +void ComicVineDialog::doLoading() +{ + QWidget * w = new QWidget; + QVBoxLayout * l = new QVBoxLayout; + + YACReaderBusyWidget * bw = new YACReaderBusyWidget; + loadingMessage = new QLabel; + + loadingMessage->setStyleSheet("QLabel {color:white; font-size:12px;font-family:Arial;}"); + + l->addStretch(); + l->addWidget(bw,0,Qt::AlignHCenter); + l->addStretch(); + l->addWidget(loadingMessage); + + + l->setContentsMargins(0,0,0,0); + w->setLayout(l); + w->setContentsMargins(0,0,0,0); + + content->addWidget(w); +} + +void ComicVineDialog::debugClientResults(const QString & string) +{ + ResponseParser p; + p.loadJSONResponse(string); + //QMessageBox::information(0,"Result", QString("Number of results : %1").arg(p.getNumResults())); + if(p.responseError()) + { + QMessageBox::critical(0,tr("Error connecting to ComicVine"), p.errorDescription()); + goBack(); + } + else + { + switch(mode) + { + case SingleComic: case SingleComicInList: + if(p.getNumResults() == 0) + showSearchSingleComic(); + else + if(status == SearchingVolume) + showSelectVolume(string); + else + showSelectComic(string); + break; + case Volume: + if(p.getNumResults() == 0) + showSearchVolume(); + else + showSelectVolume(string); + break; + } + } +} + +void ComicVineDialog::showSeriesQuestion() +{ + status = AskingForInfo; + content->setCurrentWidget(seriesQuestionWidget); + backButton->setHidden(true); + skipButton->setHidden(true); + nextButton->setVisible(true); + searchButton->setHidden(true); + closeButton->setVisible(true); + + if(mode == SingleComicInList) + skipButton->setVisible(true); + else + skipButton->setHidden(true); +} + +void ComicVineDialog::showSearchSingleComic() +{ + status = AskingForInfo; + content->setCurrentWidget(searchSingleComicWidget); + backButton->setHidden(true); + skipButton->setHidden(true); + nextButton->setHidden(true); + searchButton->setVisible(true); + closeButton->setVisible(true); + + if(mode == SingleComicInList) + skipButton->setVisible(true); + else + skipButton->setHidden(true); +} + +void ComicVineDialog::showSearchVolume() +{ + status = AskingForInfo; + content->setCurrentWidget(searchVolumeWidget); + backButton->setHidden(true); + nextButton->setHidden(true); + searchButton->setVisible(true); + closeButton->setVisible(true); + toggleSkipButton(); +} + +void ComicVineDialog::showSelectVolume(const QString & json) +{ + showSelectVolume(); + selectVolumeWidget->load(json,currentVolumeSearchString); +} + +void ComicVineDialog::showSelectVolume() +{ + status = SelectingSeries; + + content->setCurrentWidget(selectVolumeWidget); + + backButton->setVisible(true); + nextButton->setVisible(true); + searchButton->setHidden(true); + closeButton->setVisible(true); + toggleSkipButton(); +} + +void ComicVineDialog::showSelectComic(const QString &json) +{ + status = SelectingComic; + + content->setCurrentWidget(selectComicWidget); + selectComicWidget->load(json,currentVolumeId); + + backButton->setVisible(true); + nextButton->setVisible(true); + searchButton->setHidden(true); + closeButton->setVisible(true); + toggleSkipButton(); +} + +void ComicVineDialog::showSortVolumeComics(const QString &json) +{ + status = SortingComics; + + content->setCurrentWidget(sortVolumeComicsWidget); + + sortVolumeComicsWidget->setData(comics, json, currentVolumeId); + + backButton->setVisible(true); + nextButton->setVisible(true); + searchButton->setHidden(true); + closeButton->setVisible(true); + toggleSkipButton(); +} + +void ComicVineDialog::queryTimeOut() +{ + QMessageBox::warning(this,"Comic Vine error", "Time out connecting to Comic Vine"); + + switch (status) { + case AutoSearching: + if(mode == Volume) + showSearchVolume(); + else + showSearchSingleComic(); + break; + case SearchingVolume: + if(mode == Volume) + showSearchVolume(); + else + showSearchSingleComic(); + break; + case SearchingSingleComic: + showSearchSingleComic(); + break; + case GettingVolumeComics: + showSelectVolume(); + break; + default: + break; + } +} + +void ComicVineDialog::getComicsInfo(QList > & matchingInfo, int count,const QString & publisher) +{ + QPair p; + QList comics; + foreach (p, matchingInfo) { + ComicVineClient * comicVineClient = new ComicVineClient; + //connect(comicVineClient,SIGNAL(searchResult(QString)),this,SLOT(debugClientResults(QString))); + //connect(comicVineClient,SIGNAL(timeOut()),this,SLOT(queryTimeOut())); + //connect(comicVineClient,SIGNAL(finished()),comicVineClient,SLOT(deleteLater())); + bool error; + bool timeout; + QByteArray result = comicVineClient->getComicDetail(p.second,error,timeout); //TODO check timeOut or Connection error + if(error || timeout) + continue; //TODO + ComicDB comic = parseComicInfo(p.first,result,count,publisher);//TODO check result error + comic.info.comicVineID = p.second; + comics.push_back(comic); + + setLoadingMessage(tr("Retrieving tags for : %1").arg(p.first.getFileName())); + } + + QSqlDatabase db = DataBaseManagement::loadDatabase(databasePath); + db.open(); + db.transaction(); + foreach(ComicDB comic, comics) + { + DBHelper::update(&(comic.info),db); + } + db.commit(); + db.close(); + QSqlDatabase::removeDatabase(db.connectionName()); + + emit accepted(); +} + +void ComicVineDialog::getComicInfo(const QString &comicId, int count, const QString &publisher) +{ + + ComicVineClient * comicVineClient = new ComicVineClient; + bool error; + bool timeout; + QByteArray result = comicVineClient->getComicDetail(comicId,error,timeout); //TODO check timeOut or Connection error + if(error || timeout) + { + //TODO + if(mode == SingleComic || currentIndex == (comics.count()-1)) + { + emit accepted(); + } else + { + goToNextComic(); + } + } + + ComicDB comic = parseComicInfo(comics[currentIndex],result,count,publisher); //TODO check result error + comic.info.comicVineID = comicId; + setLoadingMessage(tr("Retrieving tags for : %1").arg(comics[currentIndex].getFileName())); + + QSqlDatabase db = DataBaseManagement::loadDatabase(databasePath); + db.open(); + db.transaction(); + + DBHelper::update(&(comic.info),db); + + db.commit(); + db.close(); + QSqlDatabase::removeDatabase(db.connectionName()); + + if(mode == SingleComic || currentIndex == (comics.count()-1)) + { + emit accepted(); + } else + { + goToNextComic(); + } +} + +ComicDB ComicVineDialog::parseComicInfo(ComicDB & comic, const QString & json, int count, const QString & publisher) +{ + QScriptEngine engine; + QScriptValue sc; + sc = engine.evaluate("(" + json + ")"); + + if (!sc.property("error").isValid() && sc.property("error").toString() != "OK") + { + qDebug("Error detected"); + } + else + { + int numResults = sc.property("number_of_total_results").toString().toInt(); //fix to weird behaviour using hasNext + + if(numResults > 0) + { + QScriptValue result = sc.property("results"); + + QString title = result.property("name").toString(); + + QString number = result.property("issue_number").toString(); + //QString count; //get from select volume + + + QString volume = result.property("volume").property("name").toString(); + // QString storyArc; //story_arc + // QString arcNumber; //?? + // QString arcCount; //count_of_issue_appearances -> NO + + // QString genere; //no + + QMap authors = getAuthors(result.property("person_credits")); + + QString writer = QStringList(authors.values("writer")).join("\n"); + QString penciller = QStringList(authors.values("penciller")).join("\n"); + QString inker = QStringList(authors.values("inker")).join("\n"); + QString colorist = QStringList(authors.values("colorist")).join("\n"); + QString letterer = QStringList(authors.values("letterer")).join("\n"); + QString coverArtist = QStringList(authors.values("cover")).join("\n"); + + QString date = result.property("cover_date").toString(); + + //QString publisher; //get from select volume + // QString format; //no + // bool color; //no + // QString ageRating; //no + + QString synopsis = result.property("description").toString().remove(QRegExp("<[^>]*>")); //description + QString characters = getCharacters(result.property("character_credits")); + + if (title != "null") { + comic.info.title = title; + } + + comic.info.number = number; + comic.info.count = count; + + comic.info.writer = writer; + comic.info.penciller = penciller; + comic.info.inker = inker; + comic.info.colorist = colorist; + comic.info.letterer = letterer; + comic.info.coverArtist = coverArtist; + + QStringList tempList = date.split("-"); + std::reverse(tempList.begin(),tempList.end()); + comic.info.date = tempList.join("/"); + comic.info.volume = volume; + + comic.info.publisher = publisher; + + comic.info.synopsis = synopsis; + comic.info.characters = characters; + } + } + return comic; +} + +QString ComicVineDialog::getCharacters(const QScriptValue &json_characters) +{ + QString characters; + + QScriptValueIterator it(json_characters); + QScriptValue resultsValue; + while (it.hasNext()) { + it.next(); + if(it.flags() & QScriptValue::SkipInEnumeration) + continue; + resultsValue = it.value(); + + characters += resultsValue.property("name").toString() + "\n"; + } + + return characters; +} + +QMap ComicVineDialog::getAuthors(const QScriptValue &json_authors) +{ + QMap authors; + + QScriptValueIterator it(json_authors); + QScriptValue resultsValue; + while (it.hasNext()) { + it.next(); + if(it.flags() & QScriptValue::SkipInEnumeration) + continue; + resultsValue = it.value(); + + QString authorName = resultsValue.property("name").toString(); + + QStringList roles = resultsValue.property("role").toString().split(","); + foreach(QString role, roles) + { + if(role.trimmed() == "writer") + authors.insertMulti("writer",authorName); + else if(role.trimmed() == "inker") + authors.insertMulti("inker",authorName); + else if(role.trimmed() == "penciler" || role.trimmed() == "penciller") + authors.insertMulti("penciller",authorName); + else if(role.trimmed() == "colorist") + authors.insertMulti("colorist",authorName); + else if(role.trimmed() == "letterer") + authors.insertMulti("letterer",authorName); + else if(role.trimmed() == "cover") + authors.insertMulti("cover",authorName); + } + } + + return authors; +} + +void ComicVineDialog::toggleSkipButton() +{ + if (mode == SingleComicInList) + skipButton->setVisible(true); + else + skipButton->setHidden(true); +} + +void ComicVineDialog::goToNextComic() +{ + if(mode == SingleComic || currentIndex == (comics.count()-1)) + { + emit accepted(); + return; + } + + currentIndex++; + + showSearchSingleComic(); + + ComicDB comic = comics[currentIndex]; + QString title = comic.getTitleOrFileName(); + titleHeader->setSubTitle(tr("comic %1 of %2 - %3").arg(currentIndex+1).arg(comics.length()).arg(title)); +} + +void ComicVineDialog::showLoading(const QString &message) +{ + content->setCurrentIndex(0); + loadingMessage->setText(message); + backButton->setHidden(true); + skipButton->setHidden(true); + nextButton->setHidden(true); + searchButton->setHidden(true); + closeButton->setVisible(true); +} + +void ComicVineDialog::setLoadingMessage(const QString &message) +{ + loadingMessage->setText(message); +} + +void ComicVineDialog::search() +{ + switch (mode) { + case Volume: + launchSearchVolume(); + break; + default: + launchSearchComic(); + break; + } +} + +void ComicVineDialog::searchVolume(const QString &v, int page) +{ + showLoading(tr("Looking for volume...")); + + currentVolumeSearchString = v; + + ComicVineClient * comicVineClient = new ComicVineClient; + connect(comicVineClient,SIGNAL(searchResult(QString)),this,SLOT(debugClientResults(QString))); + connect(comicVineClient,SIGNAL(timeOut()),this,SLOT(queryTimeOut())); + connect(comicVineClient,SIGNAL(finished()),comicVineClient,SLOT(deleteLater())); + comicVineClient->search(v,page); + + status = SearchingVolume; +} + +void ComicVineDialog::getVolumeComicsInfo(const QString &vID, int page) +{ + showLoading(tr("Retrieving volume info...")); + + status = GettingVolumeComics; + + ComicVineClient * comicVineClient = new ComicVineClient; + if(mode == Volume) + connect(comicVineClient,SIGNAL(volumeComicsInfo(QString)),this,SLOT(showSortVolumeComics(QString))); + else + connect(comicVineClient,SIGNAL(volumeComicsInfo(QString)),this,SLOT(showSelectComic(QString))); + connect(comicVineClient,SIGNAL(timeOut()),this,SLOT(queryTimeOut())); + connect(comicVineClient,SIGNAL(finished()),comicVineClient,SLOT(deleteLater())); + + QLOG_TRACE() << vID; + + comicVineClient->getAllVolumeComicsInfo(vID); +} + +void ComicVineDialog::launchSearchVolume() +{ + showLoading(tr("Looking for volume...")); + //TODO: check if volume info is empty. + searchVolume(searchVolumeWidget->getVolumeInfo()); +} + +void ComicVineDialog::launchSearchComic() +{ + showLoading(tr("Looking for comic...")); + + QString volumeInfo = searchSingleComicWidget->getVolumeInfo(); + //QString comicInfo = searchSingleComicWidget->getComicInfo(); + //int comicNumber = searchSingleComicWidget->getComicNumber(); + + //if(comicInfo.isEmpty() && comicNumber == -1) + searchVolume(volumeInfo); +} + diff --git a/YACReaderLibrary/comic_vine/comic_vine_dialog.h b/YACReaderLibrary/comic_vine/comic_vine_dialog.h index 1b303b45..66a2be26 100644 --- a/YACReaderLibrary/comic_vine/comic_vine_dialog.h +++ b/YACReaderLibrary/comic_vine/comic_vine_dialog.h @@ -1,131 +1,131 @@ -#ifndef COMIC_VINE_DIALOG_H -#define COMIC_VINE_DIALOG_H - -#include - -#include "comic_db.h" - -class QPushButton; -class QStackedWidget; -class QLabel; -class QRadioButton; -class ComicVineClient; -class QTableView; -class TitleHeader; -class SeriesQuestion; -class SearchSingleComic; -class SearchVolume; -class SelectComic; -class SelectVolume; -class SortVolumeComics; -class QScriptValue; - -//TODO this should use a QStateMachine -//---------------------------------------- -class ComicVineDialog : public QDialog -{ - Q_OBJECT -public: - explicit ComicVineDialog(QWidget *parent = 0); - QString databasePath; - QString basePath; - void setComics(const QList & comics); - QSize sizeHint() const; - QSize minimumSizeHint() const; - -signals: - -public slots: - void show(); - -protected slots: - void goNext(); - void goBack(); - void debugClientResults(const QString & string); - //show widget methods - void showSeriesQuestion(); - void showSearchSingleComic(); - void showSearchVolume(); - void showLoading(const QString & message = ""); - void search(); - void searchVolume(const QString & v, int page = 1); - void getVolumeComicsInfo(const QString &vID, int page = 1); - void launchSearchVolume(); - void launchSearchComic(); - void showSelectVolume(const QString & json); - void showSelectVolume(); - void showSelectComic(const QString & json); - void showSortVolumeComics(const QString & json); - void queryTimeOut(); - void getComicsInfo(QList > & matchingInfo, int count, const QString & publisher); - void getComicInfo(const QString & comicId, int count, const QString & publisher); - ComicDB parseComicInfo(ComicDB &comic, const QString & json, int count, const QString &publisher); - void setLoadingMessage(const QString &message); - void goToNextComic(); - -private: - - QString getCharacters(const QScriptValue & json_characters); - QMap getAuthors(const QScriptValue & json_authors); - - void toggleSkipButton(); - - enum ScraperMode - { - SingleComic, //the scraper has been opened for a single comic - Volume, //the scraper is trying to get comics info for a whole volume - SingleComicInList //the scraper has been opened for a list of unrelated comics - }; - - enum ScraperStatus - { - AutoSearching, - AskingForInfo, - SelectingComic, - SelectingSeries, - SearchingSingleComic, - SearchingVolume, - SortingComics, - GettingVolumeComics - }; - - ScraperMode mode; - ScraperStatus status; - - int currentIndex; - - TitleHeader * titleHeader; - - QPushButton * skipButton; - QPushButton * backButton; - QPushButton * nextButton; - QPushButton * searchButton; - QPushButton * closeButton; - - //stacked widgets - QStackedWidget * content; - - QWidget * infoNotFound; - QWidget * singleComicBrowser; - - QLabel * loadingMessage; - - void doLayout(); - void doStackedWidgets(); - void doLoading(); - void doConnections(); - - QList comics; - - SeriesQuestion * seriesQuestionWidget; - SearchSingleComic * searchSingleComicWidget; - SearchVolume * searchVolumeWidget; - SelectVolume * selectVolumeWidget; - SelectComic * selectComicWidget; - SortVolumeComics * sortVolumeComicsWidget; - - QString currentVolumeSearchString; - QString currentVolumeId; -}; - -#endif // COMIC_VINE_DIALOG_H +#ifndef COMIC_VINE_DIALOG_H +#define COMIC_VINE_DIALOG_H + +#include + +#include "comic_db.h" + +class QPushButton; +class QStackedWidget; +class QLabel; +class QRadioButton; +class ComicVineClient; +class QTableView; +class TitleHeader; +class SeriesQuestion; +class SearchSingleComic; +class SearchVolume; +class SelectComic; +class SelectVolume; +class SortVolumeComics; +class QScriptValue; + +//TODO this should use a QStateMachine +//---------------------------------------- +class ComicVineDialog : public QDialog +{ + Q_OBJECT +public: + explicit ComicVineDialog(QWidget *parent = 0); + QString databasePath; + QString basePath; + void setComics(const QList & comics); + QSize sizeHint() const; + QSize minimumSizeHint() const; + +signals: + +public slots: + void show(); + +protected slots: + void goNext(); + void goBack(); + void debugClientResults(const QString & string); + //show widget methods + void showSeriesQuestion(); + void showSearchSingleComic(); + void showSearchVolume(); + void showLoading(const QString & message = ""); + void search(); + void searchVolume(const QString & v, int page = 1); + void getVolumeComicsInfo(const QString &vID, int page = 1); + void launchSearchVolume(); + void launchSearchComic(); + void showSelectVolume(const QString & json); + void showSelectVolume(); + void showSelectComic(const QString & json); + void showSortVolumeComics(const QString & json); + void queryTimeOut(); + void getComicsInfo(QList > & matchingInfo, int count, const QString & publisher); + void getComicInfo(const QString & comicId, int count, const QString & publisher); + ComicDB parseComicInfo(ComicDB &comic, const QString & json, int count, const QString &publisher); + void setLoadingMessage(const QString &message); + void goToNextComic(); + +private: + + QString getCharacters(const QScriptValue & json_characters); + QMap getAuthors(const QScriptValue & json_authors); + + void toggleSkipButton(); + + enum ScraperMode + { + SingleComic, //the scraper has been opened for a single comic + Volume, //the scraper is trying to get comics info for a whole volume + SingleComicInList //the scraper has been opened for a list of unrelated comics + }; + + enum ScraperStatus + { + AutoSearching, + AskingForInfo, + SelectingComic, + SelectingSeries, + SearchingSingleComic, + SearchingVolume, + SortingComics, + GettingVolumeComics + }; + + ScraperMode mode; + ScraperStatus status; + + int currentIndex; + + TitleHeader * titleHeader; + + QPushButton * skipButton; + QPushButton * backButton; + QPushButton * nextButton; + QPushButton * searchButton; + QPushButton * closeButton; + + //stacked widgets + QStackedWidget * content; + + QWidget * infoNotFound; + QWidget * singleComicBrowser; + + QLabel * loadingMessage; + + void doLayout(); + void doStackedWidgets(); + void doLoading(); + void doConnections(); + + QList comics; + + SeriesQuestion * seriesQuestionWidget; + SearchSingleComic * searchSingleComicWidget; + SearchVolume * searchVolumeWidget; + SelectVolume * selectVolumeWidget; + SelectComic * selectComicWidget; + SortVolumeComics * sortVolumeComicsWidget; + + QString currentVolumeSearchString; + QString currentVolumeId; +}; + +#endif // COMIC_VINE_DIALOG_H diff --git a/YACReaderLibrary/comic_vine/model/comics_model.cpp b/YACReaderLibrary/comic_vine/model/comics_model.cpp index 5b194f24..0aa22a03 100644 --- a/YACReaderLibrary/comic_vine/model/comics_model.cpp +++ b/YACReaderLibrary/comic_vine/model/comics_model.cpp @@ -1,6 +1,6 @@ -#include "comics_model.h" - -ComicsModel::ComicsModel(QObject *parent) : - JSONModel(parent) -{ -} +#include "comics_model.h" + +ComicsModel::ComicsModel(QObject *parent) : + JSONModel(parent) +{ +} diff --git a/YACReaderLibrary/comic_vine/model/comics_model.h b/YACReaderLibrary/comic_vine/model/comics_model.h index 86bfb2e5..d99625c1 100644 --- a/YACReaderLibrary/comic_vine/model/comics_model.h +++ b/YACReaderLibrary/comic_vine/model/comics_model.h @@ -1,18 +1,18 @@ -#ifndef COMICS_MODEL_H -#define COMICS_MODEL_H - -#include "json_model.h" - -class ComicsModel : public JSONModel -{ - Q_OBJECT -public: - explicit ComicsModel(QObject *parent = 0); - -signals: - -public slots: - -}; - -#endif // COMICS_MODEL_H +#ifndef COMICS_MODEL_H +#define COMICS_MODEL_H + +#include "json_model.h" + +class ComicsModel : public JSONModel +{ + Q_OBJECT +public: + explicit ComicsModel(QObject *parent = 0); + +signals: + +public slots: + +}; + +#endif // COMICS_MODEL_H diff --git a/YACReaderLibrary/comic_vine/model/json_model.cpp b/YACReaderLibrary/comic_vine/model/json_model.cpp index d0c4ce41..65d54f32 100644 --- a/YACReaderLibrary/comic_vine/model/json_model.cpp +++ b/YACReaderLibrary/comic_vine/model/json_model.cpp @@ -1,6 +1,6 @@ -#include "json_model.h" - -JSONModel::JSONModel(QObject *parent) : - QAbstractItemModel(parent) -{ -} +#include "json_model.h" + +JSONModel::JSONModel(QObject *parent) : + QAbstractItemModel(parent) +{ +} diff --git a/YACReaderLibrary/comic_vine/model/json_model.h b/YACReaderLibrary/comic_vine/model/json_model.h index 443e9a20..7a70fb70 100644 --- a/YACReaderLibrary/comic_vine/model/json_model.h +++ b/YACReaderLibrary/comic_vine/model/json_model.h @@ -1,19 +1,19 @@ -#ifndef JSON_MODEL_H -#define JSON_MODEL_H - -#include - -class JSONModel : public QAbstractItemModel -{ - Q_OBJECT -public: - explicit JSONModel(QObject *parent = 0); - virtual void load(const QString & json) = 0 ; - -signals: - -public slots: - -}; - -#endif // JSON_MODEL_H +#ifndef JSON_MODEL_H +#define JSON_MODEL_H + +#include + +class JSONModel : public QAbstractItemModel +{ + Q_OBJECT +public: + explicit JSONModel(QObject *parent = 0); + virtual void load(const QString & json) = 0 ; + +signals: + +public slots: + +}; + +#endif // JSON_MODEL_H diff --git a/YACReaderLibrary/comic_vine/model/local_comic_list_model.cpp b/YACReaderLibrary/comic_vine/model/local_comic_list_model.cpp index e27b69b8..b4c45239 100644 --- a/YACReaderLibrary/comic_vine/model/local_comic_list_model.cpp +++ b/YACReaderLibrary/comic_vine/model/local_comic_list_model.cpp @@ -1,184 +1,184 @@ -#include "local_comic_list_model.h" - -LocalComicListModel::LocalComicListModel(QObject *parent) : - QAbstractItemModel(parent),numExtraRows(0) -{ -} - -void LocalComicListModel::load(QList &comics) -{ - _data = comics; -} - - -QModelIndex LocalComicListModel::parent(const QModelIndex &index) const -{ - Q_UNUSED(index) - return QModelIndex(); //no parent -} - -int LocalComicListModel::rowCount(const QModelIndex &parent) const -{ - Q_UNUSED(parent) - return _data.count(); -} - -int LocalComicListModel::columnCount(const QModelIndex &parent) const -{ - Q_UNUSED(parent) - if(_data.isEmpty()) - return 0; - else - return 1;//_data.at(0)->count(); -} - -QVariant LocalComicListModel::data(const QModelIndex &index, int role) const -{ - if (!index.isValid()) - return QVariant(); - - if (role == Qt::DecorationRole) - { - return QVariant(); - } - if (role == Qt::TextAlignmentRole) - { - //TODO - } - - if(role != Qt::DisplayRole) - return QVariant(); - - int row = index.row(); - - //if(row < _data.count()) - return _data[row].getFileName(); - //else - //return QVariant(); -} - -Qt::ItemFlags LocalComicListModel::flags(const QModelIndex &index) const -{ - if (!index.isValid()) - return 0; - return Qt::ItemIsEnabled | Qt::ItemIsSelectable; -} - -QVariant LocalComicListModel::headerData(int section, Qt::Orientation orientation, int role) const -{ - Q_UNUSED(section); - - if ( role == Qt::TextAlignmentRole) - return QVariant(Qt::AlignLeft | Qt::AlignVCenter); - - if (orientation == Qt::Horizontal && role == Qt::DisplayRole) - { - return QVariant(QString(tr("file name"))); - } - - return QVariant(); -} - -QModelIndex LocalComicListModel::index(int row, int column, const QModelIndex &parent) const -{ - if (!hasIndex(row, column, parent)) - return QModelIndex(); - - return createIndex(row, column); -} - -QList LocalComicListModel::getData() -{ - return _data; -} - -void LocalComicListModel::removeComics(const QList &selectedIndexes) -{ - QModelIndex mi = selectedIndexes.first(); - QModelIndex lastMi = selectedIndexes.last(); - int sourceRow = mi.row(); - int sourceLastRow = lastMi.row(); - - beginRemoveRows(QModelIndex(),selectedIndexes.first().row(),selectedIndexes.last().row()); - - for(int i = sourceLastRow;i>=sourceRow;i--) - { - _removed.push_front(_data.at(i)); - _data.removeAt(i); - } - - endRemoveRows(); - - beginInsertRows(QModelIndex(),_data.count()-_removed.count(),_data.count()-1); - for(int i = 0; i<_removed.count(); i++) - _data.append(ComicDB()); - endInsertRows(); -} - -void LocalComicListModel::restoreAll() -{ - int numItemsToRemove = 0; - for(int i = 0;numItemsToRemove<_removed.count();i++) - { - if(_data.at(i).getFileName().isEmpty()) - { - beginRemoveRows(QModelIndex(),i,i); - _data.removeAt(i); - endRemoveRows(); - - beginInsertRows(QModelIndex(),i,i); - _data.insert(i,_removed.at(numItemsToRemove)); - endInsertRows(); - - numItemsToRemove++; - } - } - - _removed.clear(); -} - -void LocalComicListModel::moveSelectionUp(const QList &selectedIndexes) -{ - QModelIndex mi = selectedIndexes.first(); - QModelIndex lastMi = selectedIndexes.last(); - int sourceRow = mi.row(); - int sourceLastRow = lastMi.row(); - int destRow = sourceRow - 1; - - if(destRow < 0) - return; - - beginMoveRows(mi.parent(),sourceRow,sourceLastRow,mi.parent(),destRow); - - for(int i = sourceRow; i <= sourceLastRow; i++) - _data.swap(i, i-1); - - endMoveRows(); -} - -void LocalComicListModel::moveSelectionDown(const QList &selectedIndexes) -{ - QModelIndex mi = selectedIndexes.first(); - QModelIndex lastMi = selectedIndexes.last(); - int sourceRow = mi.row(); - int sourceLastRow = lastMi.row(); - int destRow = sourceLastRow + 1; - - if(destRow >= _data.count()) - return; - - beginMoveRows(mi.parent(),sourceRow,sourceLastRow,mi.parent(),destRow+1); - - for(int i = sourceLastRow; i >= sourceRow; i--) - _data.swap(i, i+1); - - endMoveRows(); -} - -void LocalComicListModel::addExtraRows(int numRows) -{ - numExtraRows = numRows; - for(int i = 0; i &comics) +{ + _data = comics; +} + + +QModelIndex LocalComicListModel::parent(const QModelIndex &index) const +{ + Q_UNUSED(index) + return QModelIndex(); //no parent +} + +int LocalComicListModel::rowCount(const QModelIndex &parent) const +{ + Q_UNUSED(parent) + return _data.count(); +} + +int LocalComicListModel::columnCount(const QModelIndex &parent) const +{ + Q_UNUSED(parent) + if(_data.isEmpty()) + return 0; + else + return 1;//_data.at(0)->count(); +} + +QVariant LocalComicListModel::data(const QModelIndex &index, int role) const +{ + if (!index.isValid()) + return QVariant(); + + if (role == Qt::DecorationRole) + { + return QVariant(); + } + if (role == Qt::TextAlignmentRole) + { + //TODO + } + + if(role != Qt::DisplayRole) + return QVariant(); + + int row = index.row(); + + //if(row < _data.count()) + return _data[row].getFileName(); + //else + //return QVariant(); +} + +Qt::ItemFlags LocalComicListModel::flags(const QModelIndex &index) const +{ + if (!index.isValid()) + return 0; + return Qt::ItemIsEnabled | Qt::ItemIsSelectable; +} + +QVariant LocalComicListModel::headerData(int section, Qt::Orientation orientation, int role) const +{ + Q_UNUSED(section); + + if ( role == Qt::TextAlignmentRole) + return QVariant(Qt::AlignLeft | Qt::AlignVCenter); + + if (orientation == Qt::Horizontal && role == Qt::DisplayRole) + { + return QVariant(QString(tr("file name"))); + } + + return QVariant(); +} + +QModelIndex LocalComicListModel::index(int row, int column, const QModelIndex &parent) const +{ + if (!hasIndex(row, column, parent)) + return QModelIndex(); + + return createIndex(row, column); +} + +QList LocalComicListModel::getData() +{ + return _data; +} + +void LocalComicListModel::removeComics(const QList &selectedIndexes) +{ + QModelIndex mi = selectedIndexes.first(); + QModelIndex lastMi = selectedIndexes.last(); + int sourceRow = mi.row(); + int sourceLastRow = lastMi.row(); + + beginRemoveRows(QModelIndex(),selectedIndexes.first().row(),selectedIndexes.last().row()); + + for(int i = sourceLastRow;i>=sourceRow;i--) + { + _removed.push_front(_data.at(i)); + _data.removeAt(i); + } + + endRemoveRows(); + + beginInsertRows(QModelIndex(),_data.count()-_removed.count(),_data.count()-1); + for(int i = 0; i<_removed.count(); i++) + _data.append(ComicDB()); + endInsertRows(); +} + +void LocalComicListModel::restoreAll() +{ + int numItemsToRemove = 0; + for(int i = 0;numItemsToRemove<_removed.count();i++) + { + if(_data.at(i).getFileName().isEmpty()) + { + beginRemoveRows(QModelIndex(),i,i); + _data.removeAt(i); + endRemoveRows(); + + beginInsertRows(QModelIndex(),i,i); + _data.insert(i,_removed.at(numItemsToRemove)); + endInsertRows(); + + numItemsToRemove++; + } + } + + _removed.clear(); +} + +void LocalComicListModel::moveSelectionUp(const QList &selectedIndexes) +{ + QModelIndex mi = selectedIndexes.first(); + QModelIndex lastMi = selectedIndexes.last(); + int sourceRow = mi.row(); + int sourceLastRow = lastMi.row(); + int destRow = sourceRow - 1; + + if(destRow < 0) + return; + + beginMoveRows(mi.parent(),sourceRow,sourceLastRow,mi.parent(),destRow); + + for(int i = sourceRow; i <= sourceLastRow; i++) + _data.swap(i, i-1); + + endMoveRows(); +} + +void LocalComicListModel::moveSelectionDown(const QList &selectedIndexes) +{ + QModelIndex mi = selectedIndexes.first(); + QModelIndex lastMi = selectedIndexes.last(); + int sourceRow = mi.row(); + int sourceLastRow = lastMi.row(); + int destRow = sourceLastRow + 1; + + if(destRow >= _data.count()) + return; + + beginMoveRows(mi.parent(),sourceRow,sourceLastRow,mi.parent(),destRow+1); + + for(int i = sourceLastRow; i >= sourceRow; i--) + _data.swap(i, i+1); + + endMoveRows(); +} + +void LocalComicListModel::addExtraRows(int numRows) +{ + numExtraRows = numRows; + for(int i = 0; i - -#include "comic_db.h" - -class LocalComicListModel : public QAbstractItemModel -{ - Q_OBJECT -public: - explicit LocalComicListModel(QObject *parent = 0); - - void load(QList & comics); - - //QAbstractItemModel methods - QModelIndex parent(const QModelIndex &index) const; - int rowCount(const QModelIndex &parent = QModelIndex()) const; - int columnCount(const QModelIndex &parent) const; - QVariant data(const QModelIndex &index, int role) const; - Qt::ItemFlags flags(const QModelIndex &index) const; - QVariant headerData(int section, Qt::Orientation orientation, - int role = Qt::DisplayRole) const; - QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const; - QList getData(); - - void removeComics(const QList & selectedIndexes); - void restoreAll(); -signals: - -public slots: - void moveSelectionUp(const QList & selectedIndexes); - void moveSelectionDown(const QList & selectedIndexes); - void addExtraRows(int numRows); - -private: - int numExtraRows; - QList _data; - QList _removed; -}; - -#endif // LOCAL_COMIC_LIST_MODEL_H +#ifndef LOCAL_COMIC_LIST_MODEL_H +#define LOCAL_COMIC_LIST_MODEL_H + +#include + +#include "comic_db.h" + +class LocalComicListModel : public QAbstractItemModel +{ + Q_OBJECT +public: + explicit LocalComicListModel(QObject *parent = 0); + + void load(QList & comics); + + //QAbstractItemModel methods + QModelIndex parent(const QModelIndex &index) const; + int rowCount(const QModelIndex &parent = QModelIndex()) const; + int columnCount(const QModelIndex &parent) const; + QVariant data(const QModelIndex &index, int role) const; + Qt::ItemFlags flags(const QModelIndex &index) const; + QVariant headerData(int section, Qt::Orientation orientation, + int role = Qt::DisplayRole) const; + QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const; + QList getData(); + + void removeComics(const QList & selectedIndexes); + void restoreAll(); +signals: + +public slots: + void moveSelectionUp(const QList & selectedIndexes); + void moveSelectionDown(const QList & selectedIndexes); + void addExtraRows(int numRows); + +private: + int numExtraRows; + QList _data; + QList _removed; +}; + +#endif // LOCAL_COMIC_LIST_MODEL_H diff --git a/YACReaderLibrary/comic_vine/model/response_parser.cpp b/YACReaderLibrary/comic_vine/model/response_parser.cpp index eb212107..06a6f0a3 100644 --- a/YACReaderLibrary/comic_vine/model/response_parser.cpp +++ b/YACReaderLibrary/comic_vine/model/response_parser.cpp @@ -1,83 +1,83 @@ -#include "response_parser.h" - -#include -#include - -ResponseParser::ResponseParser(QObject *parent) : - QObject(parent),error(false),numResults(-1),currentPage(-1),totalPages(-1),errorTxt("None") -{ -} - -bool ResponseParser::responseError() -{ - return error; -} - -QString ResponseParser::errorDescription() -{ - return errorTxt; -} - -qint32 ResponseParser::getNumResults() -{ - return numResults; -} - -qint32 ResponseParser::getCurrentPage() -{ - return currentPage; -} - -qint32 ResponseParser::getTotalPages() -{ - return totalPages; -} - -bool ResponseParser::isError(qint32 error) -{ - switch(error) - { - case 100: - return true; - - default: - return false; - } -} - -void ResponseParser::loadJSONResponse(const QString &response) -{ - QScriptEngine engine; - QScriptValue sc; - sc = engine.evaluate("(" + response + ")"); - - errorTxt = "None"; - - if (!sc.property("status_code").isValid() || isError(sc.property("status_code").toInt32())) - { - error = true; - if(sc.property("error").isValid()) - errorTxt = sc.property("error").toString(); - else - errorTxt = "Unknown error"; - } - else - { - error = false; - if(sc.property("number_of_total_results").isValid()) - numResults = sc.property("number_of_total_results").toString().toInt();// sc.property("number_of_total_results").toInt32(); - else - qDebug() << sc.property("oops").toString(); - - int limit = sc.property("limit").toInt32(); - int offset = sc.property("offset").toInt32(); - int total = sc.property("number_of_total_results").toInt32(); - if(limit > 0) - { - totalPages = (total / limit) + (total%limit>0?1:0); - currentPage = (offset / limit) + 1; - } - else - totalPages = currentPage = 1; - } -} +#include "response_parser.h" + +#include +#include + +ResponseParser::ResponseParser(QObject *parent) : + QObject(parent),error(false),numResults(-1),currentPage(-1),totalPages(-1),errorTxt("None") +{ +} + +bool ResponseParser::responseError() +{ + return error; +} + +QString ResponseParser::errorDescription() +{ + return errorTxt; +} + +qint32 ResponseParser::getNumResults() +{ + return numResults; +} + +qint32 ResponseParser::getCurrentPage() +{ + return currentPage; +} + +qint32 ResponseParser::getTotalPages() +{ + return totalPages; +} + +bool ResponseParser::isError(qint32 error) +{ + switch(error) + { + case 100: + return true; + + default: + return false; + } +} + +void ResponseParser::loadJSONResponse(const QString &response) +{ + QScriptEngine engine; + QScriptValue sc; + sc = engine.evaluate("(" + response + ")"); + + errorTxt = "None"; + + if (!sc.property("status_code").isValid() || isError(sc.property("status_code").toInt32())) + { + error = true; + if(sc.property("error").isValid()) + errorTxt = sc.property("error").toString(); + else + errorTxt = "Unknown error"; + } + else + { + error = false; + if(sc.property("number_of_total_results").isValid()) + numResults = sc.property("number_of_total_results").toString().toInt();// sc.property("number_of_total_results").toInt32(); + else + qDebug() << sc.property("oops").toString(); + + int limit = sc.property("limit").toInt32(); + int offset = sc.property("offset").toInt32(); + int total = sc.property("number_of_total_results").toInt32(); + if(limit > 0) + { + totalPages = (total / limit) + (total%limit>0?1:0); + currentPage = (offset / limit) + 1; + } + else + totalPages = currentPage = 1; + } +} diff --git a/YACReaderLibrary/comic_vine/model/response_parser.h b/YACReaderLibrary/comic_vine/model/response_parser.h index 10014ecb..b3325252 100644 --- a/YACReaderLibrary/comic_vine/model/response_parser.h +++ b/YACReaderLibrary/comic_vine/model/response_parser.h @@ -1,30 +1,30 @@ -#ifndef RESPONSE_PARSER_H -#define RESPONSE_PARSER_H - -#include - -class ResponseParser : public QObject -{ - Q_OBJECT -public: - explicit ResponseParser(QObject *parent = 0); - bool responseError(); - QString errorDescription(); - qint32 getNumResults(); - qint32 getCurrentPage(); - qint32 getTotalPages(); - bool isError(qint32 error); -signals: - -public slots: - void loadJSONResponse(const QString & response); - -protected: - bool error; - QString errorTxt; - qint32 numResults; - qint32 currentPage; - qint32 totalPages; -}; - -#endif // RESPONSE_PARSER_H +#ifndef RESPONSE_PARSER_H +#define RESPONSE_PARSER_H + +#include + +class ResponseParser : public QObject +{ + Q_OBJECT +public: + explicit ResponseParser(QObject *parent = 0); + bool responseError(); + QString errorDescription(); + qint32 getNumResults(); + qint32 getCurrentPage(); + qint32 getTotalPages(); + bool isError(qint32 error); +signals: + +public slots: + void loadJSONResponse(const QString & response); + +protected: + bool error; + QString errorTxt; + qint32 numResults; + qint32 currentPage; + qint32 totalPages; +}; + +#endif // RESPONSE_PARSER_H diff --git a/YACReaderLibrary/comic_vine/model/volume_comics_model.cpp b/YACReaderLibrary/comic_vine/model/volume_comics_model.cpp index 4b7e7f6d..ceb8c3b3 100644 --- a/YACReaderLibrary/comic_vine/model/volume_comics_model.cpp +++ b/YACReaderLibrary/comic_vine/model/volume_comics_model.cpp @@ -1,180 +1,180 @@ -#include "volume_comics_model.h" -#include "qnaturalsorting.h" - - -#include - -bool lessThan(const QList & left, const QList & right) -{ - if ((left.count() > 0) && (right.count() > 0)) - return naturalSortLessThanCI(left.at(0),right.at(0)); - else - return true; -} - -VolumeComicsModel::VolumeComicsModel(QObject * parent) : - JSONModel(parent),numExtraRows(0) -{ -} - -void VolumeComicsModel::load(const QString & json) -{ - QScriptEngine engine; - QScriptValue sc; - sc = engine.evaluate("(" + json + ")"); - - if (!sc.property("error").isValid() && sc.property("error").toString() != "OK") - { - qDebug("Error detected"); - } - else - { - QScriptValueIterator it(sc.property("results")); - //bool test; - QScriptValue resultsValue; - while (it.hasNext()) { - it.next(); - if(it.flags() & QScriptValue::SkipInEnumeration) - continue; - resultsValue = it.value(); - QString issueNumber = resultsValue.property("issue_number").toString(); - QScriptValue propertyName = resultsValue.property("name"); - QString name = propertyName.isNull() ? "-" : propertyName.toString(); - QString coverURL = resultsValue.property("image").property("medium_url").toString(); - QString id = resultsValue.property("id").toString(); - QStringList l; - l << issueNumber << name << coverURL << id; - _data.push_back(l); - } - - qSort(_data.begin(),_data.end(),lessThan); - } -} - -/*void VolumeComicsModel::load(const QStringList &jsonList) -{ - foreach (QString json, jsonList) { - load(json); - } -}*/ - -QModelIndex VolumeComicsModel::parent(const QModelIndex &index) const -{ - Q_UNUSED(index) - return QModelIndex(); //no parent -} - -int VolumeComicsModel::rowCount(const QModelIndex &parent) const -{ - Q_UNUSED(parent) - return _data.count() + numExtraRows; -} - -int VolumeComicsModel::columnCount(const QModelIndex &parent) const -{ - Q_UNUSED(parent) - if(_data.isEmpty()) - return 0; - else - return 2; -} - -QVariant VolumeComicsModel::data(const QModelIndex &index, int role) const -{ - if (!index.isValid()) - return QVariant(); - - int row = index.row(); - int column = index.column(); - - if (role == Qt::DecorationRole) - { - return QVariant(); - } - if (role == Qt::TextAlignmentRole) - { - switch(column)//TODO obtener esto de la query - { - case ISSUE: - return QVariant(Qt::AlignRight | Qt::AlignVCenter); - case TITLE: - return QVariant(Qt::AlignLeft | Qt::AlignVCenter); - } - } - - if(role != Qt::DisplayRole) - return QVariant(); - - if(row<_data.count()) - return _data[row][column]; - else - return QVariant(); -} - -Qt::ItemFlags VolumeComicsModel::flags(const QModelIndex &index) const -{ - if (!index.isValid()) - return 0; - return Qt::ItemIsEnabled | Qt::ItemIsSelectable; -} - -QVariant VolumeComicsModel::headerData(int section, Qt::Orientation orientation, int role) const -{ - if (orientation == Qt::Horizontal && role == Qt::DisplayRole) - { - switch(section)//TODO obtener esto de la query - { - case ISSUE: - return QVariant(QString("issue")); - case TITLE: - return QVariant(QString(tr("title"))); - } - } - - if (orientation == Qt::Horizontal && role == Qt::TextAlignmentRole) - { - switch(section)//TODO obtener esto de la query - { - case ISSUE: - return QVariant(Qt::AlignRight | Qt::AlignVCenter); - case TITLE: - return QVariant(Qt::AlignLeft | Qt::AlignVCenter); - } - } - - return QVariant(); -} - -QModelIndex VolumeComicsModel::index(int row, int column, const QModelIndex &parent) const -{ - if (!hasIndex(row, column, parent)) - return QModelIndex(); - - return createIndex(row, column); -} - -QString VolumeComicsModel::getComicId(const QModelIndex &index) const -{ - int row = index.row(); - if(row >= _data.count()) - return ""; - return _data[row][ID]; -} - -QString VolumeComicsModel::getComicId(int row) const -{ - if(row >= _data.count()) - return ""; - return _data[row][ID]; -} - -QString VolumeComicsModel::getCoverURL(const QModelIndex &index) const -{ - return _data[index.row()][COVER_URL]; -} - -void VolumeComicsModel::addExtraRows(int numRows) -{ - numExtraRows = numRows; -} - +#include "volume_comics_model.h" +#include "qnaturalsorting.h" + + +#include + +bool lessThan(const QList & left, const QList & right) +{ + if ((left.count() > 0) && (right.count() > 0)) + return naturalSortLessThanCI(left.at(0),right.at(0)); + else + return true; +} + +VolumeComicsModel::VolumeComicsModel(QObject * parent) : + JSONModel(parent),numExtraRows(0) +{ +} + +void VolumeComicsModel::load(const QString & json) +{ + QScriptEngine engine; + QScriptValue sc; + sc = engine.evaluate("(" + json + ")"); + + if (!sc.property("error").isValid() && sc.property("error").toString() != "OK") + { + qDebug("Error detected"); + } + else + { + QScriptValueIterator it(sc.property("results")); + //bool test; + QScriptValue resultsValue; + while (it.hasNext()) { + it.next(); + if(it.flags() & QScriptValue::SkipInEnumeration) + continue; + resultsValue = it.value(); + QString issueNumber = resultsValue.property("issue_number").toString(); + QScriptValue propertyName = resultsValue.property("name"); + QString name = propertyName.isNull() ? "-" : propertyName.toString(); + QString coverURL = resultsValue.property("image").property("medium_url").toString(); + QString id = resultsValue.property("id").toString(); + QStringList l; + l << issueNumber << name << coverURL << id; + _data.push_back(l); + } + + qSort(_data.begin(),_data.end(),lessThan); + } +} + +/*void VolumeComicsModel::load(const QStringList &jsonList) +{ + foreach (QString json, jsonList) { + load(json); + } +}*/ + +QModelIndex VolumeComicsModel::parent(const QModelIndex &index) const +{ + Q_UNUSED(index) + return QModelIndex(); //no parent +} + +int VolumeComicsModel::rowCount(const QModelIndex &parent) const +{ + Q_UNUSED(parent) + return _data.count() + numExtraRows; +} + +int VolumeComicsModel::columnCount(const QModelIndex &parent) const +{ + Q_UNUSED(parent) + if(_data.isEmpty()) + return 0; + else + return 2; +} + +QVariant VolumeComicsModel::data(const QModelIndex &index, int role) const +{ + if (!index.isValid()) + return QVariant(); + + int row = index.row(); + int column = index.column(); + + if (role == Qt::DecorationRole) + { + return QVariant(); + } + if (role == Qt::TextAlignmentRole) + { + switch(column)//TODO obtener esto de la query + { + case ISSUE: + return QVariant(Qt::AlignRight | Qt::AlignVCenter); + case TITLE: + return QVariant(Qt::AlignLeft | Qt::AlignVCenter); + } + } + + if(role != Qt::DisplayRole) + return QVariant(); + + if(row<_data.count()) + return _data[row][column]; + else + return QVariant(); +} + +Qt::ItemFlags VolumeComicsModel::flags(const QModelIndex &index) const +{ + if (!index.isValid()) + return 0; + return Qt::ItemIsEnabled | Qt::ItemIsSelectable; +} + +QVariant VolumeComicsModel::headerData(int section, Qt::Orientation orientation, int role) const +{ + if (orientation == Qt::Horizontal && role == Qt::DisplayRole) + { + switch(section)//TODO obtener esto de la query + { + case ISSUE: + return QVariant(QString("issue")); + case TITLE: + return QVariant(QString(tr("title"))); + } + } + + if (orientation == Qt::Horizontal && role == Qt::TextAlignmentRole) + { + switch(section)//TODO obtener esto de la query + { + case ISSUE: + return QVariant(Qt::AlignRight | Qt::AlignVCenter); + case TITLE: + return QVariant(Qt::AlignLeft | Qt::AlignVCenter); + } + } + + return QVariant(); +} + +QModelIndex VolumeComicsModel::index(int row, int column, const QModelIndex &parent) const +{ + if (!hasIndex(row, column, parent)) + return QModelIndex(); + + return createIndex(row, column); +} + +QString VolumeComicsModel::getComicId(const QModelIndex &index) const +{ + int row = index.row(); + if(row >= _data.count()) + return ""; + return _data[row][ID]; +} + +QString VolumeComicsModel::getComicId(int row) const +{ + if(row >= _data.count()) + return ""; + return _data[row][ID]; +} + +QString VolumeComicsModel::getCoverURL(const QModelIndex &index) const +{ + return _data[index.row()][COVER_URL]; +} + +void VolumeComicsModel::addExtraRows(int numRows) +{ + numExtraRows = numRows; +} + diff --git a/YACReaderLibrary/comic_vine/model/volume_comics_model.h b/YACReaderLibrary/comic_vine/model/volume_comics_model.h index 8ccb416a..b9d9aaeb 100644 --- a/YACReaderLibrary/comic_vine/model/volume_comics_model.h +++ b/YACReaderLibrary/comic_vine/model/volume_comics_model.h @@ -1,42 +1,42 @@ -#ifndef VOLUME_COMICS_MODEL_H -#define VOLUME_COMICS_MODEL_H - -#include "json_model.h" - -class VolumeComicsModel : public JSONModel -{ - Q_OBJECT -public: - explicit VolumeComicsModel(QObject *parent = 0); - void load(const QString & json); - //void load(const QStringList & jsonList); - - QModelIndex parent(const QModelIndex &index) const; - int rowCount(const QModelIndex &parent = QModelIndex()) const; - int columnCount(const QModelIndex &parent) const; - QVariant data(const QModelIndex &index, int role) const; - Qt::ItemFlags flags(const QModelIndex &index) const; - QVariant headerData(int section, Qt::Orientation orientation, - int role = Qt::DisplayRole) const; - QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const; -signals: - -public slots: - QString getComicId(const QModelIndex &index) const; - QString getComicId(int row) const; - QString getCoverURL(const QModelIndex &index) const; - void addExtraRows(int numRows); - -private: - int numExtraRows; - QList > _data; - - enum Column { - ISSUE = 0, - TITLE, - COVER_URL, - ID - }; -}; - -#endif // VOLUME_COMICS_MODEL_H +#ifndef VOLUME_COMICS_MODEL_H +#define VOLUME_COMICS_MODEL_H + +#include "json_model.h" + +class VolumeComicsModel : public JSONModel +{ + Q_OBJECT +public: + explicit VolumeComicsModel(QObject *parent = 0); + void load(const QString & json); + //void load(const QStringList & jsonList); + + QModelIndex parent(const QModelIndex &index) const; + int rowCount(const QModelIndex &parent = QModelIndex()) const; + int columnCount(const QModelIndex &parent) const; + QVariant data(const QModelIndex &index, int role) const; + Qt::ItemFlags flags(const QModelIndex &index) const; + QVariant headerData(int section, Qt::Orientation orientation, + int role = Qt::DisplayRole) const; + QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const; +signals: + +public slots: + QString getComicId(const QModelIndex &index) const; + QString getComicId(int row) const; + QString getCoverURL(const QModelIndex &index) const; + void addExtraRows(int numRows); + +private: + int numExtraRows; + QList > _data; + + enum Column { + ISSUE = 0, + TITLE, + COVER_URL, + ID + }; +}; + +#endif // VOLUME_COMICS_MODEL_H diff --git a/YACReaderLibrary/comic_vine/model/volumes_model.cpp b/YACReaderLibrary/comic_vine/model/volumes_model.cpp index 896f3f04..7bb63408 100644 --- a/YACReaderLibrary/comic_vine/model/volumes_model.cpp +++ b/YACReaderLibrary/comic_vine/model/volumes_model.cpp @@ -1,180 +1,180 @@ -#include "volumes_model.h" - -#include - - -VolumesModel::VolumesModel(QObject *parent) : - JSONModel(parent) -{ -} - -VolumesModel::~VolumesModel() -{ - //std::for_each(_data.begin(), _data.end(), [](QList * ptr) { delete ptr; }); -} - -void VolumesModel::load(const QString &json) -{ - QScriptEngine engine; - QScriptValue sc; - sc = engine.evaluate("(" + json + ")"); - - if (!sc.property("error").isValid() && sc.property("error").toString() != "OK") - { - qDebug("Error detected"); - } - else - { - int numResults = sc.property("number_of_total_results").toString().toInt(); //fix to weird behaviour using hasNext - QScriptValueIterator it(sc.property("results")); - bool test; - QScriptValue resultsValue; - while (it.hasNext()) { - it.next(); - resultsValue = it.value(); - QString numIssues = resultsValue.property("count_of_issues").toString(); - QString year = resultsValue.property("start_year").toString(); - QString name = resultsValue.property("name").toString(); - QString publisher = resultsValue.property("publisher").property("name").toString(); - QString url = resultsValue.property("image").property("medium_url").toString(); - QString deck = resultsValue.property("deck").toString(); - QString id = resultsValue.property("id").toString(); - QStringList l; - l << name << year << numIssues << publisher << url << deck << id; - test = name.isEmpty() && year.isEmpty() && numIssues.isEmpty() && url.isEmpty(); - if(numResults>0 && !test) - _data.push_back(l); - numResults--; - } - } -} - -QModelIndex VolumesModel::parent(const QModelIndex &index) const -{ - Q_UNUSED(index) - return QModelIndex(); //no parent -} - -int VolumesModel::rowCount(const QModelIndex &parent) const -{ - Q_UNUSED(parent) - return _data.count(); -} - -int VolumesModel::columnCount(const QModelIndex &parent) const -{ - Q_UNUSED(parent) - if(_data.isEmpty()) - return 0; - else - return 4;//_data.at(0)->count(); -} - -QVariant VolumesModel::data(const QModelIndex &index, int role) const -{ - if (!index.isValid()) - return QVariant(); - - if (role == Qt::DecorationRole) - { - return QVariant(); - } - - int row = index.row(); - int column = index.column(); - - if (role == Qt::TextAlignmentRole) - { - switch(column) - { - case YEAR: - return QVariant(Qt::AlignRight | Qt::AlignVCenter); - case ISSUES: - return QVariant(Qt::AlignRight | Qt::AlignVCenter); - default: - return QVariant(Qt::AlignLeft | Qt::AlignVCenter); - } - } - - if(role != Qt::DisplayRole) - return QVariant(); - - if (column == YEAR || column == ISSUES) - { - return _data[row][column].toInt(); - } - else - { - return _data[row][column]; - } -} - -Qt::ItemFlags VolumesModel::flags(const QModelIndex &index) const -{ - if (!index.isValid()) - return 0; - return Qt::ItemIsEnabled | Qt::ItemIsSelectable; -} - -QVariant VolumesModel::headerData(int section, Qt::Orientation orientation, int role) const -{ - - if (orientation == Qt::Horizontal && role == Qt::DisplayRole) - { - switch(section)//TODO obtener esto de la query - { - case SERIES: - return QVariant(QString("series")); - case YEAR: - return QVariant(QString(tr("year"))); - case ISSUES: - return QVariant(QString(tr("issues"))); - case PUBLISHER: - return QVariant(QString(tr("publisher"))); - } - } - - if (orientation == Qt::Horizontal && role == Qt::TextAlignmentRole) - { - switch(section)//TODO obtener esto de la query - { - case YEAR: - return QVariant(Qt::AlignRight | Qt::AlignVCenter); - case ISSUES: - return QVariant(Qt::AlignRight | Qt::AlignVCenter); - default: - return QVariant(Qt::AlignLeft | Qt::AlignVCenter); - } - } - - return QVariant(); -} - -QModelIndex VolumesModel::index(int row, int column, const QModelIndex &parent) const -{ - if (!hasIndex(row, column, parent)) - return QModelIndex(); - - return createIndex(row, column); -} - -QString VolumesModel::getVolumeId(const QModelIndex &index) const -{ - return _data[index.row()][ID]; -} - -int VolumesModel::getNumIssues(const QModelIndex &index) const -{ - return _data[index.row()][ISSUES].toInt(); -} - -QString VolumesModel::getPublisher(const QModelIndex &index) const -{ - return _data[index.row()][PUBLISHER]; -} - -QString VolumesModel::getCoverURL(const QModelIndex &index) const -{ - return _data[index.row()][COVER_URL]; -} - +#include "volumes_model.h" + +#include + + +VolumesModel::VolumesModel(QObject *parent) : + JSONModel(parent) +{ +} + +VolumesModel::~VolumesModel() +{ + //std::for_each(_data.begin(), _data.end(), [](QList * ptr) { delete ptr; }); +} + +void VolumesModel::load(const QString &json) +{ + QScriptEngine engine; + QScriptValue sc; + sc = engine.evaluate("(" + json + ")"); + + if (!sc.property("error").isValid() && sc.property("error").toString() != "OK") + { + qDebug("Error detected"); + } + else + { + int numResults = sc.property("number_of_total_results").toString().toInt(); //fix to weird behaviour using hasNext + QScriptValueIterator it(sc.property("results")); + bool test; + QScriptValue resultsValue; + while (it.hasNext()) { + it.next(); + resultsValue = it.value(); + QString numIssues = resultsValue.property("count_of_issues").toString(); + QString year = resultsValue.property("start_year").toString(); + QString name = resultsValue.property("name").toString(); + QString publisher = resultsValue.property("publisher").property("name").toString(); + QString url = resultsValue.property("image").property("medium_url").toString(); + QString deck = resultsValue.property("deck").toString(); + QString id = resultsValue.property("id").toString(); + QStringList l; + l << name << year << numIssues << publisher << url << deck << id; + test = name.isEmpty() && year.isEmpty() && numIssues.isEmpty() && url.isEmpty(); + if(numResults>0 && !test) + _data.push_back(l); + numResults--; + } + } +} + +QModelIndex VolumesModel::parent(const QModelIndex &index) const +{ + Q_UNUSED(index) + return QModelIndex(); //no parent +} + +int VolumesModel::rowCount(const QModelIndex &parent) const +{ + Q_UNUSED(parent) + return _data.count(); +} + +int VolumesModel::columnCount(const QModelIndex &parent) const +{ + Q_UNUSED(parent) + if(_data.isEmpty()) + return 0; + else + return 4;//_data.at(0)->count(); +} + +QVariant VolumesModel::data(const QModelIndex &index, int role) const +{ + if (!index.isValid()) + return QVariant(); + + if (role == Qt::DecorationRole) + { + return QVariant(); + } + + int row = index.row(); + int column = index.column(); + + if (role == Qt::TextAlignmentRole) + { + switch(column) + { + case YEAR: + return QVariant(Qt::AlignRight | Qt::AlignVCenter); + case ISSUES: + return QVariant(Qt::AlignRight | Qt::AlignVCenter); + default: + return QVariant(Qt::AlignLeft | Qt::AlignVCenter); + } + } + + if(role != Qt::DisplayRole) + return QVariant(); + + if (column == YEAR || column == ISSUES) + { + return _data[row][column].toInt(); + } + else + { + return _data[row][column]; + } +} + +Qt::ItemFlags VolumesModel::flags(const QModelIndex &index) const +{ + if (!index.isValid()) + return 0; + return Qt::ItemIsEnabled | Qt::ItemIsSelectable; +} + +QVariant VolumesModel::headerData(int section, Qt::Orientation orientation, int role) const +{ + + if (orientation == Qt::Horizontal && role == Qt::DisplayRole) + { + switch(section)//TODO obtener esto de la query + { + case SERIES: + return QVariant(QString("series")); + case YEAR: + return QVariant(QString(tr("year"))); + case ISSUES: + return QVariant(QString(tr("issues"))); + case PUBLISHER: + return QVariant(QString(tr("publisher"))); + } + } + + if (orientation == Qt::Horizontal && role == Qt::TextAlignmentRole) + { + switch(section)//TODO obtener esto de la query + { + case YEAR: + return QVariant(Qt::AlignRight | Qt::AlignVCenter); + case ISSUES: + return QVariant(Qt::AlignRight | Qt::AlignVCenter); + default: + return QVariant(Qt::AlignLeft | Qt::AlignVCenter); + } + } + + return QVariant(); +} + +QModelIndex VolumesModel::index(int row, int column, const QModelIndex &parent) const +{ + if (!hasIndex(row, column, parent)) + return QModelIndex(); + + return createIndex(row, column); +} + +QString VolumesModel::getVolumeId(const QModelIndex &index) const +{ + return _data[index.row()][ID]; +} + +int VolumesModel::getNumIssues(const QModelIndex &index) const +{ + return _data[index.row()][ISSUES].toInt(); +} + +QString VolumesModel::getPublisher(const QModelIndex &index) const +{ + return _data[index.row()][PUBLISHER]; +} + +QString VolumesModel::getCoverURL(const QModelIndex &index) const +{ + return _data[index.row()][COVER_URL]; +} + diff --git a/YACReaderLibrary/comic_vine/model/volumes_model.h b/YACReaderLibrary/comic_vine/model/volumes_model.h index 00c9e800..a9811458 100644 --- a/YACReaderLibrary/comic_vine/model/volumes_model.h +++ b/YACReaderLibrary/comic_vine/model/volumes_model.h @@ -1,53 +1,53 @@ -#ifndef VOLUMES_MODEL_H -#define VOLUMES_MODEL_H - -#include "json_model.h" - -class VolumesModel : public JSONModel -{ - Q_OBJECT -public: - explicit VolumesModel(QObject *parent = 0); - virtual ~VolumesModel(); - //receive a valid json with a list of volumes - void load(const QString & json); - - //QAbstractItemModel methods - QModelIndex parent(const QModelIndex &index) const; - int rowCount(const QModelIndex &parent = QModelIndex()) const; - int columnCount(const QModelIndex &parent) const; - QVariant data(const QModelIndex &index, int role) const; - Qt::ItemFlags flags(const QModelIndex &index) const; - QVariant headerData(int section, Qt::Orientation orientation, - int role = Qt::DisplayRole) const; - QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const; - - QString getVolumeId(const QModelIndex & index) const; - int getNumIssues(const QModelIndex & index) const; - QString getPublisher(const QModelIndex & index) const; - QString getCoverURL(const QModelIndex & index) const; - -signals: - -public slots: - -private: - QList > _data; - -public: - enum Column { - SERIES = 0, - YEAR, - ISSUES, - PUBLISHER, - COVER_URL, - DECK, - ID - }; - - enum Role { - SORT_ROLE = Qt::UserRole - }; -}; - -#endif // VOLUMES_MODEL_H +#ifndef VOLUMES_MODEL_H +#define VOLUMES_MODEL_H + +#include "json_model.h" + +class VolumesModel : public JSONModel +{ + Q_OBJECT +public: + explicit VolumesModel(QObject *parent = 0); + virtual ~VolumesModel(); + //receive a valid json with a list of volumes + void load(const QString & json); + + //QAbstractItemModel methods + QModelIndex parent(const QModelIndex &index) const; + int rowCount(const QModelIndex &parent = QModelIndex()) const; + int columnCount(const QModelIndex &parent) const; + QVariant data(const QModelIndex &index, int role) const; + Qt::ItemFlags flags(const QModelIndex &index) const; + QVariant headerData(int section, Qt::Orientation orientation, + int role = Qt::DisplayRole) const; + QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const; + + QString getVolumeId(const QModelIndex & index) const; + int getNumIssues(const QModelIndex & index) const; + QString getPublisher(const QModelIndex & index) const; + QString getCoverURL(const QModelIndex & index) const; + +signals: + +public slots: + +private: + QList > _data; + +public: + enum Column { + SERIES = 0, + YEAR, + ISSUES, + PUBLISHER, + COVER_URL, + DECK, + ID + }; + + enum Role { + SORT_ROLE = Qt::UserRole + }; +}; + +#endif // VOLUMES_MODEL_H diff --git a/YACReaderLibrary/comic_vine/scraper_lineedit.cpp b/YACReaderLibrary/comic_vine/scraper_lineedit.cpp index 94d03e95..5afb4074 100644 --- a/YACReaderLibrary/comic_vine/scraper_lineedit.cpp +++ b/YACReaderLibrary/comic_vine/scraper_lineedit.cpp @@ -1,21 +1,21 @@ -#include "scraper_lineedit.h" -#include - -ScraperLineEdit::ScraperLineEdit(const QString & title, QWidget * widget) - :QLineEdit(widget) -{ - titleLabel = new QLabel(title,this); - titleLabel->setStyleSheet("QLabel {color:white;}"); - - setStyleSheet(QString("QLineEdit {" - "border:none; background-color: #2E2E2E; color : white; padding-left: %1; padding-bottom: 1px; margin-bottom: 0px;" - "}").arg(titleLabel->sizeHint().width()+6)); - - setFixedHeight(22); -} - -void ScraperLineEdit::resizeEvent(QResizeEvent *) -{ - QSize szl = titleLabel->sizeHint(); - titleLabel->move(6,(rect().bottom() + 1 - szl.height())/2); -} +#include "scraper_lineedit.h" +#include + +ScraperLineEdit::ScraperLineEdit(const QString & title, QWidget * widget) + :QLineEdit(widget) +{ + titleLabel = new QLabel(title,this); + titleLabel->setStyleSheet("QLabel {color:white;}"); + + setStyleSheet(QString("QLineEdit {" + "border:none; background-color: #2E2E2E; color : white; padding-left: %1; padding-bottom: 1px; margin-bottom: 0px;" + "}").arg(titleLabel->sizeHint().width()+6)); + + setFixedHeight(22); +} + +void ScraperLineEdit::resizeEvent(QResizeEvent *) +{ + QSize szl = titleLabel->sizeHint(); + titleLabel->move(6,(rect().bottom() + 1 - szl.height())/2); +} diff --git a/YACReaderLibrary/comic_vine/scraper_lineedit.h b/YACReaderLibrary/comic_vine/scraper_lineedit.h index 30665b11..45d58039 100644 --- a/YACReaderLibrary/comic_vine/scraper_lineedit.h +++ b/YACReaderLibrary/comic_vine/scraper_lineedit.h @@ -1,19 +1,19 @@ -#ifndef SCRAPPER_LINEEDIT_H -#define SCRAPPER_LINEEDIT_H - -#include - -class QLabel; - -class ScraperLineEdit : public QLineEdit -{ - Q_OBJECT -public: - ScraperLineEdit(const QString & title, QWidget * widget = 0); -protected: - void resizeEvent(QResizeEvent *); -private: - QLabel * titleLabel; -}; - -#endif // SCRAPPER_LINEEDIT_H +#ifndef SCRAPPER_LINEEDIT_H +#define SCRAPPER_LINEEDIT_H + +#include + +class QLabel; + +class ScraperLineEdit : public QLineEdit +{ + Q_OBJECT +public: + ScraperLineEdit(const QString & title, QWidget * widget = 0); +protected: + void resizeEvent(QResizeEvent *); +private: + QLabel * titleLabel; +}; + +#endif // SCRAPPER_LINEEDIT_H diff --git a/YACReaderLibrary/comic_vine/scraper_results_paginator.cpp b/YACReaderLibrary/comic_vine/scraper_results_paginator.cpp index f627d315..c7933510 100644 --- a/YACReaderLibrary/comic_vine/scraper_results_paginator.cpp +++ b/YACReaderLibrary/comic_vine/scraper_results_paginator.cpp @@ -1,75 +1,75 @@ -#include "scraper_results_paginator.h" -#include "response_parser.h" - -#include -#include -#include -#include - - -ScraperResultsPaginator::ScraperResultsPaginator(QWidget *parent) : - QWidget(parent),customLabel("items") -{ - QHBoxLayout * pagesButtonsLayout = new QHBoxLayout; - - QString labelStylesheet = "QLabel {color:white; font-size:12px;font-family:Arial;}"; - - nextPage = new QToolButton; - nextPage->setStyleSheet("QToolButton {border:none;}"); - QPixmap np(":/images/comic_vine/nextPage.png"); - nextPage->setIconSize(np.size()); - nextPage->setIcon(np); - - previousPage = new QToolButton; - previousPage->setStyleSheet("QToolButton {border:none;}"); - QPixmap pp(":/images/comic_vine/previousPage.png"); - previousPage->setIconSize(pp.size()); - previousPage->setIcon(pp); - - connect(nextPage,SIGNAL(clicked()),this,SIGNAL(loadNextPage())); - connect(previousPage,SIGNAL(clicked()),this,SIGNAL(loadPreviousPage())); - - numElements = new QLabel(tr("Number of volumes found : %1")); - numElements->setStyleSheet(labelStylesheet); - numPages = new QLabel(tr("page %1 of %2")); - numPages->setStyleSheet(labelStylesheet); - - pagesButtonsLayout->addSpacing(15); - pagesButtonsLayout->addWidget(numElements); - pagesButtonsLayout->addStretch(); - pagesButtonsLayout->addWidget(numPages); - pagesButtonsLayout->addWidget(previousPage); - pagesButtonsLayout->addWidget(nextPage); - - setContentsMargins(0,0,0,0); - pagesButtonsLayout->setContentsMargins(0,0,0,0); - - setLayout(pagesButtonsLayout); -} - -void ScraperResultsPaginator::update(const QString &json) -{ - ResponseParser rp; - rp.loadJSONResponse(json); - - currentPage = rp.getCurrentPage(); - numElements->setText(tr("Number of %1 found : %2").arg(customLabel).arg(rp.getNumResults())); - numPages->setText(tr("page %1 of %2").arg(currentPage).arg(rp.getTotalPages())); - - previousPage->setDisabled(currentPage == 1); - nextPage->setDisabled(currentPage == rp.getTotalPages()); - - numPages->setHidden(rp.getTotalPages()==1); - previousPage->setHidden(rp.getTotalPages()==1); - nextPage->setHidden(rp.getTotalPages()==1); -} - -int ScraperResultsPaginator::getCurrentPage() -{ - return currentPage; -} - -void ScraperResultsPaginator::setCustomLabel(const QString &label) -{ - customLabel = label; -} +#include "scraper_results_paginator.h" +#include "response_parser.h" + +#include +#include +#include +#include + + +ScraperResultsPaginator::ScraperResultsPaginator(QWidget *parent) : + QWidget(parent),customLabel("items") +{ + QHBoxLayout * pagesButtonsLayout = new QHBoxLayout; + + QString labelStylesheet = "QLabel {color:white; font-size:12px;font-family:Arial;}"; + + nextPage = new QToolButton; + nextPage->setStyleSheet("QToolButton {border:none;}"); + QPixmap np(":/images/comic_vine/nextPage.png"); + nextPage->setIconSize(np.size()); + nextPage->setIcon(np); + + previousPage = new QToolButton; + previousPage->setStyleSheet("QToolButton {border:none;}"); + QPixmap pp(":/images/comic_vine/previousPage.png"); + previousPage->setIconSize(pp.size()); + previousPage->setIcon(pp); + + connect(nextPage,SIGNAL(clicked()),this,SIGNAL(loadNextPage())); + connect(previousPage,SIGNAL(clicked()),this,SIGNAL(loadPreviousPage())); + + numElements = new QLabel(tr("Number of volumes found : %1")); + numElements->setStyleSheet(labelStylesheet); + numPages = new QLabel(tr("page %1 of %2")); + numPages->setStyleSheet(labelStylesheet); + + pagesButtonsLayout->addSpacing(15); + pagesButtonsLayout->addWidget(numElements); + pagesButtonsLayout->addStretch(); + pagesButtonsLayout->addWidget(numPages); + pagesButtonsLayout->addWidget(previousPage); + pagesButtonsLayout->addWidget(nextPage); + + setContentsMargins(0,0,0,0); + pagesButtonsLayout->setContentsMargins(0,0,0,0); + + setLayout(pagesButtonsLayout); +} + +void ScraperResultsPaginator::update(const QString &json) +{ + ResponseParser rp; + rp.loadJSONResponse(json); + + currentPage = rp.getCurrentPage(); + numElements->setText(tr("Number of %1 found : %2").arg(customLabel).arg(rp.getNumResults())); + numPages->setText(tr("page %1 of %2").arg(currentPage).arg(rp.getTotalPages())); + + previousPage->setDisabled(currentPage == 1); + nextPage->setDisabled(currentPage == rp.getTotalPages()); + + numPages->setHidden(rp.getTotalPages()==1); + previousPage->setHidden(rp.getTotalPages()==1); + nextPage->setHidden(rp.getTotalPages()==1); +} + +int ScraperResultsPaginator::getCurrentPage() +{ + return currentPage; +} + +void ScraperResultsPaginator::setCustomLabel(const QString &label) +{ + customLabel = label; +} diff --git a/YACReaderLibrary/comic_vine/scraper_results_paginator.h b/YACReaderLibrary/comic_vine/scraper_results_paginator.h index c371b7af..feeb0987 100644 --- a/YACReaderLibrary/comic_vine/scraper_results_paginator.h +++ b/YACReaderLibrary/comic_vine/scraper_results_paginator.h @@ -1,34 +1,34 @@ -#ifndef SCRAPER_RESULTS_PAGINATOR_H -#define SCRAPER_RESULTS_PAGINATOR_H - -#include - -class QToolButton; -class QLabel; - -class ScraperResultsPaginator : public QWidget -{ - Q_OBJECT -public: - explicit ScraperResultsPaginator(QWidget *parent = 0); - void update(const QString & json); - int getCurrentPage(); - void setCustomLabel(const QString & label); -signals: - void loadNextPage(); - void loadPreviousPage(); - -public slots: - -private: - QToolButton * nextPage; - QToolButton * previousPage; - QLabel * numElements; - QLabel * numPages; - - int currentPage; - - QString customLabel; -}; - -#endif // SCRAPER_RESULTS_PAGINATOR_H +#ifndef SCRAPER_RESULTS_PAGINATOR_H +#define SCRAPER_RESULTS_PAGINATOR_H + +#include + +class QToolButton; +class QLabel; + +class ScraperResultsPaginator : public QWidget +{ + Q_OBJECT +public: + explicit ScraperResultsPaginator(QWidget *parent = 0); + void update(const QString & json); + int getCurrentPage(); + void setCustomLabel(const QString & label); +signals: + void loadNextPage(); + void loadPreviousPage(); + +public slots: + +private: + QToolButton * nextPage; + QToolButton * previousPage; + QLabel * numElements; + QLabel * numPages; + + int currentPage; + + QString customLabel; +}; + +#endif // SCRAPER_RESULTS_PAGINATOR_H diff --git a/YACReaderLibrary/comic_vine/scraper_scroll_label.cpp b/YACReaderLibrary/comic_vine/scraper_scroll_label.cpp index 82ce0bd1..87c16f03 100644 --- a/YACReaderLibrary/comic_vine/scraper_scroll_label.cpp +++ b/YACReaderLibrary/comic_vine/scraper_scroll_label.cpp @@ -1,53 +1,53 @@ -#include "scraper_scroll_label.h" - -#include -#include -#include - -ScraperScrollLabel::ScraperScrollLabel(QWidget *parent) : - QScrollArea(parent) -{ - textLabel = new QLabel(this); - textLabel->setStyleSheet("QLabel {background-color: #2B2B2B; color:white; font-size:12px; font-family:Arial; }"); - - textLabel->setWordWrap(true); - textLabel->setMinimumSize(168,12); - - setWidget(textLabel); - setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); - setStyleSheet( - "QScrollArea {background-color:#2B2B2B; border:none;}" - "QScrollBar:vertical { border: none; background: #2B2B2B; width: 3px; margin: 0; }" - "QScrollBar:horizontal { border: none; background: #2B2B2B; height: 3px; margin: 0; }" - "QScrollBar::handle:vertical { background: #DDDDDD; width: 7px; min-height: 20px; }" - "QScrollBar::handle:horizontal { background: #DDDDDD; width: 7px; min-height: 20px; }" - "QScrollBar::add-line:vertical { border: none; background: #404040; height: 10px; subcontrol-position: bottom; subcontrol-origin: margin; margin: 0 3px 0 0;}" - "QScrollBar::sub-line:vertical { border: none; background: #404040; height: 10px; subcontrol-position: top; subcontrol-origin: margin; margin: 0 3px 0 0;}" - "QScrollBar::add-line:horizontal { border: none; background: #404040; width: 10px; subcontrol-position: bottom; subcontrol-origin: margin; margin: 0 0 3px 0;}" - "QScrollBar::sub-line:horizontal { border: none; background: #404040; width: 10px; subcontrol-position: top; subcontrol-origin: margin; margin: 0 0 3px 0;}" - "QScrollBar::up-arrow:vertical {border:none;width: 9px;height: 6px;background: url(':/images/folders_view/line-up.png') center top no-repeat;}" - "QScrollBar::down-arrow:vertical {border:none;width: 9px;height: 6px;background: url(':/images/folders_view/line-down.png') center top no-repeat;}" - "QScrollBar::add-page:vertical, QScrollBar::sub-page:vertical, QScrollBar::add-page:horizontal, QScrollBar::sub-page:horizontal {background: none; }" - ); - - connect(textLabel,SIGNAL(linkActivated(QString)),this,SLOT(openLink(QString))); -} - -void ScraperScrollLabel::setAltText(const QString &text) -{ - textLabel->setAlignment(Qt::AlignTop|Qt::AlignHCenter); - textLabel->setText(text); - textLabel->adjustSize(); -} - -void ScraperScrollLabel::setText(const QString &text) -{ - textLabel->setAlignment(Qt::AlignTop|Qt::AlignLeft); - textLabel->setText(text); - textLabel->adjustSize(); -} - -void ScraperScrollLabel::openLink(const QString & link) -{ - QDesktopServices::openUrl(QUrl("http://www.comicvine.com"+link)); -} +#include "scraper_scroll_label.h" + +#include +#include +#include + +ScraperScrollLabel::ScraperScrollLabel(QWidget *parent) : + QScrollArea(parent) +{ + textLabel = new QLabel(this); + textLabel->setStyleSheet("QLabel {background-color: #2B2B2B; color:white; font-size:12px; font-family:Arial; }"); + + textLabel->setWordWrap(true); + textLabel->setMinimumSize(168,12); + + setWidget(textLabel); + setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); + setStyleSheet( + "QScrollArea {background-color:#2B2B2B; border:none;}" + "QScrollBar:vertical { border: none; background: #2B2B2B; width: 3px; margin: 0; }" + "QScrollBar:horizontal { border: none; background: #2B2B2B; height: 3px; margin: 0; }" + "QScrollBar::handle:vertical { background: #DDDDDD; width: 7px; min-height: 20px; }" + "QScrollBar::handle:horizontal { background: #DDDDDD; width: 7px; min-height: 20px; }" + "QScrollBar::add-line:vertical { border: none; background: #404040; height: 10px; subcontrol-position: bottom; subcontrol-origin: margin; margin: 0 3px 0 0;}" + "QScrollBar::sub-line:vertical { border: none; background: #404040; height: 10px; subcontrol-position: top; subcontrol-origin: margin; margin: 0 3px 0 0;}" + "QScrollBar::add-line:horizontal { border: none; background: #404040; width: 10px; subcontrol-position: bottom; subcontrol-origin: margin; margin: 0 0 3px 0;}" + "QScrollBar::sub-line:horizontal { border: none; background: #404040; width: 10px; subcontrol-position: top; subcontrol-origin: margin; margin: 0 0 3px 0;}" + "QScrollBar::up-arrow:vertical {border:none;width: 9px;height: 6px;background: url(':/images/folders_view/line-up.png') center top no-repeat;}" + "QScrollBar::down-arrow:vertical {border:none;width: 9px;height: 6px;background: url(':/images/folders_view/line-down.png') center top no-repeat;}" + "QScrollBar::add-page:vertical, QScrollBar::sub-page:vertical, QScrollBar::add-page:horizontal, QScrollBar::sub-page:horizontal {background: none; }" + ); + + connect(textLabel,SIGNAL(linkActivated(QString)),this,SLOT(openLink(QString))); +} + +void ScraperScrollLabel::setAltText(const QString &text) +{ + textLabel->setAlignment(Qt::AlignTop|Qt::AlignHCenter); + textLabel->setText(text); + textLabel->adjustSize(); +} + +void ScraperScrollLabel::setText(const QString &text) +{ + textLabel->setAlignment(Qt::AlignTop|Qt::AlignLeft); + textLabel->setText(text); + textLabel->adjustSize(); +} + +void ScraperScrollLabel::openLink(const QString & link) +{ + QDesktopServices::openUrl(QUrl("http://www.comicvine.com"+link)); +} diff --git a/YACReaderLibrary/comic_vine/scraper_scroll_label.h b/YACReaderLibrary/comic_vine/scraper_scroll_label.h index 8b4c82be..3319f344 100644 --- a/YACReaderLibrary/comic_vine/scraper_scroll_label.h +++ b/YACReaderLibrary/comic_vine/scraper_scroll_label.h @@ -1,25 +1,25 @@ -#ifndef SCRAPER_SCROLL_LABEL_H -#define SCRAPER_SCROLL_LABEL_H - -#include - -class QLabel; - -class ScraperScrollLabel : public QScrollArea -{ - Q_OBJECT -public: - explicit ScraperScrollLabel(QWidget *parent = 0); - -signals: - -public slots: - void setText(const QString & text); - void setAltText(const QString &text); - - void openLink(const QString &link); -private: - QLabel * textLabel; -}; - -#endif // SCRAPER_SCROLL_LABEL_H +#ifndef SCRAPER_SCROLL_LABEL_H +#define SCRAPER_SCROLL_LABEL_H + +#include + +class QLabel; + +class ScraperScrollLabel : public QScrollArea +{ + Q_OBJECT +public: + explicit ScraperScrollLabel(QWidget *parent = 0); + +signals: + +public slots: + void setText(const QString & text); + void setAltText(const QString &text); + + void openLink(const QString &link); +private: + QLabel * textLabel; +}; + +#endif // SCRAPER_SCROLL_LABEL_H diff --git a/YACReaderLibrary/comic_vine/scraper_selector.cpp b/YACReaderLibrary/comic_vine/scraper_selector.cpp index e79117b9..bf6bd5a3 100644 --- a/YACReaderLibrary/comic_vine/scraper_selector.cpp +++ b/YACReaderLibrary/comic_vine/scraper_selector.cpp @@ -1,25 +1,25 @@ -#include "scraper_selector.h" - -ScraperSelector::ScraperSelector(QWidget *parent) : - QWidget(parent) -{ - paginator = new ScraperResultsPaginator; - connect(paginator,SIGNAL(loadNextPage()),this,SLOT(loadNextPage())); - connect(paginator,SIGNAL(loadPreviousPage()),this,SLOT(loadPreviousPage())); -} - -void ScraperSelector::load(const QString &json, const QString &searchString) -{ - currentSearchString = searchString; - paginator->update(json); -} - -void ScraperSelector::loadNextPage() -{ - emit loadPage(currentSearchString,paginator->getCurrentPage()+1); -} - -void ScraperSelector::loadPreviousPage() -{ - emit loadPage(currentSearchString,paginator->getCurrentPage()-1); -} +#include "scraper_selector.h" + +ScraperSelector::ScraperSelector(QWidget *parent) : + QWidget(parent) +{ + paginator = new ScraperResultsPaginator; + connect(paginator,SIGNAL(loadNextPage()),this,SLOT(loadNextPage())); + connect(paginator,SIGNAL(loadPreviousPage()),this,SLOT(loadPreviousPage())); +} + +void ScraperSelector::load(const QString &json, const QString &searchString) +{ + currentSearchString = searchString; + paginator->update(json); +} + +void ScraperSelector::loadNextPage() +{ + emit loadPage(currentSearchString,paginator->getCurrentPage()+1); +} + +void ScraperSelector::loadPreviousPage() +{ + emit loadPage(currentSearchString,paginator->getCurrentPage()-1); +} diff --git a/YACReaderLibrary/comic_vine/scraper_selector.h b/YACReaderLibrary/comic_vine/scraper_selector.h index 34ce409f..640a3950 100644 --- a/YACReaderLibrary/comic_vine/scraper_selector.h +++ b/YACReaderLibrary/comic_vine/scraper_selector.h @@ -1,28 +1,28 @@ -#ifndef SCRAPER_SELECTOR_H -#define SCRAPER_SELECTOR_H - -#include - -#include "scraper_results_paginator.h" - -class ScraperSelector : public QWidget -{ - Q_OBJECT -public: - explicit ScraperSelector(QWidget *parent = 0); - virtual void load(const QString & json, const QString & searchString); -public slots: - -signals: - void loadPage(QString,int); - -private slots: - void loadNextPage(); - void loadPreviousPage(); - -protected: - QString currentSearchString; - ScraperResultsPaginator * paginator; -}; - -#endif // SCRAPER_SELECTOR_H +#ifndef SCRAPER_SELECTOR_H +#define SCRAPER_SELECTOR_H + +#include + +#include "scraper_results_paginator.h" + +class ScraperSelector : public QWidget +{ + Q_OBJECT +public: + explicit ScraperSelector(QWidget *parent = 0); + virtual void load(const QString & json, const QString & searchString); +public slots: + +signals: + void loadPage(QString,int); + +private slots: + void loadNextPage(); + void loadPreviousPage(); + +protected: + QString currentSearchString; + ScraperResultsPaginator * paginator; +}; + +#endif // SCRAPER_SELECTOR_H diff --git a/YACReaderLibrary/comic_vine/scraper_tableview.cpp b/YACReaderLibrary/comic_vine/scraper_tableview.cpp index 58339d8f..f78bcc7a 100644 --- a/YACReaderLibrary/comic_vine/scraper_tableview.cpp +++ b/YACReaderLibrary/comic_vine/scraper_tableview.cpp @@ -1,60 +1,60 @@ -#include "scraper_tableview.h" - -#include - -ScraperTableView::ScraperTableView(QWidget *parent) : - QTableView(parent) -{ - QString tableStylesheet = "QTableView {color:white; border:0px;alternate-background-color: #2E2E2E;background-color: #2B2B2B; outline: 0px;}" - "QTableView::item {outline: 0px; border: 0px; color:#FFFFFF;}" - "QTableView::item:selected {outline: 0px; background-color: #555555; }" - "QHeaderView::section:horizontal {background-color:#292929; border-bottom:1px solid #1F1F1F; border-right:1px solid qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #292929, stop: 1 #1F1F1F); border-left:none; border-top:none; padding:4px; color:#ebebeb;}" - "QHeaderView::section:vertical {border-bottom: 1px solid #DFDFDF;border-top: 1px solid #FEFEFE;}" - "QHeaderView::down-arrow {image: url(':/images/comic_vine/downArrow.png');}" - "QHeaderView::up-arrow {image: url(':/images/comic_vine/upArrow.png');}" - "QScrollBar:vertical { border: none; background: #2B2B2B; width: 3px; margin: 0; }" - "QScrollBar:horizontal { border: none; background: #2B2B2B; height: 3px; margin: 0; }" - "QScrollBar::handle:vertical { background: #DDDDDD; width: 7px; min-height: 20px; }" - "QScrollBar::handle:horizontal { background: #DDDDDD; width: 7px; min-height: 20px; }" - "QScrollBar::add-line:vertical { border: none; background: #404040; height: 10px; subcontrol-position: bottom; subcontrol-origin: margin; margin: 0 3px 0 0;}" - "QScrollBar::sub-line:vertical { border: none; background: #404040; height: 10px; subcontrol-position: top; subcontrol-origin: margin; margin: 0 3px 0 0;}" - "QScrollBar::add-line:horizontal { border: none; background: #404040; width: 10px; subcontrol-position: bottom; subcontrol-origin: margin; margin: 0 0 3px 0;}" - "QScrollBar::sub-line:horizontal { border: none; background: #404040; width: 10px; subcontrol-position: top; subcontrol-origin: margin; margin: 0 0 3px 0;}" - "QScrollBar::up-arrow:vertical {border:none;width: 9px;height: 6px;background: url(':/images/folders_view/line-up.png') center top no-repeat;}" - "QScrollBar::down-arrow:vertical {border:none;width: 9px;height: 6px;background: url(':/images/folders_view/line-down.png') center top no-repeat;}" - "QScrollBar::add-page:vertical, QScrollBar::sub-page:vertical, QScrollBar::add-page:horizontal, QScrollBar::sub-page:horizontal {background: none; }"; - - setStyleSheet(tableStylesheet); - - setShowGrid(false); -#if QT_VERSION >= 0x050000 - verticalHeader()->setSectionResizeMode(QHeaderView::Fixed); -#else - verticalHeader()->setResizeMode(QHeaderView::Fixed); -#endif - - horizontalHeader()->setStretchLastSection(true); -#if QT_VERSION >= 0x050000 - horizontalHeader()->setSectionsClickable(false); -#else - horizontalHeader()->setClickable(false); -#endif - //comicView->verticalHeader()->setResizeMode(QHeaderView::ResizeToContents); - verticalHeader()->setDefaultSectionSize(24); -#if QT_VERSION >= 0x050000 - verticalHeader()->setSectionsClickable(false); //TODO comportamiento anómalo -#else - verticalHeader()->setClickable(false); //TODO comportamiento anómalo -#endif - - setCornerButtonEnabled(false); - - setSelectionBehavior(QAbstractItemView::SelectRows); - setSelectionMode(QAbstractItemView::ExtendedSelection); - - setAlternatingRowColors(true); - - verticalHeader()->hide(); - - setSelectionMode(QAbstractItemView::SingleSelection); -} +#include "scraper_tableview.h" + +#include + +ScraperTableView::ScraperTableView(QWidget *parent) : + QTableView(parent) +{ + QString tableStylesheet = "QTableView {color:white; border:0px;alternate-background-color: #2E2E2E;background-color: #2B2B2B; outline: 0px;}" + "QTableView::item {outline: 0px; border: 0px; color:#FFFFFF;}" + "QTableView::item:selected {outline: 0px; background-color: #555555; }" + "QHeaderView::section:horizontal {background-color:#292929; border-bottom:1px solid #1F1F1F; border-right:1px solid qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #292929, stop: 1 #1F1F1F); border-left:none; border-top:none; padding:4px; color:#ebebeb;}" + "QHeaderView::section:vertical {border-bottom: 1px solid #DFDFDF;border-top: 1px solid #FEFEFE;}" + "QHeaderView::down-arrow {image: url(':/images/comic_vine/downArrow.png');}" + "QHeaderView::up-arrow {image: url(':/images/comic_vine/upArrow.png');}" + "QScrollBar:vertical { border: none; background: #2B2B2B; width: 3px; margin: 0; }" + "QScrollBar:horizontal { border: none; background: #2B2B2B; height: 3px; margin: 0; }" + "QScrollBar::handle:vertical { background: #DDDDDD; width: 7px; min-height: 20px; }" + "QScrollBar::handle:horizontal { background: #DDDDDD; width: 7px; min-height: 20px; }" + "QScrollBar::add-line:vertical { border: none; background: #404040; height: 10px; subcontrol-position: bottom; subcontrol-origin: margin; margin: 0 3px 0 0;}" + "QScrollBar::sub-line:vertical { border: none; background: #404040; height: 10px; subcontrol-position: top; subcontrol-origin: margin; margin: 0 3px 0 0;}" + "QScrollBar::add-line:horizontal { border: none; background: #404040; width: 10px; subcontrol-position: bottom; subcontrol-origin: margin; margin: 0 0 3px 0;}" + "QScrollBar::sub-line:horizontal { border: none; background: #404040; width: 10px; subcontrol-position: top; subcontrol-origin: margin; margin: 0 0 3px 0;}" + "QScrollBar::up-arrow:vertical {border:none;width: 9px;height: 6px;background: url(':/images/folders_view/line-up.png') center top no-repeat;}" + "QScrollBar::down-arrow:vertical {border:none;width: 9px;height: 6px;background: url(':/images/folders_view/line-down.png') center top no-repeat;}" + "QScrollBar::add-page:vertical, QScrollBar::sub-page:vertical, QScrollBar::add-page:horizontal, QScrollBar::sub-page:horizontal {background: none; }"; + + setStyleSheet(tableStylesheet); + + setShowGrid(false); +#if QT_VERSION >= 0x050000 + verticalHeader()->setSectionResizeMode(QHeaderView::Fixed); +#else + verticalHeader()->setResizeMode(QHeaderView::Fixed); +#endif + + horizontalHeader()->setStretchLastSection(true); +#if QT_VERSION >= 0x050000 + horizontalHeader()->setSectionsClickable(false); +#else + horizontalHeader()->setClickable(false); +#endif + //comicView->verticalHeader()->setResizeMode(QHeaderView::ResizeToContents); + verticalHeader()->setDefaultSectionSize(24); +#if QT_VERSION >= 0x050000 + verticalHeader()->setSectionsClickable(false); //TODO comportamiento anómalo +#else + verticalHeader()->setClickable(false); //TODO comportamiento anómalo +#endif + + setCornerButtonEnabled(false); + + setSelectionBehavior(QAbstractItemView::SelectRows); + setSelectionMode(QAbstractItemView::ExtendedSelection); + + setAlternatingRowColors(true); + + verticalHeader()->hide(); + + setSelectionMode(QAbstractItemView::SingleSelection); +} diff --git a/YACReaderLibrary/comic_vine/scraper_tableview.h b/YACReaderLibrary/comic_vine/scraper_tableview.h index deb151c7..b6fe83ef 100644 --- a/YACReaderLibrary/comic_vine/scraper_tableview.h +++ b/YACReaderLibrary/comic_vine/scraper_tableview.h @@ -1,18 +1,18 @@ -#ifndef SCRAPPER_TABLEVIEW_H -#define SCRAPPER_TABLEVIEW_H - -#include - -class ScraperTableView : public QTableView -{ - Q_OBJECT -public: - explicit ScraperTableView(QWidget *parent = 0); - -signals: - -public slots: - -}; - -#endif // SCRAPPER_TABLEVIEW_H +#ifndef SCRAPPER_TABLEVIEW_H +#define SCRAPPER_TABLEVIEW_H + +#include + +class ScraperTableView : public QTableView +{ + Q_OBJECT +public: + explicit ScraperTableView(QWidget *parent = 0); + +signals: + +public slots: + +}; + +#endif // SCRAPPER_TABLEVIEW_H diff --git a/YACReaderLibrary/comic_vine/search_single_comic.cpp b/YACReaderLibrary/comic_vine/search_single_comic.cpp index 0e4f479d..e1a74635 100644 --- a/YACReaderLibrary/comic_vine/search_single_comic.cpp +++ b/YACReaderLibrary/comic_vine/search_single_comic.cpp @@ -1,62 +1,62 @@ -#include "search_single_comic.h" - -#include "scraper_lineedit.h" - -#include -#include -#include - -SearchSingleComic::SearchSingleComic(QWidget * parent) - :QWidget(parent) -{ - - //QLabel * label = new QLabel(tr("Please provide some additional information. At least one field is needed.")); - QLabel * label = new QLabel(tr("Please provide some additional information.")); - label->setStyleSheet("QLabel {color:white; font-size:12px;font-family:Arial;}"); - - //titleEdit = new ScraperLineEdit(tr("Title:")); - //numberEdit = new ScraperLineEdit(tr("Number:")); - volumeEdit = new ScraperLineEdit(tr("Series:")); - - //numberEdit->setMaximumWidth(126); - - QVBoxLayout * l = new QVBoxLayout; - //QHBoxLayout * hl = new QHBoxLayout; - //hl->addWidget(titleEdit); - //hl->addWidget(numberEdit); - - l->addSpacing(35); - l->addWidget(label); - //l->addLayout(hl); - l->addWidget(volumeEdit); - l->addStretch(); - - l->setContentsMargins(0,0,0,0); - setLayout(l); - setContentsMargins(0,0,0,0); -} - -QString SearchSingleComic::getVolumeInfo() -{ - return volumeEdit->text(); -} - -QString SearchSingleComic::getComicInfo() -{ - //return titleEdit->text(); - return ""; -} - -int SearchSingleComic::getComicNumber() -{ - //QString numberText = numberEdit->text(); - //if(numberText.isEmpty()) - // return -1; - //return numberText.toInt(); - return 0; -} - -void SearchSingleComic::clean() -{ - volumeEdit->clear(); -} +#include "search_single_comic.h" + +#include "scraper_lineedit.h" + +#include +#include +#include + +SearchSingleComic::SearchSingleComic(QWidget * parent) + :QWidget(parent) +{ + + //QLabel * label = new QLabel(tr("Please provide some additional information. At least one field is needed.")); + QLabel * label = new QLabel(tr("Please provide some additional information.")); + label->setStyleSheet("QLabel {color:white; font-size:12px;font-family:Arial;}"); + + //titleEdit = new ScraperLineEdit(tr("Title:")); + //numberEdit = new ScraperLineEdit(tr("Number:")); + volumeEdit = new ScraperLineEdit(tr("Series:")); + + //numberEdit->setMaximumWidth(126); + + QVBoxLayout * l = new QVBoxLayout; + //QHBoxLayout * hl = new QHBoxLayout; + //hl->addWidget(titleEdit); + //hl->addWidget(numberEdit); + + l->addSpacing(35); + l->addWidget(label); + //l->addLayout(hl); + l->addWidget(volumeEdit); + l->addStretch(); + + l->setContentsMargins(0,0,0,0); + setLayout(l); + setContentsMargins(0,0,0,0); +} + +QString SearchSingleComic::getVolumeInfo() +{ + return volumeEdit->text(); +} + +QString SearchSingleComic::getComicInfo() +{ + //return titleEdit->text(); + return ""; +} + +int SearchSingleComic::getComicNumber() +{ + //QString numberText = numberEdit->text(); + //if(numberText.isEmpty()) + // return -1; + //return numberText.toInt(); + return 0; +} + +void SearchSingleComic::clean() +{ + volumeEdit->clear(); +} diff --git a/YACReaderLibrary/comic_vine/search_single_comic.h b/YACReaderLibrary/comic_vine/search_single_comic.h index 5045ee69..bb504f0c 100644 --- a/YACReaderLibrary/comic_vine/search_single_comic.h +++ b/YACReaderLibrary/comic_vine/search_single_comic.h @@ -1,22 +1,22 @@ -#ifndef SEARCH_SINGLE_COMIC_H -#define SEARCH_SINGLE_COMIC_H - -#include - -class ScraperLineEdit; - -class SearchSingleComic : public QWidget -{ - Q_OBJECT -public: - SearchSingleComic(QWidget * parent = 0); - QString getVolumeInfo(); - QString getComicInfo(); - int getComicNumber(); - void clean(); -private: - ScraperLineEdit * titleEdit; - ScraperLineEdit * numberEdit; - ScraperLineEdit * volumeEdit; -}; -#endif // SEARCH_SINGLE_COMIC_H +#ifndef SEARCH_SINGLE_COMIC_H +#define SEARCH_SINGLE_COMIC_H + +#include + +class ScraperLineEdit; + +class SearchSingleComic : public QWidget +{ + Q_OBJECT +public: + SearchSingleComic(QWidget * parent = 0); + QString getVolumeInfo(); + QString getComicInfo(); + int getComicNumber(); + void clean(); +private: + ScraperLineEdit * titleEdit; + ScraperLineEdit * numberEdit; + ScraperLineEdit * volumeEdit; +}; +#endif // SEARCH_SINGLE_COMIC_H diff --git a/YACReaderLibrary/comic_vine/search_volume.cpp b/YACReaderLibrary/comic_vine/search_volume.cpp index 8351f685..a2cbcc36 100644 --- a/YACReaderLibrary/comic_vine/search_volume.cpp +++ b/YACReaderLibrary/comic_vine/search_volume.cpp @@ -1,36 +1,36 @@ -#include "search_volume.h" - -#include "scraper_lineedit.h" - -#include -#include - -SearchVolume::SearchVolume(QWidget * parent) - :QWidget(parent) -{ - QLabel * label = new QLabel(tr("Please provide some additional information.")); - label->setStyleSheet("QLabel {color:white; font-size:12px;font-family:Arial;}"); - - volumeEdit = new ScraperLineEdit(tr("Series:")); - - QVBoxLayout * l = new QVBoxLayout; - - l->addSpacing(35); - l->addWidget(label); - l->addWidget(volumeEdit); - l->addStretch(); - - l->setContentsMargins(0,0,0,0); - setLayout(l); - setContentsMargins(0,0,0,0); -} - -void SearchVolume::clean() -{ - volumeEdit->clear(); -} - -QString SearchVolume::getVolumeInfo() -{ - return volumeEdit->text(); -} +#include "search_volume.h" + +#include "scraper_lineedit.h" + +#include +#include + +SearchVolume::SearchVolume(QWidget * parent) + :QWidget(parent) +{ + QLabel * label = new QLabel(tr("Please provide some additional information.")); + label->setStyleSheet("QLabel {color:white; font-size:12px;font-family:Arial;}"); + + volumeEdit = new ScraperLineEdit(tr("Series:")); + + QVBoxLayout * l = new QVBoxLayout; + + l->addSpacing(35); + l->addWidget(label); + l->addWidget(volumeEdit); + l->addStretch(); + + l->setContentsMargins(0,0,0,0); + setLayout(l); + setContentsMargins(0,0,0,0); +} + +void SearchVolume::clean() +{ + volumeEdit->clear(); +} + +QString SearchVolume::getVolumeInfo() +{ + return volumeEdit->text(); +} diff --git a/YACReaderLibrary/comic_vine/search_volume.h b/YACReaderLibrary/comic_vine/search_volume.h index 627baebc..65057526 100644 --- a/YACReaderLibrary/comic_vine/search_volume.h +++ b/YACReaderLibrary/comic_vine/search_volume.h @@ -1,21 +1,21 @@ -#ifndef SEARCH_VOLUME_H -#define SEARCH_VOLUME_H - -#include - -class ScraperLineEdit; - - -class SearchVolume : public QWidget -{ - Q_OBJECT -public: - SearchVolume(QWidget * parent = 0); - void clean(); -public slots: - QString getVolumeInfo(); -private: - ScraperLineEdit * volumeEdit; -}; - -#endif // SEARCH_VOLUME_H +#ifndef SEARCH_VOLUME_H +#define SEARCH_VOLUME_H + +#include + +class ScraperLineEdit; + + +class SearchVolume : public QWidget +{ + Q_OBJECT +public: + SearchVolume(QWidget * parent = 0); + void clean(); +public slots: + QString getVolumeInfo(); +private: + ScraperLineEdit * volumeEdit; +}; + +#endif // SEARCH_VOLUME_H diff --git a/YACReaderLibrary/comic_vine/select_comic.cpp b/YACReaderLibrary/comic_vine/select_comic.cpp index 9374c7b3..c7a9286c 100644 --- a/YACReaderLibrary/comic_vine/select_comic.cpp +++ b/YACReaderLibrary/comic_vine/select_comic.cpp @@ -1,144 +1,144 @@ -#include "select_comic.h" - -#include "comic_vine_client.h" -#include "scraper_scroll_label.h" -#include "scraper_tableview.h" -#include "volume_comics_model.h" - -#include -#include -#include - -SelectComic::SelectComic(QWidget *parent) - :ScraperSelector(parent),model(0) -{ - QString labelStylesheet = "QLabel {color:white; font-size:12px;font-family:Arial;}"; - - QLabel * label = new QLabel(tr("Please, select the right comic info.")); - label->setStyleSheet(labelStylesheet); - - QVBoxLayout * l = new QVBoxLayout; - QWidget * leftWidget = new QWidget; - QVBoxLayout * left = new QVBoxLayout; - QGridLayout * content = new QGridLayout; - - //widgets - cover = new QLabel(); - cover->setScaledContents(true); - cover->setAlignment(Qt::AlignTop|Qt::AlignHCenter); - cover->setMinimumSize(168,168*5.0/3); - cover->setStyleSheet("QLabel {background-color: #2B2B2B; color:white; font-size:12px; font-family:Arial; }"); - detailLabel = new ScraperScrollLabel(this); - - tableComics = new ScraperTableView(this); - //connections - connect(tableComics,SIGNAL(clicked(QModelIndex)),this,SLOT(loadComicInfo(QModelIndex))); - - paginator->setCustomLabel(tr("comics")); - - left->addWidget(cover); - left->addWidget(detailLabel,1); - leftWidget->setMaximumWidth(180); - leftWidget->setLayout(left); - left->setContentsMargins(0,0,0,0); - leftWidget->setContentsMargins(0,0,0,0); - - content->addWidget(leftWidget, 0, 0); - content->addWidget(tableComics, 0, 1); - content->addWidget(paginator, 1, 1); - - content->setColumnStretch(1, 1); - content->setRowStretch(0, 1);; - - l->addSpacing(15); - l->addWidget(label); - l->addSpacing(5); - l->addLayout(content); - - l->setContentsMargins(0,0,0,0); - setLayout(l); - setContentsMargins(0,0,0,0); -} - -void SelectComic::load(const QString &json, const QString & searchString) -{ - VolumeComicsModel * tempM = new VolumeComicsModel(); - tempM->load(json); - tableComics->setModel(tempM); - - if(model != 0) - delete model; - - model = tempM; - - if(model->rowCount()>0) - { - tableComics->selectRow(0); - loadComicInfo(model->index(0,0)); - } - - tableComics->resizeColumnToContents(0); - - ScraperSelector::load(json,searchString); -} - -SelectComic::~SelectComic() {} - -void SelectComic::loadComicInfo(const QModelIndex &mi) -{ - QString coverURL = model->getCoverURL(mi); - QString id = model->getComicId(mi); - - QString loadingStyle = "%1"; - cover->setText(loadingStyle.arg(tr("loading cover"))); - detailLabel->setAltText(loadingStyle.arg(tr("loading description"))); - - ComicVineClient * comicVineClient = new ComicVineClient; - connect(comicVineClient,SIGNAL(comicCover(const QByteArray &)),this,SLOT(setCover(const QByteArray &))); - connect(comicVineClient,SIGNAL(finished()),comicVineClient,SLOT(deleteLater())); - comicVineClient->getComicCover(coverURL); - - ComicVineClient * comicVineClient2 = new ComicVineClient; - connect(comicVineClient2,SIGNAL(comicDetail(QString)),this,SLOT(setDescription(QString))); - connect(comicVineClient2,SIGNAL(finished()),comicVineClient2,SLOT(deleteLater())); - comicVineClient2->getComicDetailAsync(id); -} - -void SelectComic::setCover(const QByteArray & data) -{ - QPixmap p; - p.loadFromData(data); - int w = p.width(); - int h = p.height(); - - cover->setPixmap(p); - float aspectRatio = static_cast(w)/h; - - cover->setFixedSize(180,static_cast(180/aspectRatio)); - - cover->update(); -} - -void SelectComic::setDescription(const QString &jsonDetail) -{ - QScriptEngine engine; - QScriptValue sc; - sc = engine.evaluate("(" + jsonDetail + ")"); - - if (!sc.property("error").isValid() && sc.property("error").toString() != "OK") - { - qDebug("Error detected"); - } - else - { - - QScriptValue descriptionValues = sc.property("results").property("description"); - bool valid = !descriptionValues.isNull() && descriptionValues.isValid(); - detailLabel->setText(valid?descriptionValues.toString().replace("getComicId(tableComics->currentIndex()); -} +#include "select_comic.h" + +#include "comic_vine_client.h" +#include "scraper_scroll_label.h" +#include "scraper_tableview.h" +#include "volume_comics_model.h" + +#include +#include +#include + +SelectComic::SelectComic(QWidget *parent) + :ScraperSelector(parent),model(0) +{ + QString labelStylesheet = "QLabel {color:white; font-size:12px;font-family:Arial;}"; + + QLabel * label = new QLabel(tr("Please, select the right comic info.")); + label->setStyleSheet(labelStylesheet); + + QVBoxLayout * l = new QVBoxLayout; + QWidget * leftWidget = new QWidget; + QVBoxLayout * left = new QVBoxLayout; + QGridLayout * content = new QGridLayout; + + //widgets + cover = new QLabel(); + cover->setScaledContents(true); + cover->setAlignment(Qt::AlignTop|Qt::AlignHCenter); + cover->setMinimumSize(168,168*5.0/3); + cover->setStyleSheet("QLabel {background-color: #2B2B2B; color:white; font-size:12px; font-family:Arial; }"); + detailLabel = new ScraperScrollLabel(this); + + tableComics = new ScraperTableView(this); + //connections + connect(tableComics,SIGNAL(clicked(QModelIndex)),this,SLOT(loadComicInfo(QModelIndex))); + + paginator->setCustomLabel(tr("comics")); + + left->addWidget(cover); + left->addWidget(detailLabel,1); + leftWidget->setMaximumWidth(180); + leftWidget->setLayout(left); + left->setContentsMargins(0,0,0,0); + leftWidget->setContentsMargins(0,0,0,0); + + content->addWidget(leftWidget, 0, 0); + content->addWidget(tableComics, 0, 1); + content->addWidget(paginator, 1, 1); + + content->setColumnStretch(1, 1); + content->setRowStretch(0, 1);; + + l->addSpacing(15); + l->addWidget(label); + l->addSpacing(5); + l->addLayout(content); + + l->setContentsMargins(0,0,0,0); + setLayout(l); + setContentsMargins(0,0,0,0); +} + +void SelectComic::load(const QString &json, const QString & searchString) +{ + VolumeComicsModel * tempM = new VolumeComicsModel(); + tempM->load(json); + tableComics->setModel(tempM); + + if(model != 0) + delete model; + + model = tempM; + + if(model->rowCount()>0) + { + tableComics->selectRow(0); + loadComicInfo(model->index(0,0)); + } + + tableComics->resizeColumnToContents(0); + + ScraperSelector::load(json,searchString); +} + +SelectComic::~SelectComic() {} + +void SelectComic::loadComicInfo(const QModelIndex &mi) +{ + QString coverURL = model->getCoverURL(mi); + QString id = model->getComicId(mi); + + QString loadingStyle = "%1"; + cover->setText(loadingStyle.arg(tr("loading cover"))); + detailLabel->setAltText(loadingStyle.arg(tr("loading description"))); + + ComicVineClient * comicVineClient = new ComicVineClient; + connect(comicVineClient,SIGNAL(comicCover(const QByteArray &)),this,SLOT(setCover(const QByteArray &))); + connect(comicVineClient,SIGNAL(finished()),comicVineClient,SLOT(deleteLater())); + comicVineClient->getComicCover(coverURL); + + ComicVineClient * comicVineClient2 = new ComicVineClient; + connect(comicVineClient2,SIGNAL(comicDetail(QString)),this,SLOT(setDescription(QString))); + connect(comicVineClient2,SIGNAL(finished()),comicVineClient2,SLOT(deleteLater())); + comicVineClient2->getComicDetailAsync(id); +} + +void SelectComic::setCover(const QByteArray & data) +{ + QPixmap p; + p.loadFromData(data); + int w = p.width(); + int h = p.height(); + + cover->setPixmap(p); + float aspectRatio = static_cast(w)/h; + + cover->setFixedSize(180,static_cast(180/aspectRatio)); + + cover->update(); +} + +void SelectComic::setDescription(const QString &jsonDetail) +{ + QScriptEngine engine; + QScriptValue sc; + sc = engine.evaluate("(" + jsonDetail + ")"); + + if (!sc.property("error").isValid() && sc.property("error").toString() != "OK") + { + qDebug("Error detected"); + } + else + { + + QScriptValue descriptionValues = sc.property("results").property("description"); + bool valid = !descriptionValues.isNull() && descriptionValues.isValid(); + detailLabel->setText(valid?descriptionValues.toString().replace("getComicId(tableComics->currentIndex()); +} diff --git a/YACReaderLibrary/comic_vine/select_comic.h b/YACReaderLibrary/comic_vine/select_comic.h index 5d14a08b..1349b7d1 100644 --- a/YACReaderLibrary/comic_vine/select_comic.h +++ b/YACReaderLibrary/comic_vine/select_comic.h @@ -1,34 +1,34 @@ -#ifndef SELECT_COMIC_H -#define SELECT_COMIC_H - -#include "scraper_selector.h" - -class QLabel; -class VolumeComicsModel; -class QModelIndex; - -class ScraperScrollLabel; -class ScraperTableView; - -class SelectComic : public ScraperSelector -{ - Q_OBJECT -public: - SelectComic(QWidget * parent = 0); - void load(const QString & json, const QString & searchString); - virtual ~SelectComic(); - -public slots: - void loadComicInfo(const QModelIndex & mi); - void setCover(const QByteArray &); - void setDescription(const QString & jsonDetail); - QString getSelectedComicId(); - -private: - QLabel * cover; - ScraperScrollLabel * detailLabel; - ScraperTableView * tableComics; - VolumeComicsModel * model; -}; - -#endif // SELECT_COMIC_H +#ifndef SELECT_COMIC_H +#define SELECT_COMIC_H + +#include "scraper_selector.h" + +class QLabel; +class VolumeComicsModel; +class QModelIndex; + +class ScraperScrollLabel; +class ScraperTableView; + +class SelectComic : public ScraperSelector +{ + Q_OBJECT +public: + SelectComic(QWidget * parent = 0); + void load(const QString & json, const QString & searchString); + virtual ~SelectComic(); + +public slots: + void loadComicInfo(const QModelIndex & mi); + void setCover(const QByteArray &); + void setDescription(const QString & jsonDetail); + QString getSelectedComicId(); + +private: + QLabel * cover; + ScraperScrollLabel * detailLabel; + ScraperTableView * tableComics; + VolumeComicsModel * model; +}; + +#endif // SELECT_COMIC_H diff --git a/YACReaderLibrary/comic_vine/select_volume.cpp b/YACReaderLibrary/comic_vine/select_volume.cpp index d7716c6b..db7e2014 100644 --- a/YACReaderLibrary/comic_vine/select_volume.cpp +++ b/YACReaderLibrary/comic_vine/select_volume.cpp @@ -1,185 +1,185 @@ -#include "select_volume.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "scraper_tableview.h" - -#include - -#include "volumes_model.h" -#include "comic_vine_client.h" -#include "scraper_scroll_label.h" - -#include "response_parser.h" -#include "scraper_results_paginator.h" - -SelectVolume::SelectVolume(QWidget *parent) - :ScraperSelector(parent),model(0) -{ - proxyModel = new QSortFilterProxyModel; - - QString labelStylesheet = "QLabel {color:white; font-size:12px;font-family:Arial;}"; - - QLabel * label = new QLabel(tr("Please, select the right series for your comic.")); - label->setStyleSheet(labelStylesheet); - - QVBoxLayout * l = new QVBoxLayout; - QWidget * leftWidget = new QWidget; - QVBoxLayout * left = new QVBoxLayout; - QGridLayout * content = new QGridLayout; - - //widgets - cover = new QLabel(); - cover->setScaledContents(true); - cover->setAlignment(Qt::AlignTop|Qt::AlignHCenter); - cover->setMinimumSize(168,168*5.0/3); - cover->setStyleSheet("QLabel {background-color: #2B2B2B; color:white; font-size:12px; font-family:Arial; }"); - detailLabel = new ScraperScrollLabel(); - - tableVolumes = new ScraperTableView(); - tableVolumes->setSortingEnabled(true); -#if QT_VERSION >= 0x050000 - tableVolumes->horizontalHeader()->setSectionsClickable(true); -#else - tableVolumes->horizontalHeader()->setClickable(true); -#endif - //tableVolumes->horizontalHeader()->setSortIndicatorShown(false); - connect(tableVolumes->horizontalHeader(),SIGNAL(sectionClicked(int)), tableVolumes, SLOT(sortByColumn(int))); - //connections - connect(tableVolumes,SIGNAL(clicked(QModelIndex)),this,SLOT(loadVolumeInfo(QModelIndex))); - - paginator->setCustomLabel(tr("volumes")); - - left->addWidget(cover); - left->addWidget(detailLabel,1); - leftWidget->setMaximumWidth(180); - leftWidget->setLayout(left); - left->setContentsMargins(0,0,0,0); - leftWidget->setContentsMargins(0,0,0,0); - - content->addWidget(leftWidget, 0, 0); - content->addWidget(tableVolumes, 0, 1); - content->addWidget(paginator, 1, 1); - - content->setColumnStretch(1, 1); - content->setRowStretch(0, 1); - - l->addSpacing(15); - l->addWidget(label); - l->addSpacing(5); - l->addLayout(content); - - l->setContentsMargins(0,0,0,0); - setLayout(l); - setContentsMargins(0,0,0,0); -} - -void SelectVolume::load(const QString & json, const QString & searchString) -{ - VolumesModel * tempM = new VolumesModel(); - tempM->load(json); - //tableVolumes->setModel(tempM); - - proxyModel->setSourceModel( tempM ); - tableVolumes->setModel(proxyModel); - tableVolumes->sortByColumn(0,Qt::AscendingOrder); - tableVolumes->resizeColumnsToContents(); - - if(model != 0) - delete model; - - model = tempM; - - if(model->rowCount()>0) - { - tableVolumes->selectRow(0); - loadVolumeInfo(proxyModel->index(0,0)); - } - - tableVolumes->setColumnWidth(0,350); - - ScraperSelector::load(json,searchString); -} - -SelectVolume::~SelectVolume() {} - -void SelectVolume::loadVolumeInfo(const QModelIndex & omi) -{ - QModelIndex mi = proxyModel->mapToSource(omi); - QString coverURL = model->getCoverURL(mi); - QString id = model->getVolumeId(mi); - - QString loadingStyle = "%1"; - cover->setText(loadingStyle.arg(tr("loading cover"))); - detailLabel->setAltText(loadingStyle.arg(tr("loading description"))); - - ComicVineClient * comicVineClient = new ComicVineClient; - connect(comicVineClient,SIGNAL(seriesCover(const QByteArray &)),this,SLOT(setCover(const QByteArray &))); - connect(comicVineClient,SIGNAL(finished()),comicVineClient,SLOT(deleteLater())); - comicVineClient->getSeriesCover(coverURL); - - ComicVineClient * comicVineClient2 = new ComicVineClient; - connect(comicVineClient2,SIGNAL(seriesDetail(QString)),this,SLOT(setDescription(QString))); - connect(comicVineClient2,SIGNAL(finished()),comicVineClient2,SLOT(deleteLater())); - comicVineClient2->getSeriesDetail(id); -} - -void SelectVolume::setCover(const QByteArray & data) -{ - QPixmap p; - p.loadFromData(data); - int w = p.width(); - int h = p.height(); - - cover->setPixmap(p); - float aspectRatio = static_cast(w)/h; - - cover->setFixedSize(180,static_cast(180/aspectRatio)); - - cover->update(); -} - -void SelectVolume::setDescription(const QString & jsonDetail) -{ - QScriptEngine engine; - QScriptValue sc; - sc = engine.evaluate("(" + jsonDetail + ")"); - - if (!sc.property("error").isValid() && sc.property("error").toString() != "OK") - { - qDebug("Error detected"); - } - else - { - - QScriptValue descriptionValues = sc.property("results").property("description"); - bool valid = !descriptionValues.isNull() && descriptionValues.isValid(); - detailLabel->setText(valid?descriptionValues.toString().replace("getVolumeId(proxyModel->mapToSource(tableVolumes->currentIndex())); -} - -int SelectVolume::getSelectedVolumeNumIssues() -{ - return model->getNumIssues(proxyModel->mapToSource(tableVolumes->currentIndex())); -} - -QString SelectVolume::getSelectedVolumePublisher() -{ - return model->getPublisher(proxyModel->mapToSource(tableVolumes->currentIndex())); -} - - +#include "select_volume.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "scraper_tableview.h" + +#include + +#include "volumes_model.h" +#include "comic_vine_client.h" +#include "scraper_scroll_label.h" + +#include "response_parser.h" +#include "scraper_results_paginator.h" + +SelectVolume::SelectVolume(QWidget *parent) + :ScraperSelector(parent),model(0) +{ + proxyModel = new QSortFilterProxyModel; + + QString labelStylesheet = "QLabel {color:white; font-size:12px;font-family:Arial;}"; + + QLabel * label = new QLabel(tr("Please, select the right series for your comic.")); + label->setStyleSheet(labelStylesheet); + + QVBoxLayout * l = new QVBoxLayout; + QWidget * leftWidget = new QWidget; + QVBoxLayout * left = new QVBoxLayout; + QGridLayout * content = new QGridLayout; + + //widgets + cover = new QLabel(); + cover->setScaledContents(true); + cover->setAlignment(Qt::AlignTop|Qt::AlignHCenter); + cover->setMinimumSize(168,168*5.0/3); + cover->setStyleSheet("QLabel {background-color: #2B2B2B; color:white; font-size:12px; font-family:Arial; }"); + detailLabel = new ScraperScrollLabel(); + + tableVolumes = new ScraperTableView(); + tableVolumes->setSortingEnabled(true); +#if QT_VERSION >= 0x050000 + tableVolumes->horizontalHeader()->setSectionsClickable(true); +#else + tableVolumes->horizontalHeader()->setClickable(true); +#endif + //tableVolumes->horizontalHeader()->setSortIndicatorShown(false); + connect(tableVolumes->horizontalHeader(),SIGNAL(sectionClicked(int)), tableVolumes, SLOT(sortByColumn(int))); + //connections + connect(tableVolumes,SIGNAL(clicked(QModelIndex)),this,SLOT(loadVolumeInfo(QModelIndex))); + + paginator->setCustomLabel(tr("volumes")); + + left->addWidget(cover); + left->addWidget(detailLabel,1); + leftWidget->setMaximumWidth(180); + leftWidget->setLayout(left); + left->setContentsMargins(0,0,0,0); + leftWidget->setContentsMargins(0,0,0,0); + + content->addWidget(leftWidget, 0, 0); + content->addWidget(tableVolumes, 0, 1); + content->addWidget(paginator, 1, 1); + + content->setColumnStretch(1, 1); + content->setRowStretch(0, 1); + + l->addSpacing(15); + l->addWidget(label); + l->addSpacing(5); + l->addLayout(content); + + l->setContentsMargins(0,0,0,0); + setLayout(l); + setContentsMargins(0,0,0,0); +} + +void SelectVolume::load(const QString & json, const QString & searchString) +{ + VolumesModel * tempM = new VolumesModel(); + tempM->load(json); + //tableVolumes->setModel(tempM); + + proxyModel->setSourceModel( tempM ); + tableVolumes->setModel(proxyModel); + tableVolumes->sortByColumn(0,Qt::AscendingOrder); + tableVolumes->resizeColumnsToContents(); + + if(model != 0) + delete model; + + model = tempM; + + if(model->rowCount()>0) + { + tableVolumes->selectRow(0); + loadVolumeInfo(proxyModel->index(0,0)); + } + + tableVolumes->setColumnWidth(0,350); + + ScraperSelector::load(json,searchString); +} + +SelectVolume::~SelectVolume() {} + +void SelectVolume::loadVolumeInfo(const QModelIndex & omi) +{ + QModelIndex mi = proxyModel->mapToSource(omi); + QString coverURL = model->getCoverURL(mi); + QString id = model->getVolumeId(mi); + + QString loadingStyle = "%1"; + cover->setText(loadingStyle.arg(tr("loading cover"))); + detailLabel->setAltText(loadingStyle.arg(tr("loading description"))); + + ComicVineClient * comicVineClient = new ComicVineClient; + connect(comicVineClient,SIGNAL(seriesCover(const QByteArray &)),this,SLOT(setCover(const QByteArray &))); + connect(comicVineClient,SIGNAL(finished()),comicVineClient,SLOT(deleteLater())); + comicVineClient->getSeriesCover(coverURL); + + ComicVineClient * comicVineClient2 = new ComicVineClient; + connect(comicVineClient2,SIGNAL(seriesDetail(QString)),this,SLOT(setDescription(QString))); + connect(comicVineClient2,SIGNAL(finished()),comicVineClient2,SLOT(deleteLater())); + comicVineClient2->getSeriesDetail(id); +} + +void SelectVolume::setCover(const QByteArray & data) +{ + QPixmap p; + p.loadFromData(data); + int w = p.width(); + int h = p.height(); + + cover->setPixmap(p); + float aspectRatio = static_cast(w)/h; + + cover->setFixedSize(180,static_cast(180/aspectRatio)); + + cover->update(); +} + +void SelectVolume::setDescription(const QString & jsonDetail) +{ + QScriptEngine engine; + QScriptValue sc; + sc = engine.evaluate("(" + jsonDetail + ")"); + + if (!sc.property("error").isValid() && sc.property("error").toString() != "OK") + { + qDebug("Error detected"); + } + else + { + + QScriptValue descriptionValues = sc.property("results").property("description"); + bool valid = !descriptionValues.isNull() && descriptionValues.isValid(); + detailLabel->setText(valid?descriptionValues.toString().replace("getVolumeId(proxyModel->mapToSource(tableVolumes->currentIndex())); +} + +int SelectVolume::getSelectedVolumeNumIssues() +{ + return model->getNumIssues(proxyModel->mapToSource(tableVolumes->currentIndex())); +} + +QString SelectVolume::getSelectedVolumePublisher() +{ + return model->getPublisher(proxyModel->mapToSource(tableVolumes->currentIndex())); +} + + diff --git a/YACReaderLibrary/comic_vine/select_volume.h b/YACReaderLibrary/comic_vine/select_volume.h index 060933c2..d7c68aae 100644 --- a/YACReaderLibrary/comic_vine/select_volume.h +++ b/YACReaderLibrary/comic_vine/select_volume.h @@ -1,39 +1,39 @@ -#ifndef SELECT_VOLUME_H -#define SELECT_VOLUME_H - -#include "scraper_selector.h" - -class QLabel; -class VolumesModel; -class QModelIndex; -class QToolButton; -class QSortFilterProxyModel; - -class ScraperScrollLabel; -class ScraperTableView; - -class SelectVolume : public ScraperSelector -{ - Q_OBJECT -public: - SelectVolume(QWidget * parent = 0); - void load(const QString & json, const QString & searchString); - virtual ~SelectVolume(); - -public slots: - void loadVolumeInfo(const QModelIndex & mi); - void setCover(const QByteArray &); - void setDescription(const QString & jsonDetail); - QString getSelectedVolumeId(); - int getSelectedVolumeNumIssues(); - QString getSelectedVolumePublisher(); - -private: - QLabel * cover; - ScraperScrollLabel * detailLabel; - ScraperTableView * tableVolumes; - VolumesModel * model; - QSortFilterProxyModel * proxyModel; -}; - -#endif // SELECT_VOLUME_H +#ifndef SELECT_VOLUME_H +#define SELECT_VOLUME_H + +#include "scraper_selector.h" + +class QLabel; +class VolumesModel; +class QModelIndex; +class QToolButton; +class QSortFilterProxyModel; + +class ScraperScrollLabel; +class ScraperTableView; + +class SelectVolume : public ScraperSelector +{ + Q_OBJECT +public: + SelectVolume(QWidget * parent = 0); + void load(const QString & json, const QString & searchString); + virtual ~SelectVolume(); + +public slots: + void loadVolumeInfo(const QModelIndex & mi); + void setCover(const QByteArray &); + void setDescription(const QString & jsonDetail); + QString getSelectedVolumeId(); + int getSelectedVolumeNumIssues(); + QString getSelectedVolumePublisher(); + +private: + QLabel * cover; + ScraperScrollLabel * detailLabel; + ScraperTableView * tableVolumes; + VolumesModel * model; + QSortFilterProxyModel * proxyModel; +}; + +#endif // SELECT_VOLUME_H diff --git a/YACReaderLibrary/comic_vine/series_question.cpp b/YACReaderLibrary/comic_vine/series_question.cpp index 1fb93cb8..3fdba1d9 100644 --- a/YACReaderLibrary/comic_vine/series_question.cpp +++ b/YACReaderLibrary/comic_vine/series_question.cpp @@ -1,46 +1,46 @@ -#include "series_question.h" - -#include -#include -#include - - -SeriesQuestion::SeriesQuestion(QWidget * parent) - :QWidget(parent) -{ - QVBoxLayout * l = new QVBoxLayout; - - QLabel * questionLabel = new QLabel(tr("You are trying to get information for various comics at once, are they part of the same series?")); - questionLabel->setStyleSheet("QLabel {color:white; font-size:12px;font-family:Arial;}"); - yes = new QRadioButton(tr("yes")); - no = new QRadioButton(tr("no")); - - QString rbStyle = "QRadioButton {margin-left:27px; margin-top:5px; color:white;font-size:12px;font-family:Arial;}" - "QRadioButton::indicator {width:11px;height:11px;}" - "QRadioButton::indicator::unchecked {image : url(:/images/comic_vine/radioUnchecked.png);}" - "QRadioButton::indicator::checked {image : url(:/images/comic_vine/radioChecked.png);}"; - yes->setStyleSheet(rbStyle); - no->setStyleSheet(rbStyle); - - yes->setChecked(true); - - l->addSpacing(35); - l->addWidget(questionLabel); - l->addWidget(yes); - l->addWidget(no); - l->addStretch(); - - l->setContentsMargins(0,0,0,0); - setLayout(l); - setContentsMargins(0,0,0,0); -} - -bool SeriesQuestion::getYes() -{ - return yes->isChecked(); -} - -void SeriesQuestion::setYes(bool y) -{ - yes->setChecked(y); -} +#include "series_question.h" + +#include +#include +#include + + +SeriesQuestion::SeriesQuestion(QWidget * parent) + :QWidget(parent) +{ + QVBoxLayout * l = new QVBoxLayout; + + QLabel * questionLabel = new QLabel(tr("You are trying to get information for various comics at once, are they part of the same series?")); + questionLabel->setStyleSheet("QLabel {color:white; font-size:12px;font-family:Arial;}"); + yes = new QRadioButton(tr("yes")); + no = new QRadioButton(tr("no")); + + QString rbStyle = "QRadioButton {margin-left:27px; margin-top:5px; color:white;font-size:12px;font-family:Arial;}" + "QRadioButton::indicator {width:11px;height:11px;}" + "QRadioButton::indicator::unchecked {image : url(:/images/comic_vine/radioUnchecked.png);}" + "QRadioButton::indicator::checked {image : url(:/images/comic_vine/radioChecked.png);}"; + yes->setStyleSheet(rbStyle); + no->setStyleSheet(rbStyle); + + yes->setChecked(true); + + l->addSpacing(35); + l->addWidget(questionLabel); + l->addWidget(yes); + l->addWidget(no); + l->addStretch(); + + l->setContentsMargins(0,0,0,0); + setLayout(l); + setContentsMargins(0,0,0,0); +} + +bool SeriesQuestion::getYes() +{ + return yes->isChecked(); +} + +void SeriesQuestion::setYes(bool y) +{ + yes->setChecked(y); +} diff --git a/YACReaderLibrary/comic_vine/series_question.h b/YACReaderLibrary/comic_vine/series_question.h index c6620ecd..31d20e40 100644 --- a/YACReaderLibrary/comic_vine/series_question.h +++ b/YACReaderLibrary/comic_vine/series_question.h @@ -1,23 +1,23 @@ -#ifndef SERIES_QUESTION_H -#define SERIES_QUESTION_H - -#include - -class QRadioButton; - -class SeriesQuestion : public QWidget -{ - Q_OBJECT - -public: - SeriesQuestion(QWidget * parent = 0); - bool getYes(); - void setYes(bool yes = true); - -private: - QRadioButton * yes; - QRadioButton * no; -}; - - -#endif // SERIES_QUESTION_H +#ifndef SERIES_QUESTION_H +#define SERIES_QUESTION_H + +#include + +class QRadioButton; + +class SeriesQuestion : public QWidget +{ + Q_OBJECT + +public: + SeriesQuestion(QWidget * parent = 0); + bool getYes(); + void setYes(bool yes = true); + +private: + QRadioButton * yes; + QRadioButton * no; +}; + + +#endif // SERIES_QUESTION_H diff --git a/YACReaderLibrary/comic_vine/sort_volume_comics.cpp b/YACReaderLibrary/comic_vine/sort_volume_comics.cpp index 45ed0bae..2ece5279 100644 --- a/YACReaderLibrary/comic_vine/sort_volume_comics.cpp +++ b/YACReaderLibrary/comic_vine/sort_volume_comics.cpp @@ -1,222 +1,222 @@ -#include "sort_volume_comics.h" - -#include -#include -#include -#include -#include - -#include "scraper_tableview.h" -#include "local_comic_list_model.h" -#include "volume_comics_model.h" - -SortVolumeComics::SortVolumeComics(QWidget *parent) : - ScraperSelector(parent) -{ - QString labelStylesheet = "QLabel {color:white; font-size:12px;font-family:Arial;}"; - - QLabel * label = new QLabel(tr("Please, sort the list of comics on the left until it matches the comics' information.")); - label->setStyleSheet(labelStylesheet); - - QLabel * sortLabel = new QLabel(tr("sort comics to match comic information")); - sortLabel->setStyleSheet(labelStylesheet); - - moveUpButtonCL = new ScrapperToolButton(ScrapperToolButton::LEFT); - moveUpButtonCL->setIcon(QIcon(":/images/comic_vine/rowUp.png")); - moveUpButtonCL->setAutoRepeat(true); - moveDownButtonCL = new ScrapperToolButton(ScrapperToolButton::RIGHT); - moveDownButtonCL->setIcon(QIcon(":/images/comic_vine/rowDown.png")); - moveDownButtonCL->setAutoRepeat(true); - //moveUpButtonIL = new ScrapperToolButton(ScrapperToolButton::LEFT); - //moveUpButtonIL->setIcon(QIcon(":/images/comic_vine/rowUp.png")); - //moveDownButtonIL = new ScrapperToolButton(ScrapperToolButton::RIGHT); - //moveDownButtonIL->setIcon(QIcon(":/images/comic_vine/rowDown.png")); - - connect(moveUpButtonCL,SIGNAL(clicked()),this,SLOT(moveUpCL())); - connect(moveDownButtonCL,SIGNAL(clicked()),this,SLOT(moveDownCL())); - //connect(moveUpButtonIL,SIGNAL(clicked()),this,SLOT(moveUpIL())); - //connect(moveUpButtonIL,SIGNAL(clicked()),this,SLOT(moveDownIL())); - - QVBoxLayout * l = new QVBoxLayout; - QGridLayout * content = new QGridLayout; - QHBoxLayout * sortButtonsLayout = new QHBoxLayout; - - tableFiles = new ScraperTableView(); - tableVolumeComics = new ScraperTableView(); - - tableFiles->setSelectionBehavior(QAbstractItemView::SelectRows); - tableFiles->setSelectionMode(QAbstractItemView::ContiguousSelection); - - //content->addWidget(tableVolumes,0,Qt::AlignRight|Qt::AlignTop); - - connect(tableVolumeComics->verticalScrollBar(), SIGNAL(valueChanged(int)), this, SLOT(synchronizeScroll(int))); - connect(tableFiles->verticalScrollBar(), SIGNAL(valueChanged(int)), this, SLOT(synchronizeScroll(int))); - - //connect(tableVolumeComics, SIGNAL(pressed(QModelIndex)), tableFiles, SLOT(setCurrentIndex(QModelIndex))); - //connect(tableFiles, SIGNAL(pressed(QModelIndex)), tableVolumeComics, SLOT(setCurrentIndex(QModelIndex))); - - paginator->setCustomLabel(tr("issues")); - paginator->setMinimumWidth(422); - - sortButtonsLayout->addWidget(moveUpButtonCL); - sortButtonsLayout->addWidget(ScrapperToolButton::getSeparator()); - sortButtonsLayout->addWidget(moveDownButtonCL); - sortButtonsLayout->addSpacing(10); - sortButtonsLayout->addWidget(sortLabel); - sortButtonsLayout->addStretch(); - sortButtonsLayout->setSpacing(0); - - content->addWidget(tableFiles, 0, 0); - content->addWidget(tableVolumeComics, 0, 1); - content->addLayout(sortButtonsLayout, 1, 0); - content->addWidget(paginator, 1, 1); - - content->setRowStretch(0, 1); - - l->addSpacing(15); - l->addWidget(label, 0); - l->addSpacing(5); - l->addLayout(content, 1); - l->addLayout(sortButtonsLayout, 0); - - l->setContentsMargins(0,0,0,0); - setLayout(l); - setContentsMargins(0,0,0,0); - - //rows actions - QAction * removeItemFromList = new QAction(tr("remove selected comics"),this); - QAction * restoreAllItems = new QAction(tr("restore all removed comics"),this); - //QAction * restoreItems = new QAction(tr("restore removed comics"),this); - - tableFiles->setContextMenuPolicy(Qt::ActionsContextMenu); - tableFiles->addAction(removeItemFromList); - tableFiles->addAction(restoreAllItems); - //tableFiles->addAction(restoreItems); - - connect(removeItemFromList,SIGNAL(triggered()),this,SLOT(removeSelectedComics())); - connect(restoreAllItems,SIGNAL(triggered()),this,SLOT(restoreAllComics())); - //connect(restoreItems,SIGNAL(triggered()),this,SLOT(showRemovedComicsSelector())); -} - -void SortVolumeComics::setData(QList & comics, const QString &json, const QString &vID) -{ - //set up models - localComicsModel = new LocalComicListModel; - localComicsModel->load(comics); - - volumeComicsModel = new VolumeComicsModel; - volumeComicsModel->load(json); - - int numLocalComics = localComicsModel->rowCount(); - int numVolumeComics = volumeComicsModel->rowCount(); - - if(numLocalComics > numVolumeComics) - volumeComicsModel->addExtraRows(numLocalComics - numVolumeComics); - if(numLocalComics < numVolumeComics) - localComicsModel->addExtraRows(numVolumeComics - numLocalComics); - - tableFiles->setModel(localComicsModel); - tableVolumeComics->setModel(volumeComicsModel); - - tableVolumeComics->resizeColumnToContents(0); - - ScraperSelector::load(json,vID); -} - -void SortVolumeComics::synchronizeScroll(int pos) -{ - void * senderObject = sender(); - - if(senderObject == 0) //invalid call - return; - - QScrollBar * tableVolumeComicsScrollBar = tableVolumeComics->verticalScrollBar(); - QScrollBar * tableFilesScrollBar = tableFiles->verticalScrollBar(); - - if(senderObject == tableVolumeComicsScrollBar) - { - disconnect(tableFilesScrollBar,SIGNAL(valueChanged(int)),this,0); - tableFilesScrollBar->setValue(pos); - connect(tableFilesScrollBar, SIGNAL(valueChanged(int)), this, SLOT(synchronizeScroll(int))); - } - else - { - disconnect(tableVolumeComicsScrollBar,SIGNAL(valueChanged(int)),this,0); - tableVolumeComicsScrollBar->setValue(pos); - connect(tableVolumeComicsScrollBar, SIGNAL(valueChanged(int)), this, SLOT(synchronizeScroll(int))); - } -} - -void SortVolumeComics::moveUpCL() -{ - QList selection = tableFiles->selectionModel()->selectedIndexes(); - - if(selection.count() == 0) - return; - - localComicsModel->moveSelectionUp(selection); - - selection = tableFiles->selectionModel()->selectedIndexes(); - tableFiles->scrollTo(selection.first()); -} - -void SortVolumeComics::moveDownCL() -{ - QList selection = tableFiles->selectionModel()->selectedIndexes(); - - if(selection.count() > 0) - { - localComicsModel->moveSelectionDown(selection); - - selection = tableFiles->selectionModel()->selectedIndexes(); - tableFiles->scrollTo(selection.last()); - } -} - -void SortVolumeComics::moveUpIL() -{ - -} - -void SortVolumeComics::moveDownIL() -{ - -} - -void SortVolumeComics::removeSelectedComics() -{ - QList selection = tableFiles->selectionModel()->selectedIndexes(); - - localComicsModel->removeComics(selection); -} - -void SortVolumeComics::restoreAllComics() -{ - localComicsModel->restoreAll(); -} - -void SortVolumeComics::showRemovedComicsSelector() -{ - -} - -QList > SortVolumeComics::getMatchingInfo() -{ - QList comicList = localComicsModel->getData(); - QList > l; - - int index = 0; - - QString id; - foreach(ComicDB c, comicList) - { - id = volumeComicsModel->getComicId(index); - if(!c.getFileName().isEmpty() && !id.isEmpty()) //there is a valid comic, and valid comic ID - { - l.push_back(QPair(c,id)); - } - index++; - } - - return l; -} +#include "sort_volume_comics.h" + +#include +#include +#include +#include +#include + +#include "scraper_tableview.h" +#include "local_comic_list_model.h" +#include "volume_comics_model.h" + +SortVolumeComics::SortVolumeComics(QWidget *parent) : + ScraperSelector(parent) +{ + QString labelStylesheet = "QLabel {color:white; font-size:12px;font-family:Arial;}"; + + QLabel * label = new QLabel(tr("Please, sort the list of comics on the left until it matches the comics' information.")); + label->setStyleSheet(labelStylesheet); + + QLabel * sortLabel = new QLabel(tr("sort comics to match comic information")); + sortLabel->setStyleSheet(labelStylesheet); + + moveUpButtonCL = new ScrapperToolButton(ScrapperToolButton::LEFT); + moveUpButtonCL->setIcon(QIcon(":/images/comic_vine/rowUp.png")); + moveUpButtonCL->setAutoRepeat(true); + moveDownButtonCL = new ScrapperToolButton(ScrapperToolButton::RIGHT); + moveDownButtonCL->setIcon(QIcon(":/images/comic_vine/rowDown.png")); + moveDownButtonCL->setAutoRepeat(true); + //moveUpButtonIL = new ScrapperToolButton(ScrapperToolButton::LEFT); + //moveUpButtonIL->setIcon(QIcon(":/images/comic_vine/rowUp.png")); + //moveDownButtonIL = new ScrapperToolButton(ScrapperToolButton::RIGHT); + //moveDownButtonIL->setIcon(QIcon(":/images/comic_vine/rowDown.png")); + + connect(moveUpButtonCL,SIGNAL(clicked()),this,SLOT(moveUpCL())); + connect(moveDownButtonCL,SIGNAL(clicked()),this,SLOT(moveDownCL())); + //connect(moveUpButtonIL,SIGNAL(clicked()),this,SLOT(moveUpIL())); + //connect(moveUpButtonIL,SIGNAL(clicked()),this,SLOT(moveDownIL())); + + QVBoxLayout * l = new QVBoxLayout; + QGridLayout * content = new QGridLayout; + QHBoxLayout * sortButtonsLayout = new QHBoxLayout; + + tableFiles = new ScraperTableView(); + tableVolumeComics = new ScraperTableView(); + + tableFiles->setSelectionBehavior(QAbstractItemView::SelectRows); + tableFiles->setSelectionMode(QAbstractItemView::ContiguousSelection); + + //content->addWidget(tableVolumes,0,Qt::AlignRight|Qt::AlignTop); + + connect(tableVolumeComics->verticalScrollBar(), SIGNAL(valueChanged(int)), this, SLOT(synchronizeScroll(int))); + connect(tableFiles->verticalScrollBar(), SIGNAL(valueChanged(int)), this, SLOT(synchronizeScroll(int))); + + //connect(tableVolumeComics, SIGNAL(pressed(QModelIndex)), tableFiles, SLOT(setCurrentIndex(QModelIndex))); + //connect(tableFiles, SIGNAL(pressed(QModelIndex)), tableVolumeComics, SLOT(setCurrentIndex(QModelIndex))); + + paginator->setCustomLabel(tr("issues")); + paginator->setMinimumWidth(422); + + sortButtonsLayout->addWidget(moveUpButtonCL); + sortButtonsLayout->addWidget(ScrapperToolButton::getSeparator()); + sortButtonsLayout->addWidget(moveDownButtonCL); + sortButtonsLayout->addSpacing(10); + sortButtonsLayout->addWidget(sortLabel); + sortButtonsLayout->addStretch(); + sortButtonsLayout->setSpacing(0); + + content->addWidget(tableFiles, 0, 0); + content->addWidget(tableVolumeComics, 0, 1); + content->addLayout(sortButtonsLayout, 1, 0); + content->addWidget(paginator, 1, 1); + + content->setRowStretch(0, 1); + + l->addSpacing(15); + l->addWidget(label, 0); + l->addSpacing(5); + l->addLayout(content, 1); + l->addLayout(sortButtonsLayout, 0); + + l->setContentsMargins(0,0,0,0); + setLayout(l); + setContentsMargins(0,0,0,0); + + //rows actions + QAction * removeItemFromList = new QAction(tr("remove selected comics"),this); + QAction * restoreAllItems = new QAction(tr("restore all removed comics"),this); + //QAction * restoreItems = new QAction(tr("restore removed comics"),this); + + tableFiles->setContextMenuPolicy(Qt::ActionsContextMenu); + tableFiles->addAction(removeItemFromList); + tableFiles->addAction(restoreAllItems); + //tableFiles->addAction(restoreItems); + + connect(removeItemFromList,SIGNAL(triggered()),this,SLOT(removeSelectedComics())); + connect(restoreAllItems,SIGNAL(triggered()),this,SLOT(restoreAllComics())); + //connect(restoreItems,SIGNAL(triggered()),this,SLOT(showRemovedComicsSelector())); +} + +void SortVolumeComics::setData(QList & comics, const QString &json, const QString &vID) +{ + //set up models + localComicsModel = new LocalComicListModel; + localComicsModel->load(comics); + + volumeComicsModel = new VolumeComicsModel; + volumeComicsModel->load(json); + + int numLocalComics = localComicsModel->rowCount(); + int numVolumeComics = volumeComicsModel->rowCount(); + + if(numLocalComics > numVolumeComics) + volumeComicsModel->addExtraRows(numLocalComics - numVolumeComics); + if(numLocalComics < numVolumeComics) + localComicsModel->addExtraRows(numVolumeComics - numLocalComics); + + tableFiles->setModel(localComicsModel); + tableVolumeComics->setModel(volumeComicsModel); + + tableVolumeComics->resizeColumnToContents(0); + + ScraperSelector::load(json,vID); +} + +void SortVolumeComics::synchronizeScroll(int pos) +{ + void * senderObject = sender(); + + if(senderObject == 0) //invalid call + return; + + QScrollBar * tableVolumeComicsScrollBar = tableVolumeComics->verticalScrollBar(); + QScrollBar * tableFilesScrollBar = tableFiles->verticalScrollBar(); + + if(senderObject == tableVolumeComicsScrollBar) + { + disconnect(tableFilesScrollBar,SIGNAL(valueChanged(int)),this,0); + tableFilesScrollBar->setValue(pos); + connect(tableFilesScrollBar, SIGNAL(valueChanged(int)), this, SLOT(synchronizeScroll(int))); + } + else + { + disconnect(tableVolumeComicsScrollBar,SIGNAL(valueChanged(int)),this,0); + tableVolumeComicsScrollBar->setValue(pos); + connect(tableVolumeComicsScrollBar, SIGNAL(valueChanged(int)), this, SLOT(synchronizeScroll(int))); + } +} + +void SortVolumeComics::moveUpCL() +{ + QList selection = tableFiles->selectionModel()->selectedIndexes(); + + if(selection.count() == 0) + return; + + localComicsModel->moveSelectionUp(selection); + + selection = tableFiles->selectionModel()->selectedIndexes(); + tableFiles->scrollTo(selection.first()); +} + +void SortVolumeComics::moveDownCL() +{ + QList selection = tableFiles->selectionModel()->selectedIndexes(); + + if(selection.count() > 0) + { + localComicsModel->moveSelectionDown(selection); + + selection = tableFiles->selectionModel()->selectedIndexes(); + tableFiles->scrollTo(selection.last()); + } +} + +void SortVolumeComics::moveUpIL() +{ + +} + +void SortVolumeComics::moveDownIL() +{ + +} + +void SortVolumeComics::removeSelectedComics() +{ + QList selection = tableFiles->selectionModel()->selectedIndexes(); + + localComicsModel->removeComics(selection); +} + +void SortVolumeComics::restoreAllComics() +{ + localComicsModel->restoreAll(); +} + +void SortVolumeComics::showRemovedComicsSelector() +{ + +} + +QList > SortVolumeComics::getMatchingInfo() +{ + QList comicList = localComicsModel->getData(); + QList > l; + + int index = 0; + + QString id; + foreach(ComicDB c, comicList) + { + id = volumeComicsModel->getComicId(index); + if(!c.getFileName().isEmpty() && !id.isEmpty()) //there is a valid comic, and valid comic ID + { + l.push_back(QPair(c,id)); + } + index++; + } + + return l; +} diff --git a/YACReaderLibrary/comic_vine/sort_volume_comics.h b/YACReaderLibrary/comic_vine/sort_volume_comics.h index bd7b0687..6e76274a 100644 --- a/YACReaderLibrary/comic_vine/sort_volume_comics.h +++ b/YACReaderLibrary/comic_vine/sort_volume_comics.h @@ -1,99 +1,99 @@ -#ifndef SORT_VOLUME_COMICS_H -#define SORT_VOLUME_COMICS_H - -#include "scraper_selector.h" - -#include -#include -#include - -#include "comic_db.h" - -class ScraperTableView; -class LocalComicListModel; -class VolumeComicsModel; - -class ScrapperToolButton : public QPushButton -{ - Q_OBJECT -public: - enum Appearance { - DEFAULT, - LEFT, - RIGHT - }; - - ScrapperToolButton(ScrapperToolButton::Appearance appearance = DEFAULT, QWidget * parent=0):QPushButton(parent),appearance(appearance) { - setStyleSheet("QPushButton {border: none; background: #2e2e2e; color:white; border-radius:2px;}" - "QPushButton::pressed {border: none; background: #282828; color:white; border-radius:2px;}"); - setFixedSize(18,17); - } - static QWidget * getSeparator(){QWidget * w = new QWidget; w->setFixedWidth(1); w->setStyleSheet("QWidget {background:#282828;}"); return w;} - void setAppearance(ScrapperToolButton::Appearance appearance){this->appearance = appearance;} - virtual ~ScrapperToolButton() {} - - - -protected: - void paintEvent(QPaintEvent * e) - { - QPainter p(this); - - switch (appearance) { - case LEFT: - p.fillRect(16,0,2,18,QColor("#2E2E2E")); - break; - case RIGHT: - p.fillRect(0,0,2,18,QColor("#2E2E2E")); - break; - default: - break; - } - - QPushButton::paintEvent(e); - } - -private: - Appearance appearance; -}; - - -class SortVolumeComics : public ScraperSelector -{ - Q_OBJECT -public: - explicit SortVolumeComics(QWidget *parent = 0); - -signals: - -public slots: - void setData(QList & comics, const QString &json, const QString & vID); - QList > getMatchingInfo(); - -protected slots: - void synchronizeScroll(int pos); - void moveUpCL(); - void moveDownCL(); - void moveUpIL(); - void moveDownIL(); - - void removeSelectedComics(); - void restoreAllComics(); - void showRemovedComicsSelector(); - - -private: - ScraperTableView * tableFiles; - ScraperTableView * tableVolumeComics; - - LocalComicListModel * localComicsModel; - VolumeComicsModel * volumeComicsModel; - - ScrapperToolButton * moveUpButtonCL; - ScrapperToolButton * moveDownButtonCL; - ScrapperToolButton * moveUpButtonIL; - ScrapperToolButton * moveDownButtonIL; - -}; - -#endif // SORT_VOLUME_COMICS_H +#ifndef SORT_VOLUME_COMICS_H +#define SORT_VOLUME_COMICS_H + +#include "scraper_selector.h" + +#include +#include +#include + +#include "comic_db.h" + +class ScraperTableView; +class LocalComicListModel; +class VolumeComicsModel; + +class ScrapperToolButton : public QPushButton +{ + Q_OBJECT +public: + enum Appearance { + DEFAULT, + LEFT, + RIGHT + }; + + ScrapperToolButton(ScrapperToolButton::Appearance appearance = DEFAULT, QWidget * parent=0):QPushButton(parent),appearance(appearance) { + setStyleSheet("QPushButton {border: none; background: #2e2e2e; color:white; border-radius:2px;}" + "QPushButton::pressed {border: none; background: #282828; color:white; border-radius:2px;}"); + setFixedSize(18,17); + } + static QWidget * getSeparator(){QWidget * w = new QWidget; w->setFixedWidth(1); w->setStyleSheet("QWidget {background:#282828;}"); return w;} + void setAppearance(ScrapperToolButton::Appearance appearance){this->appearance = appearance;} + virtual ~ScrapperToolButton() {} + + + +protected: + void paintEvent(QPaintEvent * e) + { + QPainter p(this); + + switch (appearance) { + case LEFT: + p.fillRect(16,0,2,18,QColor("#2E2E2E")); + break; + case RIGHT: + p.fillRect(0,0,2,18,QColor("#2E2E2E")); + break; + default: + break; + } + + QPushButton::paintEvent(e); + } + +private: + Appearance appearance; +}; + + +class SortVolumeComics : public ScraperSelector +{ + Q_OBJECT +public: + explicit SortVolumeComics(QWidget *parent = 0); + +signals: + +public slots: + void setData(QList & comics, const QString &json, const QString & vID); + QList > getMatchingInfo(); + +protected slots: + void synchronizeScroll(int pos); + void moveUpCL(); + void moveDownCL(); + void moveUpIL(); + void moveDownIL(); + + void removeSelectedComics(); + void restoreAllComics(); + void showRemovedComicsSelector(); + + +private: + ScraperTableView * tableFiles; + ScraperTableView * tableVolumeComics; + + LocalComicListModel * localComicsModel; + VolumeComicsModel * volumeComicsModel; + + ScrapperToolButton * moveUpButtonCL; + ScrapperToolButton * moveDownButtonCL; + ScrapperToolButton * moveUpButtonIL; + ScrapperToolButton * moveDownButtonIL; + +}; + +#endif // SORT_VOLUME_COMICS_H diff --git a/YACReaderLibrary/comic_vine/title_header.cpp b/YACReaderLibrary/comic_vine/title_header.cpp index cebc0d6f..9fb1c494 100644 --- a/YACReaderLibrary/comic_vine/title_header.cpp +++ b/YACReaderLibrary/comic_vine/title_header.cpp @@ -1,53 +1,53 @@ -#include "title_header.h" - -#include -#include -#include - -TitleHeader::TitleHeader(QWidget * parent ) - :QWidget(parent) -{ - mainTitleLabel = new QLabel(); - subTitleLabel = new QLabel(); - - mainTitleLabel->setStyleSheet("QLabel {color:white; font-size:18px;font-family:Arial;}"); - subTitleLabel->setStyleSheet("QLabel {color:white; font-size:12px;font-family:Arial;}"); - - QHBoxLayout * titleLayout = new QHBoxLayout; - QVBoxLayout * titleLabelsLayout = new QVBoxLayout; - - titleLabelsLayout->addWidget(mainTitleLabel); - titleLabelsLayout->addWidget(subTitleLabel); - titleLabelsLayout->setSpacing(0); - - titleLayout->addLayout(titleLabelsLayout); - titleLayout->setContentsMargins(0,0,0,0); - - setLayout(titleLayout); - - setContentsMargins(0,0,0,0); - - setTitle(tr("SEARCH")); -} - -void TitleHeader::setTitle(const QString & title) -{ - mainTitleLabel->setText(title); -} - -void TitleHeader::setSubTitle(const QString & title) -{ - subTitleLabel->setText(title); -} - -void TitleHeader::showButtons(bool show) -{ - if(show) - { - - } - else - { - - } -} +#include "title_header.h" + +#include +#include +#include + +TitleHeader::TitleHeader(QWidget * parent ) + :QWidget(parent) +{ + mainTitleLabel = new QLabel(); + subTitleLabel = new QLabel(); + + mainTitleLabel->setStyleSheet("QLabel {color:white; font-size:18px;font-family:Arial;}"); + subTitleLabel->setStyleSheet("QLabel {color:white; font-size:12px;font-family:Arial;}"); + + QHBoxLayout * titleLayout = new QHBoxLayout; + QVBoxLayout * titleLabelsLayout = new QVBoxLayout; + + titleLabelsLayout->addWidget(mainTitleLabel); + titleLabelsLayout->addWidget(subTitleLabel); + titleLabelsLayout->setSpacing(0); + + titleLayout->addLayout(titleLabelsLayout); + titleLayout->setContentsMargins(0,0,0,0); + + setLayout(titleLayout); + + setContentsMargins(0,0,0,0); + + setTitle(tr("SEARCH")); +} + +void TitleHeader::setTitle(const QString & title) +{ + mainTitleLabel->setText(title); +} + +void TitleHeader::setSubTitle(const QString & title) +{ + subTitleLabel->setText(title); +} + +void TitleHeader::showButtons(bool show) +{ + if(show) + { + + } + else + { + + } +} diff --git a/YACReaderLibrary/comic_vine/title_header.h b/YACReaderLibrary/comic_vine/title_header.h index a4e62e98..ff258fa3 100644 --- a/YACReaderLibrary/comic_vine/title_header.h +++ b/YACReaderLibrary/comic_vine/title_header.h @@ -1,22 +1,22 @@ -#ifndef TITLE_HEADER_H -#define TITLE_HEADER_H - -#include - -class QLabel; - -class TitleHeader : public QWidget -{ - Q_OBJECT -public: - TitleHeader(QWidget * parent = 0); -public slots: - void setTitle(const QString & title); - void setSubTitle(const QString & title); - void showButtons(bool show); -private: - QLabel * mainTitleLabel; - QLabel * subTitleLabel; -}; - -#endif // TITLE_HEADER_H +#ifndef TITLE_HEADER_H +#define TITLE_HEADER_H + +#include + +class QLabel; + +class TitleHeader : public QWidget +{ + Q_OBJECT +public: + TitleHeader(QWidget * parent = 0); +public slots: + void setTitle(const QString & title); + void setSubTitle(const QString & title); + void showButtons(bool show); +private: + QLabel * mainTitleLabel; + QLabel * subTitleLabel; +}; + +#endif // TITLE_HEADER_H diff --git a/YACReaderLibrary/comics_remover.cpp b/YACReaderLibrary/comics_remover.cpp index 7b4eadd7..7c4bc3b9 100644 --- a/YACReaderLibrary/comics_remover.cpp +++ b/YACReaderLibrary/comics_remover.cpp @@ -1,64 +1,64 @@ -#include "comics_remover.h" - -#include -#include - -#include "QsLog.h" - -ComicsRemover::ComicsRemover(QModelIndexList & il, QList & ps, qulonglong parentId, QObject *parent) - :QObject(parent),indexList(il), paths(ps), parentId(parentId) -{ -} - -void ComicsRemover::process() -{ - QString currentComicPath; - QListIterator i(indexList); - QListIterator i2(paths); - i.toBack(); - i2.toBack(); - - while (i.hasPrevious() && i2.hasPrevious()) - { - QModelIndex mi = i.previous(); - currentComicPath = i2.previous(); - if(QFile::remove(currentComicPath)) - emit remove(mi.row()); - else - emit removeError(); - } - - emit finished(); - emit removedItemsFromFolder(parentId); -} - - -FoldersRemover::FoldersRemover(QModelIndexList &il, QList &ps, QObject *parent) - :QObject(parent),indexList(il), paths(ps) -{ - -} - -void FoldersRemover::process() -{ - QString currentFolderPath; - QListIterator i(indexList); - QListIterator i2(paths); - i.toBack(); - i2.toBack(); - - QLOG_DEBUG() << "Deleting folders" << paths.at(0); - - while (i.hasPrevious() && i2.hasPrevious()) - { - QModelIndex mi = i.previous(); - currentFolderPath = i2.previous(); - QDir d(currentFolderPath); - if(d.removeRecursively() || !d.exists()) //the folder is in the DB but no in the drive... - emit remove(mi); - else - emit removeError(); - } - - emit finished(); -} +#include "comics_remover.h" + +#include +#include + +#include "QsLog.h" + +ComicsRemover::ComicsRemover(QModelIndexList & il, QList & ps, qulonglong parentId, QObject *parent) + :QObject(parent),indexList(il), paths(ps), parentId(parentId) +{ +} + +void ComicsRemover::process() +{ + QString currentComicPath; + QListIterator i(indexList); + QListIterator i2(paths); + i.toBack(); + i2.toBack(); + + while (i.hasPrevious() && i2.hasPrevious()) + { + QModelIndex mi = i.previous(); + currentComicPath = i2.previous(); + if(QFile::remove(currentComicPath)) + emit remove(mi.row()); + else + emit removeError(); + } + + emit finished(); + emit removedItemsFromFolder(parentId); +} + + +FoldersRemover::FoldersRemover(QModelIndexList &il, QList &ps, QObject *parent) + :QObject(parent),indexList(il), paths(ps) +{ + +} + +void FoldersRemover::process() +{ + QString currentFolderPath; + QListIterator i(indexList); + QListIterator i2(paths); + i.toBack(); + i2.toBack(); + + QLOG_DEBUG() << "Deleting folders" << paths.at(0); + + while (i.hasPrevious() && i2.hasPrevious()) + { + QModelIndex mi = i.previous(); + currentFolderPath = i2.previous(); + QDir d(currentFolderPath); + if(d.removeRecursively() || !d.exists()) //the folder is in the DB but no in the drive... + emit remove(mi); + else + emit removeError(); + } + + emit finished(); +} diff --git a/YACReaderLibrary/comics_remover.h b/YACReaderLibrary/comics_remover.h index c844afbb..ffd137fd 100644 --- a/YACReaderLibrary/comics_remover.h +++ b/YACReaderLibrary/comics_remover.h @@ -1,49 +1,49 @@ -#ifndef COMICS_REMOVER_H -#define COMICS_REMOVER_H - -#include - -#include -#include - -class ComicsRemover : public QObject -{ - Q_OBJECT -public: - explicit ComicsRemover(QModelIndexList & indexList, QList & paths, qulonglong parentId, QObject *parent = 0); - -signals: - void remove(int); - void removeError(); - void finished(); - void removedItemsFromFolder(qulonglong); - -public slots: - void process(); - -private: - QModelIndexList indexList; - QList paths; - qulonglong parentId; -}; - -class FoldersRemover : public QObject -{ - Q_OBJECT -public: - explicit FoldersRemover(QModelIndexList & indexList, QList & paths, QObject *parent = 0); - -signals: - void remove(QModelIndex); - void removeError(); - void finished(); - -public slots: - void process(); - -private: - QModelIndexList indexList; - QList paths; -}; - -#endif // COMICS_REMOVER_H +#ifndef COMICS_REMOVER_H +#define COMICS_REMOVER_H + +#include + +#include +#include + +class ComicsRemover : public QObject +{ + Q_OBJECT +public: + explicit ComicsRemover(QModelIndexList & indexList, QList & paths, qulonglong parentId, QObject *parent = 0); + +signals: + void remove(int); + void removeError(); + void finished(); + void removedItemsFromFolder(qulonglong); + +public slots: + void process(); + +private: + QModelIndexList indexList; + QList paths; + qulonglong parentId; +}; + +class FoldersRemover : public QObject +{ + Q_OBJECT +public: + explicit FoldersRemover(QModelIndexList & indexList, QList & paths, QObject *parent = 0); + +signals: + void remove(QModelIndex); + void removeError(); + void finished(); + +public slots: + void process(); + +private: + QModelIndexList indexList; + QList paths; +}; + +#endif // COMICS_REMOVER_H diff --git a/YACReaderLibrary/comics_view.cpp b/YACReaderLibrary/comics_view.cpp index 96e46f75..ed4a029d 100644 --- a/YACReaderLibrary/comics_view.cpp +++ b/YACReaderLibrary/comics_view.cpp @@ -1,88 +1,88 @@ -#include "comics_view.h" -#include "comic.h" -#include "comic_files_manager.h" -#include "comic_db.h" - -#include "QsLog.h" - -#include - -ComicsView::ComicsView(QWidget *parent) : - QWidget(parent),model(NULL),comicDB(nullptr) -{ - setAcceptDrops(true); -} - -void ComicsView::setModel(ComicModel *m) -{ - model = m; -} - -void ComicsView::updateInfoForIndex(int index) -{ - QQmlContext *ctxt = view->rootContext(); - - if(comicDB != nullptr) delete comicDB; - - comicDB = new ComicDB(model->getComic(this->model->index(index, 0))); - ComicInfo *comicInfo = &(comicDB->info); - comicInfo->isFavorite = model->isFavorite(model->index(index,0)); - - ctxt->setContextProperty("comic", comicDB); - ctxt->setContextProperty("comicInfo", comicInfo); - - ctxt->setContextProperty("comic_info_index", index); -} - -void ComicsView::dragEnterEvent(QDragEnterEvent *event) -{ - if(model->canDropMimeData(event->mimeData(),event->proposedAction(),0,0,QModelIndex())) - event->acceptProposedAction(); - else - { - QLOG_TRACE() << "dragEnterEvent"; - QList urlList; - - if (event->mimeData()->hasUrls() && event->dropAction() == Qt::CopyAction) - { - urlList = event->mimeData()->urls(); - QString currentPath; - foreach (QUrl url, urlList) - { - //comics or folders are accepted, folders' content is validate in dropEvent (avoid any lag before droping) - currentPath = url.toLocalFile(); - if(Comic::fileIsComic(currentPath) || QFileInfo(currentPath).isDir()) - { - event->acceptProposedAction(); - return; - } - } - } - } -} - -void ComicsView::dropEvent(QDropEvent *event) -{ - QLOG_DEBUG() << "drop" << event->dropAction(); - - bool validAction = event->dropAction() == Qt::CopyAction;// || event->dropAction() & Qt::MoveAction; TODO move - - if(event->mimeData()->hasUrls() && validAction) - { - - QList > droppedFiles = ComicFilesManager::getDroppedFiles(event->mimeData()->urls()); - - if(event->dropAction() == Qt::CopyAction) - { - QLOG_DEBUG() << "copy :" << droppedFiles; - emit copyComicsToCurrentFolder(droppedFiles); - } - else if(event->dropAction() & Qt::MoveAction) - { - QLOG_DEBUG() << "move :" << droppedFiles; - emit moveComicsToCurrentFolder(droppedFiles); - } - - event->acceptProposedAction(); - } -} +#include "comics_view.h" +#include "comic.h" +#include "comic_files_manager.h" +#include "comic_db.h" + +#include "QsLog.h" + +#include + +ComicsView::ComicsView(QWidget *parent) : + QWidget(parent),model(NULL),comicDB(nullptr) +{ + setAcceptDrops(true); +} + +void ComicsView::setModel(ComicModel *m) +{ + model = m; +} + +void ComicsView::updateInfoForIndex(int index) +{ + QQmlContext *ctxt = view->rootContext(); + + if(comicDB != nullptr) delete comicDB; + + comicDB = new ComicDB(model->getComic(this->model->index(index, 0))); + ComicInfo *comicInfo = &(comicDB->info); + comicInfo->isFavorite = model->isFavorite(model->index(index,0)); + + ctxt->setContextProperty("comic", comicDB); + ctxt->setContextProperty("comicInfo", comicInfo); + + ctxt->setContextProperty("comic_info_index", index); +} + +void ComicsView::dragEnterEvent(QDragEnterEvent *event) +{ + if(model->canDropMimeData(event->mimeData(),event->proposedAction(),0,0,QModelIndex())) + event->acceptProposedAction(); + else + { + QLOG_TRACE() << "dragEnterEvent"; + QList urlList; + + if (event->mimeData()->hasUrls() && event->dropAction() == Qt::CopyAction) + { + urlList = event->mimeData()->urls(); + QString currentPath; + foreach (QUrl url, urlList) + { + //comics or folders are accepted, folders' content is validate in dropEvent (avoid any lag before droping) + currentPath = url.toLocalFile(); + if(Comic::fileIsComic(currentPath) || QFileInfo(currentPath).isDir()) + { + event->acceptProposedAction(); + return; + } + } + } + } +} + +void ComicsView::dropEvent(QDropEvent *event) +{ + QLOG_DEBUG() << "drop" << event->dropAction(); + + bool validAction = event->dropAction() == Qt::CopyAction;// || event->dropAction() & Qt::MoveAction; TODO move + + if(event->mimeData()->hasUrls() && validAction) + { + + QList > droppedFiles = ComicFilesManager::getDroppedFiles(event->mimeData()->urls()); + + if(event->dropAction() == Qt::CopyAction) + { + QLOG_DEBUG() << "copy :" << droppedFiles; + emit copyComicsToCurrentFolder(droppedFiles); + } + else if(event->dropAction() & Qt::MoveAction) + { + QLOG_DEBUG() << "move :" << droppedFiles; + emit moveComicsToCurrentFolder(droppedFiles); + } + + event->acceptProposedAction(); + } +} diff --git a/YACReaderLibrary/comics_view.h b/YACReaderLibrary/comics_view.h index 4a106c98..c77c8ff3 100644 --- a/YACReaderLibrary/comics_view.h +++ b/YACReaderLibrary/comics_view.h @@ -1,67 +1,67 @@ -#ifndef COMICS_VIEW_H -#define COMICS_VIEW_H - -#include - -#include "comic_model.h" - -class YACReaderTableView; -class QSplitter; -class ComicFlowWidget; -class QToolBar; -class ComicModel; -class QQuickView; - -class ComicsView : public QWidget -{ - Q_OBJECT -public: - explicit ComicsView(QWidget *parent = 0); - virtual void setToolBar(QToolBar * toolBar) = 0; - virtual void setModel(ComicModel *model); - virtual void setCurrentIndex(const QModelIndex &index) = 0; - virtual QModelIndex currentIndex() = 0; - virtual QItemSelectionModel * selectionModel() = 0; - virtual void scrollTo(const QModelIndex & mi, QAbstractItemView::ScrollHint hint ) = 0; - virtual void toFullScreen() = 0; - virtual void toNormal() = 0; - virtual void updateConfig(QSettings * settings) = 0; - virtual void enableFilterMode(bool enabled) = 0; - virtual void selectIndex(int index) = 0; - virtual void updateCurrentComicView() = 0; - -public slots: - virtual void updateInfoForIndex(int index); - virtual void setShowMarks(bool show) = 0; - virtual void selectAll() = 0; - -signals: - void selected(unsigned int); - void openComic(const ComicDB& comic); - void comicRated(int,QModelIndex); - - //Context menus - void customContextMenuViewRequested(QPoint); - void customContextMenuItemRequested(QPoint); - - //Drops - void copyComicsToCurrentFolder(QList >); - void moveComicsToCurrentFolder(QList >); - -protected: - ComicModel * model; - - //Drop to import - void dragEnterEvent(QDragEnterEvent *event); - void dropEvent(QDropEvent *event); - - QQuickView *view; - QWidget *container; - - ComicDB *comicDB; - -private: - -}; - -#endif // COMICS_VIEW_H +#ifndef COMICS_VIEW_H +#define COMICS_VIEW_H + +#include + +#include "comic_model.h" + +class YACReaderTableView; +class QSplitter; +class ComicFlowWidget; +class QToolBar; +class ComicModel; +class QQuickView; + +class ComicsView : public QWidget +{ + Q_OBJECT +public: + explicit ComicsView(QWidget *parent = 0); + virtual void setToolBar(QToolBar * toolBar) = 0; + virtual void setModel(ComicModel *model); + virtual void setCurrentIndex(const QModelIndex &index) = 0; + virtual QModelIndex currentIndex() = 0; + virtual QItemSelectionModel * selectionModel() = 0; + virtual void scrollTo(const QModelIndex & mi, QAbstractItemView::ScrollHint hint ) = 0; + virtual void toFullScreen() = 0; + virtual void toNormal() = 0; + virtual void updateConfig(QSettings * settings) = 0; + virtual void enableFilterMode(bool enabled) = 0; + virtual void selectIndex(int index) = 0; + virtual void updateCurrentComicView() = 0; + +public slots: + virtual void updateInfoForIndex(int index); + virtual void setShowMarks(bool show) = 0; + virtual void selectAll() = 0; + +signals: + void selected(unsigned int); + void openComic(const ComicDB& comic); + void comicRated(int,QModelIndex); + + //Context menus + void customContextMenuViewRequested(QPoint); + void customContextMenuItemRequested(QPoint); + + //Drops + void copyComicsToCurrentFolder(QList >); + void moveComicsToCurrentFolder(QList >); + +protected: + ComicModel * model; + + //Drop to import + void dragEnterEvent(QDragEnterEvent *event); + void dropEvent(QDropEvent *event); + + QQuickView *view; + QWidget *container; + + ComicDB *comicDB; + +private: + +}; + +#endif // COMICS_VIEW_H diff --git a/YACReaderLibrary/comics_view_transition.cpp b/YACReaderLibrary/comics_view_transition.cpp index 08893d7d..72d2e3d3 100644 --- a/YACReaderLibrary/comics_view_transition.cpp +++ b/YACReaderLibrary/comics_view_transition.cpp @@ -1,38 +1,38 @@ -#include "comics_view_transition.h" - -#include -#include -#include -#include -#include -#include -#include - -#include "yacreader_global_gui.h" - -ComicsViewTransition::ComicsViewTransition(QWidget *parent) : - QWidget(parent) -{ -#ifdef Q_OS_MAC - setStyleSheet("QWidget {background:#FFFFFF}"); -#else - setStyleSheet("QWidget {background:#2A2A2A}"); -#endif - -} - -QSize ComicsViewTransition::sizeHint() -{ - return QSize(450,350); -} - -void ComicsViewTransition::paintEvent(QPaintEvent *) -{ - QPainter painter (this); - -#ifdef Q_OS_MAC - painter.fillRect(0,0,width(),height(),QColor("#FFFFFF")); -#else - painter.fillRect(0,0,width(),height(),QColor("#2A2A2A")); -#endif -} +#include "comics_view_transition.h" + +#include +#include +#include +#include +#include +#include +#include + +#include "yacreader_global_gui.h" + +ComicsViewTransition::ComicsViewTransition(QWidget *parent) : + QWidget(parent) +{ +#ifdef Q_OS_MAC + setStyleSheet("QWidget {background:#FFFFFF}"); +#else + setStyleSheet("QWidget {background:#2A2A2A}"); +#endif + +} + +QSize ComicsViewTransition::sizeHint() +{ + return QSize(450,350); +} + +void ComicsViewTransition::paintEvent(QPaintEvent *) +{ + QPainter painter (this); + +#ifdef Q_OS_MAC + painter.fillRect(0,0,width(),height(),QColor("#FFFFFF")); +#else + painter.fillRect(0,0,width(),height(),QColor("#2A2A2A")); +#endif +} diff --git a/YACReaderLibrary/comics_view_transition.h b/YACReaderLibrary/comics_view_transition.h index 774c53bd..0a6989e5 100644 --- a/YACReaderLibrary/comics_view_transition.h +++ b/YACReaderLibrary/comics_view_transition.h @@ -1,17 +1,17 @@ -#ifndef COMICS_VIEW_TRANSITION_H -#define COMICS_VIEW_TRANSITION_H - -#include - -class ComicsViewTransition : public QWidget -{ - Q_OBJECT -public: - explicit ComicsViewTransition(QWidget *parent = 0); - QSize sizeHint(); - -protected: - void paintEvent(QPaintEvent *); -}; - -#endif // COMICS_VIEW_TRANSITION_H +#ifndef COMICS_VIEW_TRANSITION_H +#define COMICS_VIEW_TRANSITION_H + +#include + +class ComicsViewTransition : public QWidget +{ + Q_OBJECT +public: + explicit ComicsViewTransition(QWidget *parent = 0); + QSize sizeHint(); + +protected: + void paintEvent(QPaintEvent *); +}; + +#endif // COMICS_VIEW_TRANSITION_H diff --git a/YACReaderLibrary/create_library_dialog.cpp b/YACReaderLibrary/create_library_dialog.cpp index 1ae28ff1..cc856257 100644 --- a/YACReaderLibrary/create_library_dialog.cpp +++ b/YACReaderLibrary/create_library_dialog.cpp @@ -1,206 +1,206 @@ -#include "create_library_dialog.h" - -#include -#include -#include -#include -#include - -CreateLibraryDialog::CreateLibraryDialog(QWidget * parent) -:QDialog(parent) -{ - setupUI(); -} - -void CreateLibraryDialog::setupUI() -{ - textLabel = new QLabel(tr("Comics folder : ")); - path = new QLineEdit; - textLabel->setBuddy(path); - connect(path,SIGNAL(textChanged(QString)),this,SLOT(pathSetted(QString))); - - nameLabel = new QLabel(tr("Library Name : ")); - nameEdit = new QLineEdit; - nameLabel->setBuddy(nameEdit); - connect(nameEdit,SIGNAL(textChanged(QString)),this,SLOT(nameSetted(QString))); - - accept = new QPushButton(tr("Create")); - accept->setDisabled(true); - connect(accept,SIGNAL(clicked()),this,SLOT(create())); - - cancel = new QPushButton(tr("Cancel")); - connect(cancel,SIGNAL(clicked()),this,SIGNAL(cancelCreate())); - connect(cancel,SIGNAL(clicked()),this,SLOT(close())); - - find = new QPushButton(QIcon(":/images/find_folder.png"),""); - connect(find,SIGNAL(clicked()),this,SLOT(findPath())); - - QGridLayout * content = new QGridLayout; - - //QHBoxLayout *nameLayout = new QHBoxLayout; - - content->addWidget(nameLabel,0,0); - content->addWidget(nameEdit,0,1); - - //QHBoxLayout *libraryLayout = new QHBoxLayout; - - content->addWidget(textLabel,1,0); - content->addWidget(path,1,1); - content->addWidget(find,1,2); - content->setColumnMinimumWidth(2,0); //TODO - - QHBoxLayout *bottomLayout = new QHBoxLayout; - bottomLayout->addWidget(message = new QLabel(tr("Create a library could take several minutes. You can stop the process and update the library later for completing the task."))); - message->setWordWrap(true); - //message->hide(); - bottomLayout->addStretch(); - bottomLayout->addWidget(accept); - bottomLayout->addWidget(cancel); - - QVBoxLayout *mainLayout = new QVBoxLayout; - mainLayout->addLayout(content); - - mainLayout->addLayout(bottomLayout); - - QHBoxLayout * imgMainLayout = new QHBoxLayout; - QLabel * imgLabel = new QLabel(this); - QPixmap p(":/images/new.png"); - imgLabel->setPixmap(p); - imgMainLayout->addWidget(imgLabel); - imgMainLayout->addLayout(mainLayout); - - setLayout(imgMainLayout); - - setModal(true); - setWindowTitle(tr("Create new library")); -} - -void CreateLibraryDialog::open(const YACReaderLibraries & libs) -{ - libraries = libs; - QDialog::open(); -} - -void CreateLibraryDialog::create() -{ - - QFileInfo f(path->text()); - if(f.exists() && f.isDir() && f.isWritable()) - { - if(!libraries.contains(nameEdit->text())) - { - emit(createLibrary(QDir::cleanPath(path->text()),QDir::cleanPath(path->text())+"/.yacreaderlibrary",nameEdit->text())); - close(); - } - else - emit(libraryExists(nameEdit->text())); - } - else - QMessageBox::critical(NULL,tr("Path not found"),tr("The selected path does not exist or is not a valid path. Be sure that you have write access to this folder")); -} - -void CreateLibraryDialog::nameSetted(const QString & text) -{ - if(!text.isEmpty()) - { - if(!path->text().isEmpty()) - { - QFileInfo fi(path->text()); - if(fi.isDir()) - accept->setEnabled(true); - else - accept->setEnabled(false); - } - } - else - accept->setEnabled(false); -} - -void CreateLibraryDialog::pathSetted(const QString & text) -{ - QFileInfo fi(text); - if(fi.isDir()) - { - if(!nameEdit->text().isEmpty()) - accept->setEnabled(true); - } - else - accept->setEnabled(false); -} - -void CreateLibraryDialog::findPath() -{ - QString s = QFileDialog::getExistingDirectory(0,"Comics directory","."); - if(!s.isEmpty()) - { - path->setText(s); - if(!nameEdit->text().isEmpty()) - accept->setEnabled(true); - } - else - accept->setEnabled(false); -} - -void CreateLibraryDialog::close() -{ - path->clear(); - nameEdit->clear(); - accept->setEnabled(false); - QDialog::close(); -} - -void CreateLibraryDialog::setDataAndStart(QString name, QString path) -{ - this->path->setText(path); - this->nameEdit->setText(name); - QDialog::open(); - create(); -} -//----------------------------------------------------------------------------- -// UpdateLibraryDialog -//----------------------------------------------------------------------------- -UpdateLibraryDialog::UpdateLibraryDialog(QWidget * parent) -:QDialog(parent) -{ - QVBoxLayout * mainLayout = new QVBoxLayout; - mainLayout->addWidget(message = new QLabel(tr("Updating...."))); - mainLayout->addWidget(currentFileLabel = new QLabel("\n\n\n\n")); - currentFileLabel->setWordWrap(true); - - QHBoxLayout * bottom = new QHBoxLayout; - bottom->addStretch(); - bottom->addWidget(cancel = new QPushButton(tr("Cancel"))); - - connect(cancel,SIGNAL(clicked()),this,SIGNAL(cancelUpdate())); - connect(cancel,SIGNAL(clicked()),this,SLOT(close())); - - mainLayout->addStretch(); - - mainLayout->addLayout(bottom); - - QHBoxLayout * imgMainLayout = new QHBoxLayout; - QLabel * imgLabel = new QLabel(this); - QPixmap p(":/images/updateLibrary.png"); - imgLabel->setPixmap(p); - imgMainLayout->addWidget(imgLabel); - imgMainLayout->addLayout(mainLayout); - - setLayout(imgMainLayout); - - setModal(true); - setWindowTitle(tr("Update library")); -} - -void UpdateLibraryDialog::showCurrentFile(QString file) -{ - currentFileLabel->setText(file); - currentFileLabel->update(); - this->update(); -} - -void UpdateLibraryDialog::close() -{ - currentFileLabel->setText(""); - this->adjustSize(); - QDialog::close(); -} +#include "create_library_dialog.h" + +#include +#include +#include +#include +#include + +CreateLibraryDialog::CreateLibraryDialog(QWidget * parent) +:QDialog(parent) +{ + setupUI(); +} + +void CreateLibraryDialog::setupUI() +{ + textLabel = new QLabel(tr("Comics folder : ")); + path = new QLineEdit; + textLabel->setBuddy(path); + connect(path,SIGNAL(textChanged(QString)),this,SLOT(pathSetted(QString))); + + nameLabel = new QLabel(tr("Library Name : ")); + nameEdit = new QLineEdit; + nameLabel->setBuddy(nameEdit); + connect(nameEdit,SIGNAL(textChanged(QString)),this,SLOT(nameSetted(QString))); + + accept = new QPushButton(tr("Create")); + accept->setDisabled(true); + connect(accept,SIGNAL(clicked()),this,SLOT(create())); + + cancel = new QPushButton(tr("Cancel")); + connect(cancel,SIGNAL(clicked()),this,SIGNAL(cancelCreate())); + connect(cancel,SIGNAL(clicked()),this,SLOT(close())); + + find = new QPushButton(QIcon(":/images/find_folder.png"),""); + connect(find,SIGNAL(clicked()),this,SLOT(findPath())); + + QGridLayout * content = new QGridLayout; + + //QHBoxLayout *nameLayout = new QHBoxLayout; + + content->addWidget(nameLabel,0,0); + content->addWidget(nameEdit,0,1); + + //QHBoxLayout *libraryLayout = new QHBoxLayout; + + content->addWidget(textLabel,1,0); + content->addWidget(path,1,1); + content->addWidget(find,1,2); + content->setColumnMinimumWidth(2,0); //TODO + + QHBoxLayout *bottomLayout = new QHBoxLayout; + bottomLayout->addWidget(message = new QLabel(tr("Create a library could take several minutes. You can stop the process and update the library later for completing the task."))); + message->setWordWrap(true); + //message->hide(); + bottomLayout->addStretch(); + bottomLayout->addWidget(accept); + bottomLayout->addWidget(cancel); + + QVBoxLayout *mainLayout = new QVBoxLayout; + mainLayout->addLayout(content); + + mainLayout->addLayout(bottomLayout); + + QHBoxLayout * imgMainLayout = new QHBoxLayout; + QLabel * imgLabel = new QLabel(this); + QPixmap p(":/images/new.png"); + imgLabel->setPixmap(p); + imgMainLayout->addWidget(imgLabel); + imgMainLayout->addLayout(mainLayout); + + setLayout(imgMainLayout); + + setModal(true); + setWindowTitle(tr("Create new library")); +} + +void CreateLibraryDialog::open(const YACReaderLibraries & libs) +{ + libraries = libs; + QDialog::open(); +} + +void CreateLibraryDialog::create() +{ + + QFileInfo f(path->text()); + if(f.exists() && f.isDir() && f.isWritable()) + { + if(!libraries.contains(nameEdit->text())) + { + emit(createLibrary(QDir::cleanPath(path->text()),QDir::cleanPath(path->text())+"/.yacreaderlibrary",nameEdit->text())); + close(); + } + else + emit(libraryExists(nameEdit->text())); + } + else + QMessageBox::critical(NULL,tr("Path not found"),tr("The selected path does not exist or is not a valid path. Be sure that you have write access to this folder")); +} + +void CreateLibraryDialog::nameSetted(const QString & text) +{ + if(!text.isEmpty()) + { + if(!path->text().isEmpty()) + { + QFileInfo fi(path->text()); + if(fi.isDir()) + accept->setEnabled(true); + else + accept->setEnabled(false); + } + } + else + accept->setEnabled(false); +} + +void CreateLibraryDialog::pathSetted(const QString & text) +{ + QFileInfo fi(text); + if(fi.isDir()) + { + if(!nameEdit->text().isEmpty()) + accept->setEnabled(true); + } + else + accept->setEnabled(false); +} + +void CreateLibraryDialog::findPath() +{ + QString s = QFileDialog::getExistingDirectory(0,"Comics directory","."); + if(!s.isEmpty()) + { + path->setText(s); + if(!nameEdit->text().isEmpty()) + accept->setEnabled(true); + } + else + accept->setEnabled(false); +} + +void CreateLibraryDialog::close() +{ + path->clear(); + nameEdit->clear(); + accept->setEnabled(false); + QDialog::close(); +} + +void CreateLibraryDialog::setDataAndStart(QString name, QString path) +{ + this->path->setText(path); + this->nameEdit->setText(name); + QDialog::open(); + create(); +} +//----------------------------------------------------------------------------- +// UpdateLibraryDialog +//----------------------------------------------------------------------------- +UpdateLibraryDialog::UpdateLibraryDialog(QWidget * parent) +:QDialog(parent) +{ + QVBoxLayout * mainLayout = new QVBoxLayout; + mainLayout->addWidget(message = new QLabel(tr("Updating...."))); + mainLayout->addWidget(currentFileLabel = new QLabel("\n\n\n\n")); + currentFileLabel->setWordWrap(true); + + QHBoxLayout * bottom = new QHBoxLayout; + bottom->addStretch(); + bottom->addWidget(cancel = new QPushButton(tr("Cancel"))); + + connect(cancel,SIGNAL(clicked()),this,SIGNAL(cancelUpdate())); + connect(cancel,SIGNAL(clicked()),this,SLOT(close())); + + mainLayout->addStretch(); + + mainLayout->addLayout(bottom); + + QHBoxLayout * imgMainLayout = new QHBoxLayout; + QLabel * imgLabel = new QLabel(this); + QPixmap p(":/images/updateLibrary.png"); + imgLabel->setPixmap(p); + imgMainLayout->addWidget(imgLabel); + imgMainLayout->addLayout(mainLayout); + + setLayout(imgMainLayout); + + setModal(true); + setWindowTitle(tr("Update library")); +} + +void UpdateLibraryDialog::showCurrentFile(QString file) +{ + currentFileLabel->setText(file); + currentFileLabel->update(); + this->update(); +} + +void UpdateLibraryDialog::close() +{ + currentFileLabel->setText(""); + this->adjustSize(); + QDialog::close(); +} diff --git a/YACReaderLibrary/create_library_dialog.h b/YACReaderLibrary/create_library_dialog.h index 2736552c..4b44221c 100644 --- a/YACReaderLibrary/create_library_dialog.h +++ b/YACReaderLibrary/create_library_dialog.h @@ -1,61 +1,61 @@ -#ifndef __CREATE_LIBRARY_DIALOG_H -#define __CREATE_LIBRARY_DIALOG_H - -#include "yacreader_libraries.h" - -#include -#include -#include -#include -#include -#include - - class CreateLibraryDialog : public QDialog - { - Q_OBJECT - public: - CreateLibraryDialog(QWidget * parent = 0); - private: - QLabel * nameLabel; - QLabel * textLabel; - QLabel * message; - QProgressBar *progressBar; - QLineEdit * path; - QLineEdit * nameEdit; - QPushButton * find; - QPushButton * accept; - QPushButton * cancel; - YACReaderLibraries libraries; - void setupUI(); - public slots: - void create(); - void findPath(); - void close(); - void setDataAndStart(QString name, QString paht); - void nameSetted(const QString & text); - void pathSetted(const QString & text); - void open(const YACReaderLibraries &libraries); - signals: - void createLibrary(QString source, QString target, QString name); - void cancelCreate(); - void libraryExists(const QString & name); - }; - - class UpdateLibraryDialog : public QDialog - { - Q_OBJECT - public: - UpdateLibraryDialog(QWidget * parent = 0); - private: - QLabel * message; - QLabel * currentFileLabel; - QProgressBar *progressBar; - QPushButton * cancel; - public slots: - void showCurrentFile(QString file); - void close(); - signals: - void cancelUpdate(); - }; - -#endif +#ifndef __CREATE_LIBRARY_DIALOG_H +#define __CREATE_LIBRARY_DIALOG_H + +#include "yacreader_libraries.h" + +#include +#include +#include +#include +#include +#include + + class CreateLibraryDialog : public QDialog + { + Q_OBJECT + public: + CreateLibraryDialog(QWidget * parent = 0); + private: + QLabel * nameLabel; + QLabel * textLabel; + QLabel * message; + QProgressBar *progressBar; + QLineEdit * path; + QLineEdit * nameEdit; + QPushButton * find; + QPushButton * accept; + QPushButton * cancel; + YACReaderLibraries libraries; + void setupUI(); + public slots: + void create(); + void findPath(); + void close(); + void setDataAndStart(QString name, QString paht); + void nameSetted(const QString & text); + void pathSetted(const QString & text); + void open(const YACReaderLibraries &libraries); + signals: + void createLibrary(QString source, QString target, QString name); + void cancelCreate(); + void libraryExists(const QString & name); + }; + + class UpdateLibraryDialog : public QDialog + { + Q_OBJECT + public: + UpdateLibraryDialog(QWidget * parent = 0); + private: + QLabel * message; + QLabel * currentFileLabel; + QProgressBar *progressBar; + QPushButton * cancel; + public slots: + void showCurrentFile(QString file); + void close(); + signals: + void cancelUpdate(); + }; + +#endif diff --git a/YACReaderLibrary/current_comic_view_helper.cpp b/YACReaderLibrary/current_comic_view_helper.cpp index 787b0ec6..ea879013 100644 --- a/YACReaderLibrary/current_comic_view_helper.cpp +++ b/YACReaderLibrary/current_comic_view_helper.cpp @@ -1,17 +1,17 @@ -#include "current_comic_view_helper.h" - -#include "comic_db.h" - -ComicDB currentComicFromModel(ComicModel *model, bool &found) { - auto comics = model->getAllComics(); - - foreach (auto comic, comics) { - if (comic.info.read == false) { - found = true; - return comic; - } - } - - found = false; - return ComicDB(); -} +#include "current_comic_view_helper.h" + +#include "comic_db.h" + +ComicDB currentComicFromModel(ComicModel *model, bool &found) { + auto comics = model->getAllComics(); + + foreach (auto comic, comics) { + if (comic.info.read == false) { + found = true; + return comic; + } + } + + found = false; + return ComicDB(); +} diff --git a/YACReaderLibrary/current_comic_view_helper.h b/YACReaderLibrary/current_comic_view_helper.h index 595a6332..d6e94cd3 100644 --- a/YACReaderLibrary/current_comic_view_helper.h +++ b/YACReaderLibrary/current_comic_view_helper.h @@ -1,8 +1,8 @@ -#ifndef CURRENT_COMIC_VIEW_HELPER_H -#define CURRENT_COMIC_VIEW_HELPER_H - -#include "comic_model.h" - -ComicDB currentComicFromModel(ComicModel *model, bool &found); - -#endif // CURRENT_COMIC_VIEW_HELPER_H +#ifndef CURRENT_COMIC_VIEW_HELPER_H +#define CURRENT_COMIC_VIEW_HELPER_H + +#include "comic_model.h" + +ComicDB currentComicFromModel(ComicModel *model, bool &found); + +#endif // CURRENT_COMIC_VIEW_HELPER_H diff --git a/YACReaderLibrary/db/comic_item.cpp b/YACReaderLibrary/db/comic_item.cpp index 9382d897..18adb83a 100644 --- a/YACReaderLibrary/db/comic_item.cpp +++ b/YACReaderLibrary/db/comic_item.cpp @@ -1,47 +1,47 @@ - -#include - -#include "comic_item.h" - -//! [0] -ComicItem::ComicItem(const QList &data) - -{ - itemData = data; -} -//! [0] - -//! [1] -ComicItem::~ComicItem() -{ - -} -//! [1] - - -//! [5] -int ComicItem::columnCount() const -{ - return itemData.count(); -} -//! [5] - -//! [6] -QVariant ComicItem::data(int column) const -{ - return itemData.value(column); -} -//! [6] - -void ComicItem::setData(int column,const QVariant & value) -{ - itemData[column] = value; -} - -//! [8] -int ComicItem::row() const -{ - - return 0; -} -//! [8] + +#include + +#include "comic_item.h" + +//! [0] +ComicItem::ComicItem(const QList &data) + +{ + itemData = data; +} +//! [0] + +//! [1] +ComicItem::~ComicItem() +{ + +} +//! [1] + + +//! [5] +int ComicItem::columnCount() const +{ + return itemData.count(); +} +//! [5] + +//! [6] +QVariant ComicItem::data(int column) const +{ + return itemData.value(column); +} +//! [6] + +void ComicItem::setData(int column,const QVariant & value) +{ + itemData[column] = value; +} + +//! [8] +int ComicItem::row() const +{ + + return 0; +} +//! [8] diff --git a/YACReaderLibrary/db/comic_item.h b/YACReaderLibrary/db/comic_item.h index 35d6fa54..c708e38a 100644 --- a/YACReaderLibrary/db/comic_item.h +++ b/YACReaderLibrary/db/comic_item.h @@ -1,27 +1,27 @@ -#ifndef TABLEITEM_H -#define TABLEITEM_H - -#include -#include - -//! [0] -class ComicItem : public QObject -{ - Q_OBJECT -public: - ComicItem(const QList &data); - ~ComicItem(); - int columnCount() const; - QVariant data(int column) const; - void setData(int column,const QVariant & value); - int row() const; - //unsigned long long int id; //TODO sustituir por una clase adecuada - //Comic comic; -private: - QList itemData; - - -}; -//! [0] - -#endif +#ifndef TABLEITEM_H +#define TABLEITEM_H + +#include +#include + +//! [0] +class ComicItem : public QObject +{ + Q_OBJECT +public: + ComicItem(const QList &data); + ~ComicItem(); + int columnCount() const; + QVariant data(int column) const; + void setData(int column,const QVariant & value); + int row() const; + //unsigned long long int id; //TODO sustituir por una clase adecuada + //Comic comic; +private: + QList itemData; + + +}; +//! [0] + +#endif diff --git a/YACReaderLibrary/db/comic_model.cpp b/YACReaderLibrary/db/comic_model.cpp index 763d1b9e..f73309c1 100644 --- a/YACReaderLibrary/db/comic_model.cpp +++ b/YACReaderLibrary/db/comic_model.cpp @@ -1,1140 +1,1140 @@ - -#include -#include -#include - -#include "comic_item.h" -#include "comic_model.h" -#include "data_base_management.h" -#include "qnaturalsorting.h" -#include "comic_db.h" -#include "db_helper.h" - -//ci.number,ci.title,c.fileName,ci.numPages,c.id,c.parentId,c.path,ci.hash,ci.read -#include "QsLog.h" - - -ComicModel::ComicModel(QObject *parent) - : QAbstractItemModel(parent) -{ - connect(this,SIGNAL(beforeReset()),this,SIGNAL(modelAboutToBeReset())); - connect(this,SIGNAL(reset()),this,SIGNAL(modelReset())); -} - -ComicModel::ComicModel( QSqlQuery &sqlquery, QObject *parent) - : QAbstractItemModel(parent) -{ - setupModelData(sqlquery); -} - -ComicModel::~ComicModel() -{ - qDeleteAll(_data); -} - -int ComicModel::columnCount(const QModelIndex &parent) const -{ - Q_UNUSED(parent) - if(_data.isEmpty()) - return 0; - return _data.first()->columnCount(); -} - -bool ComicModel::canDropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent) const -{ - Q_UNUSED(action); - Q_UNUSED(row); - Q_UNUSED(column); - Q_UNUSED(parent); - - if(!enableResorting) - return false; - return data->formats().contains(YACReader::YACReaderLibrarComiscSelectionMimeDataFormat); -} - -//TODO: optimize this method (seriously) -bool ComicModel::dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent) -{ - - QAbstractItemModel::dropMimeData(data,action,row,column,parent); - QLOG_TRACE() << ">>>>>>>>>>>>>>dropMimeData ComicModel<<<<<<<<<<<<<<<<<"<< parent << row << "," << column; - - if(!data->formats().contains(YACReader::YACReaderLibrarComiscSelectionMimeDataFormat)) - return false; - - QList comicIds = YACReader::mimeDataToComicsIds(data); - QList currentIndexes; - int i; - foreach(qulonglong id, comicIds) - { - i = 0; - foreach (ComicItem *item, _data) { - if(item->data(Id)==id) - { - currentIndexes << i; - break; - } - i++; - } - } - - std::sort(currentIndexes.begin(), currentIndexes.end()); - QList resortedData; - - if(currentIndexes.contains(row))//no resorting - return false; - - ComicItem * destinationItem; - if(row == -1 || row >= _data.length()) - destinationItem = 0; - else - destinationItem = _data.at(row); - - QList newSorting; - - i = 0; - foreach (ComicItem *item, _data) { - if(!currentIndexes.contains(i)) - { - - if(item == destinationItem) { - foreach(int index, currentIndexes) - { - resortedData << _data.at(index); - newSorting << index; - } - } - - resortedData << item; - newSorting << i; - } - - i++; - } - - if(destinationItem == 0) - { - foreach(int index, currentIndexes) - { - resortedData << _data.at(index); - newSorting << index; - } - } - - QLOG_TRACE() << newSorting; - - int tempRow = row; - - if(tempRow < 0) - tempRow = _data.count(); - - foreach(qulonglong id, comicIds) - { - int i = 0; - foreach (ComicItem *item, _data) { - if(item->data(Id) == id) - { - beginMoveRows(parent,i,i,parent,tempRow); - - bool skipElement = i == tempRow || i + 1 == tempRow; - - if(!skipElement) - { - if(i > tempRow) - _data.move(i, tempRow); - else - _data.move(i, tempRow - 1); - } - - endMoveRows(); - - if(i > tempRow) - tempRow++; - - break; - } - i++; - } - } - - //TODO fix selection - QList allComicIds; - foreach (ComicItem *item, _data) { - allComicIds << item->data(Id).toULongLong(); - } - - QSqlDatabase db = DataBaseManagement::loadDatabase(_databasePath); - switch (mode) { - case Favorites: - DBHelper::reasignOrderToComicsInFavorites(allComicIds,db); - break; - case Label: - DBHelper::reasignOrderToComicsInLabel(sourceId,allComicIds,db); - break; - case ReadingList: - DBHelper::reasignOrderToComicsInReadingList(sourceId,allComicIds,db); - break; - } - - QSqlDatabase::removeDatabase(db.connectionName()); - - //endMoveRows(); - - emit resortedIndexes(newSorting); - int destSelectedIndex = row<0?_data.length():row; - - if(destSelectedIndex>currentIndexes.at(0)) - emit newSelectedIndex(index(qMax(0,destSelectedIndex-1),0,parent)); - else - emit newSelectedIndex(index(qMax(0,destSelectedIndex),0,parent)); - - return true; -} - -bool ComicModel::canBeResorted() -{ - return enableResorting; -} - -QMimeData *ComicModel::mimeData(const QModelIndexList &indexes) const -{ - //custom model data - //application/yacreader-comics-ids + list of ids in a QByteArray - QList ids; - foreach(QModelIndex index, indexes) - { - QLOG_DEBUG() << "dragging : " << index.data(IdRole).toULongLong(); - ids << index.data(IdRole).toULongLong(); - - } - - QByteArray data; - QDataStream out(&data,QIODevice::WriteOnly); - out << ids; //serialize the list of identifiers - - QMimeData * mimeData = new QMimeData(); - mimeData->setData(YACReader::YACReaderLibrarComiscSelectionMimeDataFormat, data); - - return mimeData; -} - -QStringList ComicModel::mimeTypes() const -{ - QLOG_DEBUG() << "mimeTypes"; - QStringList list; - list << YACReader::YACReaderLibrarComiscSelectionMimeDataFormat; - return list; -} - -QHash ComicModel::roleNames() const { - QHash roles; - - roles[NumberRole] = "number"; - roles[TitleRole] = "title"; - roles[FileNameRole] = "file_name"; - roles[NumPagesRole] = "num_pages"; - roles[IdRole] = "id"; - roles[Parent_IdRole] = "parent_id"; - roles[PathRole] = "path"; - roles[HashRole] = "hash"; - roles[ReadColumnRole] = "read_column"; - roles[IsBisRole] = "is_bis"; - roles[CurrentPageRole] = "current_page"; - roles[RatingRole] = "rating"; - roles[HasBeenOpenedRole] = "has_been_opened"; - roles[CoverPathRole] = "cover_path"; - - return roles; -} - -QVariant ComicModel::data(const QModelIndex &index, int role) const -{ - if (!index.isValid()) - return QVariant(); - - /*if (index.column() == TableModel::Rating && role == Qt::DecorationRole) - { - TableItem *item = static_cast(index.internalPointer()); - return QPixmap(QString(":/images/rating%1.png").arg(item->data(index.column()).toInt())); - }*/ - - if (role == Qt::DecorationRole) - { - return QVariant(); - } - - if (role == Qt::TextAlignmentRole) - { - switch(index.column())//TODO obtener esto de la query - { - case ComicModel::Number: - return QVariant(Qt::AlignRight | Qt::AlignVCenter); - case ComicModel::NumPages: - return QVariant(Qt::AlignRight | Qt::AlignVCenter); - case ComicModel::Hash: - return QVariant(Qt::AlignRight | Qt::AlignVCenter); - case ComicModel::CurrentPage: - return QVariant(Qt::AlignRight | Qt::AlignVCenter); - default: - return QVariant(Qt::AlignLeft | Qt::AlignVCenter); - } - } - - - //TODO check here if any view is asking for TableModel::Roles - //these roles will be used from QML/GridView - - ComicItem *item = static_cast(index.internalPointer()); - - if (role == NumberRole) - return item->data(Number); - else if (role == TitleRole) - return item->data(Title).isNull()?item->data(FileName):item->data(Title); - else if (role == FileNameRole) - return item->data(FileName); - else if (role == RatingRole) - return item->data(Rating); - else if (role == CoverPathRole) - return getCoverUrlPathForComicHash(item->data(Hash).toString()); - else if (role == NumPagesRole) - return item->data(NumPages); - else if (role == CurrentPageRole) - return item->data(CurrentPage); - else if (role == ReadColumnRole) - return item->data(ReadColumn).toBool(); - else if (role == HasBeenOpenedRole) - return item->data(ComicModel::HasBeenOpened); - else if (role == IdRole) - return item->data(Id); - - if (role != Qt::DisplayRole) - return QVariant(); - - if(index.column() == ComicModel::Hash) - return QString::number(item->data(index.column()).toString().right(item->data(index.column()).toString().length()-40).toInt()/1024.0/1024.0,'f',2)+"Mb"; - if(index.column() == ComicModel::ReadColumn) - return (item->data(ComicModel::CurrentPage).toInt()==item->data(ComicModel::NumPages).toInt() || item->data(ComicModel::ReadColumn).toBool())?QVariant(tr("yes")):QVariant(tr("no")); - if(index.column() == ComicModel::CurrentPage) - return item->data(ComicModel::HasBeenOpened).toBool()?item->data(index.column()):QVariant("-"); - - if (index.column() == ComicModel::Rating) - return QVariant(); - - return item->data(index.column()); -} - -Qt::ItemFlags ComicModel::flags(const QModelIndex &index) const -{ - if (!index.isValid()) - return 0; - if(index.column() == ComicModel::Rating) - return Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsEditable; - return Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsDragEnabled ; -} - -QVariant ComicModel::headerData(int section, Qt::Orientation orientation, - int role) const -{ - if (orientation == Qt::Horizontal && role == Qt::DisplayRole) - { - switch(section)//TODO obtener esto de la query - { - case ComicModel::Number: - return QVariant(QString("#")); - case ComicModel::Title: - return QVariant(QString(tr("Title"))); - case ComicModel::FileName: - return QVariant(QString(tr("File Name"))); - case ComicModel::NumPages: - return QVariant(QString(tr("Pages"))); - case ComicModel::Hash: - return QVariant(QString(tr("Size"))); - case ComicModel::ReadColumn: - return QVariant(QString(tr("Read"))); - case ComicModel::CurrentPage: - return QVariant(QString(tr("Current Page"))); - case ComicModel::Rating: - return QVariant(QString(tr("Rating"))); - } - } - - if (orientation == Qt::Horizontal && role == Qt::TextAlignmentRole) - { - switch(section)//TODO obtener esto de la query - { - case ComicModel::Number: - return QVariant(Qt::AlignRight | Qt::AlignVCenter); - case ComicModel::NumPages: - return QVariant(Qt::AlignRight | Qt::AlignVCenter); - case ComicModel::Hash: - return QVariant(Qt::AlignRight | Qt::AlignVCenter); - case ComicModel::CurrentPage: - return QVariant(Qt::AlignRight | Qt::AlignVCenter); - default: - return QVariant(Qt::AlignLeft | Qt::AlignVCenter); - } - } - - - if(orientation == Qt::Vertical && role == Qt::DecorationRole) - { - QString fileName = _data.value(section)->data(ComicModel::FileName).toString(); - QFileInfo fi(fileName); - QString ext = fi.suffix(); - - if (ext.compare("cbr",Qt::CaseInsensitive) == 0) - return QVariant(QIcon(":/images/comicRar.png")); - else if (ext.compare("cbz",Qt::CaseInsensitive) == 0) - return QVariant(QIcon(":/images/comicZip.png")); - else if(ext.compare("pdf",Qt::CaseInsensitive) == 0) - return QVariant(QIcon(":/images/pdf.png")); - else if (ext.compare("tar",Qt::CaseInsensitive) == 0) - return QVariant(QIcon(":/images/tar.png")); - else if(ext.compare("zip",Qt::CaseInsensitive) == 0) - return QVariant(QIcon(":/images/zip.png")); - else if(ext.compare("rar",Qt::CaseInsensitive) == 0) - return QVariant(QIcon(":/images/rar.png")); -#ifndef use_unarr - else if (ext.compare("7z",Qt::CaseInsensitive) == 0) - return QVariant(QIcon(":/images/7z.png")); - else if (ext.compare("cb7",Qt::CaseInsensitive) == 0) - return QVariant(QIcon(":/images/comic7z.png")); -#endif - else if (ext.compare("cbt",Qt::CaseInsensitive) == 0) - return QVariant(QIcon(":/images/comicTar.png")); - - } - - return QVariant(); -} - -QModelIndex ComicModel::index(int row, int column, const QModelIndex &parent) - const -{ - if (!hasIndex(row, column, parent)) - return QModelIndex(); - - return createIndex(row, column, _data.at(row)); -} - -QModelIndex ComicModel::parent(const QModelIndex &index) const -{ - Q_UNUSED(index) - return QModelIndex(); -} - -int ComicModel::rowCount(const QModelIndex &parent) const -{ - if (parent.column() > 0) - return 0; - - if (!parent.isValid()) - return _data.count(); - - return 0; -} - -QStringList ComicModel::getPaths(const QString & _source) -{ - QStringList paths; - QString source = _source + "/.yacreaderlibrary/covers/"; - QList::ConstIterator itr; - for(itr = _data.constBegin();itr != _data.constEnd();itr++) - { - QString hash = (*itr)->data(ComicModel::Hash).toString(); - paths << source+ hash +".jpg"; - } - - return paths; -} - -void ComicModel::setupFolderModelData(unsigned long long int folderId,const QString & databasePath) -{ - enableResorting = false; - mode = Folder; - sourceId=folderId; - - beginResetModel(); - qDeleteAll(_data); - _data.clear(); - - _databasePath = databasePath; - QSqlDatabase db = DataBaseManagement::loadDatabase(databasePath); - { - QSqlQuery selectQuery(db); - selectQuery.prepare("SELECT ci.number,ci.title,c.fileName,ci.numPages,c.id,c.parentId,c.path,ci.hash,ci.read,ci.isBis,ci.currentPage,ci.rating,ci.hasBeenOpened " - "FROM comic c INNER JOIN comic_info ci ON (c.comicInfoId = ci.id) " - "WHERE c.parentId = :parentId"); - selectQuery.bindValue(":parentId", folderId); - selectQuery.exec(); - setupModelData(selectQuery); - } - db.close(); - QSqlDatabase::removeDatabase(db.connectionName()); - endResetModel(); - - /*if(_data.length()==0) - emit isEmpty();*/ -} - -void ComicModel::setupLabelModelData(unsigned long long parentLabel, const QString &databasePath) -{ - enableResorting = true; - mode = Label; - sourceId = parentLabel; - - beginResetModel(); - qDeleteAll(_data); - _data.clear(); - - _databasePath = databasePath; - QSqlDatabase db = DataBaseManagement::loadDatabase(databasePath); - { - QSqlQuery selectQuery(db); - selectQuery.prepare("SELECT ci.number,ci.title,c.fileName,ci.numPages,c.id,c.parentId,c.path,ci.hash,ci.read,ci.isBis,ci.currentPage,ci.rating,ci.hasBeenOpened " - "FROM comic c INNER JOIN comic_info ci ON (c.comicInfoId = ci.id) " - "INNER JOIN comic_label cl ON (c.id == cl.comic_id) " - "WHERE cl.label_id = :parentLabelId " - "ORDER BY cl.ordering"); - selectQuery.bindValue(":parentLabelId", parentLabel); - selectQuery.exec(); - setupModelDataForList(selectQuery); - } - db.close(); - QSqlDatabase::removeDatabase(db.connectionName()); - endResetModel(); - - /*if(_data.length()==0) - emit isEmpty();*/ -} - -void ComicModel::setupReadingListModelData(unsigned long long parentReadingList, const QString &databasePath) -{ - mode = ReadingList; - sourceId = parentReadingList; - - beginResetModel(); - qDeleteAll(_data); - _data.clear(); - - _databasePath = databasePath; - QSqlDatabase db = DataBaseManagement::loadDatabase(databasePath); - { - QList ids; - ids << parentReadingList; - - QSqlQuery subfolders(db); - subfolders.prepare("SELECT id " - "FROM reading_list " - "WHERE parentId = :parentId " - "ORDER BY ordering ASC"); - subfolders.bindValue(":parentId", parentReadingList); - subfolders.exec(); - while(subfolders.next()) - ids << subfolders.record().value(0).toULongLong(); - - enableResorting = ids.length()==1;//only resorting if no sublists exist - - - foreach(qulonglong id, ids) - { - QSqlQuery selectQuery(db); - selectQuery.prepare("SELECT ci.number,ci.title,c.fileName,ci.numPages,c.id,c.parentId,c.path,ci.hash,ci.read,ci.isBis,ci.currentPage,ci.rating,ci.hasBeenOpened " - "FROM comic c INNER JOIN comic_info ci ON (c.comicInfoId = ci.id) " - "INNER JOIN comic_reading_list crl ON (c.id == crl.comic_id) " - "WHERE crl.reading_list_id = :parentReadingList " - "ORDER BY crl.ordering"); - selectQuery.bindValue(":parentReadingList", id); - selectQuery.exec(); - - //TODO, extra information is needed (resorting) - QList tempData = _data; - _data.clear(); - - setupModelDataForList(selectQuery); - - _data = tempData << _data; - } - - } - db.close(); - QSqlDatabase::removeDatabase(db.connectionName()); - endResetModel(); -} - -void ComicModel::setupFavoritesModelData(const QString &databasePath) -{ - enableResorting = true; - mode = Favorites; - - beginResetModel(); - qDeleteAll(_data); - _data.clear(); - - _databasePath = databasePath; - QSqlDatabase db = DataBaseManagement::loadDatabase(databasePath); - { - QSqlQuery selectQuery(db); - selectQuery.prepare("SELECT ci.number,ci.title,c.fileName,ci.numPages,c.id,c.parentId,c.path,ci.hash,ci.read,ci.isBis,ci.currentPage,ci.rating,ci.hasBeenOpened " - "FROM comic c INNER JOIN comic_info ci ON (c.comicInfoId = ci.id) " - "INNER JOIN comic_default_reading_list cdrl ON (c.id == cdrl.comic_id) " - "WHERE cdrl.default_reading_list_id = :parentDefaultListId " - "ORDER BY cdrl.ordering"); - selectQuery.bindValue(":parentDefaultListId", 1); - selectQuery.exec(); - setupModelDataForList(selectQuery); - } - db.close(); - QSqlDatabase::removeDatabase(db.connectionName()); - endResetModel(); - - /*if(_data.length()==0) - emit isEmpty();*/ -} - -void ComicModel::setupReadingModelData(const QString &databasePath) -{ - enableResorting = false; - mode = Reading; - - beginResetModel(); - qDeleteAll(_data); - _data.clear(); - - _databasePath = databasePath; - QSqlDatabase db = DataBaseManagement::loadDatabase(databasePath); - { - QSqlQuery selectQuery(db); - selectQuery.prepare("SELECT ci.number,ci.title,c.fileName,ci.numPages,c.id,c.parentId,c.path,ci.hash,ci.read,ci.isBis,ci.currentPage,ci.rating,ci.hasBeenOpened " - "FROM comic c INNER JOIN comic_info ci ON (c.comicInfoId = ci.id) " - "WHERE ci.hasBeenOpened = 1 AND ci.read = 0 " - "ORDER BY ci.lastTimeOpened DESC"); - selectQuery.exec(); - - setupModelDataForList(selectQuery); - } - db.close(); - QSqlDatabase::removeDatabase(db.connectionName()); - endResetModel(); - - /*if(_data.length()==0) - emit isEmpty();*/ -} - -void ComicModel::setupModelData(const SearchModifiers modifier, const QString &filter, const QString &databasePath) -{ - //QFile f(QCoreApplication::applicationDirPath()+"/performance.txt"); - //f.open(QIODevice::Append); - beginResetModel(); - //QElapsedTimer timer; - //timer.start(); - qDeleteAll(_data); - _data.clear(); - - //QTextStream txtS(&f); - //txtS << "TABLEMODEL: Tiempo de borrado: " << timer.elapsed() << "ms\r\n"; - _databasePath = databasePath; - QSqlDatabase db = DataBaseManagement::loadDatabase(databasePath); - { - //crear la consulta - //timer.restart(); - QSqlQuery selectQuery(db); - - switch (modifier) { - case YACReader::NoModifiers: - selectQuery.prepare("SELECT ci.number,ci.title,c.fileName,ci.numPages,c.id,c.parentId,c.path,ci.hash,ci.read,ci.isBis,ci.currentPage,ci.rating,ci.hasBeenOpened " - "FROM comic c INNER JOIN comic_info ci ON (c.comicInfoId = ci.id) " - "WHERE UPPER(ci.title) LIKE UPPER(:filter) OR UPPER(c.fileName) LIKE UPPER(:filter) LIMIT :limit"); - selectQuery.bindValue(":filter", "%%"+filter+"%%"); - selectQuery.bindValue(":limit",500); //TODO, load this value from settings - break; - - case YACReader::OnlyRead: - selectQuery.prepare("SELECT ci.number,ci.title,c.fileName,ci.numPages,c.id,c.parentId,c.path,ci.hash,ci.read,ci.isBis,ci.currentPage,ci.rating,ci.hasBeenOpened " - "FROM comic c INNER JOIN comic_info ci ON (c.comicInfoId = ci.id) " - "WHERE (UPPER(ci.title) LIKE UPPER(:filter) OR UPPER(c.fileName) LIKE UPPER(:filter)) AND ci.read = 1 LIMIT :limit"); - selectQuery.bindValue(":filter", "%%"+filter+"%%"); - selectQuery.bindValue(":limit",500); //TODO, load this value from settings - break; - - case YACReader::OnlyUnread: - selectQuery.prepare("SELECT ci.number,ci.title,c.fileName,ci.numPages,c.id,c.parentId,c.path,ci.hash,ci.read,ci.isBis,ci.currentPage,ci.rating,ci.hasBeenOpened " - "FROM comic c INNER JOIN comic_info ci ON (c.comicInfoId = ci.id) " - "WHERE (UPPER(ci.title) LIKE UPPER(:filter) OR UPPER(c.fileName) LIKE UPPER(:filter)) AND ci.read = 0 LIMIT :limit"); - selectQuery.bindValue(":filter", "%%"+filter+"%%"); - selectQuery.bindValue(":limit",500); //TODO, load this value from settings - break; - - default: - QLOG_ERROR() << "not implemented"; - break; - } - - - selectQuery.exec(); - - QLOG_DEBUG() << selectQuery.lastError() << "--"; - - //txtS << "TABLEMODEL: Tiempo de consulta: " << timer.elapsed() << "ms\r\n"; - //timer.restart(); - setupModelData(selectQuery); - //txtS << "TABLEMODEL: Tiempo de creaci�n del modelo: " << timer.elapsed() << "ms\r\n"; - //selectQuery.finish(); - } - db.close(); - QSqlDatabase::removeDatabase(db.connectionName()); - endResetModel(); - - emit searchNumResults(_data.length()); -} - -QString ComicModel::getComicPath(QModelIndex mi) -{ - if(mi.isValid()) - return _data.at(mi.row())->data(ComicModel::Path).toString(); - return ""; -} - -void ComicModel::setupModelData(QSqlQuery &sqlquery) -{ - int numColumns = sqlquery.record().count(); - - while (sqlquery.next()) - { - QList data; - - for(int i=0;idata(ComicModel::Number).isNull() && c2->data(ComicModel::Number).isNull()) - { - return naturalSortLessThanCI(c1->data(ComicModel::FileName).toString(), c2->data(ComicModel::FileName).toString()); - } - else - { - if (c1->data(ComicModel::Number).isNull() == false && c2->data(ComicModel::Number).isNull() == false) - { - return c1->data(ComicModel::Number).toInt() < c2->data(ComicModel::Number).toInt(); - } - else - { - return c2->data(ComicModel::Number).isNull(); - } - } - }); -} - -//comics are sorted by "ordering", the sorting is done in the sql query -void ComicModel::setupModelDataForList(QSqlQuery &sqlquery) -{ - int numColumns = sqlquery.record().count(); - - while (sqlquery.next()) - { - QList data; - for(int i=0;idata(ComicModel::Id).toULongLong(),db); - db.close(); - QSqlDatabase::removeDatabase(db.connectionName()); - - return c; -} - -ComicDB ComicModel::_getComic(const QModelIndex & mi) -{ - QSqlDatabase db = DataBaseManagement::loadDatabase(_databasePath); - ComicDB c = DBHelper::loadComic(_data.at(mi.row())->data(ComicModel::Id).toULongLong(),db); - db.close(); - QSqlDatabase::removeDatabase(db.connectionName()); - - return c; -} - - -QVector ComicModel::getReadList() -{ - int numComics = _data.count(); - QVector readList(numComics); - for(int i=0;idata(ComicModel::ReadColumn).toBool()) - readList[i] = YACReader::Read; - else if (_data.value(i)->data(ComicModel::CurrentPage).toInt() == _data.value(i)->data(ComicModel::NumPages).toInt()) - readList[i] = YACReader::Read; - else if (_data.value(i)->data(ComicModel::HasBeenOpened).toBool()) - readList[i] = YACReader::Opened; - else - readList[i] = YACReader::Unread; - } - return readList; -} -//TODO untested, this method is no longer used -QVector ComicModel::setAllComicsRead(YACReaderComicReadStatus read) -{ - return setComicsRead(persistentIndexList(),read); -} - -QList ComicModel::getAllComics() -{ - QSqlDatabase db = DataBaseManagement::loadDatabase(_databasePath); - db.transaction(); - - QList comics; - int numComics = _data.count(); - for(int i=0;idata(ComicModel::Id).toULongLong(),db)); - } - - db.commit(); - db.close(); - QSqlDatabase::removeDatabase(db.connectionName()); - - return comics; -} - -QList ComicModel::getComics(QList list) -{ - QList comics; - - QSqlDatabase db = DataBaseManagement::loadDatabase(_databasePath); - db.transaction(); - QList::const_iterator itr; - for(itr = list.constBegin(); itr!= list.constEnd();itr++) - { - comics.append(_getComic(*itr)); - } - db.commit(); - db.close(); - QSqlDatabase::removeDatabase(db.connectionName()); - return comics; -} -//TODO -QVector ComicModel::setComicsRead(QList list,YACReaderComicReadStatus read) -{ - QSqlDatabase db = DataBaseManagement::loadDatabase(_databasePath); - db.transaction(); - 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); - c.info.read = true; - DBHelper::update(&(c.info),db); - } - if(read == YACReader::Unread) - { - _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); - c.info.read = false; - c.info.currentPage = 1; - c.info.hasBeenOpened = false; - DBHelper::update(&(c.info),db); - } - } - db.commit(); - db.close(); - QSqlDatabase::removeDatabase(db.connectionName()); - - emit dataChanged(index(list.first().row(),ComicModel::ReadColumn),index(list.last().row(),ComicModel::HasBeenOpened),QVector() << ReadColumnRole << CurrentPageRole << HasBeenOpenedRole); - - return getReadList(); -} -qint64 ComicModel::asignNumbers(QList list,int startingNumber) -{ - QSqlDatabase db = DataBaseManagement::loadDatabase(_databasePath); - db.transaction(); - qint64 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); - c.info.number = startingNumber+i; - c.info.edited = true; - DBHelper::update(&(c.info),db); - i++; - } - - db.commit(); - db.close(); - QSqlDatabase::removeDatabase(db.connectionName()); - - //emit dataChanged(index(0,ComicModel::Number),index(_data.count()-1,ComicModel::HasBeenOpened)); - - return idFirst; -} -QModelIndex ComicModel::getIndexFromId(quint64 id) -{ - QList::ConstIterator itr; - int i=0; - for(itr = _data.constBegin();itr != _data.constEnd();itr++) - { - if((*itr)->data(ComicModel::Id).toULongLong() == id) - break; - i++; - } - - return index(i,0); -} - -//TODO completely inefficiently -QList ComicModel::getIndexesFromIds(const QList &comicIds) -{ - QList comicsIndexes; - - foreach(qulonglong id,comicIds) - comicsIndexes << getIndexFromId(id); - - return comicsIndexes; -} - -void ComicModel::startTransaction() -{ - dbTransaction = DataBaseManagement::loadDatabase(_databasePath); - dbTransaction.transaction(); -} - -void ComicModel::finishTransaction() -{ - dbTransaction.commit(); - dbTransaction.close(); - QSqlDatabase::removeDatabase(dbTransaction.connectionName()); -} - -void ComicModel::removeInTransaction(int row) -{ - ComicDB c = DBHelper::loadComic(_data.at(row)->data(ComicModel::Id).toULongLong(),dbTransaction); - - DBHelper::removeFromDB(&c,dbTransaction); - beginRemoveRows(QModelIndex(),row,row); - removeRow(row); - delete _data.at(row); - _data.removeAt(row); - - endRemoveRows(); -} -/* -void ComicModel::remove(ComicDB * comic, int row) -{ - beginRemoveRows(QModelIndex(),row,row); - QSqlDatabase db = DataBaseManagement::loadDatabase(_databasePath); - - DBHelper::removeFromDB(comic,db); - - removeRow(row); - delete _data.at(row); - _data.removeAt(row); - - db.close(); - QSqlDatabase::removeDatabase(db.connectionName()); - endRemoveRows(); -} -*/ -/*ComicDB TableModel::getComic(int row) -{ - return getComic(index(row,0)); -}*/ - -void ComicModel::remove(int row) -{ - removeInTransaction(row); -} - -void ComicModel::reload(const ComicDB & comic) -{ - int row = 0; - bool found = false; - foreach(ComicItem * item,_data) - { - if(item->data(ComicModel::Id).toULongLong() == comic.id) - { - found = true; - item->setData(ComicModel::ReadColumn,comic.info.read); - item->setData(ComicModel::CurrentPage,comic.info.currentPage); - item->setData(ComicModel::HasBeenOpened,true); - break; - - } - row++; - } - if(found) - emit dataChanged(index(row,ReadColumn),index(row,HasBeenOpened), QVector() << ReadColumnRole << CurrentPageRole << HasBeenOpenedRole); -} - -void ComicModel::resetComicRating(const QModelIndex &mi) -{ - ComicDB comic = getComic(mi); - - QSqlDatabase db = DataBaseManagement::loadDatabase(_databasePath); - - comic.info.rating = 0; - _data[mi.row()]->setData(ComicModel::Rating,0); - DBHelper::update(&(comic.info),db); - - emit dataChanged(mi,mi); - - db.close(); - QSqlDatabase::removeDatabase(db.connectionName()); -} - -QUrl ComicModel::getCoverUrlPathForComicHash(const QString &hash) const -{ - return QUrl("file:"+_databasePath+"/covers/"+hash+".jpg"); -} - -void ComicModel::addComicsToFavorites(const QList &comicIds) -{ - addComicsToFavorites(getIndexesFromIds(comicIds)); -} - -void ComicModel::addComicsToFavorites(const QList & comicsList) -{ - QList comics = getComics(comicsList); - - QSqlDatabase db = DataBaseManagement::loadDatabase(_databasePath); - - DBHelper::insertComicsInFavorites(comics,db); - - db.close(); - QSqlDatabase::removeDatabase(db.connectionName()); -} - -void ComicModel::addComicsToLabel(const QList &comicIds, qulonglong labelId) -{ - addComicsToLabel(getIndexesFromIds(comicIds),labelId); -} - -void ComicModel::addComicsToLabel(const QList &comicsList, qulonglong labelId) -{ - QList comics = getComics(comicsList); - - QSqlDatabase db = DataBaseManagement::loadDatabase(_databasePath); - - DBHelper::insertComicsInLabel(comics,labelId,db); - - db.close(); - QSqlDatabase::removeDatabase(db.connectionName()); -} - -void ComicModel::addComicsToReadingList(const QList &comicIds, qulonglong readingListId) -{ - addComicsToReadingList(getIndexesFromIds(comicIds),readingListId); -} - -void ComicModel::addComicsToReadingList(const QList &comicsList, qulonglong readingListId) -{ - QList comics = getComics(comicsList); - - QSqlDatabase db = DataBaseManagement::loadDatabase(_databasePath); - - DBHelper::insertComicsInReadingList(comics,readingListId,db); - - db.close(); - QSqlDatabase::removeDatabase(db.connectionName()); -} - -void ComicModel::deleteComicsFromFavorites(const QList &comicsList) -{ - QList comics = getComics(comicsList); - - QSqlDatabase db = DataBaseManagement::loadDatabase(_databasePath); - - DBHelper::deleteComicsFromFavorites(comics,db); - - db.close(); - QSqlDatabase::removeDatabase(db.connectionName()); - - if(mode == Favorites) - deleteComicsFromModel(comicsList); -} - -void ComicModel::deleteComicsFromLabel(const QList &comicsList, qulonglong labelId) -{ - QList comics = getComics(comicsList); - - QSqlDatabase db = DataBaseManagement::loadDatabase(_databasePath); - - DBHelper::deleteComicsFromLabel(comics,labelId,db); - - db.close(); - QSqlDatabase::removeDatabase(db.connectionName()); - - deleteComicsFromModel(comicsList); -} - -void ComicModel::deleteComicsFromReadingList(const QList &comicsList, qulonglong readingListId) -{ - QList comics = getComics(comicsList); - - QSqlDatabase db = DataBaseManagement::loadDatabase(_databasePath); - - DBHelper::deleteComicsFromReadingList(comics,readingListId,db); - - db.close(); - QSqlDatabase::removeDatabase(db.connectionName()); - - deleteComicsFromModel(comicsList); -} - -void ComicModel::deleteComicsFromModel(const QList &comicsList) -{ - QListIterator it(comicsList); - it.toBack(); - while(it.hasPrevious()) - { - int row = it.previous().row(); - beginRemoveRows(QModelIndex(),row,row); - _data.removeAt(row); - endRemoveRows(); - } - - if(_data.isEmpty()) - emit isEmpty(); -} - -bool ComicModel::isFavorite(const QModelIndex &index) -{ - bool isFavorite; - - QSqlDatabase db = DataBaseManagement::loadDatabase(_databasePath); - - isFavorite = DBHelper::isFavoriteComic(_data[index.row()]->data(Id).toLongLong(),db); - - db.close(); - QSqlDatabase::removeDatabase(db.connectionName()); - - return isFavorite; -} - -void ComicModel::updateRating(int rating, QModelIndex mi) -{ - ComicDB comic = getComic(mi); - - QSqlDatabase db = DataBaseManagement::loadDatabase(_databasePath); - //TODO optimize update - - comic.info.rating = rating; - _data[mi.row()]->setData(ComicModel::Rating,rating); - DBHelper::update(&(comic.info),db); - - emit dataChanged(mi,mi); - - db.close(); - QSqlDatabase::removeDatabase(db.connectionName()); -} + +#include +#include +#include + +#include "comic_item.h" +#include "comic_model.h" +#include "data_base_management.h" +#include "qnaturalsorting.h" +#include "comic_db.h" +#include "db_helper.h" + +//ci.number,ci.title,c.fileName,ci.numPages,c.id,c.parentId,c.path,ci.hash,ci.read +#include "QsLog.h" + + +ComicModel::ComicModel(QObject *parent) + : QAbstractItemModel(parent) +{ + connect(this,SIGNAL(beforeReset()),this,SIGNAL(modelAboutToBeReset())); + connect(this,SIGNAL(reset()),this,SIGNAL(modelReset())); +} + +ComicModel::ComicModel( QSqlQuery &sqlquery, QObject *parent) + : QAbstractItemModel(parent) +{ + setupModelData(sqlquery); +} + +ComicModel::~ComicModel() +{ + qDeleteAll(_data); +} + +int ComicModel::columnCount(const QModelIndex &parent) const +{ + Q_UNUSED(parent) + if(_data.isEmpty()) + return 0; + return _data.first()->columnCount(); +} + +bool ComicModel::canDropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent) const +{ + Q_UNUSED(action); + Q_UNUSED(row); + Q_UNUSED(column); + Q_UNUSED(parent); + + if(!enableResorting) + return false; + return data->formats().contains(YACReader::YACReaderLibrarComiscSelectionMimeDataFormat); +} + +//TODO: optimize this method (seriously) +bool ComicModel::dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent) +{ + + QAbstractItemModel::dropMimeData(data,action,row,column,parent); + QLOG_TRACE() << ">>>>>>>>>>>>>>dropMimeData ComicModel<<<<<<<<<<<<<<<<<"<< parent << row << "," << column; + + if(!data->formats().contains(YACReader::YACReaderLibrarComiscSelectionMimeDataFormat)) + return false; + + QList comicIds = YACReader::mimeDataToComicsIds(data); + QList currentIndexes; + int i; + foreach(qulonglong id, comicIds) + { + i = 0; + foreach (ComicItem *item, _data) { + if(item->data(Id)==id) + { + currentIndexes << i; + break; + } + i++; + } + } + + std::sort(currentIndexes.begin(), currentIndexes.end()); + QList resortedData; + + if(currentIndexes.contains(row))//no resorting + return false; + + ComicItem * destinationItem; + if(row == -1 || row >= _data.length()) + destinationItem = 0; + else + destinationItem = _data.at(row); + + QList newSorting; + + i = 0; + foreach (ComicItem *item, _data) { + if(!currentIndexes.contains(i)) + { + + if(item == destinationItem) { + foreach(int index, currentIndexes) + { + resortedData << _data.at(index); + newSorting << index; + } + } + + resortedData << item; + newSorting << i; + } + + i++; + } + + if(destinationItem == 0) + { + foreach(int index, currentIndexes) + { + resortedData << _data.at(index); + newSorting << index; + } + } + + QLOG_TRACE() << newSorting; + + int tempRow = row; + + if(tempRow < 0) + tempRow = _data.count(); + + foreach(qulonglong id, comicIds) + { + int i = 0; + foreach (ComicItem *item, _data) { + if(item->data(Id) == id) + { + beginMoveRows(parent,i,i,parent,tempRow); + + bool skipElement = i == tempRow || i + 1 == tempRow; + + if(!skipElement) + { + if(i > tempRow) + _data.move(i, tempRow); + else + _data.move(i, tempRow - 1); + } + + endMoveRows(); + + if(i > tempRow) + tempRow++; + + break; + } + i++; + } + } + + //TODO fix selection + QList allComicIds; + foreach (ComicItem *item, _data) { + allComicIds << item->data(Id).toULongLong(); + } + + QSqlDatabase db = DataBaseManagement::loadDatabase(_databasePath); + switch (mode) { + case Favorites: + DBHelper::reasignOrderToComicsInFavorites(allComicIds,db); + break; + case Label: + DBHelper::reasignOrderToComicsInLabel(sourceId,allComicIds,db); + break; + case ReadingList: + DBHelper::reasignOrderToComicsInReadingList(sourceId,allComicIds,db); + break; + } + + QSqlDatabase::removeDatabase(db.connectionName()); + + //endMoveRows(); + + emit resortedIndexes(newSorting); + int destSelectedIndex = row<0?_data.length():row; + + if(destSelectedIndex>currentIndexes.at(0)) + emit newSelectedIndex(index(qMax(0,destSelectedIndex-1),0,parent)); + else + emit newSelectedIndex(index(qMax(0,destSelectedIndex),0,parent)); + + return true; +} + +bool ComicModel::canBeResorted() +{ + return enableResorting; +} + +QMimeData *ComicModel::mimeData(const QModelIndexList &indexes) const +{ + //custom model data + //application/yacreader-comics-ids + list of ids in a QByteArray + QList ids; + foreach(QModelIndex index, indexes) + { + QLOG_DEBUG() << "dragging : " << index.data(IdRole).toULongLong(); + ids << index.data(IdRole).toULongLong(); + + } + + QByteArray data; + QDataStream out(&data,QIODevice::WriteOnly); + out << ids; //serialize the list of identifiers + + QMimeData * mimeData = new QMimeData(); + mimeData->setData(YACReader::YACReaderLibrarComiscSelectionMimeDataFormat, data); + + return mimeData; +} + +QStringList ComicModel::mimeTypes() const +{ + QLOG_DEBUG() << "mimeTypes"; + QStringList list; + list << YACReader::YACReaderLibrarComiscSelectionMimeDataFormat; + return list; +} + +QHash ComicModel::roleNames() const { + QHash roles; + + roles[NumberRole] = "number"; + roles[TitleRole] = "title"; + roles[FileNameRole] = "file_name"; + roles[NumPagesRole] = "num_pages"; + roles[IdRole] = "id"; + roles[Parent_IdRole] = "parent_id"; + roles[PathRole] = "path"; + roles[HashRole] = "hash"; + roles[ReadColumnRole] = "read_column"; + roles[IsBisRole] = "is_bis"; + roles[CurrentPageRole] = "current_page"; + roles[RatingRole] = "rating"; + roles[HasBeenOpenedRole] = "has_been_opened"; + roles[CoverPathRole] = "cover_path"; + + return roles; +} + +QVariant ComicModel::data(const QModelIndex &index, int role) const +{ + if (!index.isValid()) + return QVariant(); + + /*if (index.column() == TableModel::Rating && role == Qt::DecorationRole) + { + TableItem *item = static_cast(index.internalPointer()); + return QPixmap(QString(":/images/rating%1.png").arg(item->data(index.column()).toInt())); + }*/ + + if (role == Qt::DecorationRole) + { + return QVariant(); + } + + if (role == Qt::TextAlignmentRole) + { + switch(index.column())//TODO obtener esto de la query + { + case ComicModel::Number: + return QVariant(Qt::AlignRight | Qt::AlignVCenter); + case ComicModel::NumPages: + return QVariant(Qt::AlignRight | Qt::AlignVCenter); + case ComicModel::Hash: + return QVariant(Qt::AlignRight | Qt::AlignVCenter); + case ComicModel::CurrentPage: + return QVariant(Qt::AlignRight | Qt::AlignVCenter); + default: + return QVariant(Qt::AlignLeft | Qt::AlignVCenter); + } + } + + + //TODO check here if any view is asking for TableModel::Roles + //these roles will be used from QML/GridView + + ComicItem *item = static_cast(index.internalPointer()); + + if (role == NumberRole) + return item->data(Number); + else if (role == TitleRole) + return item->data(Title).isNull()?item->data(FileName):item->data(Title); + else if (role == FileNameRole) + return item->data(FileName); + else if (role == RatingRole) + return item->data(Rating); + else if (role == CoverPathRole) + return getCoverUrlPathForComicHash(item->data(Hash).toString()); + else if (role == NumPagesRole) + return item->data(NumPages); + else if (role == CurrentPageRole) + return item->data(CurrentPage); + else if (role == ReadColumnRole) + return item->data(ReadColumn).toBool(); + else if (role == HasBeenOpenedRole) + return item->data(ComicModel::HasBeenOpened); + else if (role == IdRole) + return item->data(Id); + + if (role != Qt::DisplayRole) + return QVariant(); + + if(index.column() == ComicModel::Hash) + return QString::number(item->data(index.column()).toString().right(item->data(index.column()).toString().length()-40).toInt()/1024.0/1024.0,'f',2)+"Mb"; + if(index.column() == ComicModel::ReadColumn) + return (item->data(ComicModel::CurrentPage).toInt()==item->data(ComicModel::NumPages).toInt() || item->data(ComicModel::ReadColumn).toBool())?QVariant(tr("yes")):QVariant(tr("no")); + if(index.column() == ComicModel::CurrentPage) + return item->data(ComicModel::HasBeenOpened).toBool()?item->data(index.column()):QVariant("-"); + + if (index.column() == ComicModel::Rating) + return QVariant(); + + return item->data(index.column()); +} + +Qt::ItemFlags ComicModel::flags(const QModelIndex &index) const +{ + if (!index.isValid()) + return 0; + if(index.column() == ComicModel::Rating) + return Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsEditable; + return Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsDragEnabled ; +} + +QVariant ComicModel::headerData(int section, Qt::Orientation orientation, + int role) const +{ + if (orientation == Qt::Horizontal && role == Qt::DisplayRole) + { + switch(section)//TODO obtener esto de la query + { + case ComicModel::Number: + return QVariant(QString("#")); + case ComicModel::Title: + return QVariant(QString(tr("Title"))); + case ComicModel::FileName: + return QVariant(QString(tr("File Name"))); + case ComicModel::NumPages: + return QVariant(QString(tr("Pages"))); + case ComicModel::Hash: + return QVariant(QString(tr("Size"))); + case ComicModel::ReadColumn: + return QVariant(QString(tr("Read"))); + case ComicModel::CurrentPage: + return QVariant(QString(tr("Current Page"))); + case ComicModel::Rating: + return QVariant(QString(tr("Rating"))); + } + } + + if (orientation == Qt::Horizontal && role == Qt::TextAlignmentRole) + { + switch(section)//TODO obtener esto de la query + { + case ComicModel::Number: + return QVariant(Qt::AlignRight | Qt::AlignVCenter); + case ComicModel::NumPages: + return QVariant(Qt::AlignRight | Qt::AlignVCenter); + case ComicModel::Hash: + return QVariant(Qt::AlignRight | Qt::AlignVCenter); + case ComicModel::CurrentPage: + return QVariant(Qt::AlignRight | Qt::AlignVCenter); + default: + return QVariant(Qt::AlignLeft | Qt::AlignVCenter); + } + } + + + if(orientation == Qt::Vertical && role == Qt::DecorationRole) + { + QString fileName = _data.value(section)->data(ComicModel::FileName).toString(); + QFileInfo fi(fileName); + QString ext = fi.suffix(); + + if (ext.compare("cbr",Qt::CaseInsensitive) == 0) + return QVariant(QIcon(":/images/comicRar.png")); + else if (ext.compare("cbz",Qt::CaseInsensitive) == 0) + return QVariant(QIcon(":/images/comicZip.png")); + else if(ext.compare("pdf",Qt::CaseInsensitive) == 0) + return QVariant(QIcon(":/images/pdf.png")); + else if (ext.compare("tar",Qt::CaseInsensitive) == 0) + return QVariant(QIcon(":/images/tar.png")); + else if(ext.compare("zip",Qt::CaseInsensitive) == 0) + return QVariant(QIcon(":/images/zip.png")); + else if(ext.compare("rar",Qt::CaseInsensitive) == 0) + return QVariant(QIcon(":/images/rar.png")); +#ifndef use_unarr + else if (ext.compare("7z",Qt::CaseInsensitive) == 0) + return QVariant(QIcon(":/images/7z.png")); + else if (ext.compare("cb7",Qt::CaseInsensitive) == 0) + return QVariant(QIcon(":/images/comic7z.png")); +#endif + else if (ext.compare("cbt",Qt::CaseInsensitive) == 0) + return QVariant(QIcon(":/images/comicTar.png")); + + } + + return QVariant(); +} + +QModelIndex ComicModel::index(int row, int column, const QModelIndex &parent) + const +{ + if (!hasIndex(row, column, parent)) + return QModelIndex(); + + return createIndex(row, column, _data.at(row)); +} + +QModelIndex ComicModel::parent(const QModelIndex &index) const +{ + Q_UNUSED(index) + return QModelIndex(); +} + +int ComicModel::rowCount(const QModelIndex &parent) const +{ + if (parent.column() > 0) + return 0; + + if (!parent.isValid()) + return _data.count(); + + return 0; +} + +QStringList ComicModel::getPaths(const QString & _source) +{ + QStringList paths; + QString source = _source + "/.yacreaderlibrary/covers/"; + QList::ConstIterator itr; + for(itr = _data.constBegin();itr != _data.constEnd();itr++) + { + QString hash = (*itr)->data(ComicModel::Hash).toString(); + paths << source+ hash +".jpg"; + } + + return paths; +} + +void ComicModel::setupFolderModelData(unsigned long long int folderId,const QString & databasePath) +{ + enableResorting = false; + mode = Folder; + sourceId=folderId; + + beginResetModel(); + qDeleteAll(_data); + _data.clear(); + + _databasePath = databasePath; + QSqlDatabase db = DataBaseManagement::loadDatabase(databasePath); + { + QSqlQuery selectQuery(db); + selectQuery.prepare("SELECT ci.number,ci.title,c.fileName,ci.numPages,c.id,c.parentId,c.path,ci.hash,ci.read,ci.isBis,ci.currentPage,ci.rating,ci.hasBeenOpened " + "FROM comic c INNER JOIN comic_info ci ON (c.comicInfoId = ci.id) " + "WHERE c.parentId = :parentId"); + selectQuery.bindValue(":parentId", folderId); + selectQuery.exec(); + setupModelData(selectQuery); + } + db.close(); + QSqlDatabase::removeDatabase(db.connectionName()); + endResetModel(); + + /*if(_data.length()==0) + emit isEmpty();*/ +} + +void ComicModel::setupLabelModelData(unsigned long long parentLabel, const QString &databasePath) +{ + enableResorting = true; + mode = Label; + sourceId = parentLabel; + + beginResetModel(); + qDeleteAll(_data); + _data.clear(); + + _databasePath = databasePath; + QSqlDatabase db = DataBaseManagement::loadDatabase(databasePath); + { + QSqlQuery selectQuery(db); + selectQuery.prepare("SELECT ci.number,ci.title,c.fileName,ci.numPages,c.id,c.parentId,c.path,ci.hash,ci.read,ci.isBis,ci.currentPage,ci.rating,ci.hasBeenOpened " + "FROM comic c INNER JOIN comic_info ci ON (c.comicInfoId = ci.id) " + "INNER JOIN comic_label cl ON (c.id == cl.comic_id) " + "WHERE cl.label_id = :parentLabelId " + "ORDER BY cl.ordering"); + selectQuery.bindValue(":parentLabelId", parentLabel); + selectQuery.exec(); + setupModelDataForList(selectQuery); + } + db.close(); + QSqlDatabase::removeDatabase(db.connectionName()); + endResetModel(); + + /*if(_data.length()==0) + emit isEmpty();*/ +} + +void ComicModel::setupReadingListModelData(unsigned long long parentReadingList, const QString &databasePath) +{ + mode = ReadingList; + sourceId = parentReadingList; + + beginResetModel(); + qDeleteAll(_data); + _data.clear(); + + _databasePath = databasePath; + QSqlDatabase db = DataBaseManagement::loadDatabase(databasePath); + { + QList ids; + ids << parentReadingList; + + QSqlQuery subfolders(db); + subfolders.prepare("SELECT id " + "FROM reading_list " + "WHERE parentId = :parentId " + "ORDER BY ordering ASC"); + subfolders.bindValue(":parentId", parentReadingList); + subfolders.exec(); + while(subfolders.next()) + ids << subfolders.record().value(0).toULongLong(); + + enableResorting = ids.length()==1;//only resorting if no sublists exist + + + foreach(qulonglong id, ids) + { + QSqlQuery selectQuery(db); + selectQuery.prepare("SELECT ci.number,ci.title,c.fileName,ci.numPages,c.id,c.parentId,c.path,ci.hash,ci.read,ci.isBis,ci.currentPage,ci.rating,ci.hasBeenOpened " + "FROM comic c INNER JOIN comic_info ci ON (c.comicInfoId = ci.id) " + "INNER JOIN comic_reading_list crl ON (c.id == crl.comic_id) " + "WHERE crl.reading_list_id = :parentReadingList " + "ORDER BY crl.ordering"); + selectQuery.bindValue(":parentReadingList", id); + selectQuery.exec(); + + //TODO, extra information is needed (resorting) + QList tempData = _data; + _data.clear(); + + setupModelDataForList(selectQuery); + + _data = tempData << _data; + } + + } + db.close(); + QSqlDatabase::removeDatabase(db.connectionName()); + endResetModel(); +} + +void ComicModel::setupFavoritesModelData(const QString &databasePath) +{ + enableResorting = true; + mode = Favorites; + + beginResetModel(); + qDeleteAll(_data); + _data.clear(); + + _databasePath = databasePath; + QSqlDatabase db = DataBaseManagement::loadDatabase(databasePath); + { + QSqlQuery selectQuery(db); + selectQuery.prepare("SELECT ci.number,ci.title,c.fileName,ci.numPages,c.id,c.parentId,c.path,ci.hash,ci.read,ci.isBis,ci.currentPage,ci.rating,ci.hasBeenOpened " + "FROM comic c INNER JOIN comic_info ci ON (c.comicInfoId = ci.id) " + "INNER JOIN comic_default_reading_list cdrl ON (c.id == cdrl.comic_id) " + "WHERE cdrl.default_reading_list_id = :parentDefaultListId " + "ORDER BY cdrl.ordering"); + selectQuery.bindValue(":parentDefaultListId", 1); + selectQuery.exec(); + setupModelDataForList(selectQuery); + } + db.close(); + QSqlDatabase::removeDatabase(db.connectionName()); + endResetModel(); + + /*if(_data.length()==0) + emit isEmpty();*/ +} + +void ComicModel::setupReadingModelData(const QString &databasePath) +{ + enableResorting = false; + mode = Reading; + + beginResetModel(); + qDeleteAll(_data); + _data.clear(); + + _databasePath = databasePath; + QSqlDatabase db = DataBaseManagement::loadDatabase(databasePath); + { + QSqlQuery selectQuery(db); + selectQuery.prepare("SELECT ci.number,ci.title,c.fileName,ci.numPages,c.id,c.parentId,c.path,ci.hash,ci.read,ci.isBis,ci.currentPage,ci.rating,ci.hasBeenOpened " + "FROM comic c INNER JOIN comic_info ci ON (c.comicInfoId = ci.id) " + "WHERE ci.hasBeenOpened = 1 AND ci.read = 0 " + "ORDER BY ci.lastTimeOpened DESC"); + selectQuery.exec(); + + setupModelDataForList(selectQuery); + } + db.close(); + QSqlDatabase::removeDatabase(db.connectionName()); + endResetModel(); + + /*if(_data.length()==0) + emit isEmpty();*/ +} + +void ComicModel::setupModelData(const SearchModifiers modifier, const QString &filter, const QString &databasePath) +{ + //QFile f(QCoreApplication::applicationDirPath()+"/performance.txt"); + //f.open(QIODevice::Append); + beginResetModel(); + //QElapsedTimer timer; + //timer.start(); + qDeleteAll(_data); + _data.clear(); + + //QTextStream txtS(&f); + //txtS << "TABLEMODEL: Tiempo de borrado: " << timer.elapsed() << "ms\r\n"; + _databasePath = databasePath; + QSqlDatabase db = DataBaseManagement::loadDatabase(databasePath); + { + //crear la consulta + //timer.restart(); + QSqlQuery selectQuery(db); + + switch (modifier) { + case YACReader::NoModifiers: + selectQuery.prepare("SELECT ci.number,ci.title,c.fileName,ci.numPages,c.id,c.parentId,c.path,ci.hash,ci.read,ci.isBis,ci.currentPage,ci.rating,ci.hasBeenOpened " + "FROM comic c INNER JOIN comic_info ci ON (c.comicInfoId = ci.id) " + "WHERE UPPER(ci.title) LIKE UPPER(:filter) OR UPPER(c.fileName) LIKE UPPER(:filter) LIMIT :limit"); + selectQuery.bindValue(":filter", "%%"+filter+"%%"); + selectQuery.bindValue(":limit",500); //TODO, load this value from settings + break; + + case YACReader::OnlyRead: + selectQuery.prepare("SELECT ci.number,ci.title,c.fileName,ci.numPages,c.id,c.parentId,c.path,ci.hash,ci.read,ci.isBis,ci.currentPage,ci.rating,ci.hasBeenOpened " + "FROM comic c INNER JOIN comic_info ci ON (c.comicInfoId = ci.id) " + "WHERE (UPPER(ci.title) LIKE UPPER(:filter) OR UPPER(c.fileName) LIKE UPPER(:filter)) AND ci.read = 1 LIMIT :limit"); + selectQuery.bindValue(":filter", "%%"+filter+"%%"); + selectQuery.bindValue(":limit",500); //TODO, load this value from settings + break; + + case YACReader::OnlyUnread: + selectQuery.prepare("SELECT ci.number,ci.title,c.fileName,ci.numPages,c.id,c.parentId,c.path,ci.hash,ci.read,ci.isBis,ci.currentPage,ci.rating,ci.hasBeenOpened " + "FROM comic c INNER JOIN comic_info ci ON (c.comicInfoId = ci.id) " + "WHERE (UPPER(ci.title) LIKE UPPER(:filter) OR UPPER(c.fileName) LIKE UPPER(:filter)) AND ci.read = 0 LIMIT :limit"); + selectQuery.bindValue(":filter", "%%"+filter+"%%"); + selectQuery.bindValue(":limit",500); //TODO, load this value from settings + break; + + default: + QLOG_ERROR() << "not implemented"; + break; + } + + + selectQuery.exec(); + + QLOG_DEBUG() << selectQuery.lastError() << "--"; + + //txtS << "TABLEMODEL: Tiempo de consulta: " << timer.elapsed() << "ms\r\n"; + //timer.restart(); + setupModelData(selectQuery); + //txtS << "TABLEMODEL: Tiempo de creaci�n del modelo: " << timer.elapsed() << "ms\r\n"; + //selectQuery.finish(); + } + db.close(); + QSqlDatabase::removeDatabase(db.connectionName()); + endResetModel(); + + emit searchNumResults(_data.length()); +} + +QString ComicModel::getComicPath(QModelIndex mi) +{ + if(mi.isValid()) + return _data.at(mi.row())->data(ComicModel::Path).toString(); + return ""; +} + +void ComicModel::setupModelData(QSqlQuery &sqlquery) +{ + int numColumns = sqlquery.record().count(); + + while (sqlquery.next()) + { + QList data; + + for(int i=0;idata(ComicModel::Number).isNull() && c2->data(ComicModel::Number).isNull()) + { + return naturalSortLessThanCI(c1->data(ComicModel::FileName).toString(), c2->data(ComicModel::FileName).toString()); + } + else + { + if (c1->data(ComicModel::Number).isNull() == false && c2->data(ComicModel::Number).isNull() == false) + { + return c1->data(ComicModel::Number).toInt() < c2->data(ComicModel::Number).toInt(); + } + else + { + return c2->data(ComicModel::Number).isNull(); + } + } + }); +} + +//comics are sorted by "ordering", the sorting is done in the sql query +void ComicModel::setupModelDataForList(QSqlQuery &sqlquery) +{ + int numColumns = sqlquery.record().count(); + + while (sqlquery.next()) + { + QList data; + for(int i=0;idata(ComicModel::Id).toULongLong(),db); + db.close(); + QSqlDatabase::removeDatabase(db.connectionName()); + + return c; +} + +ComicDB ComicModel::_getComic(const QModelIndex & mi) +{ + QSqlDatabase db = DataBaseManagement::loadDatabase(_databasePath); + ComicDB c = DBHelper::loadComic(_data.at(mi.row())->data(ComicModel::Id).toULongLong(),db); + db.close(); + QSqlDatabase::removeDatabase(db.connectionName()); + + return c; +} + + +QVector ComicModel::getReadList() +{ + int numComics = _data.count(); + QVector readList(numComics); + for(int i=0;idata(ComicModel::ReadColumn).toBool()) + readList[i] = YACReader::Read; + else if (_data.value(i)->data(ComicModel::CurrentPage).toInt() == _data.value(i)->data(ComicModel::NumPages).toInt()) + readList[i] = YACReader::Read; + else if (_data.value(i)->data(ComicModel::HasBeenOpened).toBool()) + readList[i] = YACReader::Opened; + else + readList[i] = YACReader::Unread; + } + return readList; +} +//TODO untested, this method is no longer used +QVector ComicModel::setAllComicsRead(YACReaderComicReadStatus read) +{ + return setComicsRead(persistentIndexList(),read); +} + +QList ComicModel::getAllComics() +{ + QSqlDatabase db = DataBaseManagement::loadDatabase(_databasePath); + db.transaction(); + + QList comics; + int numComics = _data.count(); + for(int i=0;idata(ComicModel::Id).toULongLong(),db)); + } + + db.commit(); + db.close(); + QSqlDatabase::removeDatabase(db.connectionName()); + + return comics; +} + +QList ComicModel::getComics(QList list) +{ + QList comics; + + QSqlDatabase db = DataBaseManagement::loadDatabase(_databasePath); + db.transaction(); + QList::const_iterator itr; + for(itr = list.constBegin(); itr!= list.constEnd();itr++) + { + comics.append(_getComic(*itr)); + } + db.commit(); + db.close(); + QSqlDatabase::removeDatabase(db.connectionName()); + return comics; +} +//TODO +QVector ComicModel::setComicsRead(QList list,YACReaderComicReadStatus read) +{ + QSqlDatabase db = DataBaseManagement::loadDatabase(_databasePath); + db.transaction(); + 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); + c.info.read = true; + DBHelper::update(&(c.info),db); + } + if(read == YACReader::Unread) + { + _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); + c.info.read = false; + c.info.currentPage = 1; + c.info.hasBeenOpened = false; + DBHelper::update(&(c.info),db); + } + } + db.commit(); + db.close(); + QSqlDatabase::removeDatabase(db.connectionName()); + + emit dataChanged(index(list.first().row(),ComicModel::ReadColumn),index(list.last().row(),ComicModel::HasBeenOpened),QVector() << ReadColumnRole << CurrentPageRole << HasBeenOpenedRole); + + return getReadList(); +} +qint64 ComicModel::asignNumbers(QList list,int startingNumber) +{ + QSqlDatabase db = DataBaseManagement::loadDatabase(_databasePath); + db.transaction(); + qint64 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); + c.info.number = startingNumber+i; + c.info.edited = true; + DBHelper::update(&(c.info),db); + i++; + } + + db.commit(); + db.close(); + QSqlDatabase::removeDatabase(db.connectionName()); + + //emit dataChanged(index(0,ComicModel::Number),index(_data.count()-1,ComicModel::HasBeenOpened)); + + return idFirst; +} +QModelIndex ComicModel::getIndexFromId(quint64 id) +{ + QList::ConstIterator itr; + int i=0; + for(itr = _data.constBegin();itr != _data.constEnd();itr++) + { + if((*itr)->data(ComicModel::Id).toULongLong() == id) + break; + i++; + } + + return index(i,0); +} + +//TODO completely inefficiently +QList ComicModel::getIndexesFromIds(const QList &comicIds) +{ + QList comicsIndexes; + + foreach(qulonglong id,comicIds) + comicsIndexes << getIndexFromId(id); + + return comicsIndexes; +} + +void ComicModel::startTransaction() +{ + dbTransaction = DataBaseManagement::loadDatabase(_databasePath); + dbTransaction.transaction(); +} + +void ComicModel::finishTransaction() +{ + dbTransaction.commit(); + dbTransaction.close(); + QSqlDatabase::removeDatabase(dbTransaction.connectionName()); +} + +void ComicModel::removeInTransaction(int row) +{ + ComicDB c = DBHelper::loadComic(_data.at(row)->data(ComicModel::Id).toULongLong(),dbTransaction); + + DBHelper::removeFromDB(&c,dbTransaction); + beginRemoveRows(QModelIndex(),row,row); + removeRow(row); + delete _data.at(row); + _data.removeAt(row); + + endRemoveRows(); +} +/* +void ComicModel::remove(ComicDB * comic, int row) +{ + beginRemoveRows(QModelIndex(),row,row); + QSqlDatabase db = DataBaseManagement::loadDatabase(_databasePath); + + DBHelper::removeFromDB(comic,db); + + removeRow(row); + delete _data.at(row); + _data.removeAt(row); + + db.close(); + QSqlDatabase::removeDatabase(db.connectionName()); + endRemoveRows(); +} +*/ +/*ComicDB TableModel::getComic(int row) +{ + return getComic(index(row,0)); +}*/ + +void ComicModel::remove(int row) +{ + removeInTransaction(row); +} + +void ComicModel::reload(const ComicDB & comic) +{ + int row = 0; + bool found = false; + foreach(ComicItem * item,_data) + { + if(item->data(ComicModel::Id).toULongLong() == comic.id) + { + found = true; + item->setData(ComicModel::ReadColumn,comic.info.read); + item->setData(ComicModel::CurrentPage,comic.info.currentPage); + item->setData(ComicModel::HasBeenOpened,true); + break; + + } + row++; + } + if(found) + emit dataChanged(index(row,ReadColumn),index(row,HasBeenOpened), QVector() << ReadColumnRole << CurrentPageRole << HasBeenOpenedRole); +} + +void ComicModel::resetComicRating(const QModelIndex &mi) +{ + ComicDB comic = getComic(mi); + + QSqlDatabase db = DataBaseManagement::loadDatabase(_databasePath); + + comic.info.rating = 0; + _data[mi.row()]->setData(ComicModel::Rating,0); + DBHelper::update(&(comic.info),db); + + emit dataChanged(mi,mi); + + db.close(); + QSqlDatabase::removeDatabase(db.connectionName()); +} + +QUrl ComicModel::getCoverUrlPathForComicHash(const QString &hash) const +{ + return QUrl("file:"+_databasePath+"/covers/"+hash+".jpg"); +} + +void ComicModel::addComicsToFavorites(const QList &comicIds) +{ + addComicsToFavorites(getIndexesFromIds(comicIds)); +} + +void ComicModel::addComicsToFavorites(const QList & comicsList) +{ + QList comics = getComics(comicsList); + + QSqlDatabase db = DataBaseManagement::loadDatabase(_databasePath); + + DBHelper::insertComicsInFavorites(comics,db); + + db.close(); + QSqlDatabase::removeDatabase(db.connectionName()); +} + +void ComicModel::addComicsToLabel(const QList &comicIds, qulonglong labelId) +{ + addComicsToLabel(getIndexesFromIds(comicIds),labelId); +} + +void ComicModel::addComicsToLabel(const QList &comicsList, qulonglong labelId) +{ + QList comics = getComics(comicsList); + + QSqlDatabase db = DataBaseManagement::loadDatabase(_databasePath); + + DBHelper::insertComicsInLabel(comics,labelId,db); + + db.close(); + QSqlDatabase::removeDatabase(db.connectionName()); +} + +void ComicModel::addComicsToReadingList(const QList &comicIds, qulonglong readingListId) +{ + addComicsToReadingList(getIndexesFromIds(comicIds),readingListId); +} + +void ComicModel::addComicsToReadingList(const QList &comicsList, qulonglong readingListId) +{ + QList comics = getComics(comicsList); + + QSqlDatabase db = DataBaseManagement::loadDatabase(_databasePath); + + DBHelper::insertComicsInReadingList(comics,readingListId,db); + + db.close(); + QSqlDatabase::removeDatabase(db.connectionName()); +} + +void ComicModel::deleteComicsFromFavorites(const QList &comicsList) +{ + QList comics = getComics(comicsList); + + QSqlDatabase db = DataBaseManagement::loadDatabase(_databasePath); + + DBHelper::deleteComicsFromFavorites(comics,db); + + db.close(); + QSqlDatabase::removeDatabase(db.connectionName()); + + if(mode == Favorites) + deleteComicsFromModel(comicsList); +} + +void ComicModel::deleteComicsFromLabel(const QList &comicsList, qulonglong labelId) +{ + QList comics = getComics(comicsList); + + QSqlDatabase db = DataBaseManagement::loadDatabase(_databasePath); + + DBHelper::deleteComicsFromLabel(comics,labelId,db); + + db.close(); + QSqlDatabase::removeDatabase(db.connectionName()); + + deleteComicsFromModel(comicsList); +} + +void ComicModel::deleteComicsFromReadingList(const QList &comicsList, qulonglong readingListId) +{ + QList comics = getComics(comicsList); + + QSqlDatabase db = DataBaseManagement::loadDatabase(_databasePath); + + DBHelper::deleteComicsFromReadingList(comics,readingListId,db); + + db.close(); + QSqlDatabase::removeDatabase(db.connectionName()); + + deleteComicsFromModel(comicsList); +} + +void ComicModel::deleteComicsFromModel(const QList &comicsList) +{ + QListIterator it(comicsList); + it.toBack(); + while(it.hasPrevious()) + { + int row = it.previous().row(); + beginRemoveRows(QModelIndex(),row,row); + _data.removeAt(row); + endRemoveRows(); + } + + if(_data.isEmpty()) + emit isEmpty(); +} + +bool ComicModel::isFavorite(const QModelIndex &index) +{ + bool isFavorite; + + QSqlDatabase db = DataBaseManagement::loadDatabase(_databasePath); + + isFavorite = DBHelper::isFavoriteComic(_data[index.row()]->data(Id).toLongLong(),db); + + db.close(); + QSqlDatabase::removeDatabase(db.connectionName()); + + return isFavorite; +} + +void ComicModel::updateRating(int rating, QModelIndex mi) +{ + ComicDB comic = getComic(mi); + + QSqlDatabase db = DataBaseManagement::loadDatabase(_databasePath); + //TODO optimize update + + comic.info.rating = rating; + _data[mi.row()]->setData(ComicModel::Rating,rating); + DBHelper::update(&(comic.info),db); + + emit dataChanged(mi,mi); + + db.close(); + QSqlDatabase::removeDatabase(db.connectionName()); +} diff --git a/YACReaderLibrary/db/comic_model.h b/YACReaderLibrary/db/comic_model.h index 7e33f51a..8aaa9ed4 100644 --- a/YACReaderLibrary/db/comic_model.h +++ b/YACReaderLibrary/db/comic_model.h @@ -1,173 +1,173 @@ -#ifndef TABLEMODEL_H -#define TABLEMODEL_H - -#include -#include -#include -#include -#include -#include - -#include "yacreader_global_gui.h" - -class ComicDB; - -class ComicItem; - -using namespace YACReader; - -//! [0] -class ComicModel : public QAbstractItemModel -{ - Q_OBJECT - -public: - enum Columns { - Number = 0, - Title = 1, - FileName = 2, - NumPages = 3, - Id = 4, - Parent_Id = 5, - Path = 6, - Hash = 7, - ReadColumn = 8, - IsBis = 9, - CurrentPage = 10, - Rating = 11, - HasBeenOpened = 12 - }; - - enum Roles { - NumberRole = Qt::UserRole + 1, - TitleRole, - FileNameRole, - NumPagesRole, - IdRole, - Parent_IdRole, - PathRole, - HashRole, - ReadColumnRole, - IsBisRole, - CurrentPageRole, - RatingRole, - HasBeenOpenedRole, - CoverPathRole - - }; - - enum Mode { - Folder, - Favorites, - Reading, - Label, - ReadingList - }; - - -public: - ComicModel(QObject *parent = 0); - ComicModel( QSqlQuery &sqlquery, QObject *parent = 0); - ~ComicModel(); - - QVariant data(const QModelIndex &index, int role) const; - Qt::ItemFlags flags(const QModelIndex &index) const; - QVariant headerData(int section, Qt::Orientation orientation, - int role = Qt::DisplayRole) const; - QModelIndex index(int row, int column, - const QModelIndex &parent = QModelIndex()) const; - QModelIndex parent(const QModelIndex &index) const; - int rowCount(const QModelIndex &parent = QModelIndex()) const; - int columnCount(const QModelIndex &parent = QModelIndex()) const; - bool canDropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent) const; - bool dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent); - bool canBeResorted(); - QMimeData * mimeData(const QModelIndexList &indexes) const; - QStringList mimeTypes() const; - - void setupFolderModelData(unsigned long long int parentFolder,const QString & databasePath); - void setupLabelModelData(unsigned long long int parentLabel, const QString & databasePath); - void setupReadingListModelData(unsigned long long int parentReadingList, const QString & databasePath); - void setupFavoritesModelData(const QString & databasePath); - void setupReadingModelData(const QString & databasePath); - //configures the model for showing the comics matching the filter criteria. - void setupModelData(const SearchModifiers modifier, const QString & filter, const QString & databasePath); - - //Métodos de conveniencia - QStringList getPaths(const QString & _source); - QString getComicPath(QModelIndex mi); - QString getCurrentPath(){return QString(_databasePath).remove("/.yacreaderlibrary");} - ComicDB getComic(const QModelIndex & mi); //--> para la edición - //ComicDB getComic(int row); - QVector getReadList(); - QVector setAllComicsRead(YACReaderComicReadStatus readStatus); - QList getComics(QList list); //--> recupera la información común a los comics seleccionados - QList getAllComics(); - QModelIndex getIndexFromId(quint64 id); - QList getIndexesFromIds(const QList &comicIds); - //setcomicInfo(QModelIndex & mi); --> inserta en la base datos - //setComicInfoForAllComics(); --> inserta la información común a todos los cómics de una sola vez. - //setComicInfoForSelectedComis(QList list); -->inserta la información común para los comics seleccionados - QVector setComicsRead(QList list,YACReaderComicReadStatus read); - qint64 asignNumbers(QList list,int startingNumber); - //void remove(ComicDB * comic, int row); - void removeInTransaction(int row); - void reload(const ComicDB & comic); - void resetComicRating(const QModelIndex & mi); - - Q_INVOKABLE QUrl getCoverUrlPathForComicHash(const QString& hash) const; - - - void addComicsToFavorites(const QList &comicsList); - void addComicsToLabel(const QList &comicsList, qulonglong labelId); - void addComicsToReadingList(const QList &comicsList, qulonglong readingListId); - - void deleteComicsFromFavorites(const QList &comicsList); - void deleteComicsFromLabel(const QList &comicsList, qulonglong labelId); - void deleteComicsFromReadingList(const QList &comicsList, qulonglong readingListId); - - void deleteComicsFromModel(const QList &comicsList); - - bool isFavorite(const QModelIndex &index); - - ComicModel::Mode getMode() {return mode;} - - QHash roleNames() const; - -public slots: - void remove(int row); - void startTransaction(); - void finishTransaction(); - void updateRating(int rating, QModelIndex mi); - - void addComicsToFavorites(const QList &comicIds); - void addComicsToLabel(const QList &comicIds, qulonglong labelId); - void addComicsToReadingList(const QList &comicIds, qulonglong readingListId); - -protected: - -private: - void setupModelData( QSqlQuery &sqlquery); - void setupModelDataForList(QSqlQuery &sqlquery); - ComicDB _getComic(const QModelIndex & mi); - QList _data; - - QString _databasePath; - - QSqlDatabase dbTransaction; - - bool enableResorting; - Mode mode; - qulonglong sourceId; - -signals: - void beforeReset(); - void reset(); - void isEmpty(); - void searchNumResults(int); - void resortedIndexes(QList); - void newSelectedIndex(const QModelIndex &); -}; -//! [0] - -#endif +#ifndef TABLEMODEL_H +#define TABLEMODEL_H + +#include +#include +#include +#include +#include +#include + +#include "yacreader_global_gui.h" + +class ComicDB; + +class ComicItem; + +using namespace YACReader; + +//! [0] +class ComicModel : public QAbstractItemModel +{ + Q_OBJECT + +public: + enum Columns { + Number = 0, + Title = 1, + FileName = 2, + NumPages = 3, + Id = 4, + Parent_Id = 5, + Path = 6, + Hash = 7, + ReadColumn = 8, + IsBis = 9, + CurrentPage = 10, + Rating = 11, + HasBeenOpened = 12 + }; + + enum Roles { + NumberRole = Qt::UserRole + 1, + TitleRole, + FileNameRole, + NumPagesRole, + IdRole, + Parent_IdRole, + PathRole, + HashRole, + ReadColumnRole, + IsBisRole, + CurrentPageRole, + RatingRole, + HasBeenOpenedRole, + CoverPathRole + + }; + + enum Mode { + Folder, + Favorites, + Reading, + Label, + ReadingList + }; + + +public: + ComicModel(QObject *parent = 0); + ComicModel( QSqlQuery &sqlquery, QObject *parent = 0); + ~ComicModel(); + + QVariant data(const QModelIndex &index, int role) const; + Qt::ItemFlags flags(const QModelIndex &index) const; + QVariant headerData(int section, Qt::Orientation orientation, + int role = Qt::DisplayRole) const; + QModelIndex index(int row, int column, + const QModelIndex &parent = QModelIndex()) const; + QModelIndex parent(const QModelIndex &index) const; + int rowCount(const QModelIndex &parent = QModelIndex()) const; + int columnCount(const QModelIndex &parent = QModelIndex()) const; + bool canDropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent) const; + bool dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent); + bool canBeResorted(); + QMimeData * mimeData(const QModelIndexList &indexes) const; + QStringList mimeTypes() const; + + void setupFolderModelData(unsigned long long int parentFolder,const QString & databasePath); + void setupLabelModelData(unsigned long long int parentLabel, const QString & databasePath); + void setupReadingListModelData(unsigned long long int parentReadingList, const QString & databasePath); + void setupFavoritesModelData(const QString & databasePath); + void setupReadingModelData(const QString & databasePath); + //configures the model for showing the comics matching the filter criteria. + void setupModelData(const SearchModifiers modifier, const QString & filter, const QString & databasePath); + + //Métodos de conveniencia + QStringList getPaths(const QString & _source); + QString getComicPath(QModelIndex mi); + QString getCurrentPath(){return QString(_databasePath).remove("/.yacreaderlibrary");} + ComicDB getComic(const QModelIndex & mi); //--> para la edición + //ComicDB getComic(int row); + QVector getReadList(); + QVector setAllComicsRead(YACReaderComicReadStatus readStatus); + QList getComics(QList list); //--> recupera la información común a los comics seleccionados + QList getAllComics(); + QModelIndex getIndexFromId(quint64 id); + QList getIndexesFromIds(const QList &comicIds); + //setcomicInfo(QModelIndex & mi); --> inserta en la base datos + //setComicInfoForAllComics(); --> inserta la información común a todos los cómics de una sola vez. + //setComicInfoForSelectedComis(QList list); -->inserta la información común para los comics seleccionados + QVector setComicsRead(QList list,YACReaderComicReadStatus read); + qint64 asignNumbers(QList list,int startingNumber); + //void remove(ComicDB * comic, int row); + void removeInTransaction(int row); + void reload(const ComicDB & comic); + void resetComicRating(const QModelIndex & mi); + + Q_INVOKABLE QUrl getCoverUrlPathForComicHash(const QString& hash) const; + + + void addComicsToFavorites(const QList &comicsList); + void addComicsToLabel(const QList &comicsList, qulonglong labelId); + void addComicsToReadingList(const QList &comicsList, qulonglong readingListId); + + void deleteComicsFromFavorites(const QList &comicsList); + void deleteComicsFromLabel(const QList &comicsList, qulonglong labelId); + void deleteComicsFromReadingList(const QList &comicsList, qulonglong readingListId); + + void deleteComicsFromModel(const QList &comicsList); + + bool isFavorite(const QModelIndex &index); + + ComicModel::Mode getMode() {return mode;} + + QHash roleNames() const; + +public slots: + void remove(int row); + void startTransaction(); + void finishTransaction(); + void updateRating(int rating, QModelIndex mi); + + void addComicsToFavorites(const QList &comicIds); + void addComicsToLabel(const QList &comicIds, qulonglong labelId); + void addComicsToReadingList(const QList &comicIds, qulonglong readingListId); + +protected: + +private: + void setupModelData( QSqlQuery &sqlquery); + void setupModelDataForList(QSqlQuery &sqlquery); + ComicDB _getComic(const QModelIndex & mi); + QList _data; + + QString _databasePath; + + QSqlDatabase dbTransaction; + + bool enableResorting; + Mode mode; + qulonglong sourceId; + +signals: + void beforeReset(); + void reset(); + void isEmpty(); + void searchNumResults(int); + void resortedIndexes(QList); + void newSelectedIndex(const QModelIndex &); +}; +//! [0] + +#endif diff --git a/YACReaderLibrary/db/data_base_management.cpp b/YACReaderLibrary/db/data_base_management.cpp index c79b7cde..c0694406 100644 --- a/YACReaderLibrary/db/data_base_management.cpp +++ b/YACReaderLibrary/db/data_base_management.cpp @@ -1,909 +1,909 @@ -#include "data_base_management.h" - -#include -#include "library_creator.h" -#include "check_new_version.h" -#include "db_helper.h" - -#include "QsLog.h" - -static QString fields = "title ," - - "coverPage," - "numPages," - - "number," - "isBis," - "count," - - "volume," - "storyArc," - "arcNumber," - "arcCount," - - "genere," - - "writer," - "penciller," - "inker," - "colorist," - "letterer," - "coverArtist," - - "date," - "publisher," - "format," - "color," - "ageRating," - - "synopsis," - "characters," - "notes," - - "comicVineID," - - "hash" - ; - -DataBaseManagement::DataBaseManagement() - :QObject(),dataBasesList() -{ - -} - -/*TreeModel * DataBaseManagement::newTreeModel(QString path) -{ - //la consulta se ejecuta... - QSqlQuery selectQuery(loadDatabase(path)); - selectQuery.setForwardOnly(true); - selectQuery.exec("select * from folder order by parentId,name"); - //selectQuery.finish(); - return new TreeModel(selectQuery); -}*/ - -QSqlDatabase DataBaseManagement::createDatabase(QString name, QString path) -{ - return createDatabase(QDir::cleanPath(path) + "/" + name + ".ydb"); -} - -QSqlDatabase DataBaseManagement::createDatabase(QString dest) +#include "data_base_management.h" + +#include +#include "library_creator.h" +#include "check_new_version.h" +#include "db_helper.h" + +#include "QsLog.h" + +static QString fields = "title ," + + "coverPage," + "numPages," + + "number," + "isBis," + "count," + + "volume," + "storyArc," + "arcNumber," + "arcCount," + + "genere," + + "writer," + "penciller," + "inker," + "colorist," + "letterer," + "coverArtist," + + "date," + "publisher," + "format," + "color," + "ageRating," + + "synopsis," + "characters," + "notes," + + "comicVineID," + + "hash" + ; + +DataBaseManagement::DataBaseManagement() + :QObject(),dataBasesList() +{ + +} + +/*TreeModel * DataBaseManagement::newTreeModel(QString path) +{ + //la consulta se ejecuta... + QSqlQuery selectQuery(loadDatabase(path)); + selectQuery.setForwardOnly(true); + selectQuery.exec("select * from folder order by parentId,name"); + //selectQuery.finish(); + return new TreeModel(selectQuery); +}*/ + +QSqlDatabase DataBaseManagement::createDatabase(QString name, QString path) +{ + return createDatabase(QDir::cleanPath(path) + "/" + name + ".ydb"); +} + +QSqlDatabase DataBaseManagement::createDatabase(QString dest) +{ + QString threadId = QString::number((long long)QThread::currentThreadId(), 16); + QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE",dest+threadId); + db.setDatabaseName(dest); + if (!db.open()) + qDebug() << db.lastError(); + else { + qDebug() << db.tables(); + } + + { + QSqlQuery pragma("PRAGMA foreign_keys = ON",db); + //pragma.finish(); + DataBaseManagement::createTables(db); + + QSqlQuery query("INSERT INTO folder (parentId, name, path) " + "VALUES (1,'root', '/')",db); + } + //query.finish(); + //db.close(); + + return db; +} + +QSqlDatabase DataBaseManagement::loadDatabase(QString path) { - QString threadId = QString::number((long long)QThread::currentThreadId(), 16); - QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE",dest+threadId); - db.setDatabaseName(dest); - if (!db.open()) - qDebug() << db.lastError(); - else { - qDebug() << db.tables(); - } - - { - QSqlQuery pragma("PRAGMA foreign_keys = ON",db); - //pragma.finish(); - DataBaseManagement::createTables(db); - - QSqlQuery query("INSERT INTO folder (parentId, name, path) " - "VALUES (1,'root', '/')",db); - } - //query.finish(); - //db.close(); - - return db; -} - -QSqlDatabase DataBaseManagement::loadDatabase(QString path) -{ //TODO check path - QString threadId = QString::number((long long)QThread::currentThreadId(), 16); + QString threadId = QString::number((long long)QThread::currentThreadId(), 16); QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE",path+threadId); - db.setDatabaseName(path + "/library.ydb"); - if (!db.open()) { - //se devuelve una base de datos vacía e inválida - - return QSqlDatabase(); - } - QSqlQuery pragma("PRAGMA foreign_keys = ON",db); - //pragma.finish(); - //devuelve la base de datos - return db; -} - -QSqlDatabase DataBaseManagement::loadDatabaseFromFile(QString filePath) -{ + db.setDatabaseName(path + "/library.ydb"); + if (!db.open()) { + //se devuelve una base de datos vacía e inválida + + return QSqlDatabase(); + } + QSqlQuery pragma("PRAGMA foreign_keys = ON",db); + //pragma.finish(); + //devuelve la base de datos + return db; +} + +QSqlDatabase DataBaseManagement::loadDatabaseFromFile(QString filePath) +{ //TODO check path - QString threadId = QString::number((long long)QThread::currentThreadId(), 16); - QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE",filePath+threadId); - db.setDatabaseName(filePath); - if (!db.open()) { - //se devuelve una base de datos vacía e inválida - - return QSqlDatabase(); - } - { - QSqlQuery pragma("PRAGMA foreign_keys = ON",db); - } - //pragma.finish(); - //devuelve la base de datos - return db; -} - -bool DataBaseManagement::createTables(QSqlDatabase & database) -{ - bool success = true; - - { - //COMIC INFO (representa la información de un cómic, cada cómic tendrá un idéntificador único formado por un hash sha1'de los primeros 512kb' + su tamaño en bytes) - QSqlQuery queryComicInfo(database); - queryComicInfo.prepare("CREATE TABLE comic_info (" - "id INTEGER PRIMARY KEY," - "title TEXT," - - "coverPage INTEGER DEFAULT 1," - "numPages INTEGER," - - "number INTEGER," - "isBis BOOLEAN," - "count INTEGER," - - "volume TEXT," - "storyArc TEXT," - "arcNumber INTEGER," - "arcCount INTEGER," - - "genere TEXT," - - "writer TEXT," - "penciller TEXT," - "inker TEXT," - "colorist TEXT," - "letterer TEXT," - "coverArtist TEXT," - - "date TEXT," //dd/mm/yyyy --> se mostrará en 3 campos diferentes - "publisher TEXT," - "format TEXT," - "color BOOLEAN," - "ageRating BOOLEAN," - - "synopsis TEXT," - "characters TEXT," - "notes TEXT," - - "hash TEXT UNIQUE NOT NULL," - "edited BOOLEAN DEFAULT 0," - "read BOOLEAN DEFAULT 0," - //new 7.0 fields - - "hasBeenOpened BOOLEAN DEFAULT 0," - "rating INTEGER DEFAULT 0," - "currentPage INTEGER DEFAULT 1, " - "bookmark1 INTEGER DEFAULT -1, " - "bookmark2 INTEGER DEFAULT -1, " - "bookmark3 INTEGER DEFAULT -1, " - "brightness INTEGER DEFAULT -1, " - "contrast INTEGER DEFAULT -1, " - "gamma INTEGER DEFAULT -1, " - //new 7.1 fields - "comicVineID TEXT," - //new 9.5 fields - "lastTimeOpened INTEGER," - "coverSizeRatio REAL," - "originalCoverSize STRING"//h/w - - ")"); - success = success && queryComicInfo.exec(); - //queryComicInfo.finish(); - - //FOLDER (representa una carpeta en disco) - QSqlQuery queryFolder(database); - queryFolder.prepare("CREATE TABLE folder (" - "id INTEGER PRIMARY KEY," - "parentId INTEGER NOT NULL," - "name TEXT NOT NULL," - "path TEXT NOT NULL," - //new 7.1 fields - "finished BOOLEAN DEFAULT 0," //reading - "completed BOOLEAN DEFAULT 1," //collecting - //new 9.5 fields - "numChildren INTEGER," - "firstChildHash TEXT," - "customImage TEXT," - "FOREIGN KEY(parentId) REFERENCES folder(id) ON DELETE CASCADE)"); - success = success && queryFolder.exec(); - - //COMIC (representa un cómic en disco, contiene el nombre de fichero) - QSqlQuery queryComic(database); - queryComic.prepare("CREATE TABLE comic (id INTEGER PRIMARY KEY, parentId INTEGER NOT NULL, comicInfoId INTEGER NOT NULL, fileName TEXT NOT NULL, path TEXT, FOREIGN KEY(parentId) REFERENCES folder(id) ON DELETE CASCADE, FOREIGN KEY(comicInfoId) REFERENCES comic_info(id))"); - success = success && queryComic.exec(); - //queryComic.finish(); - //DB INFO - QSqlQuery queryDBInfo(database); - queryDBInfo.prepare("CREATE TABLE db_info (version TEXT NOT NULL)"); - success = success && queryDBInfo.exec(); - //queryDBInfo.finish(); - - QSqlQuery query("INSERT INTO db_info (version) " - "VALUES ('" VERSION "')",database); - //query.finish(); - - //8.0> tables - success = success && DataBaseManagement::createV8Tables(database); - } - - return success; -} - -bool DataBaseManagement::createV8Tables(QSqlDatabase &database) -{ - bool success = true; - { - //8.0> tables - //LABEL - QSqlQuery queryLabel(database); - success = success && queryLabel.exec("CREATE TABLE label (id INTEGER PRIMARY KEY, " - "name TEXT NOT NULL, " - "color TEXT NOT NULL, " - "ordering INTEGER NOT NULL); "); //order depends on the color - - QSqlQuery queryIndexLabel(database); - success = success && queryIndexLabel.exec("CREATE INDEX label_ordering_index ON label (ordering)"); - - //COMIC LABEL - QSqlQuery queryComicLabel(database); - success = success && queryComicLabel.exec("CREATE TABLE comic_label (" - "comic_id INTEGER, " - "label_id INTEGER, " - "ordering INTEGER, " //TODO order???? - "FOREIGN KEY(label_id) REFERENCES label(id) ON DELETE CASCADE, " - "FOREIGN KEY(comic_id) REFERENCES comic(id) ON DELETE CASCADE, " - "PRIMARY KEY(label_id, comic_id))"); - - QSqlQuery queryIndexComicLabel(database); - success = success && queryIndexComicLabel.exec("CREATE INDEX comic_label_ordering_index ON label (ordering)"); - - //READING LIST - QSqlQuery queryReadingList(database); - success = success && queryReadingList.exec("CREATE TABLE reading_list (" - "id INTEGER PRIMARY KEY, " - "parentId INTEGER, " - "ordering INTEGER DEFAULT 0, " //only use it if the parentId is NULL - "name TEXT NOT NULL, " - "finished BOOLEAN DEFAULT 0, " - "completed BOOLEAN DEFAULT 1, " - "FOREIGN KEY(parentId) REFERENCES reading_list(id) ON DELETE CASCADE)"); - - QSqlQuery queryIndexReadingList(database); - success = success && queryIndexReadingList.exec("CREATE INDEX reading_list_ordering_index ON label (ordering)"); - - //COMIC READING LIST - QSqlQuery queryComicReadingList(database); - success = success && queryComicReadingList.exec("CREATE TABLE comic_reading_list (" - "reading_list_id INTEGER, " - "comic_id INTEGER, " - "ordering INTEGER, " - "FOREIGN KEY(reading_list_id) REFERENCES reading_list(id) ON DELETE CASCADE, " - "FOREIGN KEY(comic_id) REFERENCES comic(id) ON DELETE CASCADE, " - "PRIMARY KEY(reading_list_id, comic_id))"); - - QSqlQuery queryIndexComicReadingList(database); - success = success && queryIndexComicReadingList.exec("CREATE INDEX comic_reading_list_ordering_index ON label (ordering)"); - - //DEFAULT READING LISTS - QSqlQuery queryDefaultReadingList(database); - success = success && queryDefaultReadingList.exec("CREATE TABLE default_reading_list (" - "id INTEGER PRIMARY KEY, " - "name TEXT NOT NULL" - //TODO icon???? - ")"); - - //COMIC DEFAULT READING LISTS - QSqlQuery queryComicDefaultReadingList(database); - success = success && queryComicDefaultReadingList.exec("CREATE TABLE comic_default_reading_list (" - "comic_id INTEGER, " - "default_reading_list_id INTEGER, " - "ordering INTEGER, " //order???? - "FOREIGN KEY(default_reading_list_id) REFERENCES default_reading_list(id) ON DELETE CASCADE, " - "FOREIGN KEY(comic_id) REFERENCES comic(id) ON DELETE CASCADE," - "PRIMARY KEY(default_reading_list_id, comic_id))"); - - QSqlQuery queryIndexComicDefaultReadingList(database); - success = success && queryIndexComicDefaultReadingList.exec("CREATE INDEX comic_default_reading_list_ordering_index ON label (ordering)"); - - //INSERT DEFAULT READING LISTS - QSqlQuery queryInsertDefaultReadingList(database); - //if(!queryInsertDefaultReadingList.prepare()) - - //1 Favorites - //queryInsertDefaultReadingList.bindValue(":name", "Favorites"); - success = success && queryInsertDefaultReadingList.exec("INSERT INTO default_reading_list (name) VALUES (\"Favorites\")"); - - //Reading doesn't need its onw list - - } - return success; -} - -void DataBaseManagement::exportComicsInfo(QString source, QString dest) -{ - //QSqlDatabase sourceDB = loadDatabase(source); - QSqlDatabase destDB = loadDatabaseFromFile(dest); - //sourceDB.open(); - { - QSqlQuery attach(destDB); - attach.prepare("ATTACH DATABASE '"+QDir().toNativeSeparators(dest) +"' AS dest;"); - //attach.bindValue(":dest",QDir().toNativeSeparators(dest)); - attach.exec(); - //attach.finish(); - - QSqlQuery attach2(destDB); - attach2.prepare("ATTACH DATABASE '"+QDir().toNativeSeparators(source) +"' AS source;"); - attach2.exec(); - //attach2.finish(); - - //sourceDB.close(); - QSqlQuery queryDBInfo(destDB); - queryDBInfo.prepare("CREATE TABLE dest.db_info (version TEXT NOT NULL)"); - queryDBInfo.exec(); - //queryDBInfo.finish(); - - /*QSqlQuery queryComicsInfo(sourceDB); - queryComicsInfo.prepare("CREATE TABLE dest.comic_info (id INTEGER PRIMARY KEY, hash TEXT NOT NULL, edited BOOLEAN DEFAULT FALSE, title TEXT, read BOOLEAN)"); - queryComicsInfo.exec();*/ - - QSqlQuery query("INSERT INTO dest.db_info (version) " - "VALUES ('" VERSION "')",destDB); - //query.finish(); - - QSqlQuery exportData(destDB); - exportData.prepare("create table dest.comic_info as select " + fields + - " from source.comic_info where source.comic_info.edited = 1"); - exportData.exec(); - //exportData.finish(); - } - - //sourceDB.close(); - destDB.close(); - QSqlDatabase::removeDatabase(dest); - -} - -bool DataBaseManagement::importComicsInfo(QString source, QString dest) -{ - QString error; - QString driver; - QStringList hashes; - - bool b = false; - - QSqlDatabase sourceDB = loadDatabaseFromFile(source); - QSqlDatabase destDB = loadDatabaseFromFile(dest); - - { - QSqlQuery pragma("PRAGMA synchronous=OFF",destDB); - - - QSqlQuery newInfo(sourceDB); - newInfo.prepare("SELECT * FROM comic_info"); - newInfo.exec(); - destDB.transaction(); - int cp; - while (newInfo.next()) //cada tupla deberá ser insertada o actualizada - { - QSqlQuery update(destDB); - update.prepare("UPDATE comic_info SET " - "title = :title," - - "coverPage = :coverPage," - "numPages = :numPages," - - "number = :number," - "isBis = :isBis," - "count = :count," - - "volume = :volume," - "storyArc = :storyArc," - "arcNumber = :arcNumber," - "arcCount = :arcCount," - - "genere = :genere," - - "writer = :writer," - "penciller = :penciller," - "inker = :inker," - "colorist = :colorist," - "letterer = :letterer," - "coverArtist = :coverArtist," - - "date = :date," - "publisher = :publisher," - "format = :format," - "color = :color," - "ageRating = :ageRating," - - "synopsis = :synopsis," - "characters = :characters," - "notes = :notes," - - "edited = :edited," - - "comicVineID = :comicVineID," - - "lastTimeOpened = :lastTimeOpened," - - "coverSizeRatio = :coverSizeRatio," - "originalCoverSize = :originalCoverSize" - - " WHERE hash = :hash "); - - QSqlQuery insert(destDB); - insert.prepare("INSERT INTO comic_info " - "(title," - "coverPage," - "numPages," - "number," - "isBis," - "count," - "volume," - "storyArc," - "arcNumber," - "arcCount," - "genere," - "writer," - "penciller," - "inker," - "colorist," - "letterer," - "coverArtist," - "date," - "publisher," - "format," - "color," - "ageRating," - "synopsis," - "characters," - "notes," - "read," - "edited," - "comicVineID," - "lastTimeOpened," - "coverSizeRatio," - "hash)" - - "VALUES (:title," - ":coverPage," - ":numPages," - ":number," - ":isBis," - ":count," - - ":volume," - ":storyArc," - ":arcNumber," - ":arcCount," - - ":genere," - - ":writer," - ":penciller," - ":inker," - ":colorist," - ":letterer," - ":coverArtist," - - ":date," - ":publisher," - ":format," - ":color," - ":ageRating," - - ":synopsis," - ":characters," - ":notes," - - ":read," - ":edited," - ":comicVineID," - - ":lastTimeOpened," - - ":coverSizeRatio," - ":originalCoverSize," - - ":hash )"); - - QSqlRecord record = newInfo.record(); - cp = record.value("coverPage").toInt(); - if(cp>1) - { - QSqlQuery checkCoverPage(destDB); - checkCoverPage.prepare("SELECT coverPage FROM comic_info where hash = :hash"); - checkCoverPage.bindValue(":hash",record.value("hash").toString()); - checkCoverPage.exec(); - bool extract = false; - if(checkCoverPage.next()) - { - extract = checkCoverPage.record().value("coverPage").toInt() != cp; - } - if(extract) - hashes.append(record.value("hash").toString()); - } - - bindValuesFromRecord(record,update); - - update.bindValue(":edited",1); - - - update.exec(); - - if(update.numRowsAffected() == 0) - { - - bindValuesFromRecord(record,insert); - insert.bindValue(":edited",1); - insert.bindValue(":read",0); - - insert.exec(); - - QString error1 = insert.lastError().databaseText(); - QString error2 = insert.lastError().driverText(); - - //QMessageBox::critical(NULL,"db",error1); - //QMessageBox::critical(NULL,"driver",error2); - } - //update.finish(); - //insert.finish(); - } - } - - destDB.commit(); - QString hash; - foreach(hash, hashes) - { - QSqlQuery getComic(destDB); - getComic.prepare("SELECT c.path,ci.coverPage FROM comic c INNER JOIN comic_info ci ON (c.comicInfoId = ci.id) where ci.hash = :hash"); - getComic.bindValue(":hash",hash); - getComic.exec(); - if(getComic.next()) - { - QString basePath = QString(dest).remove("/.yacreaderlibrary/library.ydb"); - QString path = basePath + getComic.record().value("path").toString(); - int coverPage = getComic.record().value("coverPage").toInt(); - ThumbnailCreator tc(path,basePath+"/.yacreaderlibrary/covers/"+hash+".jpg",coverPage); - tc.create(); - - } - } - - destDB.close(); - sourceDB.close(); - QSqlDatabase::removeDatabase(source); - QSqlDatabase::removeDatabase(dest); - return b; - -} -//TODO fix these bindings -void DataBaseManagement::bindValuesFromRecord(const QSqlRecord & record, QSqlQuery & query) -{ - bindString("title",record,query); - - bindInt("coverPage",record,query); - bindInt("numPages",record,query); - - bindInt("number",record,query); - bindInt("isBis",record,query); - bindInt("count",record,query); - - bindString("volume",record,query); - bindString("storyArc",record,query); - bindInt("arcNumber",record,query); - bindInt("arcCount",record,query); - - bindString("genere",record,query); - - bindString("writer",record,query); - bindString("penciller",record,query); - bindString("inker",record,query); - bindString("colorist",record,query); - bindString("letterer",record,query); - bindString("coverArtist",record,query); - - bindString("date",record,query); - bindString("publisher",record,query); - bindString("format",record,query); - bindInt("color",record,query); - bindString("ageRating",record,query); - - bindString("synopsis",record,query); - bindString("characters",record,query); - bindString("notes",record,query); - - bindString("comicVineID",record,query); - - bindString("lastTimeOpened",record,query); - - bindDouble("coverSizeRatio",record,query); - bindString("originalCoverSize",record,query); - - bindString("hash",record,query); -} - -bool DataBaseManagement::addColumns(const QString &tableName, const QStringList &columnDefs, const QSqlDatabase &db) -{ - QString sql = "ALTER TABLE %1 ADD COLUMN %2"; - bool returnValue = true; - - foreach(QString columnDef, columnDefs) - { - QSqlQuery alterTable(db); - alterTable.prepare(sql.arg(tableName).arg(columnDef)); - //alterTableComicInfo.bindValue(":column_def",columnDef); - bool exec = alterTable.exec(); - returnValue = returnValue && exec; - if (!exec) { - QLOG_ERROR() << alterTable.lastError().text(); - } - //returnValue = returnValue && (alterTable.numRowsAffected() > 0); - } - - return returnValue; -} - -bool DataBaseManagement::addConstraint(const QString &tableName, const QString &constraint, const QSqlDatabase &db) -{ - QString sql = "ALTER TABLE %1 ADD %2"; - bool returnValue = true; - - QSqlQuery alterTable(db); - alterTable.prepare(sql.arg(tableName).arg(constraint)); - alterTable.exec(); - returnValue = returnValue && (alterTable.numRowsAffected() > 0); - - return returnValue; -} - -void DataBaseManagement::bindString(const QString & name, const QSqlRecord & record, QSqlQuery & query) -{ - if(!record.value(name).isNull()) - { - query.bindValue(":"+name,record.value(name).toString()); - } -} -void DataBaseManagement::bindInt(const QString & name, const QSqlRecord & record, QSqlQuery & query) -{ - if(!record.value(name).isNull()) - { - query.bindValue(":"+name,record.value(name).toInt()); - } -} - -void DataBaseManagement::bindDouble(const QString & name, const QSqlRecord & record, QSqlQuery & query) -{ - if(!record.value(name).isNull()) - { - query.bindValue(":"+name,record.value(name).toDouble()); - } -} - -QString DataBaseManagement::checkValidDB(const QString & fullPath) -{ - QSqlDatabase db = loadDatabaseFromFile(fullPath); - QString versionString = ""; - if(db.isValid() && db.isOpen()) - { - QSqlQuery version(db); - version.prepare("SELECT * FROM db_info"); - version.exec(); - - if(version.next()) - versionString = version.record().value("version").toString(); - } - - db.close(); + QString threadId = QString::number((long long)QThread::currentThreadId(), 16); + QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE",filePath+threadId); + db.setDatabaseName(filePath); + if (!db.open()) { + //se devuelve una base de datos vacía e inválida + + return QSqlDatabase(); + } + { + QSqlQuery pragma("PRAGMA foreign_keys = ON",db); + } + //pragma.finish(); + //devuelve la base de datos + return db; +} + +bool DataBaseManagement::createTables(QSqlDatabase & database) +{ + bool success = true; + + { + //COMIC INFO (representa la información de un cómic, cada cómic tendrá un idéntificador único formado por un hash sha1'de los primeros 512kb' + su tamaño en bytes) + QSqlQuery queryComicInfo(database); + queryComicInfo.prepare("CREATE TABLE comic_info (" + "id INTEGER PRIMARY KEY," + "title TEXT," + + "coverPage INTEGER DEFAULT 1," + "numPages INTEGER," + + "number INTEGER," + "isBis BOOLEAN," + "count INTEGER," + + "volume TEXT," + "storyArc TEXT," + "arcNumber INTEGER," + "arcCount INTEGER," + + "genere TEXT," + + "writer TEXT," + "penciller TEXT," + "inker TEXT," + "colorist TEXT," + "letterer TEXT," + "coverArtist TEXT," + + "date TEXT," //dd/mm/yyyy --> se mostrará en 3 campos diferentes + "publisher TEXT," + "format TEXT," + "color BOOLEAN," + "ageRating BOOLEAN," + + "synopsis TEXT," + "characters TEXT," + "notes TEXT," + + "hash TEXT UNIQUE NOT NULL," + "edited BOOLEAN DEFAULT 0," + "read BOOLEAN DEFAULT 0," + //new 7.0 fields + + "hasBeenOpened BOOLEAN DEFAULT 0," + "rating INTEGER DEFAULT 0," + "currentPage INTEGER DEFAULT 1, " + "bookmark1 INTEGER DEFAULT -1, " + "bookmark2 INTEGER DEFAULT -1, " + "bookmark3 INTEGER DEFAULT -1, " + "brightness INTEGER DEFAULT -1, " + "contrast INTEGER DEFAULT -1, " + "gamma INTEGER DEFAULT -1, " + //new 7.1 fields + "comicVineID TEXT," + //new 9.5 fields + "lastTimeOpened INTEGER," + "coverSizeRatio REAL," + "originalCoverSize STRING"//h/w + + ")"); + success = success && queryComicInfo.exec(); + //queryComicInfo.finish(); + + //FOLDER (representa una carpeta en disco) + QSqlQuery queryFolder(database); + queryFolder.prepare("CREATE TABLE folder (" + "id INTEGER PRIMARY KEY," + "parentId INTEGER NOT NULL," + "name TEXT NOT NULL," + "path TEXT NOT NULL," + //new 7.1 fields + "finished BOOLEAN DEFAULT 0," //reading + "completed BOOLEAN DEFAULT 1," //collecting + //new 9.5 fields + "numChildren INTEGER," + "firstChildHash TEXT," + "customImage TEXT," + "FOREIGN KEY(parentId) REFERENCES folder(id) ON DELETE CASCADE)"); + success = success && queryFolder.exec(); + + //COMIC (representa un cómic en disco, contiene el nombre de fichero) + QSqlQuery queryComic(database); + queryComic.prepare("CREATE TABLE comic (id INTEGER PRIMARY KEY, parentId INTEGER NOT NULL, comicInfoId INTEGER NOT NULL, fileName TEXT NOT NULL, path TEXT, FOREIGN KEY(parentId) REFERENCES folder(id) ON DELETE CASCADE, FOREIGN KEY(comicInfoId) REFERENCES comic_info(id))"); + success = success && queryComic.exec(); + //queryComic.finish(); + //DB INFO + QSqlQuery queryDBInfo(database); + queryDBInfo.prepare("CREATE TABLE db_info (version TEXT NOT NULL)"); + success = success && queryDBInfo.exec(); + //queryDBInfo.finish(); + + QSqlQuery query("INSERT INTO db_info (version) " + "VALUES ('" VERSION "')",database); + //query.finish(); + + //8.0> tables + success = success && DataBaseManagement::createV8Tables(database); + } + + return success; +} + +bool DataBaseManagement::createV8Tables(QSqlDatabase &database) +{ + bool success = true; + { + //8.0> tables + //LABEL + QSqlQuery queryLabel(database); + success = success && queryLabel.exec("CREATE TABLE label (id INTEGER PRIMARY KEY, " + "name TEXT NOT NULL, " + "color TEXT NOT NULL, " + "ordering INTEGER NOT NULL); "); //order depends on the color + + QSqlQuery queryIndexLabel(database); + success = success && queryIndexLabel.exec("CREATE INDEX label_ordering_index ON label (ordering)"); + + //COMIC LABEL + QSqlQuery queryComicLabel(database); + success = success && queryComicLabel.exec("CREATE TABLE comic_label (" + "comic_id INTEGER, " + "label_id INTEGER, " + "ordering INTEGER, " //TODO order???? + "FOREIGN KEY(label_id) REFERENCES label(id) ON DELETE CASCADE, " + "FOREIGN KEY(comic_id) REFERENCES comic(id) ON DELETE CASCADE, " + "PRIMARY KEY(label_id, comic_id))"); + + QSqlQuery queryIndexComicLabel(database); + success = success && queryIndexComicLabel.exec("CREATE INDEX comic_label_ordering_index ON label (ordering)"); + + //READING LIST + QSqlQuery queryReadingList(database); + success = success && queryReadingList.exec("CREATE TABLE reading_list (" + "id INTEGER PRIMARY KEY, " + "parentId INTEGER, " + "ordering INTEGER DEFAULT 0, " //only use it if the parentId is NULL + "name TEXT NOT NULL, " + "finished BOOLEAN DEFAULT 0, " + "completed BOOLEAN DEFAULT 1, " + "FOREIGN KEY(parentId) REFERENCES reading_list(id) ON DELETE CASCADE)"); + + QSqlQuery queryIndexReadingList(database); + success = success && queryIndexReadingList.exec("CREATE INDEX reading_list_ordering_index ON label (ordering)"); + + //COMIC READING LIST + QSqlQuery queryComicReadingList(database); + success = success && queryComicReadingList.exec("CREATE TABLE comic_reading_list (" + "reading_list_id INTEGER, " + "comic_id INTEGER, " + "ordering INTEGER, " + "FOREIGN KEY(reading_list_id) REFERENCES reading_list(id) ON DELETE CASCADE, " + "FOREIGN KEY(comic_id) REFERENCES comic(id) ON DELETE CASCADE, " + "PRIMARY KEY(reading_list_id, comic_id))"); + + QSqlQuery queryIndexComicReadingList(database); + success = success && queryIndexComicReadingList.exec("CREATE INDEX comic_reading_list_ordering_index ON label (ordering)"); + + //DEFAULT READING LISTS + QSqlQuery queryDefaultReadingList(database); + success = success && queryDefaultReadingList.exec("CREATE TABLE default_reading_list (" + "id INTEGER PRIMARY KEY, " + "name TEXT NOT NULL" + //TODO icon???? + ")"); + + //COMIC DEFAULT READING LISTS + QSqlQuery queryComicDefaultReadingList(database); + success = success && queryComicDefaultReadingList.exec("CREATE TABLE comic_default_reading_list (" + "comic_id INTEGER, " + "default_reading_list_id INTEGER, " + "ordering INTEGER, " //order???? + "FOREIGN KEY(default_reading_list_id) REFERENCES default_reading_list(id) ON DELETE CASCADE, " + "FOREIGN KEY(comic_id) REFERENCES comic(id) ON DELETE CASCADE," + "PRIMARY KEY(default_reading_list_id, comic_id))"); + + QSqlQuery queryIndexComicDefaultReadingList(database); + success = success && queryIndexComicDefaultReadingList.exec("CREATE INDEX comic_default_reading_list_ordering_index ON label (ordering)"); + + //INSERT DEFAULT READING LISTS + QSqlQuery queryInsertDefaultReadingList(database); + //if(!queryInsertDefaultReadingList.prepare()) + + //1 Favorites + //queryInsertDefaultReadingList.bindValue(":name", "Favorites"); + success = success && queryInsertDefaultReadingList.exec("INSERT INTO default_reading_list (name) VALUES (\"Favorites\")"); + + //Reading doesn't need its onw list + + } + return success; +} + +void DataBaseManagement::exportComicsInfo(QString source, QString dest) +{ + //QSqlDatabase sourceDB = loadDatabase(source); + QSqlDatabase destDB = loadDatabaseFromFile(dest); + //sourceDB.open(); + { + QSqlQuery attach(destDB); + attach.prepare("ATTACH DATABASE '"+QDir().toNativeSeparators(dest) +"' AS dest;"); + //attach.bindValue(":dest",QDir().toNativeSeparators(dest)); + attach.exec(); + //attach.finish(); + + QSqlQuery attach2(destDB); + attach2.prepare("ATTACH DATABASE '"+QDir().toNativeSeparators(source) +"' AS source;"); + attach2.exec(); + //attach2.finish(); + + //sourceDB.close(); + QSqlQuery queryDBInfo(destDB); + queryDBInfo.prepare("CREATE TABLE dest.db_info (version TEXT NOT NULL)"); + queryDBInfo.exec(); + //queryDBInfo.finish(); + + /*QSqlQuery queryComicsInfo(sourceDB); + queryComicsInfo.prepare("CREATE TABLE dest.comic_info (id INTEGER PRIMARY KEY, hash TEXT NOT NULL, edited BOOLEAN DEFAULT FALSE, title TEXT, read BOOLEAN)"); + queryComicsInfo.exec();*/ + + QSqlQuery query("INSERT INTO dest.db_info (version) " + "VALUES ('" VERSION "')",destDB); + //query.finish(); + + QSqlQuery exportData(destDB); + exportData.prepare("create table dest.comic_info as select " + fields + + " from source.comic_info where source.comic_info.edited = 1"); + exportData.exec(); + //exportData.finish(); + } + + //sourceDB.close(); + destDB.close(); + QSqlDatabase::removeDatabase(dest); + +} + +bool DataBaseManagement::importComicsInfo(QString source, QString dest) +{ + QString error; + QString driver; + QStringList hashes; + + bool b = false; + + QSqlDatabase sourceDB = loadDatabaseFromFile(source); + QSqlDatabase destDB = loadDatabaseFromFile(dest); + + { + QSqlQuery pragma("PRAGMA synchronous=OFF",destDB); + + + QSqlQuery newInfo(sourceDB); + newInfo.prepare("SELECT * FROM comic_info"); + newInfo.exec(); + destDB.transaction(); + int cp; + while (newInfo.next()) //cada tupla deberá ser insertada o actualizada + { + QSqlQuery update(destDB); + update.prepare("UPDATE comic_info SET " + "title = :title," + + "coverPage = :coverPage," + "numPages = :numPages," + + "number = :number," + "isBis = :isBis," + "count = :count," + + "volume = :volume," + "storyArc = :storyArc," + "arcNumber = :arcNumber," + "arcCount = :arcCount," + + "genere = :genere," + + "writer = :writer," + "penciller = :penciller," + "inker = :inker," + "colorist = :colorist," + "letterer = :letterer," + "coverArtist = :coverArtist," + + "date = :date," + "publisher = :publisher," + "format = :format," + "color = :color," + "ageRating = :ageRating," + + "synopsis = :synopsis," + "characters = :characters," + "notes = :notes," + + "edited = :edited," + + "comicVineID = :comicVineID," + + "lastTimeOpened = :lastTimeOpened," + + "coverSizeRatio = :coverSizeRatio," + "originalCoverSize = :originalCoverSize" + + " WHERE hash = :hash "); + + QSqlQuery insert(destDB); + insert.prepare("INSERT INTO comic_info " + "(title," + "coverPage," + "numPages," + "number," + "isBis," + "count," + "volume," + "storyArc," + "arcNumber," + "arcCount," + "genere," + "writer," + "penciller," + "inker," + "colorist," + "letterer," + "coverArtist," + "date," + "publisher," + "format," + "color," + "ageRating," + "synopsis," + "characters," + "notes," + "read," + "edited," + "comicVineID," + "lastTimeOpened," + "coverSizeRatio," + "hash)" + + "VALUES (:title," + ":coverPage," + ":numPages," + ":number," + ":isBis," + ":count," + + ":volume," + ":storyArc," + ":arcNumber," + ":arcCount," + + ":genere," + + ":writer," + ":penciller," + ":inker," + ":colorist," + ":letterer," + ":coverArtist," + + ":date," + ":publisher," + ":format," + ":color," + ":ageRating," + + ":synopsis," + ":characters," + ":notes," + + ":read," + ":edited," + ":comicVineID," + + ":lastTimeOpened," + + ":coverSizeRatio," + ":originalCoverSize," + + ":hash )"); + + QSqlRecord record = newInfo.record(); + cp = record.value("coverPage").toInt(); + if(cp>1) + { + QSqlQuery checkCoverPage(destDB); + checkCoverPage.prepare("SELECT coverPage FROM comic_info where hash = :hash"); + checkCoverPage.bindValue(":hash",record.value("hash").toString()); + checkCoverPage.exec(); + bool extract = false; + if(checkCoverPage.next()) + { + extract = checkCoverPage.record().value("coverPage").toInt() != cp; + } + if(extract) + hashes.append(record.value("hash").toString()); + } + + bindValuesFromRecord(record,update); + + update.bindValue(":edited",1); + + + update.exec(); + + if(update.numRowsAffected() == 0) + { + + bindValuesFromRecord(record,insert); + insert.bindValue(":edited",1); + insert.bindValue(":read",0); + + insert.exec(); + + QString error1 = insert.lastError().databaseText(); + QString error2 = insert.lastError().driverText(); + + //QMessageBox::critical(NULL,"db",error1); + //QMessageBox::critical(NULL,"driver",error2); + } + //update.finish(); + //insert.finish(); + } + } + + destDB.commit(); + QString hash; + foreach(hash, hashes) + { + QSqlQuery getComic(destDB); + getComic.prepare("SELECT c.path,ci.coverPage FROM comic c INNER JOIN comic_info ci ON (c.comicInfoId = ci.id) where ci.hash = :hash"); + getComic.bindValue(":hash",hash); + getComic.exec(); + if(getComic.next()) + { + QString basePath = QString(dest).remove("/.yacreaderlibrary/library.ydb"); + QString path = basePath + getComic.record().value("path").toString(); + int coverPage = getComic.record().value("coverPage").toInt(); + ThumbnailCreator tc(path,basePath+"/.yacreaderlibrary/covers/"+hash+".jpg",coverPage); + tc.create(); + + } + } + + destDB.close(); + sourceDB.close(); + QSqlDatabase::removeDatabase(source); + QSqlDatabase::removeDatabase(dest); + return b; + +} +//TODO fix these bindings +void DataBaseManagement::bindValuesFromRecord(const QSqlRecord & record, QSqlQuery & query) +{ + bindString("title",record,query); + + bindInt("coverPage",record,query); + bindInt("numPages",record,query); + + bindInt("number",record,query); + bindInt("isBis",record,query); + bindInt("count",record,query); + + bindString("volume",record,query); + bindString("storyArc",record,query); + bindInt("arcNumber",record,query); + bindInt("arcCount",record,query); + + bindString("genere",record,query); + + bindString("writer",record,query); + bindString("penciller",record,query); + bindString("inker",record,query); + bindString("colorist",record,query); + bindString("letterer",record,query); + bindString("coverArtist",record,query); + + bindString("date",record,query); + bindString("publisher",record,query); + bindString("format",record,query); + bindInt("color",record,query); + bindString("ageRating",record,query); + + bindString("synopsis",record,query); + bindString("characters",record,query); + bindString("notes",record,query); + + bindString("comicVineID",record,query); + + bindString("lastTimeOpened",record,query); + + bindDouble("coverSizeRatio",record,query); + bindString("originalCoverSize",record,query); + + bindString("hash",record,query); +} + +bool DataBaseManagement::addColumns(const QString &tableName, const QStringList &columnDefs, const QSqlDatabase &db) +{ + QString sql = "ALTER TABLE %1 ADD COLUMN %2"; + bool returnValue = true; + + foreach(QString columnDef, columnDefs) + { + QSqlQuery alterTable(db); + alterTable.prepare(sql.arg(tableName).arg(columnDef)); + //alterTableComicInfo.bindValue(":column_def",columnDef); + bool exec = alterTable.exec(); + returnValue = returnValue && exec; + if (!exec) { + QLOG_ERROR() << alterTable.lastError().text(); + } + //returnValue = returnValue && (alterTable.numRowsAffected() > 0); + } + + return returnValue; +} + +bool DataBaseManagement::addConstraint(const QString &tableName, const QString &constraint, const QSqlDatabase &db) +{ + QString sql = "ALTER TABLE %1 ADD %2"; + bool returnValue = true; + + QSqlQuery alterTable(db); + alterTable.prepare(sql.arg(tableName).arg(constraint)); + alterTable.exec(); + returnValue = returnValue && (alterTable.numRowsAffected() > 0); + + return returnValue; +} + +void DataBaseManagement::bindString(const QString & name, const QSqlRecord & record, QSqlQuery & query) +{ + if(!record.value(name).isNull()) + { + query.bindValue(":"+name,record.value(name).toString()); + } +} +void DataBaseManagement::bindInt(const QString & name, const QSqlRecord & record, QSqlQuery & query) +{ + if(!record.value(name).isNull()) + { + query.bindValue(":"+name,record.value(name).toInt()); + } +} + +void DataBaseManagement::bindDouble(const QString & name, const QSqlRecord & record, QSqlQuery & query) +{ + if(!record.value(name).isNull()) + { + query.bindValue(":"+name,record.value(name).toDouble()); + } +} + +QString DataBaseManagement::checkValidDB(const QString & fullPath) +{ + QSqlDatabase db = loadDatabaseFromFile(fullPath); + QString versionString = ""; + if(db.isValid() && db.isOpen()) + { + QSqlQuery version(db); + version.prepare("SELECT * FROM db_info"); + version.exec(); + + if(version.next()) + versionString = version.record().value("version").toString(); + } + + db.close(); QSqlDatabase::removeDatabase(db.connectionName()); - - return versionString; -} - -int DataBaseManagement::compareVersions(const QString & v1, const QString v2) -{ - QStringList v1l = v1.split('.'); - QStringList v2l = v2.split('.'); - QList v1il; - QList v2il; - - foreach(QString s, v1l) - v1il.append(s.toInt()); - - foreach(QString s,v2l) - v2il.append(s.toInt()); - - for(int i=0;iv2il[i]) - return 1; - } - - if(v1il.length() < v2il.length()) - return -1; - if(v1il.length() == v2il.length()) - return 0; - if(v1il.length() > v2il.length()) - return 1; - - return 0; -} - -bool DataBaseManagement::updateToCurrentVersion(const QString & path) -{ - bool pre7 = false; - bool pre7_1 = false; - bool pre8 = false; - bool pre9_5 = false; - - QString fullPath = path + "/library.ydb"; - - if(compareVersions(DataBaseManagement::checkValidDB(fullPath),"7.0.0")<0) - pre7 = true; - if(compareVersions(DataBaseManagement::checkValidDB(fullPath),"7.0.3")<0) - pre7_1 = true; - if(compareVersions(DataBaseManagement::checkValidDB(fullPath),"8.0.0")<0) - pre8 = true; - if(compareVersions(DataBaseManagement::checkValidDB(fullPath),"9.5.0")<0) - pre9_5 = true; - - QSqlDatabase db = loadDatabaseFromFile(fullPath); - bool returnValue = false; - if(db.isValid() && db.isOpen()) - { - QSqlQuery updateVersion(db); - updateVersion.prepare("UPDATE db_info SET " - "version = :version"); - updateVersion.bindValue(":version",VERSION); - updateVersion.exec(); - - if(updateVersion.numRowsAffected() > 0) - returnValue = true; - - if(pre7) //TODO: execute only if previous version was < 7.0 - { - //new 7.0 fields - QStringList columnDefs; - columnDefs << "hasBeenOpened BOOLEAN DEFAULT 0" - << "rating INTEGER DEFAULT 0" - << "currentPage INTEGER DEFAULT 1" - << "bookmark1 INTEGER DEFAULT -1" - << "bookmark2 INTEGER DEFAULT -1" - << "bookmark3 INTEGER DEFAULT -1" - << "brightness INTEGER DEFAULT -1" - << "contrast INTEGER DEFAULT -1" - << "gamma INTEGER DEFAULT -1"; - - bool successAddingColumns = addColumns("comic_info", columnDefs, db); - returnValue = returnValue && successAddingColumns; - } - //TODO update hasBeenOpened value - - if(pre7_1) - { - { - QStringList columnDefs; - columnDefs << "finished BOOLEAN DEFAULT 0" - << "completed BOOLEAN DEFAULT 1"; - bool successAddingColumns = addColumns("folder", columnDefs, db); - returnValue = returnValue && successAddingColumns; - } - - {//comic_info - QStringList columnDefs; - columnDefs << "comicVineID TEXT DEFAULT NULL"; - bool successAddingColumns = addColumns("comic_info", columnDefs, db); - returnValue = returnValue && successAddingColumns; - } - } - - if(pre8) - { - bool successCreatingNewTables = createV8Tables(db); - returnValue = returnValue && successCreatingNewTables; - } - - if(pre9_5) - { - {//folder - QStringList columnDefs; - //a full library update is needed after updating the table - columnDefs << "numChildren INTEGER"; - columnDefs << "firstChildHash TEXT"; - columnDefs << "customImage TEXT"; - bool successAddingColumns = addColumns("folder", columnDefs, db); - returnValue = returnValue && successAddingColumns; - } - - {//comic_info - QStringList columnDefs; - columnDefs << "lastTimeOpened INTEGER"; - columnDefs << "coverSizeRatio REAL"; - columnDefs << "originalCoverSize TEXT"; - bool successAddingColumns = addColumns("comic_info", columnDefs, db); - returnValue = returnValue && successAddingColumns; - - QSqlQuery queryIndexLastTimeOpened(db); - bool successCreatingIndex = queryIndexLastTimeOpened.exec("CREATE INDEX last_time_opened_index ON comic_info (lastTimeOpened)"); - returnValue = returnValue && successCreatingIndex; - } - - //update folders info - { - DBHelper::updateChildrenInfo(db); - } - - { - QSqlQuery selectQuery(db); - selectQuery.prepare("SELECT id, hash FROM comic_info"); - selectQuery.exec(); - - db.transaction(); - - QSqlQuery updateCoverInfo(db); - updateCoverInfo.prepare("UPDATE comic_info SET coverSizeRatio = :coverSizeRatio WHERE id = :id"); - - QImageReader thumbnail; - while (selectQuery.next()) - { - thumbnail.setFileName(path % "/covers/" % selectQuery.value(1).toString() % ".jpg"); - - float coverSizeRatio = static_cast(thumbnail.size().width()) / thumbnail.size().height(); - updateCoverInfo.bindValue(":coverSizeRatio", coverSizeRatio); - updateCoverInfo.bindValue(":id", selectQuery.value(0)); - - updateCoverInfo.exec(); - } - - db.commit(); - } - } - } - - db.close(); - QSqlDatabase::removeDatabase(db.connectionName()); - return returnValue; -} - -//COMICS_INFO_EXPORTER -ComicsInfoExporter::ComicsInfoExporter() -:QThread() -{ -} - -void ComicsInfoExporter::exportComicsInfo(QSqlDatabase & source, QSqlDatabase & dest) -{ - Q_UNUSED(source) - Q_UNUSED(dest) - //TODO check this method -} - -void ComicsInfoExporter::run() -{ - -} - - -//COMICS_INFO_IMPORTER -ComicsInfoImporter::ComicsInfoImporter() -:QThread() -{ -} - -void ComicsInfoImporter::importComicsInfo(QSqlDatabase & source, QSqlDatabase & dest) -{ - Q_UNUSED(source) - Q_UNUSED(dest) - //TODO check this method -} - -void ComicsInfoImporter::run() -{ - -} + + return versionString; +} + +int DataBaseManagement::compareVersions(const QString & v1, const QString v2) +{ + QStringList v1l = v1.split('.'); + QStringList v2l = v2.split('.'); + QList v1il; + QList v2il; + + foreach(QString s, v1l) + v1il.append(s.toInt()); + + foreach(QString s,v2l) + v2il.append(s.toInt()); + + for(int i=0;iv2il[i]) + return 1; + } + + if(v1il.length() < v2il.length()) + return -1; + if(v1il.length() == v2il.length()) + return 0; + if(v1il.length() > v2il.length()) + return 1; + + return 0; +} + +bool DataBaseManagement::updateToCurrentVersion(const QString & path) +{ + bool pre7 = false; + bool pre7_1 = false; + bool pre8 = false; + bool pre9_5 = false; + + QString fullPath = path + "/library.ydb"; + + if(compareVersions(DataBaseManagement::checkValidDB(fullPath),"7.0.0")<0) + pre7 = true; + if(compareVersions(DataBaseManagement::checkValidDB(fullPath),"7.0.3")<0) + pre7_1 = true; + if(compareVersions(DataBaseManagement::checkValidDB(fullPath),"8.0.0")<0) + pre8 = true; + if(compareVersions(DataBaseManagement::checkValidDB(fullPath),"9.5.0")<0) + pre9_5 = true; + + QSqlDatabase db = loadDatabaseFromFile(fullPath); + bool returnValue = false; + if(db.isValid() && db.isOpen()) + { + QSqlQuery updateVersion(db); + updateVersion.prepare("UPDATE db_info SET " + "version = :version"); + updateVersion.bindValue(":version",VERSION); + updateVersion.exec(); + + if(updateVersion.numRowsAffected() > 0) + returnValue = true; + + if(pre7) //TODO: execute only if previous version was < 7.0 + { + //new 7.0 fields + QStringList columnDefs; + columnDefs << "hasBeenOpened BOOLEAN DEFAULT 0" + << "rating INTEGER DEFAULT 0" + << "currentPage INTEGER DEFAULT 1" + << "bookmark1 INTEGER DEFAULT -1" + << "bookmark2 INTEGER DEFAULT -1" + << "bookmark3 INTEGER DEFAULT -1" + << "brightness INTEGER DEFAULT -1" + << "contrast INTEGER DEFAULT -1" + << "gamma INTEGER DEFAULT -1"; + + bool successAddingColumns = addColumns("comic_info", columnDefs, db); + returnValue = returnValue && successAddingColumns; + } + //TODO update hasBeenOpened value + + if(pre7_1) + { + { + QStringList columnDefs; + columnDefs << "finished BOOLEAN DEFAULT 0" + << "completed BOOLEAN DEFAULT 1"; + bool successAddingColumns = addColumns("folder", columnDefs, db); + returnValue = returnValue && successAddingColumns; + } + + {//comic_info + QStringList columnDefs; + columnDefs << "comicVineID TEXT DEFAULT NULL"; + bool successAddingColumns = addColumns("comic_info", columnDefs, db); + returnValue = returnValue && successAddingColumns; + } + } + + if(pre8) + { + bool successCreatingNewTables = createV8Tables(db); + returnValue = returnValue && successCreatingNewTables; + } + + if(pre9_5) + { + {//folder + QStringList columnDefs; + //a full library update is needed after updating the table + columnDefs << "numChildren INTEGER"; + columnDefs << "firstChildHash TEXT"; + columnDefs << "customImage TEXT"; + bool successAddingColumns = addColumns("folder", columnDefs, db); + returnValue = returnValue && successAddingColumns; + } + + {//comic_info + QStringList columnDefs; + columnDefs << "lastTimeOpened INTEGER"; + columnDefs << "coverSizeRatio REAL"; + columnDefs << "originalCoverSize TEXT"; + bool successAddingColumns = addColumns("comic_info", columnDefs, db); + returnValue = returnValue && successAddingColumns; + + QSqlQuery queryIndexLastTimeOpened(db); + bool successCreatingIndex = queryIndexLastTimeOpened.exec("CREATE INDEX last_time_opened_index ON comic_info (lastTimeOpened)"); + returnValue = returnValue && successCreatingIndex; + } + + //update folders info + { + DBHelper::updateChildrenInfo(db); + } + + { + QSqlQuery selectQuery(db); + selectQuery.prepare("SELECT id, hash FROM comic_info"); + selectQuery.exec(); + + db.transaction(); + + QSqlQuery updateCoverInfo(db); + updateCoverInfo.prepare("UPDATE comic_info SET coverSizeRatio = :coverSizeRatio WHERE id = :id"); + + QImageReader thumbnail; + while (selectQuery.next()) + { + thumbnail.setFileName(path % "/covers/" % selectQuery.value(1).toString() % ".jpg"); + + float coverSizeRatio = static_cast(thumbnail.size().width()) / thumbnail.size().height(); + updateCoverInfo.bindValue(":coverSizeRatio", coverSizeRatio); + updateCoverInfo.bindValue(":id", selectQuery.value(0)); + + updateCoverInfo.exec(); + } + + db.commit(); + } + } + } + + db.close(); + QSqlDatabase::removeDatabase(db.connectionName()); + return returnValue; +} + +//COMICS_INFO_EXPORTER +ComicsInfoExporter::ComicsInfoExporter() +:QThread() +{ +} + +void ComicsInfoExporter::exportComicsInfo(QSqlDatabase & source, QSqlDatabase & dest) +{ + Q_UNUSED(source) + Q_UNUSED(dest) + //TODO check this method +} + +void ComicsInfoExporter::run() +{ + +} + + +//COMICS_INFO_IMPORTER +ComicsInfoImporter::ComicsInfoImporter() +:QThread() +{ +} + +void ComicsInfoImporter::importComicsInfo(QSqlDatabase & source, QSqlDatabase & dest) +{ + Q_UNUSED(source) + Q_UNUSED(dest) + //TODO check this method +} + +void ComicsInfoImporter::run() +{ + +} diff --git a/YACReaderLibrary/db/data_base_management.h b/YACReaderLibrary/db/data_base_management.h index db3bc031..cbc7c9c8 100644 --- a/YACReaderLibrary/db/data_base_management.h +++ b/YACReaderLibrary/db/data_base_management.h @@ -1,64 +1,64 @@ -#ifndef __DATA_BASE_MANAGEMENT_H -#define __DATA_BASE_MANAGEMENT_H - -#include -#include -#include - -#include "folder_model.h" - -class ComicsInfoExporter : public QThread -{ - Q_OBJECT -public: - ComicsInfoExporter(); - void exportComicsInfo(QSqlDatabase & source, QSqlDatabase & dest); -private: - void run(); -}; - -class ComicsInfoImporter : public QThread -{ - Q_OBJECT -public: - ComicsInfoImporter(); - void importComicsInfo(QSqlDatabase & source, QSqlDatabase & dest); -private: - void run(); - -}; - -class DataBaseManagement : public QObject -{ - Q_OBJECT -private: - QList dataBasesList; - static void bindString(const QString & name, const QSqlRecord & record, QSqlQuery & query); - static void bindInt(const QString & name, const QSqlRecord & record, QSqlQuery & query); - static void bindDouble(const QString & name, const QSqlRecord & record, QSqlQuery & query); - static void bindValuesFromRecord(const QSqlRecord & record, QSqlQuery & query); - - static bool addColumns(const QString & tableName, const QStringList & columnDefs, const QSqlDatabase & db); - static bool addConstraint(const QString &tableName, const QString & constraint, const QSqlDatabase & db); - -public: - DataBaseManagement(); - //TreeModel * newTreeModel(QString path); - //crea una base de datos y todas sus tablas - static QSqlDatabase createDatabase(QString name, QString path); - static QSqlDatabase createDatabase(QString dest); - //carga una base de datos desde la ruta path - static QSqlDatabase loadDatabase(QString path); - static QSqlDatabase loadDatabaseFromFile(QString path); - static bool createTables(QSqlDatabase & database); - static bool createV8Tables(QSqlDatabase & database); - - static void exportComicsInfo(QString source, QString dest); - static bool importComicsInfo(QString source, QString dest); - - static QString checkValidDB(const QString & fullPath); //retorna "" si la DB es inválida ó la versión si es válida. - static int compareVersions(const QString & v1, const QString v2); //retorna <0 si v1 < v2, 0 si v1 = v2 y >0 si v1 > v2 - static bool updateToCurrentVersion(const QString & path); -}; - -#endif +#ifndef __DATA_BASE_MANAGEMENT_H +#define __DATA_BASE_MANAGEMENT_H + +#include +#include +#include + +#include "folder_model.h" + +class ComicsInfoExporter : public QThread +{ + Q_OBJECT +public: + ComicsInfoExporter(); + void exportComicsInfo(QSqlDatabase & source, QSqlDatabase & dest); +private: + void run(); +}; + +class ComicsInfoImporter : public QThread +{ + Q_OBJECT +public: + ComicsInfoImporter(); + void importComicsInfo(QSqlDatabase & source, QSqlDatabase & dest); +private: + void run(); + +}; + +class DataBaseManagement : public QObject +{ + Q_OBJECT +private: + QList dataBasesList; + static void bindString(const QString & name, const QSqlRecord & record, QSqlQuery & query); + static void bindInt(const QString & name, const QSqlRecord & record, QSqlQuery & query); + static void bindDouble(const QString & name, const QSqlRecord & record, QSqlQuery & query); + static void bindValuesFromRecord(const QSqlRecord & record, QSqlQuery & query); + + static bool addColumns(const QString & tableName, const QStringList & columnDefs, const QSqlDatabase & db); + static bool addConstraint(const QString &tableName, const QString & constraint, const QSqlDatabase & db); + +public: + DataBaseManagement(); + //TreeModel * newTreeModel(QString path); + //crea una base de datos y todas sus tablas + static QSqlDatabase createDatabase(QString name, QString path); + static QSqlDatabase createDatabase(QString dest); + //carga una base de datos desde la ruta path + static QSqlDatabase loadDatabase(QString path); + static QSqlDatabase loadDatabaseFromFile(QString path); + static bool createTables(QSqlDatabase & database); + static bool createV8Tables(QSqlDatabase & database); + + static void exportComicsInfo(QString source, QString dest); + static bool importComicsInfo(QString source, QString dest); + + static QString checkValidDB(const QString & fullPath); //retorna "" si la DB es inválida ó la versión si es válida. + static int compareVersions(const QString & v1, const QString v2); //retorna <0 si v1 < v2, 0 si v1 = v2 y >0 si v1 > v2 + static bool updateToCurrentVersion(const QString & path); +}; + +#endif diff --git a/YACReaderLibrary/db/folder_item.cpp b/YACReaderLibrary/db/folder_item.cpp index 069147f3..bf9ae4e0 100644 --- a/YACReaderLibrary/db/folder_item.cpp +++ b/YACReaderLibrary/db/folder_item.cpp @@ -1,103 +1,103 @@ -#include - -#include "folder_item.h" -#include "qnaturalsorting.h" - -FolderItem::FolderItem(const QList &data, FolderItem *parent) -{ - parentItem = parent; - itemData = data; -} - -FolderItem::~FolderItem() -{ - qDeleteAll(childItems); -} - -void FolderItem::appendChild(FolderItem *item) -{ - item->parentItem = this; - - if(childItems.isEmpty()) - childItems.append(item); - else - { - FolderItem * last = childItems.back(); - QString nameLast = last->data(1).toString(); //TODO usar info name si est� disponible, sino el nombre del fichero..... - QString nameCurrent = item->data(1).toString(); - QList::iterator i; - i = childItems.end(); - i--; - while (naturalSortLessThanCI(nameCurrent,nameLast) && i != childItems.begin()) - { - i--; - nameLast = (*i)->data(1).toString(); - } - if(!naturalSortLessThanCI(nameCurrent,nameLast)) //si se ha encontrado un elemento menor que current, se inserta justo despu�s - childItems.insert(++i,item); - else - childItems.insert(i,item); - - } - - //childItems.append(item); -} - -FolderItem *FolderItem::child(int row) -{ - return childItems.value(row); -} - -int FolderItem::childCount() const -{ - return childItems.count(); -} - -int FolderItem::columnCount() const -{ - return itemData.count(); -} - -QVariant FolderItem::data(int column) const -{ - return itemData.value(column); -} - -void FolderItem::setData(int column, const QVariant & value) -{ - itemData[column] = value; -} - -void FolderItem::removeChild(int childIndex) -{ - childItems.removeAt(childIndex); -} - -void FolderItem::clearChildren() -{ - qDeleteAll(childItems); - childItems.clear(); -} - -QList FolderItem::children() -{ - return childItems; -} - -FolderItem *FolderItem::parent() -{ - return parentItem; -} - -int FolderItem::row() const -{ - if (parentItem) - return parentItem->childItems.indexOf(const_cast(this)); - - return 0; -} - -QList FolderItem::getData() const -{ - return itemData; -} +#include + +#include "folder_item.h" +#include "qnaturalsorting.h" + +FolderItem::FolderItem(const QList &data, FolderItem *parent) +{ + parentItem = parent; + itemData = data; +} + +FolderItem::~FolderItem() +{ + qDeleteAll(childItems); +} + +void FolderItem::appendChild(FolderItem *item) +{ + item->parentItem = this; + + if(childItems.isEmpty()) + childItems.append(item); + else + { + FolderItem * last = childItems.back(); + QString nameLast = last->data(1).toString(); //TODO usar info name si est� disponible, sino el nombre del fichero..... + QString nameCurrent = item->data(1).toString(); + QList::iterator i; + i = childItems.end(); + i--; + while (naturalSortLessThanCI(nameCurrent,nameLast) && i != childItems.begin()) + { + i--; + nameLast = (*i)->data(1).toString(); + } + if(!naturalSortLessThanCI(nameCurrent,nameLast)) //si se ha encontrado un elemento menor que current, se inserta justo despu�s + childItems.insert(++i,item); + else + childItems.insert(i,item); + + } + + //childItems.append(item); +} + +FolderItem *FolderItem::child(int row) +{ + return childItems.value(row); +} + +int FolderItem::childCount() const +{ + return childItems.count(); +} + +int FolderItem::columnCount() const +{ + return itemData.count(); +} + +QVariant FolderItem::data(int column) const +{ + return itemData.value(column); +} + +void FolderItem::setData(int column, const QVariant & value) +{ + itemData[column] = value; +} + +void FolderItem::removeChild(int childIndex) +{ + childItems.removeAt(childIndex); +} + +void FolderItem::clearChildren() +{ + qDeleteAll(childItems); + childItems.clear(); +} + +QList FolderItem::children() +{ + return childItems; +} + +FolderItem *FolderItem::parent() +{ + return parentItem; +} + +int FolderItem::row() const +{ + if (parentItem) + return parentItem->childItems.indexOf(const_cast(this)); + + return 0; +} + +QList FolderItem::getData() const +{ + return itemData; +} diff --git a/YACReaderLibrary/db/folder_item.h b/YACReaderLibrary/db/folder_item.h index f0841c0f..5718e1ae 100644 --- a/YACReaderLibrary/db/folder_item.h +++ b/YACReaderLibrary/db/folder_item.h @@ -1,77 +1,77 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the examples of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:BSD$ -** You may use this file under the terms of the BSD license as follows: -** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor -** the names of its contributors may be used to endorse or promote -** products derived from this software without specific prior written -** permission. -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef TREEITEM_H -#define TREEITEM_H - -#include -#include -#include - -class FolderItem -{ -public: - FolderItem(const QList &data, FolderItem *parent = 0); - ~FolderItem(); - - void appendChild(FolderItem *child); - - FolderItem *child(int row); - int childCount() const; - int columnCount() const; - QVariant data(int column) const; - QList getData() const; - int row() const; - FolderItem *parent(); - FolderItem *parentItem; - unsigned long long int id; - QList comicNames; - FolderItem * originalItem; - void setData(int column, const QVariant &value); - void removeChild(int childIndex); - void clearChildren(); - QList children(); -private: - QList childItems; - QList itemData; -}; -//! [0] - -#endif +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef TREEITEM_H +#define TREEITEM_H + +#include +#include +#include + +class FolderItem +{ +public: + FolderItem(const QList &data, FolderItem *parent = 0); + ~FolderItem(); + + void appendChild(FolderItem *child); + + FolderItem *child(int row); + int childCount() const; + int columnCount() const; + QVariant data(int column) const; + QList getData() const; + int row() const; + FolderItem *parent(); + FolderItem *parentItem; + unsigned long long int id; + QList comicNames; + FolderItem * originalItem; + void setData(int column, const QVariant &value); + void removeChild(int childIndex); + void clearChildren(); + QList children(); +private: + QList childItems; + QList itemData; +}; +//! [0] + +#endif diff --git a/YACReaderLibrary/db/folder_model.cpp b/YACReaderLibrary/db/folder_model.cpp index a6e095d3..67ddda1a 100644 --- a/YACReaderLibrary/db/folder_model.cpp +++ b/YACReaderLibrary/db/folder_model.cpp @@ -1,835 +1,835 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the examples of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:BSD$ -** You may use this file under the terms of the BSD license as follows: -** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor -** the names of its contributors may be used to endorse or promote -** products derived from this software without specific prior written -** permission. -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** $QT_END_LICENSE$ -** -****************************************************************************/ - -/* - treemodel.cpp - - Provides a simple tree model to show how to create and use hierarchical - models. -*/ - -#include - - -#include "folder_item.h" -#include "folder_model.h" -#include "data_base_management.h" -#include "folder.h" -#include "db_helper.h" -#include "qnaturalsorting.h" -#include "yacreader_global_gui.h" -#include "QsLog.h" - -#ifdef Q_OS_MAC -#include -QIcon finishedFolderIcon; -void drawMacOSXFinishedFolderIcon() -{ - QIcon ico = QFileIconProvider().icon(QFileIconProvider::Folder); - QPixmap pixNormalOff = ico.pixmap(16,16, QIcon::Normal, QIcon::Off); - QPixmap pixNormalOn = ico.pixmap(16,16, QIcon::Normal, QIcon::On); - QPixmap pixSelectedOff = ico.pixmap(16,16, QIcon::Selected, QIcon::Off); - QPixmap pixSelectedOn = ico.pixmap(16,16, QIcon::Selected, QIcon::On); - QPixmap tick(":/images/folder_finished_macosx.png"); - - - { - QPainter p(&pixNormalOff); - p.drawPixmap(4,7,tick); - } - finishedFolderIcon.addPixmap(pixNormalOff, QIcon::Normal, QIcon::Off); - - { - QPainter p(&pixNormalOn); - p.drawPixmap(4,7,tick); - } - finishedFolderIcon.addPixmap(pixNormalOn, QIcon::Normal, QIcon::On); - - { - QPainter p(&pixSelectedOff); - p.drawPixmap(4,7,tick); - } - finishedFolderIcon.addPixmap(pixSelectedOff, QIcon::Selected, QIcon::Off); - - { - QPainter p(&pixSelectedOn); - p.drawPixmap(4,7,tick); - } - finishedFolderIcon.addPixmap(pixSelectedOn, QIcon::Selected, QIcon::On); -} -#endif - -#define ROOT 1 - -FolderModel::FolderModel(QObject *parent) - : QAbstractItemModel(parent),rootItem(0) -{ - connect(this,SIGNAL(beforeReset()),this,SIGNAL(modelAboutToBeReset())); - connect(this,SIGNAL(reset()),this,SIGNAL(modelReset())); -} - -//! [0] -FolderModel::FolderModel( QSqlQuery &sqlquery, QObject *parent) - : QAbstractItemModel(parent),rootItem(0) -{ - //lo m�s probable es que el nodo ra�z no necesite tener informaci�n - QList 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; - setupModelData(sqlquery, rootItem); - //sqlquery.finish(); -} -//! [0] - -//! [1] -FolderModel::~FolderModel() -{ - if(rootItem != 0) - delete rootItem; -} -//! [1] - -//! [2] -int FolderModel::columnCount(const QModelIndex &parent) const -{ - if (parent.isValid()) - return static_cast(parent.internalPointer())->columnCount(); - else - return rootItem->columnCount(); -} -//! [2] - -//! [3] -QVariant FolderModel::data(const QModelIndex &index, int role) const -{ - if (!index.isValid()) - return QVariant(); - - FolderItem *item = static_cast(index.internalPointer()); - - if (role == Qt::ToolTipRole) - { - QString toolTip = item->data(FolderModel::Name).toString(); - int totalNumOfChildren = item->childCount() + item->comicNames.size(); - if(totalNumOfChildren > 0) - { - toolTip = toolTip + " - " + QString::number(totalNumOfChildren); - } - - return toolTip; - } - - if (role == Qt::DecorationRole) - -#ifdef Q_OS_MAC - if(item->data(FolderModel::Finished).toBool()){ - if(finishedFolderIcon.isNull()){ - drawMacOSXFinishedFolderIcon(); - } - - return QVariant(finishedFolderIcon); - } - else { - return QVariant(QFileIconProvider().icon(QFileIconProvider::Folder)); - } -#else - if(item->data(FolderModel::Finished).toBool()) - return QVariant(YACReader::noHighlightedIcon(":/images/sidebar/folder_finished.png")); - else - return QVariant(YACReader::noHighlightedIcon(":/images/sidebar/folder.png")); -#endif - - if(role == FolderModel::CompletedRole) - return item->data(FolderModel::Completed); - - if(role == FolderModel::FinishedRole) - return item->data(FolderModel::Finished); - - if(role == FolderModel::IdRole) - return item->id; - - if (role != Qt::DisplayRole) - return QVariant(); - - return item->data(index.column()); -} -//! [3] - -//! [4] -Qt::ItemFlags FolderModel::flags(const QModelIndex &index) const -{ - if (!index.isValid()) - return 0; - - return Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsDropEnabled | Qt::ItemIsDragEnabled; -} -//! [4] - -//! [5] -QVariant FolderModel::headerData(int section, Qt::Orientation orientation, - int role) const -{ - if (orientation == Qt::Horizontal && role == Qt::DisplayRole) - return rootItem->data(section); - - return QVariant(); -} -//! [5] - -//! [6] -QModelIndex FolderModel::index(int row, int column, const QModelIndex &parent) - const -{ - if (!hasIndex(row, column, parent)) - return QModelIndex(); - - FolderItem *parentItem; - - if (!parent.isValid()) - parentItem = rootItem; - else - parentItem = static_cast(parent.internalPointer()); - - FolderItem *childItem = parentItem->child(row); - if (childItem) - return createIndex(row, column, childItem); - else - return QModelIndex(); -} -//! [6] - -//! [7] -QModelIndex FolderModel::parent(const QModelIndex &index) const -{ - if (!index.isValid()) - return QModelIndex(); - - FolderItem *childItem = static_cast(index.internalPointer()); - FolderItem *parentItem = childItem->parent(); - - if (parentItem == rootItem) - return QModelIndex(); - - return createIndex(parentItem->row(), 0, parentItem); -} -//! [7] - -/* -QModelIndex FolderModel::indexFromItem(FolderItem * item,int column) -{ - //if(item->parent() != 0) - // return index(item->row(),column,parent(indexFromItem(item->parent(),column-1))); - //else - // return index(item->row(),0,QModelIndex()); - return createIndex(item->row(), column, item); -}*/ - - -//! [8] -int FolderModel::rowCount(const QModelIndex &parent) const -{ - FolderItem *parentItem; - if (parent.column() > 0) - return 0; - - if (!parent.isValid()) - parentItem = rootItem; - else - parentItem = static_cast(parent.internalPointer()); - - return parentItem->childCount(); -} -//! [8] - -void FolderModel::setupModelData(QString path) -{ - beginResetModel(); - if(rootItem != 0) - delete rootItem; //TODO comprobar que se libera bien la memoria - - rootItem = 0; - - //inicializar el nodo ra�z - QList 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; - - //cargar la base de datos - _databasePath = path; - QSqlDatabase db = DataBaseManagement::loadDatabase(path); - //crear la consulta - { - QSqlQuery selectQuery("select * from folder where id <> 1 order by parentId,name",db); - - setupModelData(selectQuery,rootItem); - } - //selectQuery.finish(); - db.close(); - QSqlDatabase::removeDatabase(db.connectionName()); - endResetModel(); - -} - - -void FolderModel::setupModelData(QSqlQuery &sqlquery, FolderItem *parent) -{ - //64 bits para la primary key, es decir la misma precisi�n que soporta sqlit 2^64 - //el diccionario permitir� encontrar cualquier nodo del �rbol r�pidamente, de forma que a�adir un hijo a un padre sea O(1) - items.clear(); - //se a�ade el nodo 0 - items.insert(parent->id,parent); - - QSqlRecord record = sqlquery.record(); - - int name = record.indexOf("name"); - int path = record.indexOf("path"); - int finished = record.indexOf("finished"); - int completed = record.indexOf("completed"); - int id = record.indexOf("id"); - int parentId = record.indexOf("parentId"); - - while (sqlquery.next()) { - QList data; - - data << sqlquery.value(name).toString(); - data << sqlquery.value(path).toString(); - data << sqlquery.value(finished).toBool(); - data << sqlquery.value(completed).toBool(); - FolderItem * item = new FolderItem(data); - - item->id = sqlquery.value(id).toULongLong(); - //la inserci�n de hijos se hace de forma ordenada - FolderItem * parent = items.value(sqlquery.value(parentId).toULongLong()); - //if(parent !=0) //TODO if parent==0 the parent of item was removed from the DB and delete on cascade didn't work, ERROR. - parent->appendChild(item); - //se a�ade el item al map, de forma que se pueda encontrar como padre en siguientes iteraciones - items.insert(item->id,item); - } -} - -void FolderModel::updateFolderModelData(QSqlQuery &sqlquery, FolderItem *parent) -{ - Q_UNUSED(parent); - - QSqlRecord record = sqlquery.record(); - - int name = record.indexOf("name"); - int path = record.indexOf("path"); - int finished = record.indexOf("finished"); - int completed = record.indexOf("completed"); - int id = record.indexOf("id"); - int parentId = record.indexOf("parentId"); - - while (sqlquery.next()) { - QList data; - - data << sqlquery.value(name).toString(); - data << sqlquery.value(path).toString(); - data << sqlquery.value(finished).toBool(); - data << sqlquery.value(completed).toBool(); - FolderItem * item = new FolderItem(data); - - item->id = sqlquery.value(id).toULongLong(); - //la inserci�n de hijos se hace de forma ordenada - FolderItem * parent = items.value(sqlquery.value(parentId).toULongLong()); - if(parent !=0) //TODO if parent==0 the parent of item was removed from the DB and delete on cascade didn't work, ERROR. - parent->appendChild(item); - //se a�ade el item al map, de forma que se pueda encontrar como padre en siguientes iteraciones - items.insert(item->id,item); - } -} - -QString FolderModel::getDatabase() -{ - return _databasePath; -} - -QString FolderModel::getFolderPath(const QModelIndex &folder) -{ - if(!folder.isValid()) //root folder - return "/"; - return static_cast(folder.internalPointer())->data(FolderModel::Path).toString(); -} - -/* -void FolderModel::resetFilter() -{ - beginResetModel(); - filter = ""; - includeComics = false; - //TODO hay que liberar la memoria reservada para el filtrado - //items.clear(); - filteredItems.clear(); - FolderItem * root = rootItem; - rootItem = rootBeforeFilter; //TODO si no se aplica el filtro previamente, esto invalidar�a en modelo - if(root !=0) - delete root; - - rootBeforeFilter = 0; - filterEnabled = false; - endResetModel(); - - -}*/ - -void FolderModel::updateFolderCompletedStatus(const QModelIndexList &list, bool status) -{ - QSqlDatabase db = DataBaseManagement::loadDatabase(_databasePath); - db.transaction(); - foreach (QModelIndex mi, list) - { - FolderItem * item = static_cast(mi.internalPointer()); - item->setData(FolderModel::Completed,status); - - Folder f = DBHelper::loadFolder(item->id,db); - f.setCompleted(status); - DBHelper::update(f,db); - } - db.commit(); - db.close(); - QSqlDatabase::removeDatabase(db.connectionName()); - - emit dataChanged(index(list.first().row(),FolderModel::Name),index(list.last().row(),FolderModel::Completed)); -} - -void FolderModel::updateFolderFinishedStatus(const QModelIndexList &list, bool status) -{ - QSqlDatabase db = DataBaseManagement::loadDatabase(_databasePath); - db.transaction(); - foreach (QModelIndex mi, list) - { - FolderItem * item = static_cast(mi.internalPointer()); - item->setData(FolderModel::Finished,status); - - Folder f = DBHelper::loadFolder(item->id,db); - f.setFinished(status); - DBHelper::update(f,db); - } - db.commit(); - db.close(); - QSqlDatabase::removeDatabase(db.connectionName()); - - emit dataChanged(index(list.first().row(),FolderModel::Name),index(list.last().row(),FolderModel::Completed)); -} - -QStringList FolderModel::getSubfoldersNames(const QModelIndex &mi) -{ - QStringList result; - qulonglong id = 1; - if(mi.isValid()){ - FolderItem * item = static_cast(mi.internalPointer()); - id = item->id; - } - - QSqlDatabase db = DataBaseManagement::loadDatabase(_databasePath); - db.transaction(); - - result = DBHelper::loadSubfoldersNames(id,db); - - db.commit(); - db.close(); - QSqlDatabase::removeDatabase(db.connectionName()); - - //TODO sort result)) - qSort(result.begin(),result.end(),naturalSortLessThanCI); - return result; -} - -void FolderModel::fetchMoreFromDB(const QModelIndex &parent) -{ - FolderItem * item; - if(parent.isValid()) - item = static_cast(parent.internalPointer()); - else - item = rootItem; - - //Remove all children - if(item->childCount() > 0) - { - beginRemoveRows(parent, 0, item->childCount()-1); - item->clearChildren(); - endRemoveRows(); - } - - QSqlDatabase db = DataBaseManagement::loadDatabase(_databasePath); - - QList items; - QList nextLevelItems; - - QSqlQuery selectQuery(db); - selectQuery.prepare("select * from folder where id <> 1 and parentId = :parentId order by parentId,name"); - - items << item; - bool firstLevelUpdated = false; - while(items.size() > 0) - { - nextLevelItems.clear(); - foreach(FolderItem * item, items) - { - QLOG_DEBUG() << "ID " << item->id; - selectQuery.bindValue(":parentId", item->id); - - selectQuery.exec(); - - if(!firstLevelUpdated) - { - //NO size support - int numResults = 0; - while(selectQuery.next()) - numResults++; - - if(!selectQuery.seek(-1)) - selectQuery.exec(); - //END no size support - - beginInsertRows(parent, 0, numResults-1); - } - - updateFolderModelData(selectQuery,item); - - if(!firstLevelUpdated) - { - endInsertRows(); - firstLevelUpdated = true; - } - - nextLevelItems << item->children(); - - } - - items.clear(); - items = nextLevelItems; - } - - QLOG_DEBUG() << "item->childCount()-1" << item->childCount()-1; - - - db.close(); - QSqlDatabase::removeDatabase(db.connectionName()); -} - -QModelIndex FolderModel::addFolderAtParent(const QString &folderName, const QModelIndex &parent) -{ - FolderItem * parentItem; - - if(parent.isValid()) - parentItem = static_cast(parent.internalPointer()); - else - parentItem = rootItem; - - Folder newFolder; - newFolder.name = folderName; - newFolder.parentId = parentItem->id; - newFolder.path = parentItem->data(1).toString() + "/" + folderName; - - QSqlDatabase db = DataBaseManagement::loadDatabase(_databasePath); - newFolder.id = DBHelper::insert(&newFolder, db); - DBHelper::updateChildrenInfo(parentItem->id, db); - QSqlDatabase::removeDatabase(db.connectionName()); - - int destRow = 0; - - QList data; - data << newFolder.name; - data << newFolder.path; - data << false; //finished - data << true; //completed - - FolderItem * item = new FolderItem(data); - item->id = newFolder.id; - - beginInsertRows(parent,0,0); //TODO calculate the destRow before inserting the new child - - parentItem->appendChild(item); - destRow = parentItem->children().indexOf(item); //TODO optimize this, appendChild should return the index of the new item - items.insert(item->id,item); - - endInsertRows(); - - return index(destRow,0,parent); -} - -void FolderModel::deleteFolder(const QModelIndex &mi) -{ - beginRemoveRows(mi.parent(),mi.row(),mi.row()); - - FolderItem * item = static_cast(mi.internalPointer()); - - FolderItem * parent = item->parent(); - parent->removeChild(mi.row()); - - Folder f; - f.setId(item->id); - - QSqlDatabase db = DataBaseManagement::loadDatabase(_databasePath); - DBHelper::removeFromDB(&f,db); - DBHelper::updateChildrenInfo(item->parent()->id, db); - QSqlDatabase::removeDatabase(db.connectionName()); - - endRemoveRows(); -} - -void FolderModel::updateFolderChildrenInfo(qulonglong folderId) -{ - QSqlDatabase db = DataBaseManagement::loadDatabase(_databasePath); - DBHelper::updateChildrenInfo(folderId, db); - QSqlDatabase::removeDatabase(db.connectionName()); -} - -//PROXY - -FolderModelProxy::FolderModelProxy(QObject *parent) - :QSortFilterProxyModel(parent),rootItem(0),filterEnabled(false),filter(""),includeComics(true) -{ - -} - -FolderModelProxy::~FolderModelProxy() -{ - -} - -bool FolderModelProxy::filterAcceptsRow(int source_row, const QModelIndex &source_parent) const -{ - if(!filterEnabled) - return true; - - FolderItem * parent = static_cast(source_parent.internalPointer()); - - if(parent == 0) - parent = static_cast(sourceModel())->rootItem; - - FolderItem * item = parent->children().at(source_row); - - return filteredItems.contains(item->id); -} - -void FolderModelProxy::setFilter(const YACReader::SearchModifiers modifier, QString filter, bool includeComics) -{ - clear(); - this->filter = filter; - this->includeComics = includeComics; - this->modifier = modifier; - filterEnabled = true; - setupFilteredModelData(); -} - -void FolderModelProxy::setupFilteredModelData() -{ - beginResetModel(); - - //TODO hay que liberar memoria de anteriores filtrados - - //inicializar el nodo ra�z - - if(rootItem != 0) - delete rootItem; //TODO comprobar que se libera bien la memoria - - rootItem = 0; - - //inicializar el nodo ra�z - QList rootData; - rootData << "root"; - rootItem = new FolderItem(rootData); - rootItem->id = ROOT; - rootItem->parentItem = 0; - - FolderModel * model = static_cast(sourceModel()); - - //cargar la base de datos - QSqlDatabase db = DataBaseManagement::loadDatabase(model->_databasePath); - //crear la consulta - { - QSqlQuery selectQuery(db); //TODO check - if(!includeComics) - { - selectQuery.prepare("select * from folder where id <> 1 and upper(name) like upper(:filter) order by parentId,name "); - selectQuery.bindValue(":filter", "%%"+filter+"%%"); - } - else - { - switch(modifier) - { - case YACReader::NoModifiers: - selectQuery.prepare("SELECT DISTINCT f.id, f.parentId, f.name, f.path, f.finished, f.completed " - "FROM folder f LEFT JOIN comic c ON (f.id = c.parentId) " - "WHERE f.id <> 1 AND ((UPPER(c.fileName) like UPPER(:filter)) OR (UPPER(f.name) like UPPER(:filter2))) ORDER BY f.parentId,f.name"); - selectQuery.bindValue(":filter", "%%"+filter+"%%"); - selectQuery.bindValue(":filter2", "%%"+filter+"%%"); - break; - - case YACReader::OnlyRead: - selectQuery.prepare("SELECT DISTINCT f.id, f.parentId, f.name, f.path, f.finished, f.completed " - "FROM folder f LEFT JOIN (comic c INNER JOIN comic_info ci ON (c.comicInfoId = ci.id)) ON (f.id = c.parentId) " - "WHERE f.id <> 1 AND ((UPPER(c.fileName) like UPPER(:filter)) OR (UPPER(f.name) like UPPER(:filter2))) AND ci.read = 1 ORDER BY f.parentId,f.name;"); - selectQuery.bindValue(":filter", "%%"+filter+"%%"); - selectQuery.bindValue(":filter2", "%%"+filter+"%%"); - break; - - case YACReader::OnlyUnread: - selectQuery.prepare("SELECT DISTINCT f.id, f.parentId, f.name, f.path, f.finished, f.completed " - "FROM folder f LEFT JOIN (comic c INNER JOIN comic_info ci ON (c.comicInfoId = ci.id)) ON (f.id = c.parentId) " - "WHERE f.id <> 1 AND ((UPPER(c.fileName) like UPPER(:filter)) OR (UPPER(f.name) like UPPER(:filter2))) AND ci.read = 0 ORDER BY f.parentId,f.name;"); - selectQuery.bindValue(":filter", "%%"+filter+"%%"); - selectQuery.bindValue(":filter2", "%%"+filter+"%%"); - break; - - default: - QLOG_ERROR() << "not implemented"; - break; - - } - - - } - selectQuery.exec(); - - setupFilteredModelData(selectQuery,rootItem); - } - //selectQuery.finish(); - db.close(); - QSqlDatabase::removeDatabase(db.connectionName()); - - endResetModel(); -} - -void FolderModelProxy::clear() -{ - filterEnabled = false; - - filteredItems.clear(); - - QSortFilterProxyModel::clear(); -} - -void FolderModelProxy::setupFilteredModelData(QSqlQuery &sqlquery, FolderItem *parent) -{ - FolderModel * model = static_cast(sourceModel()); - - //64 bits para la primary key, es decir la misma precisi�n que soporta sqlit 2^64 - filteredItems.clear(); - - //se a�ade el nodo 0 al modelo que representa el arbol de elementos que cumplen con el filtro - filteredItems.insert(parent->id,parent); - - QSqlRecord record = sqlquery.record(); - - int name = record.indexOf("name"); - int path = record.indexOf("path"); - int finished = record.indexOf("finished"); - int completed = record.indexOf("completed"); - int parentIdIndex = record.indexOf("parentId"); - - while (sqlquery.next()) { //se procesan todos los folders que cumplen con el filtro - //datos de la base de datos - QList data; - - data << sqlquery.value(name).toString(); - data << sqlquery.value(path).toString(); - data << sqlquery.value(finished).toBool(); - data << sqlquery.value(completed).toBool(); - - FolderItem * item = new FolderItem(data); - item->id = sqlquery.value(0).toULongLong(); - - //id del padre - quint64 parentId = sqlquery.value(parentIdIndex).toULongLong(); - - //se a�ade el item al map, de forma que se pueda encontrar como padre en siguientes iteraciones - if(!filteredItems.contains(item->id)) - filteredItems.insert(item->id,item); - - //es necesario conocer las coordenadas de origen para poder realizar scroll autom�tico en la vista - item->originalItem = model->items.value(item->id); - - //si el padre ya existe en el modelo, el item se a�ade como hijo - if(filteredItems.contains(parentId)) - filteredItems.value(parentId)->appendChild(item); - else//si el padre a�n no se ha a�adido, hay que a�adirlo a �l y todos los padres hasta el nodo ra�z - { - //comprobamos con esta variable si el �ltimo de los padres (antes del nodo ra�z) ya exist�a en el modelo - bool parentPreviousInserted = false; - - //mientras no se alcance el nodo ra�z se procesan todos los padres (de abajo a arriba) - while(parentId != ROOT ) - { - //el padre no estaba en el modelo filtrado, as� que se rescata del modelo original - FolderItem * parentItem = model->items.value(parentId); - //se debe crear un nuevo nodo (para no compartir los hijos con el nodo original) - FolderItem * newparentItem = new FolderItem(parentItem->getData()); //padre que se a�adir� a la estructura de directorios filtrados - newparentItem->id = parentId; - - newparentItem->originalItem = parentItem; - - //si el modelo contiene al padre, se a�ade el item actual como hijo - if(filteredItems.contains(parentId)) - { - filteredItems.value(parentId)->appendChild(item); - parentPreviousInserted = true; - } - //sino se registra el nodo para poder encontrarlo con posterioridad y se a�ade el item actual como hijo - else - { - newparentItem->appendChild(item); - filteredItems.insert(newparentItem->id,newparentItem); - parentPreviousInserted = false; - } - - //variables de control del bucle, se avanza hacia el nodo padre - item = newparentItem; - parentId = parentItem->parentItem->id; - } - - //si el nodo es hijo de 1 y no hab�a sido previamente insertado como hijo, se a�ade como tal - if(!parentPreviousInserted) - { - filteredItems.value(ROOT)->appendChild(item); - } - else - { - delete item; - } - } - } -} +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** $QT_END_LICENSE$ +** +****************************************************************************/ + +/* + treemodel.cpp + + Provides a simple tree model to show how to create and use hierarchical + models. +*/ + +#include + + +#include "folder_item.h" +#include "folder_model.h" +#include "data_base_management.h" +#include "folder.h" +#include "db_helper.h" +#include "qnaturalsorting.h" +#include "yacreader_global_gui.h" +#include "QsLog.h" + +#ifdef Q_OS_MAC +#include +QIcon finishedFolderIcon; +void drawMacOSXFinishedFolderIcon() +{ + QIcon ico = QFileIconProvider().icon(QFileIconProvider::Folder); + QPixmap pixNormalOff = ico.pixmap(16,16, QIcon::Normal, QIcon::Off); + QPixmap pixNormalOn = ico.pixmap(16,16, QIcon::Normal, QIcon::On); + QPixmap pixSelectedOff = ico.pixmap(16,16, QIcon::Selected, QIcon::Off); + QPixmap pixSelectedOn = ico.pixmap(16,16, QIcon::Selected, QIcon::On); + QPixmap tick(":/images/folder_finished_macosx.png"); + + + { + QPainter p(&pixNormalOff); + p.drawPixmap(4,7,tick); + } + finishedFolderIcon.addPixmap(pixNormalOff, QIcon::Normal, QIcon::Off); + + { + QPainter p(&pixNormalOn); + p.drawPixmap(4,7,tick); + } + finishedFolderIcon.addPixmap(pixNormalOn, QIcon::Normal, QIcon::On); + + { + QPainter p(&pixSelectedOff); + p.drawPixmap(4,7,tick); + } + finishedFolderIcon.addPixmap(pixSelectedOff, QIcon::Selected, QIcon::Off); + + { + QPainter p(&pixSelectedOn); + p.drawPixmap(4,7,tick); + } + finishedFolderIcon.addPixmap(pixSelectedOn, QIcon::Selected, QIcon::On); +} +#endif + +#define ROOT 1 + +FolderModel::FolderModel(QObject *parent) + : QAbstractItemModel(parent),rootItem(0) +{ + connect(this,SIGNAL(beforeReset()),this,SIGNAL(modelAboutToBeReset())); + connect(this,SIGNAL(reset()),this,SIGNAL(modelReset())); +} + +//! [0] +FolderModel::FolderModel( QSqlQuery &sqlquery, QObject *parent) + : QAbstractItemModel(parent),rootItem(0) +{ + //lo m�s probable es que el nodo ra�z no necesite tener informaci�n + QList 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; + setupModelData(sqlquery, rootItem); + //sqlquery.finish(); +} +//! [0] + +//! [1] +FolderModel::~FolderModel() +{ + if(rootItem != 0) + delete rootItem; +} +//! [1] + +//! [2] +int FolderModel::columnCount(const QModelIndex &parent) const +{ + if (parent.isValid()) + return static_cast(parent.internalPointer())->columnCount(); + else + return rootItem->columnCount(); +} +//! [2] + +//! [3] +QVariant FolderModel::data(const QModelIndex &index, int role) const +{ + if (!index.isValid()) + return QVariant(); + + FolderItem *item = static_cast(index.internalPointer()); + + if (role == Qt::ToolTipRole) + { + QString toolTip = item->data(FolderModel::Name).toString(); + int totalNumOfChildren = item->childCount() + item->comicNames.size(); + if(totalNumOfChildren > 0) + { + toolTip = toolTip + " - " + QString::number(totalNumOfChildren); + } + + return toolTip; + } + + if (role == Qt::DecorationRole) + +#ifdef Q_OS_MAC + if(item->data(FolderModel::Finished).toBool()){ + if(finishedFolderIcon.isNull()){ + drawMacOSXFinishedFolderIcon(); + } + + return QVariant(finishedFolderIcon); + } + else { + return QVariant(QFileIconProvider().icon(QFileIconProvider::Folder)); + } +#else + if(item->data(FolderModel::Finished).toBool()) + return QVariant(YACReader::noHighlightedIcon(":/images/sidebar/folder_finished.png")); + else + return QVariant(YACReader::noHighlightedIcon(":/images/sidebar/folder.png")); +#endif + + if(role == FolderModel::CompletedRole) + return item->data(FolderModel::Completed); + + if(role == FolderModel::FinishedRole) + return item->data(FolderModel::Finished); + + if(role == FolderModel::IdRole) + return item->id; + + if (role != Qt::DisplayRole) + return QVariant(); + + return item->data(index.column()); +} +//! [3] + +//! [4] +Qt::ItemFlags FolderModel::flags(const QModelIndex &index) const +{ + if (!index.isValid()) + return 0; + + return Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsDropEnabled | Qt::ItemIsDragEnabled; +} +//! [4] + +//! [5] +QVariant FolderModel::headerData(int section, Qt::Orientation orientation, + int role) const +{ + if (orientation == Qt::Horizontal && role == Qt::DisplayRole) + return rootItem->data(section); + + return QVariant(); +} +//! [5] + +//! [6] +QModelIndex FolderModel::index(int row, int column, const QModelIndex &parent) + const +{ + if (!hasIndex(row, column, parent)) + return QModelIndex(); + + FolderItem *parentItem; + + if (!parent.isValid()) + parentItem = rootItem; + else + parentItem = static_cast(parent.internalPointer()); + + FolderItem *childItem = parentItem->child(row); + if (childItem) + return createIndex(row, column, childItem); + else + return QModelIndex(); +} +//! [6] + +//! [7] +QModelIndex FolderModel::parent(const QModelIndex &index) const +{ + if (!index.isValid()) + return QModelIndex(); + + FolderItem *childItem = static_cast(index.internalPointer()); + FolderItem *parentItem = childItem->parent(); + + if (parentItem == rootItem) + return QModelIndex(); + + return createIndex(parentItem->row(), 0, parentItem); +} +//! [7] + +/* +QModelIndex FolderModel::indexFromItem(FolderItem * item,int column) +{ + //if(item->parent() != 0) + // return index(item->row(),column,parent(indexFromItem(item->parent(),column-1))); + //else + // return index(item->row(),0,QModelIndex()); + return createIndex(item->row(), column, item); +}*/ + + +//! [8] +int FolderModel::rowCount(const QModelIndex &parent) const +{ + FolderItem *parentItem; + if (parent.column() > 0) + return 0; + + if (!parent.isValid()) + parentItem = rootItem; + else + parentItem = static_cast(parent.internalPointer()); + + return parentItem->childCount(); +} +//! [8] + +void FolderModel::setupModelData(QString path) +{ + beginResetModel(); + if(rootItem != 0) + delete rootItem; //TODO comprobar que se libera bien la memoria + + rootItem = 0; + + //inicializar el nodo ra�z + QList 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; + + //cargar la base de datos + _databasePath = path; + QSqlDatabase db = DataBaseManagement::loadDatabase(path); + //crear la consulta + { + QSqlQuery selectQuery("select * from folder where id <> 1 order by parentId,name",db); + + setupModelData(selectQuery,rootItem); + } + //selectQuery.finish(); + db.close(); + QSqlDatabase::removeDatabase(db.connectionName()); + endResetModel(); + +} + + +void FolderModel::setupModelData(QSqlQuery &sqlquery, FolderItem *parent) +{ + //64 bits para la primary key, es decir la misma precisi�n que soporta sqlit 2^64 + //el diccionario permitir� encontrar cualquier nodo del �rbol r�pidamente, de forma que a�adir un hijo a un padre sea O(1) + items.clear(); + //se a�ade el nodo 0 + items.insert(parent->id,parent); + + QSqlRecord record = sqlquery.record(); + + int name = record.indexOf("name"); + int path = record.indexOf("path"); + int finished = record.indexOf("finished"); + int completed = record.indexOf("completed"); + int id = record.indexOf("id"); + int parentId = record.indexOf("parentId"); + + while (sqlquery.next()) { + QList data; + + data << sqlquery.value(name).toString(); + data << sqlquery.value(path).toString(); + data << sqlquery.value(finished).toBool(); + data << sqlquery.value(completed).toBool(); + FolderItem * item = new FolderItem(data); + + item->id = sqlquery.value(id).toULongLong(); + //la inserci�n de hijos se hace de forma ordenada + FolderItem * parent = items.value(sqlquery.value(parentId).toULongLong()); + //if(parent !=0) //TODO if parent==0 the parent of item was removed from the DB and delete on cascade didn't work, ERROR. + parent->appendChild(item); + //se a�ade el item al map, de forma que se pueda encontrar como padre en siguientes iteraciones + items.insert(item->id,item); + } +} + +void FolderModel::updateFolderModelData(QSqlQuery &sqlquery, FolderItem *parent) +{ + Q_UNUSED(parent); + + QSqlRecord record = sqlquery.record(); + + int name = record.indexOf("name"); + int path = record.indexOf("path"); + int finished = record.indexOf("finished"); + int completed = record.indexOf("completed"); + int id = record.indexOf("id"); + int parentId = record.indexOf("parentId"); + + while (sqlquery.next()) { + QList data; + + data << sqlquery.value(name).toString(); + data << sqlquery.value(path).toString(); + data << sqlquery.value(finished).toBool(); + data << sqlquery.value(completed).toBool(); + FolderItem * item = new FolderItem(data); + + item->id = sqlquery.value(id).toULongLong(); + //la inserci�n de hijos se hace de forma ordenada + FolderItem * parent = items.value(sqlquery.value(parentId).toULongLong()); + if(parent !=0) //TODO if parent==0 the parent of item was removed from the DB and delete on cascade didn't work, ERROR. + parent->appendChild(item); + //se a�ade el item al map, de forma que se pueda encontrar como padre en siguientes iteraciones + items.insert(item->id,item); + } +} + +QString FolderModel::getDatabase() +{ + return _databasePath; +} + +QString FolderModel::getFolderPath(const QModelIndex &folder) +{ + if(!folder.isValid()) //root folder + return "/"; + return static_cast(folder.internalPointer())->data(FolderModel::Path).toString(); +} + +/* +void FolderModel::resetFilter() +{ + beginResetModel(); + filter = ""; + includeComics = false; + //TODO hay que liberar la memoria reservada para el filtrado + //items.clear(); + filteredItems.clear(); + FolderItem * root = rootItem; + rootItem = rootBeforeFilter; //TODO si no se aplica el filtro previamente, esto invalidar�a en modelo + if(root !=0) + delete root; + + rootBeforeFilter = 0; + filterEnabled = false; + endResetModel(); + + +}*/ + +void FolderModel::updateFolderCompletedStatus(const QModelIndexList &list, bool status) +{ + QSqlDatabase db = DataBaseManagement::loadDatabase(_databasePath); + db.transaction(); + foreach (QModelIndex mi, list) + { + FolderItem * item = static_cast(mi.internalPointer()); + item->setData(FolderModel::Completed,status); + + Folder f = DBHelper::loadFolder(item->id,db); + f.setCompleted(status); + DBHelper::update(f,db); + } + db.commit(); + db.close(); + QSqlDatabase::removeDatabase(db.connectionName()); + + emit dataChanged(index(list.first().row(),FolderModel::Name),index(list.last().row(),FolderModel::Completed)); +} + +void FolderModel::updateFolderFinishedStatus(const QModelIndexList &list, bool status) +{ + QSqlDatabase db = DataBaseManagement::loadDatabase(_databasePath); + db.transaction(); + foreach (QModelIndex mi, list) + { + FolderItem * item = static_cast(mi.internalPointer()); + item->setData(FolderModel::Finished,status); + + Folder f = DBHelper::loadFolder(item->id,db); + f.setFinished(status); + DBHelper::update(f,db); + } + db.commit(); + db.close(); + QSqlDatabase::removeDatabase(db.connectionName()); + + emit dataChanged(index(list.first().row(),FolderModel::Name),index(list.last().row(),FolderModel::Completed)); +} + +QStringList FolderModel::getSubfoldersNames(const QModelIndex &mi) +{ + QStringList result; + qulonglong id = 1; + if(mi.isValid()){ + FolderItem * item = static_cast(mi.internalPointer()); + id = item->id; + } + + QSqlDatabase db = DataBaseManagement::loadDatabase(_databasePath); + db.transaction(); + + result = DBHelper::loadSubfoldersNames(id,db); + + db.commit(); + db.close(); + QSqlDatabase::removeDatabase(db.connectionName()); + + //TODO sort result)) + qSort(result.begin(),result.end(),naturalSortLessThanCI); + return result; +} + +void FolderModel::fetchMoreFromDB(const QModelIndex &parent) +{ + FolderItem * item; + if(parent.isValid()) + item = static_cast(parent.internalPointer()); + else + item = rootItem; + + //Remove all children + if(item->childCount() > 0) + { + beginRemoveRows(parent, 0, item->childCount()-1); + item->clearChildren(); + endRemoveRows(); + } + + QSqlDatabase db = DataBaseManagement::loadDatabase(_databasePath); + + QList items; + QList nextLevelItems; + + QSqlQuery selectQuery(db); + selectQuery.prepare("select * from folder where id <> 1 and parentId = :parentId order by parentId,name"); + + items << item; + bool firstLevelUpdated = false; + while(items.size() > 0) + { + nextLevelItems.clear(); + foreach(FolderItem * item, items) + { + QLOG_DEBUG() << "ID " << item->id; + selectQuery.bindValue(":parentId", item->id); + + selectQuery.exec(); + + if(!firstLevelUpdated) + { + //NO size support + int numResults = 0; + while(selectQuery.next()) + numResults++; + + if(!selectQuery.seek(-1)) + selectQuery.exec(); + //END no size support + + beginInsertRows(parent, 0, numResults-1); + } + + updateFolderModelData(selectQuery,item); + + if(!firstLevelUpdated) + { + endInsertRows(); + firstLevelUpdated = true; + } + + nextLevelItems << item->children(); + + } + + items.clear(); + items = nextLevelItems; + } + + QLOG_DEBUG() << "item->childCount()-1" << item->childCount()-1; + + + db.close(); + QSqlDatabase::removeDatabase(db.connectionName()); +} + +QModelIndex FolderModel::addFolderAtParent(const QString &folderName, const QModelIndex &parent) +{ + FolderItem * parentItem; + + if(parent.isValid()) + parentItem = static_cast(parent.internalPointer()); + else + parentItem = rootItem; + + Folder newFolder; + newFolder.name = folderName; + newFolder.parentId = parentItem->id; + newFolder.path = parentItem->data(1).toString() + "/" + folderName; + + QSqlDatabase db = DataBaseManagement::loadDatabase(_databasePath); + newFolder.id = DBHelper::insert(&newFolder, db); + DBHelper::updateChildrenInfo(parentItem->id, db); + QSqlDatabase::removeDatabase(db.connectionName()); + + int destRow = 0; + + QList data; + data << newFolder.name; + data << newFolder.path; + data << false; //finished + data << true; //completed + + FolderItem * item = new FolderItem(data); + item->id = newFolder.id; + + beginInsertRows(parent,0,0); //TODO calculate the destRow before inserting the new child + + parentItem->appendChild(item); + destRow = parentItem->children().indexOf(item); //TODO optimize this, appendChild should return the index of the new item + items.insert(item->id,item); + + endInsertRows(); + + return index(destRow,0,parent); +} + +void FolderModel::deleteFolder(const QModelIndex &mi) +{ + beginRemoveRows(mi.parent(),mi.row(),mi.row()); + + FolderItem * item = static_cast(mi.internalPointer()); + + FolderItem * parent = item->parent(); + parent->removeChild(mi.row()); + + Folder f; + f.setId(item->id); + + QSqlDatabase db = DataBaseManagement::loadDatabase(_databasePath); + DBHelper::removeFromDB(&f,db); + DBHelper::updateChildrenInfo(item->parent()->id, db); + QSqlDatabase::removeDatabase(db.connectionName()); + + endRemoveRows(); +} + +void FolderModel::updateFolderChildrenInfo(qulonglong folderId) +{ + QSqlDatabase db = DataBaseManagement::loadDatabase(_databasePath); + DBHelper::updateChildrenInfo(folderId, db); + QSqlDatabase::removeDatabase(db.connectionName()); +} + +//PROXY + +FolderModelProxy::FolderModelProxy(QObject *parent) + :QSortFilterProxyModel(parent),rootItem(0),filterEnabled(false),filter(""),includeComics(true) +{ + +} + +FolderModelProxy::~FolderModelProxy() +{ + +} + +bool FolderModelProxy::filterAcceptsRow(int source_row, const QModelIndex &source_parent) const +{ + if(!filterEnabled) + return true; + + FolderItem * parent = static_cast(source_parent.internalPointer()); + + if(parent == 0) + parent = static_cast(sourceModel())->rootItem; + + FolderItem * item = parent->children().at(source_row); + + return filteredItems.contains(item->id); +} + +void FolderModelProxy::setFilter(const YACReader::SearchModifiers modifier, QString filter, bool includeComics) +{ + clear(); + this->filter = filter; + this->includeComics = includeComics; + this->modifier = modifier; + filterEnabled = true; + setupFilteredModelData(); +} + +void FolderModelProxy::setupFilteredModelData() +{ + beginResetModel(); + + //TODO hay que liberar memoria de anteriores filtrados + + //inicializar el nodo ra�z + + if(rootItem != 0) + delete rootItem; //TODO comprobar que se libera bien la memoria + + rootItem = 0; + + //inicializar el nodo ra�z + QList rootData; + rootData << "root"; + rootItem = new FolderItem(rootData); + rootItem->id = ROOT; + rootItem->parentItem = 0; + + FolderModel * model = static_cast(sourceModel()); + + //cargar la base de datos + QSqlDatabase db = DataBaseManagement::loadDatabase(model->_databasePath); + //crear la consulta + { + QSqlQuery selectQuery(db); //TODO check + if(!includeComics) + { + selectQuery.prepare("select * from folder where id <> 1 and upper(name) like upper(:filter) order by parentId,name "); + selectQuery.bindValue(":filter", "%%"+filter+"%%"); + } + else + { + switch(modifier) + { + case YACReader::NoModifiers: + selectQuery.prepare("SELECT DISTINCT f.id, f.parentId, f.name, f.path, f.finished, f.completed " + "FROM folder f LEFT JOIN comic c ON (f.id = c.parentId) " + "WHERE f.id <> 1 AND ((UPPER(c.fileName) like UPPER(:filter)) OR (UPPER(f.name) like UPPER(:filter2))) ORDER BY f.parentId,f.name"); + selectQuery.bindValue(":filter", "%%"+filter+"%%"); + selectQuery.bindValue(":filter2", "%%"+filter+"%%"); + break; + + case YACReader::OnlyRead: + selectQuery.prepare("SELECT DISTINCT f.id, f.parentId, f.name, f.path, f.finished, f.completed " + "FROM folder f LEFT JOIN (comic c INNER JOIN comic_info ci ON (c.comicInfoId = ci.id)) ON (f.id = c.parentId) " + "WHERE f.id <> 1 AND ((UPPER(c.fileName) like UPPER(:filter)) OR (UPPER(f.name) like UPPER(:filter2))) AND ci.read = 1 ORDER BY f.parentId,f.name;"); + selectQuery.bindValue(":filter", "%%"+filter+"%%"); + selectQuery.bindValue(":filter2", "%%"+filter+"%%"); + break; + + case YACReader::OnlyUnread: + selectQuery.prepare("SELECT DISTINCT f.id, f.parentId, f.name, f.path, f.finished, f.completed " + "FROM folder f LEFT JOIN (comic c INNER JOIN comic_info ci ON (c.comicInfoId = ci.id)) ON (f.id = c.parentId) " + "WHERE f.id <> 1 AND ((UPPER(c.fileName) like UPPER(:filter)) OR (UPPER(f.name) like UPPER(:filter2))) AND ci.read = 0 ORDER BY f.parentId,f.name;"); + selectQuery.bindValue(":filter", "%%"+filter+"%%"); + selectQuery.bindValue(":filter2", "%%"+filter+"%%"); + break; + + default: + QLOG_ERROR() << "not implemented"; + break; + + } + + + } + selectQuery.exec(); + + setupFilteredModelData(selectQuery,rootItem); + } + //selectQuery.finish(); + db.close(); + QSqlDatabase::removeDatabase(db.connectionName()); + + endResetModel(); +} + +void FolderModelProxy::clear() +{ + filterEnabled = false; + + filteredItems.clear(); + + QSortFilterProxyModel::clear(); +} + +void FolderModelProxy::setupFilteredModelData(QSqlQuery &sqlquery, FolderItem *parent) +{ + FolderModel * model = static_cast(sourceModel()); + + //64 bits para la primary key, es decir la misma precisi�n que soporta sqlit 2^64 + filteredItems.clear(); + + //se a�ade el nodo 0 al modelo que representa el arbol de elementos que cumplen con el filtro + filteredItems.insert(parent->id,parent); + + QSqlRecord record = sqlquery.record(); + + int name = record.indexOf("name"); + int path = record.indexOf("path"); + int finished = record.indexOf("finished"); + int completed = record.indexOf("completed"); + int parentIdIndex = record.indexOf("parentId"); + + while (sqlquery.next()) { //se procesan todos los folders que cumplen con el filtro + //datos de la base de datos + QList data; + + data << sqlquery.value(name).toString(); + data << sqlquery.value(path).toString(); + data << sqlquery.value(finished).toBool(); + data << sqlquery.value(completed).toBool(); + + FolderItem * item = new FolderItem(data); + item->id = sqlquery.value(0).toULongLong(); + + //id del padre + quint64 parentId = sqlquery.value(parentIdIndex).toULongLong(); + + //se a�ade el item al map, de forma que se pueda encontrar como padre en siguientes iteraciones + if(!filteredItems.contains(item->id)) + filteredItems.insert(item->id,item); + + //es necesario conocer las coordenadas de origen para poder realizar scroll autom�tico en la vista + item->originalItem = model->items.value(item->id); + + //si el padre ya existe en el modelo, el item se a�ade como hijo + if(filteredItems.contains(parentId)) + filteredItems.value(parentId)->appendChild(item); + else//si el padre a�n no se ha a�adido, hay que a�adirlo a �l y todos los padres hasta el nodo ra�z + { + //comprobamos con esta variable si el �ltimo de los padres (antes del nodo ra�z) ya exist�a en el modelo + bool parentPreviousInserted = false; + + //mientras no se alcance el nodo ra�z se procesan todos los padres (de abajo a arriba) + while(parentId != ROOT ) + { + //el padre no estaba en el modelo filtrado, as� que se rescata del modelo original + FolderItem * parentItem = model->items.value(parentId); + //se debe crear un nuevo nodo (para no compartir los hijos con el nodo original) + FolderItem * newparentItem = new FolderItem(parentItem->getData()); //padre que se a�adir� a la estructura de directorios filtrados + newparentItem->id = parentId; + + newparentItem->originalItem = parentItem; + + //si el modelo contiene al padre, se a�ade el item actual como hijo + if(filteredItems.contains(parentId)) + { + filteredItems.value(parentId)->appendChild(item); + parentPreviousInserted = true; + } + //sino se registra el nodo para poder encontrarlo con posterioridad y se a�ade el item actual como hijo + else + { + newparentItem->appendChild(item); + filteredItems.insert(newparentItem->id,newparentItem); + parentPreviousInserted = false; + } + + //variables de control del bucle, se avanza hacia el nodo padre + item = newparentItem; + parentId = parentItem->parentItem->id; + } + + //si el nodo es hijo de 1 y no hab�a sido previamente insertado como hijo, se a�ade como tal + if(!parentPreviousInserted) + { + filteredItems.value(ROOT)->appendChild(item); + } + else + { + delete item; + } + } + } +} diff --git a/YACReaderLibrary/db/folder_model.h b/YACReaderLibrary/db/folder_model.h index ae28a33c..da83bf5d 100644 --- a/YACReaderLibrary/db/folder_model.h +++ b/YACReaderLibrary/db/folder_model.h @@ -1,153 +1,153 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the examples of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:BSD$ -** You may use this file under the terms of the BSD license as follows: -** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor -** the names of its contributors may be used to endorse or promote -** products derived from this software without specific prior written -** permission. -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef TREEMODEL_H -#define TREEMODEL_H - -#include -#include -#include -#include -#include -#include - -#include "yacreader_global.h" - -class FolderItem; - -class FolderModelProxy : public QSortFilterProxyModel -{ - Q_OBJECT -public: - explicit FolderModelProxy(QObject *parent = 0); - ~FolderModelProxy(); - - void setFilter(const YACReader::SearchModifiers modifier, QString filter, bool includeComics); - void setupFilteredModelData( QSqlQuery &sqlquery, FolderItem *parent); - void setupFilteredModelData(); - void clear(); - - bool filterAcceptsRow(int source_row, const QModelIndex &source_parent) const; - -protected: - FolderItem *rootItem; - QMap filteredItems; //relación entre folders - - bool includeComics; - QString filter; - bool filterEnabled; - - YACReader::SearchModifiers modifier; -}; - -class FolderModel : public QAbstractItemModel -{ - - Q_OBJECT - - friend class FolderModelProxy; - -public: - FolderModel(QObject *parent = 0); - FolderModel( QSqlQuery &sqlquery, QObject *parent = 0); - ~FolderModel(); - - //QAbstractItemModel methods - QVariant data(const QModelIndex &index, int role) const; - Qt::ItemFlags flags(const QModelIndex &index) const; - QVariant headerData(int section, Qt::Orientation orientation, - int role = Qt::DisplayRole) const; - QModelIndex index(int row, int column, - const QModelIndex &parent = QModelIndex()) const; - QModelIndex parent(const QModelIndex &index) const; - int rowCount(const QModelIndex &parent = QModelIndex()) const; - int columnCount(const QModelIndex &parent = QModelIndex()) const; - - //Convenience methods - void setupModelData(QString path); - QString getDatabase(); - QString getFolderPath(const QModelIndex &folder); - //QModelIndex indexFromItem(FolderItem * item, int column); - - - //bool isFilterEnabled(){return filterEnabled;}; - - void updateFolderCompletedStatus(const QModelIndexList & list, bool status); - void updateFolderFinishedStatus(const QModelIndexList & list, bool status); - - QStringList getSubfoldersNames(const QModelIndex & mi); - - void fetchMoreFromDB(const QModelIndex & parent); - - QModelIndex addFolderAtParent(const QString & folderName, const QModelIndex & parent); - - enum Columns { - Name = 0, - Path = 1, - Finished = 2, - Completed = 3 - };//id INTEGER PRIMARY KEY, parentId INTEGER NOT NULL, name TEXT NOT NULL, path TEXT NOT NULL - - enum Roles { - FinishedRole = Qt::UserRole + 1, - CompletedRole, - IdRole - }; - -public slots: - void deleteFolder(const QModelIndex & mi); - void updateFolderChildrenInfo(qulonglong folderId); - -private: - void setupModelData( QSqlQuery &sqlquery, FolderItem *parent); - void updateFolderModelData( QSqlQuery &sqlquery, FolderItem *parent); - - FolderItem *rootItem; //el árbol - QMap items; //relación entre folders - - QString _databasePath; - -signals: - void beforeReset(); - void reset(); -}; -//! [0] - -#endif +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef TREEMODEL_H +#define TREEMODEL_H + +#include +#include +#include +#include +#include +#include + +#include "yacreader_global.h" + +class FolderItem; + +class FolderModelProxy : public QSortFilterProxyModel +{ + Q_OBJECT +public: + explicit FolderModelProxy(QObject *parent = 0); + ~FolderModelProxy(); + + void setFilter(const YACReader::SearchModifiers modifier, QString filter, bool includeComics); + void setupFilteredModelData( QSqlQuery &sqlquery, FolderItem *parent); + void setupFilteredModelData(); + void clear(); + + bool filterAcceptsRow(int source_row, const QModelIndex &source_parent) const; + +protected: + FolderItem *rootItem; + QMap filteredItems; //relación entre folders + + bool includeComics; + QString filter; + bool filterEnabled; + + YACReader::SearchModifiers modifier; +}; + +class FolderModel : public QAbstractItemModel +{ + + Q_OBJECT + + friend class FolderModelProxy; + +public: + FolderModel(QObject *parent = 0); + FolderModel( QSqlQuery &sqlquery, QObject *parent = 0); + ~FolderModel(); + + //QAbstractItemModel methods + QVariant data(const QModelIndex &index, int role) const; + Qt::ItemFlags flags(const QModelIndex &index) const; + QVariant headerData(int section, Qt::Orientation orientation, + int role = Qt::DisplayRole) const; + QModelIndex index(int row, int column, + const QModelIndex &parent = QModelIndex()) const; + QModelIndex parent(const QModelIndex &index) const; + int rowCount(const QModelIndex &parent = QModelIndex()) const; + int columnCount(const QModelIndex &parent = QModelIndex()) const; + + //Convenience methods + void setupModelData(QString path); + QString getDatabase(); + QString getFolderPath(const QModelIndex &folder); + //QModelIndex indexFromItem(FolderItem * item, int column); + + + //bool isFilterEnabled(){return filterEnabled;}; + + void updateFolderCompletedStatus(const QModelIndexList & list, bool status); + void updateFolderFinishedStatus(const QModelIndexList & list, bool status); + + QStringList getSubfoldersNames(const QModelIndex & mi); + + void fetchMoreFromDB(const QModelIndex & parent); + + QModelIndex addFolderAtParent(const QString & folderName, const QModelIndex & parent); + + enum Columns { + Name = 0, + Path = 1, + Finished = 2, + Completed = 3 + };//id INTEGER PRIMARY KEY, parentId INTEGER NOT NULL, name TEXT NOT NULL, path TEXT NOT NULL + + enum Roles { + FinishedRole = Qt::UserRole + 1, + CompletedRole, + IdRole + }; + +public slots: + void deleteFolder(const QModelIndex & mi); + void updateFolderChildrenInfo(qulonglong folderId); + +private: + void setupModelData( QSqlQuery &sqlquery, FolderItem *parent); + void updateFolderModelData( QSqlQuery &sqlquery, FolderItem *parent); + + FolderItem *rootItem; //el árbol + QMap items; //relación entre folders + + QString _databasePath; + +signals: + void beforeReset(); + void reset(); +}; +//! [0] + +#endif diff --git a/YACReaderLibrary/db/reading_list_item.cpp b/YACReaderLibrary/db/reading_list_item.cpp index f2db1e48..4c2946f4 100644 --- a/YACReaderLibrary/db/reading_list_item.cpp +++ b/YACReaderLibrary/db/reading_list_item.cpp @@ -1,276 +1,276 @@ -#include "reading_list_item.h" -#include "qnaturalsorting.h" - -#include - -#include "QsLog.h" - -ListItem::ListItem(const QList &data) - :itemData(data) -{ - -} - -int ListItem::columnCount() -{ - return itemData.count(); -} - -QVariant ListItem::data(int column) const -{ - return itemData.at(column); -} - -qulonglong ListItem::getId() const -{ - return 0; -} - -//------------------------------------------------------ - -SpecialListItem::SpecialListItem(const QList &data) - :ListItem(data) -{ - -} - -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)); - } - - QLOG_WARN() << "Icon for SpecialListItem not available"; - - return QIcon(); -} - -ReadingListModel::TypeSpecialList SpecialListItem::getType() const -{ - if(itemData.count()>Id) - { - int id = itemData.at(Id).toInt(); - return (ReadingListModel::TypeSpecialList)id; - } - - QLOG_WARN() << "TypeSpecialList not available"; - - return (ReadingListModel::TypeSpecialList)0; -} - -//------------------------------------------------------ - -LabelItem::LabelItem(const QList &data) - :ListItem(data) -{ - -} - -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()); - } - - QLOG_WARN() << "Icon for label item not available"; - - return QIcon(); -} - -YACReader::LabelColors LabelItem::colorid() const -{ - if(itemData.count()>Ordering) - { - return YACReader::LabelColors(itemData.at(Ordering).toInt()); - } - - QLOG_WARN() << "Label color for label item not available"; - - return (YACReader::LabelColors)0; -} - -QString LabelItem::name() const -{ - if(itemData.count()>Name) - { - return itemData.at(Name).toString(); - } - - QLOG_WARN() << "Name for label item not available"; - - return ""; -} - -void LabelItem::setName(const QString &name) -{ - if(itemData.count()>Name) - { - itemData[Name] = name; - } -} - -qulonglong LabelItem::getId() const -{ - if(itemData.count()>Id) - { - return YACReader::LabelColors(itemData.at(Id).toULongLong()); - } - - QLOG_WARN() << "Id for Label item not available"; - - return 0; -} - -//------------------------------------------------------ - -ReadingListItem::ReadingListItem(const QList &data, ReadingListItem *p) - :ListItem(data), parent(p) -{ - -} - -QIcon ReadingListItem::getIcon() const -{ - if(parent->getId() == 0) - return YACReader::noHighlightedIcon(":/images/lists/list.png"); //top level list - else -#ifdef Q_OS_MAC - return QFileIconProvider().icon(QFileIconProvider::Folder); -#else - return YACReader::noHighlightedIcon(":/images/sidebar/folder.png"); //sublist -#endif -} - -int ReadingListItem::childCount() const -{ - return childItems.count(); -} - -ReadingListItem *ReadingListItem::child(int row) -{ - return childItems.at(row); -} - -//items are sorted by order -void ReadingListItem::appendChild(ReadingListItem *item) -{ - item->parent = this; - - if(childItems.isEmpty()) - childItems.append(item); - else - { - if(item->parent->getId()==0) //sort by name, top level child - { - int i= 0; - while(iname(),item->name())) - i++; - childItems.insert(i,item); - } - else - { - int i= 0; - while(igetOrdering()getOrdering())) - i++; - childItems.insert(i,item); - } - - /*ReadingListItem * last = childItems.back(); - QString nameLast = last->data(1).toString(); //TODO usar info name si est� disponible, sino el nombre del fichero..... - QString nameCurrent = item->data(1).toString(); - QList::iterator i; - i = childItems.end(); - i--; - while (naturalSortLessThanCI(nameCurrent,nameLast) && i != childItems.begin()) - { - i--; - nameLast = (*i)->data(1).toString(); - } - if(!naturalSortLessThanCI(nameCurrent,nameLast)) //si se ha encontrado un elemento menor que current, se inserta justo despu�s - childItems.insert(++i,item); - else - childItems.insert(i,item);*/ - - } - -} - -void ReadingListItem::appendChild(ReadingListItem *item, int pos) -{ - childItems.insert(pos, item); -} - -void ReadingListItem::removeChild(ReadingListItem *item) -{ - childItems.removeOne(item); -} - -qulonglong ReadingListItem::getId() const -{ - if(itemData.count()>Id) - return itemData.at(Id).toULongLong(); - - QLOG_WARN() << "Name for reading list item not available"; - - return 0; -} - -QString ReadingListItem::name() const -{ - if(itemData.count()>Name) - return itemData.at(Name).toString(); - - QLOG_WARN() << "Name for reading list item not available"; - - return ""; -} - -void ReadingListItem::setName(const QString &name) -{ - if(itemData.count()>Name) - itemData[Name] = name; -} - -int ReadingListItem::getOrdering() const -{ - if(itemData.count()>Ordering) - return itemData[Ordering].toInt(); - - QLOG_WARN() << "Ordering for Item not available"; - return 0; -} - -void ReadingListItem::setOrdering(const int ordering) -{ - if(itemData.count()>Ordering) - itemData[Ordering] = ordering; -} - -QList ReadingListItem::children() -{ - return childItems; -} - -int ReadingListItem::row() const -{ - if (parent) - return parent->childItems.indexOf(const_cast(this)); - - return 0; -} - - -ReadingListSeparatorItem::ReadingListSeparatorItem() - :ListItem(QList()) -{ - -} - -QIcon ReadingListSeparatorItem::getIcon() const -{ - return QIcon(); -} +#include "reading_list_item.h" +#include "qnaturalsorting.h" + +#include + +#include "QsLog.h" + +ListItem::ListItem(const QList &data) + :itemData(data) +{ + +} + +int ListItem::columnCount() +{ + return itemData.count(); +} + +QVariant ListItem::data(int column) const +{ + return itemData.at(column); +} + +qulonglong ListItem::getId() const +{ + return 0; +} + +//------------------------------------------------------ + +SpecialListItem::SpecialListItem(const QList &data) + :ListItem(data) +{ + +} + +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)); + } + + QLOG_WARN() << "Icon for SpecialListItem not available"; + + return QIcon(); +} + +ReadingListModel::TypeSpecialList SpecialListItem::getType() const +{ + if(itemData.count()>Id) + { + int id = itemData.at(Id).toInt(); + return (ReadingListModel::TypeSpecialList)id; + } + + QLOG_WARN() << "TypeSpecialList not available"; + + return (ReadingListModel::TypeSpecialList)0; +} + +//------------------------------------------------------ + +LabelItem::LabelItem(const QList &data) + :ListItem(data) +{ + +} + +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()); + } + + QLOG_WARN() << "Icon for label item not available"; + + return QIcon(); +} + +YACReader::LabelColors LabelItem::colorid() const +{ + if(itemData.count()>Ordering) + { + return YACReader::LabelColors(itemData.at(Ordering).toInt()); + } + + QLOG_WARN() << "Label color for label item not available"; + + return (YACReader::LabelColors)0; +} + +QString LabelItem::name() const +{ + if(itemData.count()>Name) + { + return itemData.at(Name).toString(); + } + + QLOG_WARN() << "Name for label item not available"; + + return ""; +} + +void LabelItem::setName(const QString &name) +{ + if(itemData.count()>Name) + { + itemData[Name] = name; + } +} + +qulonglong LabelItem::getId() const +{ + if(itemData.count()>Id) + { + return YACReader::LabelColors(itemData.at(Id).toULongLong()); + } + + QLOG_WARN() << "Id for Label item not available"; + + return 0; +} + +//------------------------------------------------------ + +ReadingListItem::ReadingListItem(const QList &data, ReadingListItem *p) + :ListItem(data), parent(p) +{ + +} + +QIcon ReadingListItem::getIcon() const +{ + if(parent->getId() == 0) + return YACReader::noHighlightedIcon(":/images/lists/list.png"); //top level list + else +#ifdef Q_OS_MAC + return QFileIconProvider().icon(QFileIconProvider::Folder); +#else + return YACReader::noHighlightedIcon(":/images/sidebar/folder.png"); //sublist +#endif +} + +int ReadingListItem::childCount() const +{ + return childItems.count(); +} + +ReadingListItem *ReadingListItem::child(int row) +{ + return childItems.at(row); +} + +//items are sorted by order +void ReadingListItem::appendChild(ReadingListItem *item) +{ + item->parent = this; + + if(childItems.isEmpty()) + childItems.append(item); + else + { + if(item->parent->getId()==0) //sort by name, top level child + { + int i= 0; + while(iname(),item->name())) + i++; + childItems.insert(i,item); + } + else + { + int i= 0; + while(igetOrdering()getOrdering())) + i++; + childItems.insert(i,item); + } + + /*ReadingListItem * last = childItems.back(); + QString nameLast = last->data(1).toString(); //TODO usar info name si est� disponible, sino el nombre del fichero..... + QString nameCurrent = item->data(1).toString(); + QList::iterator i; + i = childItems.end(); + i--; + while (naturalSortLessThanCI(nameCurrent,nameLast) && i != childItems.begin()) + { + i--; + nameLast = (*i)->data(1).toString(); + } + if(!naturalSortLessThanCI(nameCurrent,nameLast)) //si se ha encontrado un elemento menor que current, se inserta justo despu�s + childItems.insert(++i,item); + else + childItems.insert(i,item);*/ + + } + +} + +void ReadingListItem::appendChild(ReadingListItem *item, int pos) +{ + childItems.insert(pos, item); +} + +void ReadingListItem::removeChild(ReadingListItem *item) +{ + childItems.removeOne(item); +} + +qulonglong ReadingListItem::getId() const +{ + if(itemData.count()>Id) + return itemData.at(Id).toULongLong(); + + QLOG_WARN() << "Name for reading list item not available"; + + return 0; +} + +QString ReadingListItem::name() const +{ + if(itemData.count()>Name) + return itemData.at(Name).toString(); + + QLOG_WARN() << "Name for reading list item not available"; + + return ""; +} + +void ReadingListItem::setName(const QString &name) +{ + if(itemData.count()>Name) + itemData[Name] = name; +} + +int ReadingListItem::getOrdering() const +{ + if(itemData.count()>Ordering) + return itemData[Ordering].toInt(); + + QLOG_WARN() << "Ordering for Item not available"; + return 0; +} + +void ReadingListItem::setOrdering(const int ordering) +{ + if(itemData.count()>Ordering) + itemData[Ordering] = ordering; +} + +QList ReadingListItem::children() +{ + return childItems; +} + +int ReadingListItem::row() const +{ + if (parent) + return parent->childItems.indexOf(const_cast(this)); + + return 0; +} + + +ReadingListSeparatorItem::ReadingListSeparatorItem() + :ListItem(QList()) +{ + +} + +QIcon ReadingListSeparatorItem::getIcon() const +{ + return QIcon(); +} diff --git a/YACReaderLibrary/db/reading_list_item.h b/YACReaderLibrary/db/reading_list_item.h index 06bcc3ec..d69090f9 100644 --- a/YACReaderLibrary/db/reading_list_item.h +++ b/YACReaderLibrary/db/reading_list_item.h @@ -1,104 +1,104 @@ -#ifndef READING_LIST_ITEM_H -#define READING_LIST_ITEM_H - -#include -#include - -#include "yacreader_global_gui.h" -#include "reading_list_model.h" -//TODO add propper constructors, using QList is not safe - -class ListItem -{ -public: - ListItem(const QList &data); - int columnCount(); - virtual QIcon getIcon() const = 0; - QVariant data(int column) const; - virtual qulonglong getId() const; - QList itemData; - virtual ~ListItem() {} -}; - -//------------------------------------------------------ - -class SpecialListItem : public ListItem -{ -public: - SpecialListItem(const QList &data); - QIcon getIcon() const; - ReadingListModel::TypeSpecialList getType() const; -private: - enum DataIndexes { - Name, - Id - }; - -}; - -//------------------------------------------------------ - -class LabelItem : public ListItem -{ -public: - LabelItem(const QList &data); - QIcon getIcon() const; - YACReader::LabelColors colorid() const; - QString name() const; - void setName(const QString & name); - qulonglong getId() const; - - -private: - enum DataIndexes { - Name, - Color, - Id, - Ordering - }; -}; - -//------------------------------------------------------ - -class ReadingListItem : public ListItem -{ -public: - ReadingListItem(const QList &data, ReadingListItem * parent = 0); - QIcon getIcon() const; - ReadingListItem * parent; - int childCount() const; - int row() const; - ReadingListItem * child(int row); - void appendChild(ReadingListItem *item); - void appendChild(ReadingListItem *item, int pos); - void removeChild(ReadingListItem *item); - qulonglong getId() const; - QString name() const; - void setName(const QString & name); - int getOrdering() const; - void setOrdering(const int ordering); - QList children(); - -private: - QList childItems; - - enum DataIndexes { - Name, - Id, - Finished, - Completed, - Ordering - }; - -}; - -//------------------------------------------------------ - -class ReadingListSeparatorItem : public ListItem -{ -public: - ReadingListSeparatorItem(); - QIcon getIcon() const; -}; - -#endif // READING_LIST_ITEM_H +#ifndef READING_LIST_ITEM_H +#define READING_LIST_ITEM_H + +#include +#include + +#include "yacreader_global_gui.h" +#include "reading_list_model.h" +//TODO add propper constructors, using QList is not safe + +class ListItem +{ +public: + ListItem(const QList &data); + int columnCount(); + virtual QIcon getIcon() const = 0; + QVariant data(int column) const; + virtual qulonglong getId() const; + QList itemData; + virtual ~ListItem() {} +}; + +//------------------------------------------------------ + +class SpecialListItem : public ListItem +{ +public: + SpecialListItem(const QList &data); + QIcon getIcon() const; + ReadingListModel::TypeSpecialList getType() const; +private: + enum DataIndexes { + Name, + Id + }; + +}; + +//------------------------------------------------------ + +class LabelItem : public ListItem +{ +public: + LabelItem(const QList &data); + QIcon getIcon() const; + YACReader::LabelColors colorid() const; + QString name() const; + void setName(const QString & name); + qulonglong getId() const; + + +private: + enum DataIndexes { + Name, + Color, + Id, + Ordering + }; +}; + +//------------------------------------------------------ + +class ReadingListItem : public ListItem +{ +public: + ReadingListItem(const QList &data, ReadingListItem * parent = 0); + QIcon getIcon() const; + ReadingListItem * parent; + int childCount() const; + int row() const; + ReadingListItem * child(int row); + void appendChild(ReadingListItem *item); + void appendChild(ReadingListItem *item, int pos); + void removeChild(ReadingListItem *item); + qulonglong getId() const; + QString name() const; + void setName(const QString & name); + int getOrdering() const; + void setOrdering(const int ordering); + QList children(); + +private: + QList childItems; + + enum DataIndexes { + Name, + Id, + Finished, + Completed, + Ordering + }; + +}; + +//------------------------------------------------------ + +class ReadingListSeparatorItem : public ListItem +{ +public: + ReadingListSeparatorItem(); + QIcon getIcon() const; +}; + +#endif // READING_LIST_ITEM_H diff --git a/YACReaderLibrary/db/reading_list_model.cpp b/YACReaderLibrary/db/reading_list_model.cpp index 7bd920ed..b6e1a754 100644 --- a/YACReaderLibrary/db/reading_list_model.cpp +++ b/YACReaderLibrary/db/reading_list_model.cpp @@ -1,806 +1,806 @@ -#include "reading_list_model.h" - -#include "reading_list_item.h" - -#include "data_base_management.h" -#include "qnaturalsorting.h" -#include "db_helper.h" - -#include "QsLog.h" - -#include - -ReadingListModel::ReadingListModel(QObject *parent) : - QAbstractItemModel(parent),rootItem(0) -{ - separator1 = new ReadingListSeparatorItem; - separator2 = new ReadingListSeparatorItem; -} - -int ReadingListModel::rowCount(const QModelIndex &parent) const -{ - if(!parent.isValid()) //TOP - { - int separatorsCount = 2;//labels.isEmpty()?1:2; - return specialLists.count() + labels.count() + rootItem->childCount() + separatorsCount; - } - else - { - ListItem * item = static_cast(parent.internalPointer()); - - if(typeid(*item) == typeid(ReadingListItem)) - { - ReadingListItem * item = static_cast(parent.internalPointer()); - return item->childCount(); - } - } - - return 0; -} - -int ReadingListModel::columnCount(const QModelIndex &parent) const -{ - if(parent.isValid()) - { - ListItem * item = static_cast(parent.internalPointer()); - if(typeid(*item) == typeid(ReadingListSeparatorItem)) - return 0; - } - return 1; - /*if (parent.isValid()) - return static_cast(parent.internalPointer())->columnCount(); - else - return rootItem->columnCount();*/ -} - -QVariant ReadingListModel::data(const QModelIndex &index, int role) const -{ - if(!index.isValid()) - return QVariant(); - - ListItem * item = static_cast(index.internalPointer()); - - if (role == ReadingListModel::TypeListsRole) - { - if(typeid(*item) == typeid(SpecialListItem)) - return QVariant(ReadingListModel::SpecialList); - - if(typeid(*item) == typeid(LabelItem)) - return QVariant(ReadingListModel::Label); - - if(typeid(*item) == typeid(ReadingListItem)) - return QVariant(ReadingListModel::ReadingList); - - if(typeid(*item) == typeid(ReadingListSeparatorItem)) - return QVariant(ReadingListModel::Separator); - } - - if (role == ReadingListModel::LabelColorRole && typeid(*item) == typeid(LabelItem) ) - { - LabelItem * labelItem = static_cast(item); - return QVariant(labelItem->colorid()); - } - - if (role == ReadingListModel::IDRole) - { - QLOG_DEBUG() << "getting role"; - return item->getId(); -} - - if (role == ReadingListModel::SpecialListTypeRole && typeid(*item) == typeid(SpecialListItem)) - { - SpecialListItem * specialListItem = static_cast(item); - return QVariant(specialListItem->getType()); - } - - if(typeid(*item) == typeid(ReadingListSeparatorItem)) - return QVariant(); - - if (role == Qt::DecorationRole) - { - return QVariant(item->getIcon()); - } - - if (role != Qt::DisplayRole) - return QVariant(); - - return item->data(index.column()); -} - -Qt::ItemFlags ReadingListModel::flags(const QModelIndex &index) const -{ - if (!index.isValid()) - return 0; - - ListItem * item = static_cast(index.internalPointer()); - if(typeid(*item) == typeid(ReadingListSeparatorItem)) - return 0; - - if(typeid(*item) == typeid(ReadingListItem) && static_cast(item)->parent->getId()!=0) - return Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsDropEnabled | Qt::ItemIsDragEnabled; //only sublists are dragable - - return Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsDropEnabled; -} - -QVariant ReadingListModel::headerData(int section, Qt::Orientation orientation, int role) const -{ - if (orientation == Qt::Horizontal && role == Qt::DisplayRole) - return rootItem->data(section); - - return QVariant(); -} - -QModelIndex ReadingListModel::index(int row, int column, const QModelIndex &parent) const -{ - if (!hasIndex(row, column, parent)) - return QModelIndex(); - - if(!parent.isValid()) - { - int separatorsCount = 2;//labels.isEmpty()?1:2; - - if(rowIsSpecialList(row,parent)) - return createIndex(row, column, specialLists.at(row)); - - if(row == specialLists.count()) - return createIndex(row,column,separator1); - - if(rowIsLabel(row,parent)) - return createIndex(row,column,labels.at(row-specialLists.count()-1)); - - if(separatorsCount == 2) - if(row == specialLists.count() + labels.count() + 1) - return createIndex(row,column,separator2); - - if(rowIsReadingList(row,parent)) - return createIndex(row,column,rootItem->child(row - (specialLists.count() + labels.count() + separatorsCount))); - - } else //sublist - { - ReadingListItem *parentItem; - - if (!parent.isValid()) - parentItem = rootItem; //this should be impossible - else - parentItem = static_cast(parent.internalPointer()); - - ReadingListItem *childItem = parentItem->child(row); - return createIndex(row,column,childItem); - } - /*FolderItem *childItem = parentItem->child(row); - if (childItem) - return createIndex(row, column, childItem); - else*/ - return QModelIndex(); - -} - -QModelIndex ReadingListModel::parent(const QModelIndex &index) const -{ - - if(!index.isValid()) - return QModelIndex(); - - ListItem * item = static_cast(index.internalPointer()); - - if(typeid(*item) == typeid(ReadingListItem)) - { - ReadingListItem * childItem = static_cast(index.internalPointer()); - ReadingListItem * parent = childItem->parent; - if(parent->getId() != 0) - return createIndex(parent->row()+specialLists.count()+labels.count()+2, 0, parent); - } - - return QModelIndex(); -} - -bool ReadingListModel::canDropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent) const -{ - Q_UNUSED(action); - - QLOG_DEBUG() << "trying to drop into row = " << row << "column column = " << column << "parent" << parent; - - if(row == -1) - return false; - - if(!parent.isValid()) //top level items - { - if(row == -1) //no list - return false; - - if(row == 1) //reading is just an smart list - return false; - - if(rowIsSeparator(row,parent)) - return false; - } - - if(data->formats().contains(YACReader::YACReaderLibrarComiscSelectionMimeDataFormat)) - return true; - - if(rowIsReadingList(row,parent))// TODO avoid droping in a different parent - if(!parent.isValid()) - return false; - else - { - QList > sublistsRows; - QByteArray rawData = data->data(YACReader::YACReaderLibrarSubReadingListMimeDataFormat); - QDataStream in(&rawData,QIODevice::ReadOnly); - in >> sublistsRows; //deserialize the list of indentifiers - if(parent.row()!= sublistsRows.at(0).second) - return false; - return data->formats().contains(YACReader::YACReaderLibrarSubReadingListMimeDataFormat); - - } - - return false; -} - -bool ReadingListModel::dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent) -{ - QLOG_DEBUG() << "drop mimedata into row = " << row << " column = " << column << "parent" << parent; - if(data->formats().contains(YACReader::YACReaderLibrarComiscSelectionMimeDataFormat)) - return dropComics(data, action, row, column, parent); - - if(data->formats().contains(YACReader::YACReaderLibrarSubReadingListMimeDataFormat)) - return dropSublist(data, action, row, column, parent); - - return false; -} - -bool ReadingListModel::dropComics(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent) -{ - Q_UNUSED(action); - - QList comicIds = YACReader::mimeDataToComicsIds(data); - - QLOG_DEBUG() << "dropped : " << comicIds; - - QModelIndex dest; - QModelIndex parentDest; - - if(row == -1) - { - dest = parent; - } - else - dest = index(row,column,parent); - - parentDest = dest.parent(); - - if(rowIsSpecialList(dest.row(),parentDest)) { - if(dest.row() == 0) //add to favorites - { - QLOG_DEBUG() << "-------addComicsToFavorites : " << comicIds << " to " << dest.data(IDRole).toULongLong(); - emit addComicsToFavorites(comicIds); - return true; - } - } - - if(rowIsLabel(dest.row(),parentDest)) { - QLOG_DEBUG() << "+++++++++++addComicsToLabel : " << comicIds << " to " << dest.data(IDRole).toULongLong(); - emit addComicsToLabel(comicIds, dest.data(IDRole).toULongLong()); - return true; - } - - if(rowIsReadingList(dest.row(),parentDest)) { - QLOG_DEBUG() << "///////////addComicsToReadingList : " << comicIds << " to " << dest.data(IDRole).toULongLong(); - emit addComicsToReadingList(comicIds, dest.data(IDRole).toULongLong()); - return true; - } - - return false; -} - -bool ReadingListModel::dropSublist(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent) -{ - Q_UNUSED(action); - Q_UNUSED(column); - - QList > sublistsRows; - QByteArray rawData = data->data(YACReader::YACReaderLibrarSubReadingListMimeDataFormat); - QDataStream in(&rawData,QIODevice::ReadOnly); - in >> sublistsRows; //deserialize the list of indentifiers - - QLOG_DEBUG() << "dropped : " << sublistsRows; - - int sourceRow = sublistsRows.at(0).first; - int destRow = row; - QModelIndex destParent = parent; - if(row == -1) - { - QLOG_DEBUG() << "droping inside parent"; - destRow = parent.row(); - destParent = parent.parent(); - } - QLOG_DEBUG() << "move " << sourceRow << "-" << destRow; - - if(sourceRow == destRow) - return false; - - //beginMoveRows(destParent,sourceRow,sourceRow,destParent,destRow); - - ReadingListItem * parentItem = static_cast(destParent.internalPointer()); - ReadingListItem * child = parentItem->child(sourceRow); - parentItem->removeChild(child); - parentItem->appendChild(child,destRow); - - reorderingChildren(parentItem->children()); - //endMoveRows(); - - return true; -} - -QMimeData *ReadingListModel::mimeData(const QModelIndexList &indexes) const -{ - QLOG_DEBUG() << "mimeData requested" << indexes; - - if(indexes.length() == 0) - { - QLOG_ERROR() << "mimeData requested: indexes is empty"; - return new QMimeData();//TODO what happens if 0 is returned? - } - - if(indexes.length() > 1) - QLOG_DEBUG() << "mimeData requested for more than one index, this shouldn't be possible"; - - QModelIndex modelIndex = indexes.at(0); - - QList > rows; - rows << QPair(modelIndex.row(),modelIndex.parent().row()); - QLOG_DEBUG() << "mimeData requested for row : " << modelIndex.row(); - - QByteArray data; - QDataStream out(&data,QIODevice::WriteOnly); - out << rows; //serialize the list of identifiers - - QMimeData * mimeData = new QMimeData(); - mimeData->setData(YACReader::YACReaderLibrarSubReadingListMimeDataFormat, data); - - return mimeData; -} - -void ReadingListModel::setupReadingListsData(QString path) -{ - beginResetModel(); - - cleanAll(); - - _databasePath = path; - QSqlDatabase db = DataBaseManagement::loadDatabase(path); - - //setup special lists - specialLists = setupSpecialLists(db); - - //separator-------------------------------------------- - - //setup labels - setupLabels(db); - - //separator-------------------------------------------- - - //setup reading list - setupReadingLists(db); - - endResetModel(); -} - -void ReadingListModel::addNewLabel(const QString &name, YACReader::LabelColors color) -{ - QSqlDatabase db = DataBaseManagement::loadDatabase(_databasePath); - qulonglong id = DBHelper::insertLabel(name, color, db); - - int newPos = addLabelIntoList(new LabelItem(QList() << name << YACReader::colorToName(color) << id << color)); - beginInsertRows(QModelIndex(),specialLists.count()+1+newPos+1, specialLists.count()+1+newPos+1); - - - endInsertRows(); - - QSqlDatabase::removeDatabase(db.connectionName()); -} - -void ReadingListModel::addReadingList(const QString &name) -{ - QSqlDatabase db = DataBaseManagement::loadDatabase(_databasePath); - - beginInsertRows(QModelIndex(), 0, 0); //TODO calculate the right coordinates before inserting - - qulonglong id = DBHelper::insertReadingList(name,db); - ReadingListItem * newItem; - rootItem->appendChild(newItem = new ReadingListItem(QList() - << name - << id - << false - << true - << 0)); - - items.insert(id, newItem); - - /*int pos = rootItem->children().indexOf(newItem); - - pos += specialLists.count()+1+labels.count()+labels.count()>0?1:0;*/ - - - endInsertRows(); - - QSqlDatabase::removeDatabase(db.connectionName()); -} - -void ReadingListModel::addReadingListAt(const QString &name, const QModelIndex &mi) -{ - QSqlDatabase db = DataBaseManagement::loadDatabase(_databasePath); - - beginInsertRows(mi, 0, 0); //TODO calculate the right coordinates before inserting - - ReadingListItem * readingListParent = static_cast(mi.internalPointer()); - qulonglong id = DBHelper::insertReadingSubList(name,mi.data(IDRole).toULongLong(),readingListParent->childCount(),db); - ReadingListItem * newItem; - - readingListParent->appendChild(newItem = new ReadingListItem(QList() - << name - << id - << false - << true - << readingListParent->childCount())); - - items.insert(id, newItem); - - /*int pos = readingListParent->children().indexOf(newItem); - - pos += specialLists.count()+1+labels.count()+labels.count()>0?1:0;*/ - - - endInsertRows(); - - QSqlDatabase::removeDatabase(db.connectionName()); -} - -bool ReadingListModel::isEditable(const QModelIndex &mi) -{ - if(!mi.isValid()) - return false; - ListItem * item = static_cast(mi.internalPointer()); - return typeid(*item) != typeid(SpecialListItem); -} - -bool ReadingListModel::isReadingList(const QModelIndex &mi) -{ - if(!mi.isValid()) - return false; - ListItem * item = static_cast(mi.internalPointer()); - return typeid(*item) == typeid(ReadingListItem); -} - -bool ReadingListModel::isReadingSubList(const QModelIndex &mi) -{ - if(!mi.isValid()) - return false; - ListItem * item = static_cast(mi.internalPointer()); - if(typeid(*item) == typeid(ReadingListItem)) - { - ReadingListItem * readingListItem = static_cast(item); - if(readingListItem->parent == rootItem) - return false; - else - return true; - } - else - return false; -} - -QString ReadingListModel::name(const QModelIndex &mi) -{ - return data(mi,Qt::DisplayRole).toString(); -} - -void ReadingListModel::rename(const QModelIndex &mi, const QString &name) -{ - if(!isEditable(mi)) - return; - - QSqlDatabase db = DataBaseManagement::loadDatabase(_databasePath); - - ListItem * item = static_cast(mi.internalPointer()); - - if(typeid(*item) == typeid(ReadingListItem)) - { - ReadingListItem * rli = static_cast(item); - rli->setName(name); - DBHelper::renameList(item->getId(), name, db); - - if(rli->parent->getId()!=0) - { - //TODO - //move row depending on the name - }else - emit dataChanged(index(mi.row(), 0), index(mi.row(), 0)); - } - else if(typeid(*item) == typeid(LabelItem)) - { - LabelItem * li = static_cast(item); - li->setName(name); - DBHelper::renameLabel(item->getId(), name, db); - emit dataChanged(index(mi.row(), 0), index(mi.row(), 0)); - } - - QSqlDatabase::removeDatabase(db.connectionName()); -} - -void ReadingListModel::deleteItem(const QModelIndex &mi) -{ - if(isEditable(mi)) - { - QLOG_DEBUG() << "parent row :" << mi.parent().data() << "-" << mi.row(); - beginRemoveRows(mi.parent(),mi.row(),mi.row()); - - QSqlDatabase db = DataBaseManagement::loadDatabase(_databasePath); - - ListItem * item = static_cast(mi.internalPointer()); - - if(typeid(*item) == typeid(ReadingListItem)) - { - ReadingListItem * rli = static_cast(item); - QLOG_DEBUG() << "num children : " << rli->parent->childCount(); - rli->parent->removeChild(rli); - QLOG_DEBUG() << "num children : " << rli->parent->childCount(); - DBHelper::removeListFromDB(item->getId(), db); - if(rli->parent->getId()!=0) - { - reorderingChildren(rli->parent->children()); - } - QLOG_DEBUG() << "num children : " << rli->parent->childCount(); - } - else if(typeid(*item) == typeid(LabelItem)) - { - LabelItem * li = static_cast(item); - labels.removeOne(li); - DBHelper::removeLabelFromDB(item->getId(), db); - } - - QSqlDatabase::removeDatabase(db.connectionName()); - - endRemoveRows(); - } -} - -const QList ReadingListModel::getLabels() -{ - return labels; -} - -void ReadingListModel::cleanAll() -{ - if(rootItem != 0) - { - delete rootItem; - - qDeleteAll(specialLists); - qDeleteAll(labels); - - specialLists.clear(); - labels.clear(); - - items.clear(); - } - - rootItem = 0; -} - -void ReadingListModel::setupReadingListsData(QSqlQuery &sqlquery, ReadingListItem *parent) -{ - items.insert(parent->getId(),parent); - - QSqlRecord record = sqlquery.record(); - - int name = record.indexOf("name"); - int id = record.indexOf("id"); - int finished = record.indexOf("finished"); - int completed = record.indexOf("completed"); - int ordering = record.indexOf("ordering"); - int parentId = record.indexOf("parentId"); - - while (sqlquery.next()) - { - ReadingListItem * rli = new ReadingListItem(QList() - << sqlquery.value(name) - << sqlquery.value(id) - << sqlquery.value(finished) - << sqlquery.value(completed) - << sqlquery.value(ordering)); - - ReadingListItem * currentParent; - if(sqlquery.value(parentId).isNull()) - currentParent = rootItem; - else - currentParent = items.value(sqlquery.value(parentId).toULongLong()); - - currentParent->appendChild(rli); - - items.insert(rli->getId(),rli); - } -} - -QList ReadingListModel::setupSpecialLists(QSqlDatabase & db) -{ - QList list; - - QSqlQuery selectQuery("SELECT * FROM default_reading_list ORDER BY id,name",db); - - QSqlRecord record = selectQuery.record(); - - int name = record.indexOf("name"); - int id = record.indexOf("id"); - - while(selectQuery.next()) { - list << new SpecialListItem(QList() - << selectQuery.value(name) - << selectQuery.value(id)); - } - - //Reading after Favorites, Why? Because I want to :P - list.insert(1,new SpecialListItem(QList() << "Reading" << 0)); - - return list; -} - -void ReadingListModel::setupLabels(QSqlDatabase & db) -{ - QSqlQuery selectQuery("SELECT * FROM label ORDER BY ordering,name",db); - - QSqlRecord record = selectQuery.record(); - - int name = record.indexOf("name"); - int color = record.indexOf("color"); - int id = record.indexOf("id"); - int ordering = record.indexOf("ordering"); - - while(selectQuery.next()) { - addLabelIntoList(new LabelItem(QList() - << selectQuery.value(name) - << selectQuery.value(color) - << selectQuery.value(id) - << selectQuery.value(ordering))); - } - - //TEST - -// INSERT INTO label (name, color, ordering) VALUES ("Oh Oh", "red", 1); -// INSERT INTO label (name, color, ordering) VALUES ("lalala", "orange", 2); -// INSERT INTO label (name, color, ordering) VALUES ("we are not sorry", "yellow", 3); -// INSERT INTO label (name, color, ordering) VALUES ("there we go", "green", 4); -// INSERT INTO label (name, color, ordering) VALUES ("oklabunga", "cyan", 5); -// INSERT INTO label (name, color, ordering) VALUES ("hailer mailer", "blue", 6); -// INSERT INTO label (name, color, ordering) VALUES ("lol", "violet", 7); -// INSERT INTO label (name, color, ordering) VALUES ("problems", "purple", 8); -// INSERT INTO label (name, color, ordering) VALUES ("me gussssta", "pink", 9); -// INSERT INTO label (name, color, ordering) VALUES (":D", "white", 10); -// INSERT INTO label (name, color, ordering) VALUES ("ainsss", "light", 11); -// INSERT INTO label (name, color, ordering) VALUES ("put a smile on my face", "dark", 12); - -} - -void ReadingListModel::setupReadingLists(QSqlDatabase & db) -{ - //setup root item - rootItem = new ReadingListItem(QList() << "ROOT" << 0 << true << false); - - QSqlQuery selectQuery("select * from reading_list order by parentId IS NULL DESC",db); - - //setup reading lists - setupReadingListsData(selectQuery,rootItem); - - //TEST -// ReadingListItem * node1; -// rootItem->appendChild(node1 = new ReadingListItem(QList() /*<< 0*/ << "My reading list" << "atr")); -// rootItem->appendChild(new ReadingListItem(QList() /*<< 0*/ << "X timeline" << "atr")); - -// node1->appendChild(new ReadingListItem(QList() /*<< 0*/ << "sublist" << "atr",node1)); -} - -int ReadingListModel::addLabelIntoList(LabelItem *item) -{ - if(labels.isEmpty()) - labels << item; - else - { - int i = 0; - - while (i < labels.count() && (labels.at(i)->colorid() < item->colorid()) ) - i++; - - if(i < labels.count()) - { - if(labels.at(i)->colorid() == item->colorid()) //sort by name - { - while( i < labels.count() && labels.at(i)->colorid() == item->colorid() && naturalSortLessThanCI(labels.at(i)->name(),item->name())) - i++; - } - } - - - if(i >= labels.count()) - { - QLOG_DEBUG() << "insertando label al final " << item->name(); - labels << item; - } - else - { - QLOG_DEBUG() << "insertando label en " << i << "-" << item->name(); - labels.insert(i,item); - } - - return i; - } - - return 0; -} - -void ReadingListModel::reorderingChildren(QList children) -{ - QList childrenIds; - int i = 0; - foreach (ReadingListItem * item, children) { - item->setOrdering(i++); - childrenIds << item->getId(); - } - - QSqlDatabase db = DataBaseManagement::loadDatabase(_databasePath); - DBHelper::reasignOrderToSublists(childrenIds, db); - QSqlDatabase::removeDatabase(db.connectionName()); -} - -bool ReadingListModel::rowIsSpecialList(int row, const QModelIndex &parent) const -{ - if(parent.isValid()) - return false; //by now no sublists in special list - - if(row >=0 && row < specialLists.count()) - return true; - - return false; -} - -bool ReadingListModel::rowIsLabel(int row, const QModelIndex &parent) const -{ - if(parent.isValid()) - return false; //by now no sublists in labels - - if(row > specialLists.count() && row <= specialLists.count() + labels.count()) - return true; - - return false; -} - -bool ReadingListModel::rowIsReadingList(int row, const QModelIndex &parent) const -{ - if(parent.isValid()) - return true; //only lists with sublists - - int separatorsCount = labels.isEmpty()?1:2; - - if(row >= specialLists.count() + labels.count() + separatorsCount) - return true; - - return false; -} - -bool ReadingListModel::rowIsSeparator(int row, const QModelIndex &parent) const -{ - if(parent.isValid()) - return false; //only separators at top level - - if(row == specialLists.count()) - return true; - - int separatorsCount = labels.isEmpty()?1:2; - if(separatorsCount == 2 && row == specialLists.count() + labels.count() + 1) - return true; - - return false; -} - -ReadingListModelProxy::ReadingListModelProxy(QObject *parent) - :QSortFilterProxyModel(parent) -{ - -} +#include "reading_list_model.h" + +#include "reading_list_item.h" + +#include "data_base_management.h" +#include "qnaturalsorting.h" +#include "db_helper.h" + +#include "QsLog.h" + +#include + +ReadingListModel::ReadingListModel(QObject *parent) : + QAbstractItemModel(parent),rootItem(0) +{ + separator1 = new ReadingListSeparatorItem; + separator2 = new ReadingListSeparatorItem; +} + +int ReadingListModel::rowCount(const QModelIndex &parent) const +{ + if(!parent.isValid()) //TOP + { + int separatorsCount = 2;//labels.isEmpty()?1:2; + return specialLists.count() + labels.count() + rootItem->childCount() + separatorsCount; + } + else + { + ListItem * item = static_cast(parent.internalPointer()); + + if(typeid(*item) == typeid(ReadingListItem)) + { + ReadingListItem * item = static_cast(parent.internalPointer()); + return item->childCount(); + } + } + + return 0; +} + +int ReadingListModel::columnCount(const QModelIndex &parent) const +{ + if(parent.isValid()) + { + ListItem * item = static_cast(parent.internalPointer()); + if(typeid(*item) == typeid(ReadingListSeparatorItem)) + return 0; + } + return 1; + /*if (parent.isValid()) + return static_cast(parent.internalPointer())->columnCount(); + else + return rootItem->columnCount();*/ +} + +QVariant ReadingListModel::data(const QModelIndex &index, int role) const +{ + if(!index.isValid()) + return QVariant(); + + ListItem * item = static_cast(index.internalPointer()); + + if (role == ReadingListModel::TypeListsRole) + { + if(typeid(*item) == typeid(SpecialListItem)) + return QVariant(ReadingListModel::SpecialList); + + if(typeid(*item) == typeid(LabelItem)) + return QVariant(ReadingListModel::Label); + + if(typeid(*item) == typeid(ReadingListItem)) + return QVariant(ReadingListModel::ReadingList); + + if(typeid(*item) == typeid(ReadingListSeparatorItem)) + return QVariant(ReadingListModel::Separator); + } + + if (role == ReadingListModel::LabelColorRole && typeid(*item) == typeid(LabelItem) ) + { + LabelItem * labelItem = static_cast(item); + return QVariant(labelItem->colorid()); + } + + if (role == ReadingListModel::IDRole) + { + QLOG_DEBUG() << "getting role"; + return item->getId(); +} + + if (role == ReadingListModel::SpecialListTypeRole && typeid(*item) == typeid(SpecialListItem)) + { + SpecialListItem * specialListItem = static_cast(item); + return QVariant(specialListItem->getType()); + } + + if(typeid(*item) == typeid(ReadingListSeparatorItem)) + return QVariant(); + + if (role == Qt::DecorationRole) + { + return QVariant(item->getIcon()); + } + + if (role != Qt::DisplayRole) + return QVariant(); + + return item->data(index.column()); +} + +Qt::ItemFlags ReadingListModel::flags(const QModelIndex &index) const +{ + if (!index.isValid()) + return 0; + + ListItem * item = static_cast(index.internalPointer()); + if(typeid(*item) == typeid(ReadingListSeparatorItem)) + return 0; + + if(typeid(*item) == typeid(ReadingListItem) && static_cast(item)->parent->getId()!=0) + return Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsDropEnabled | Qt::ItemIsDragEnabled; //only sublists are dragable + + return Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsDropEnabled; +} + +QVariant ReadingListModel::headerData(int section, Qt::Orientation orientation, int role) const +{ + if (orientation == Qt::Horizontal && role == Qt::DisplayRole) + return rootItem->data(section); + + return QVariant(); +} + +QModelIndex ReadingListModel::index(int row, int column, const QModelIndex &parent) const +{ + if (!hasIndex(row, column, parent)) + return QModelIndex(); + + if(!parent.isValid()) + { + int separatorsCount = 2;//labels.isEmpty()?1:2; + + if(rowIsSpecialList(row,parent)) + return createIndex(row, column, specialLists.at(row)); + + if(row == specialLists.count()) + return createIndex(row,column,separator1); + + if(rowIsLabel(row,parent)) + return createIndex(row,column,labels.at(row-specialLists.count()-1)); + + if(separatorsCount == 2) + if(row == specialLists.count() + labels.count() + 1) + return createIndex(row,column,separator2); + + if(rowIsReadingList(row,parent)) + return createIndex(row,column,rootItem->child(row - (specialLists.count() + labels.count() + separatorsCount))); + + } else //sublist + { + ReadingListItem *parentItem; + + if (!parent.isValid()) + parentItem = rootItem; //this should be impossible + else + parentItem = static_cast(parent.internalPointer()); + + ReadingListItem *childItem = parentItem->child(row); + return createIndex(row,column,childItem); + } + /*FolderItem *childItem = parentItem->child(row); + if (childItem) + return createIndex(row, column, childItem); + else*/ + return QModelIndex(); + +} + +QModelIndex ReadingListModel::parent(const QModelIndex &index) const +{ + + if(!index.isValid()) + return QModelIndex(); + + ListItem * item = static_cast(index.internalPointer()); + + if(typeid(*item) == typeid(ReadingListItem)) + { + ReadingListItem * childItem = static_cast(index.internalPointer()); + ReadingListItem * parent = childItem->parent; + if(parent->getId() != 0) + return createIndex(parent->row()+specialLists.count()+labels.count()+2, 0, parent); + } + + return QModelIndex(); +} + +bool ReadingListModel::canDropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent) const +{ + Q_UNUSED(action); + + QLOG_DEBUG() << "trying to drop into row = " << row << "column column = " << column << "parent" << parent; + + if(row == -1) + return false; + + if(!parent.isValid()) //top level items + { + if(row == -1) //no list + return false; + + if(row == 1) //reading is just an smart list + return false; + + if(rowIsSeparator(row,parent)) + return false; + } + + if(data->formats().contains(YACReader::YACReaderLibrarComiscSelectionMimeDataFormat)) + return true; + + if(rowIsReadingList(row,parent))// TODO avoid droping in a different parent + if(!parent.isValid()) + return false; + else + { + QList > sublistsRows; + QByteArray rawData = data->data(YACReader::YACReaderLibrarSubReadingListMimeDataFormat); + QDataStream in(&rawData,QIODevice::ReadOnly); + in >> sublistsRows; //deserialize the list of indentifiers + if(parent.row()!= sublistsRows.at(0).second) + return false; + return data->formats().contains(YACReader::YACReaderLibrarSubReadingListMimeDataFormat); + + } + + return false; +} + +bool ReadingListModel::dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent) +{ + QLOG_DEBUG() << "drop mimedata into row = " << row << " column = " << column << "parent" << parent; + if(data->formats().contains(YACReader::YACReaderLibrarComiscSelectionMimeDataFormat)) + return dropComics(data, action, row, column, parent); + + if(data->formats().contains(YACReader::YACReaderLibrarSubReadingListMimeDataFormat)) + return dropSublist(data, action, row, column, parent); + + return false; +} + +bool ReadingListModel::dropComics(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent) +{ + Q_UNUSED(action); + + QList comicIds = YACReader::mimeDataToComicsIds(data); + + QLOG_DEBUG() << "dropped : " << comicIds; + + QModelIndex dest; + QModelIndex parentDest; + + if(row == -1) + { + dest = parent; + } + else + dest = index(row,column,parent); + + parentDest = dest.parent(); + + if(rowIsSpecialList(dest.row(),parentDest)) { + if(dest.row() == 0) //add to favorites + { + QLOG_DEBUG() << "-------addComicsToFavorites : " << comicIds << " to " << dest.data(IDRole).toULongLong(); + emit addComicsToFavorites(comicIds); + return true; + } + } + + if(rowIsLabel(dest.row(),parentDest)) { + QLOG_DEBUG() << "+++++++++++addComicsToLabel : " << comicIds << " to " << dest.data(IDRole).toULongLong(); + emit addComicsToLabel(comicIds, dest.data(IDRole).toULongLong()); + return true; + } + + if(rowIsReadingList(dest.row(),parentDest)) { + QLOG_DEBUG() << "///////////addComicsToReadingList : " << comicIds << " to " << dest.data(IDRole).toULongLong(); + emit addComicsToReadingList(comicIds, dest.data(IDRole).toULongLong()); + return true; + } + + return false; +} + +bool ReadingListModel::dropSublist(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent) +{ + Q_UNUSED(action); + Q_UNUSED(column); + + QList > sublistsRows; + QByteArray rawData = data->data(YACReader::YACReaderLibrarSubReadingListMimeDataFormat); + QDataStream in(&rawData,QIODevice::ReadOnly); + in >> sublistsRows; //deserialize the list of indentifiers + + QLOG_DEBUG() << "dropped : " << sublistsRows; + + int sourceRow = sublistsRows.at(0).first; + int destRow = row; + QModelIndex destParent = parent; + if(row == -1) + { + QLOG_DEBUG() << "droping inside parent"; + destRow = parent.row(); + destParent = parent.parent(); + } + QLOG_DEBUG() << "move " << sourceRow << "-" << destRow; + + if(sourceRow == destRow) + return false; + + //beginMoveRows(destParent,sourceRow,sourceRow,destParent,destRow); + + ReadingListItem * parentItem = static_cast(destParent.internalPointer()); + ReadingListItem * child = parentItem->child(sourceRow); + parentItem->removeChild(child); + parentItem->appendChild(child,destRow); + + reorderingChildren(parentItem->children()); + //endMoveRows(); + + return true; +} + +QMimeData *ReadingListModel::mimeData(const QModelIndexList &indexes) const +{ + QLOG_DEBUG() << "mimeData requested" << indexes; + + if(indexes.length() == 0) + { + QLOG_ERROR() << "mimeData requested: indexes is empty"; + return new QMimeData();//TODO what happens if 0 is returned? + } + + if(indexes.length() > 1) + QLOG_DEBUG() << "mimeData requested for more than one index, this shouldn't be possible"; + + QModelIndex modelIndex = indexes.at(0); + + QList > rows; + rows << QPair(modelIndex.row(),modelIndex.parent().row()); + QLOG_DEBUG() << "mimeData requested for row : " << modelIndex.row(); + + QByteArray data; + QDataStream out(&data,QIODevice::WriteOnly); + out << rows; //serialize the list of identifiers + + QMimeData * mimeData = new QMimeData(); + mimeData->setData(YACReader::YACReaderLibrarSubReadingListMimeDataFormat, data); + + return mimeData; +} + +void ReadingListModel::setupReadingListsData(QString path) +{ + beginResetModel(); + + cleanAll(); + + _databasePath = path; + QSqlDatabase db = DataBaseManagement::loadDatabase(path); + + //setup special lists + specialLists = setupSpecialLists(db); + + //separator-------------------------------------------- + + //setup labels + setupLabels(db); + + //separator-------------------------------------------- + + //setup reading list + setupReadingLists(db); + + endResetModel(); +} + +void ReadingListModel::addNewLabel(const QString &name, YACReader::LabelColors color) +{ + QSqlDatabase db = DataBaseManagement::loadDatabase(_databasePath); + qulonglong id = DBHelper::insertLabel(name, color, db); + + int newPos = addLabelIntoList(new LabelItem(QList() << name << YACReader::colorToName(color) << id << color)); + beginInsertRows(QModelIndex(),specialLists.count()+1+newPos+1, specialLists.count()+1+newPos+1); + + + endInsertRows(); + + QSqlDatabase::removeDatabase(db.connectionName()); +} + +void ReadingListModel::addReadingList(const QString &name) +{ + QSqlDatabase db = DataBaseManagement::loadDatabase(_databasePath); + + beginInsertRows(QModelIndex(), 0, 0); //TODO calculate the right coordinates before inserting + + qulonglong id = DBHelper::insertReadingList(name,db); + ReadingListItem * newItem; + rootItem->appendChild(newItem = new ReadingListItem(QList() + << name + << id + << false + << true + << 0)); + + items.insert(id, newItem); + + /*int pos = rootItem->children().indexOf(newItem); + + pos += specialLists.count()+1+labels.count()+labels.count()>0?1:0;*/ + + + endInsertRows(); + + QSqlDatabase::removeDatabase(db.connectionName()); +} + +void ReadingListModel::addReadingListAt(const QString &name, const QModelIndex &mi) +{ + QSqlDatabase db = DataBaseManagement::loadDatabase(_databasePath); + + beginInsertRows(mi, 0, 0); //TODO calculate the right coordinates before inserting + + ReadingListItem * readingListParent = static_cast(mi.internalPointer()); + qulonglong id = DBHelper::insertReadingSubList(name,mi.data(IDRole).toULongLong(),readingListParent->childCount(),db); + ReadingListItem * newItem; + + readingListParent->appendChild(newItem = new ReadingListItem(QList() + << name + << id + << false + << true + << readingListParent->childCount())); + + items.insert(id, newItem); + + /*int pos = readingListParent->children().indexOf(newItem); + + pos += specialLists.count()+1+labels.count()+labels.count()>0?1:0;*/ + + + endInsertRows(); + + QSqlDatabase::removeDatabase(db.connectionName()); +} + +bool ReadingListModel::isEditable(const QModelIndex &mi) +{ + if(!mi.isValid()) + return false; + ListItem * item = static_cast(mi.internalPointer()); + return typeid(*item) != typeid(SpecialListItem); +} + +bool ReadingListModel::isReadingList(const QModelIndex &mi) +{ + if(!mi.isValid()) + return false; + ListItem * item = static_cast(mi.internalPointer()); + return typeid(*item) == typeid(ReadingListItem); +} + +bool ReadingListModel::isReadingSubList(const QModelIndex &mi) +{ + if(!mi.isValid()) + return false; + ListItem * item = static_cast(mi.internalPointer()); + if(typeid(*item) == typeid(ReadingListItem)) + { + ReadingListItem * readingListItem = static_cast(item); + if(readingListItem->parent == rootItem) + return false; + else + return true; + } + else + return false; +} + +QString ReadingListModel::name(const QModelIndex &mi) +{ + return data(mi,Qt::DisplayRole).toString(); +} + +void ReadingListModel::rename(const QModelIndex &mi, const QString &name) +{ + if(!isEditable(mi)) + return; + + QSqlDatabase db = DataBaseManagement::loadDatabase(_databasePath); + + ListItem * item = static_cast(mi.internalPointer()); + + if(typeid(*item) == typeid(ReadingListItem)) + { + ReadingListItem * rli = static_cast(item); + rli->setName(name); + DBHelper::renameList(item->getId(), name, db); + + if(rli->parent->getId()!=0) + { + //TODO + //move row depending on the name + }else + emit dataChanged(index(mi.row(), 0), index(mi.row(), 0)); + } + else if(typeid(*item) == typeid(LabelItem)) + { + LabelItem * li = static_cast(item); + li->setName(name); + DBHelper::renameLabel(item->getId(), name, db); + emit dataChanged(index(mi.row(), 0), index(mi.row(), 0)); + } + + QSqlDatabase::removeDatabase(db.connectionName()); +} + +void ReadingListModel::deleteItem(const QModelIndex &mi) +{ + if(isEditable(mi)) + { + QLOG_DEBUG() << "parent row :" << mi.parent().data() << "-" << mi.row(); + beginRemoveRows(mi.parent(),mi.row(),mi.row()); + + QSqlDatabase db = DataBaseManagement::loadDatabase(_databasePath); + + ListItem * item = static_cast(mi.internalPointer()); + + if(typeid(*item) == typeid(ReadingListItem)) + { + ReadingListItem * rli = static_cast(item); + QLOG_DEBUG() << "num children : " << rli->parent->childCount(); + rli->parent->removeChild(rli); + QLOG_DEBUG() << "num children : " << rli->parent->childCount(); + DBHelper::removeListFromDB(item->getId(), db); + if(rli->parent->getId()!=0) + { + reorderingChildren(rli->parent->children()); + } + QLOG_DEBUG() << "num children : " << rli->parent->childCount(); + } + else if(typeid(*item) == typeid(LabelItem)) + { + LabelItem * li = static_cast(item); + labels.removeOne(li); + DBHelper::removeLabelFromDB(item->getId(), db); + } + + QSqlDatabase::removeDatabase(db.connectionName()); + + endRemoveRows(); + } +} + +const QList ReadingListModel::getLabels() +{ + return labels; +} + +void ReadingListModel::cleanAll() +{ + if(rootItem != 0) + { + delete rootItem; + + qDeleteAll(specialLists); + qDeleteAll(labels); + + specialLists.clear(); + labels.clear(); + + items.clear(); + } + + rootItem = 0; +} + +void ReadingListModel::setupReadingListsData(QSqlQuery &sqlquery, ReadingListItem *parent) +{ + items.insert(parent->getId(),parent); + + QSqlRecord record = sqlquery.record(); + + int name = record.indexOf("name"); + int id = record.indexOf("id"); + int finished = record.indexOf("finished"); + int completed = record.indexOf("completed"); + int ordering = record.indexOf("ordering"); + int parentId = record.indexOf("parentId"); + + while (sqlquery.next()) + { + ReadingListItem * rli = new ReadingListItem(QList() + << sqlquery.value(name) + << sqlquery.value(id) + << sqlquery.value(finished) + << sqlquery.value(completed) + << sqlquery.value(ordering)); + + ReadingListItem * currentParent; + if(sqlquery.value(parentId).isNull()) + currentParent = rootItem; + else + currentParent = items.value(sqlquery.value(parentId).toULongLong()); + + currentParent->appendChild(rli); + + items.insert(rli->getId(),rli); + } +} + +QList ReadingListModel::setupSpecialLists(QSqlDatabase & db) +{ + QList list; + + QSqlQuery selectQuery("SELECT * FROM default_reading_list ORDER BY id,name",db); + + QSqlRecord record = selectQuery.record(); + + int name = record.indexOf("name"); + int id = record.indexOf("id"); + + while(selectQuery.next()) { + list << new SpecialListItem(QList() + << selectQuery.value(name) + << selectQuery.value(id)); + } + + //Reading after Favorites, Why? Because I want to :P + list.insert(1,new SpecialListItem(QList() << "Reading" << 0)); + + return list; +} + +void ReadingListModel::setupLabels(QSqlDatabase & db) +{ + QSqlQuery selectQuery("SELECT * FROM label ORDER BY ordering,name",db); + + QSqlRecord record = selectQuery.record(); + + int name = record.indexOf("name"); + int color = record.indexOf("color"); + int id = record.indexOf("id"); + int ordering = record.indexOf("ordering"); + + while(selectQuery.next()) { + addLabelIntoList(new LabelItem(QList() + << selectQuery.value(name) + << selectQuery.value(color) + << selectQuery.value(id) + << selectQuery.value(ordering))); + } + + //TEST + +// INSERT INTO label (name, color, ordering) VALUES ("Oh Oh", "red", 1); +// INSERT INTO label (name, color, ordering) VALUES ("lalala", "orange", 2); +// INSERT INTO label (name, color, ordering) VALUES ("we are not sorry", "yellow", 3); +// INSERT INTO label (name, color, ordering) VALUES ("there we go", "green", 4); +// INSERT INTO label (name, color, ordering) VALUES ("oklabunga", "cyan", 5); +// INSERT INTO label (name, color, ordering) VALUES ("hailer mailer", "blue", 6); +// INSERT INTO label (name, color, ordering) VALUES ("lol", "violet", 7); +// INSERT INTO label (name, color, ordering) VALUES ("problems", "purple", 8); +// INSERT INTO label (name, color, ordering) VALUES ("me gussssta", "pink", 9); +// INSERT INTO label (name, color, ordering) VALUES (":D", "white", 10); +// INSERT INTO label (name, color, ordering) VALUES ("ainsss", "light", 11); +// INSERT INTO label (name, color, ordering) VALUES ("put a smile on my face", "dark", 12); + +} + +void ReadingListModel::setupReadingLists(QSqlDatabase & db) +{ + //setup root item + rootItem = new ReadingListItem(QList() << "ROOT" << 0 << true << false); + + QSqlQuery selectQuery("select * from reading_list order by parentId IS NULL DESC",db); + + //setup reading lists + setupReadingListsData(selectQuery,rootItem); + + //TEST +// ReadingListItem * node1; +// rootItem->appendChild(node1 = new ReadingListItem(QList() /*<< 0*/ << "My reading list" << "atr")); +// rootItem->appendChild(new ReadingListItem(QList() /*<< 0*/ << "X timeline" << "atr")); + +// node1->appendChild(new ReadingListItem(QList() /*<< 0*/ << "sublist" << "atr",node1)); +} + +int ReadingListModel::addLabelIntoList(LabelItem *item) +{ + if(labels.isEmpty()) + labels << item; + else + { + int i = 0; + + while (i < labels.count() && (labels.at(i)->colorid() < item->colorid()) ) + i++; + + if(i < labels.count()) + { + if(labels.at(i)->colorid() == item->colorid()) //sort by name + { + while( i < labels.count() && labels.at(i)->colorid() == item->colorid() && naturalSortLessThanCI(labels.at(i)->name(),item->name())) + i++; + } + } + + + if(i >= labels.count()) + { + QLOG_DEBUG() << "insertando label al final " << item->name(); + labels << item; + } + else + { + QLOG_DEBUG() << "insertando label en " << i << "-" << item->name(); + labels.insert(i,item); + } + + return i; + } + + return 0; +} + +void ReadingListModel::reorderingChildren(QList children) +{ + QList childrenIds; + int i = 0; + foreach (ReadingListItem * item, children) { + item->setOrdering(i++); + childrenIds << item->getId(); + } + + QSqlDatabase db = DataBaseManagement::loadDatabase(_databasePath); + DBHelper::reasignOrderToSublists(childrenIds, db); + QSqlDatabase::removeDatabase(db.connectionName()); +} + +bool ReadingListModel::rowIsSpecialList(int row, const QModelIndex &parent) const +{ + if(parent.isValid()) + return false; //by now no sublists in special list + + if(row >=0 && row < specialLists.count()) + return true; + + return false; +} + +bool ReadingListModel::rowIsLabel(int row, const QModelIndex &parent) const +{ + if(parent.isValid()) + return false; //by now no sublists in labels + + if(row > specialLists.count() && row <= specialLists.count() + labels.count()) + return true; + + return false; +} + +bool ReadingListModel::rowIsReadingList(int row, const QModelIndex &parent) const +{ + if(parent.isValid()) + return true; //only lists with sublists + + int separatorsCount = labels.isEmpty()?1:2; + + if(row >= specialLists.count() + labels.count() + separatorsCount) + return true; + + return false; +} + +bool ReadingListModel::rowIsSeparator(int row, const QModelIndex &parent) const +{ + if(parent.isValid()) + return false; //only separators at top level + + if(row == specialLists.count()) + return true; + + int separatorsCount = labels.isEmpty()?1:2; + if(separatorsCount == 2 && row == specialLists.count() + labels.count() + 1) + return true; + + return false; +} + +ReadingListModelProxy::ReadingListModelProxy(QObject *parent) + :QSortFilterProxyModel(parent) +{ + +} diff --git a/YACReaderLibrary/db/reading_list_model.h b/YACReaderLibrary/db/reading_list_model.h index c60eaa3b..1c76d120 100644 --- a/YACReaderLibrary/db/reading_list_model.h +++ b/YACReaderLibrary/db/reading_list_model.h @@ -1,117 +1,117 @@ -#ifndef READING_LIST_MODEL_H -#define READING_LIST_MODEL_H - -#include -#include -#include -#include -#include -#include - -#include "yacreader_global.h" - -class LabelItem; -class SpecialListItem; -class ReadingListItem; -class ReadingListSeparatorItem; - -class ReadingListModelProxy : public QSortFilterProxyModel -{ - Q_OBJECT -public: - explicit ReadingListModelProxy(QObject *parent = 0); -}; - -class ReadingListModel : public QAbstractItemModel -{ - Q_OBJECT -public: - explicit ReadingListModel(QObject *parent = 0); - - //QAbstractItemModel methods - int rowCount(const QModelIndex &parent = QModelIndex()) const; - int columnCount(const QModelIndex &parent = QModelIndex()) const; - QVariant data(const QModelIndex &index, int role) const; - Qt::ItemFlags flags(const QModelIndex &index) const; - QVariant headerData(int section, Qt::Orientation orientation, - int role = Qt::DisplayRole) const; - QModelIndex index(int row, int column, - const QModelIndex &parent = QModelIndex()) const; - QModelIndex parent(const QModelIndex &index) const; - bool canDropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent) const; - bool dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent); - QMimeData *mimeData(const QModelIndexList &indexes) const; - - //Convenience methods - void setupReadingListsData(QString path); - void addNewLabel(const QString & name, YACReader::LabelColors color); - void addReadingList(const QString & name);//top level reading list - void addReadingListAt(const QString & name, const QModelIndex & mi); - bool isEditable(const QModelIndex & mi); - bool isReadingList(const QModelIndex & mi); - bool isReadingSubList(const QModelIndex & mi); - QString name(const QModelIndex & mi); - void rename(const QModelIndex & mi, const QString & name); - void deleteItem(const QModelIndex & mi); - const QList getLabels(); - - enum Roles { - TypeListsRole = Qt::UserRole + 1, - IDRole, - LabelColorRole, - SpecialListTypeRole - }; - - enum TypeList { - SpecialList, - Label, - ReadingList, - Separator - }; - - enum TypeSpecialList { - Reading, - Favorites - }; - -signals: - - void addComicsToFavorites(const QList & comicIds); - void addComicsToLabel(const QList & comicIds, qulonglong labelId); - void addComicsToReadingList(const QList & comicIds, qulonglong readingListId); - -private: - void cleanAll(); - void setupReadingListsData(QSqlQuery &sqlquery, ReadingListItem *parent); - QList setupSpecialLists(QSqlDatabase &db); - void setupLabels(QSqlDatabase &db); - void setupReadingLists(QSqlDatabase &db); - int addLabelIntoList(LabelItem *item); - void reorderingChildren(QList children); - - bool rowIsSpecialList(int row, const QModelIndex & parent = QModelIndex()) const; - bool rowIsLabel(int row, const QModelIndex & parent = QModelIndex()) const; - bool rowIsReadingList(int row, const QModelIndex & parent = QModelIndex()) const; - bool rowIsSeparator(int row, const QModelIndex & parent = QModelIndex()) const; - - bool dropComics(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent); - bool dropSublist(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent); - //Special lists - QList specialLists; - - //Label - QList labels; - - //Reading lists - ReadingListItem * rootItem; // - QMap items; //lists relationship - - //separators - ReadingListSeparatorItem * separator1; - ReadingListSeparatorItem * separator2; - - QString _databasePath; - -}; - -#endif // READING_LIST_MODEL_H +#ifndef READING_LIST_MODEL_H +#define READING_LIST_MODEL_H + +#include +#include +#include +#include +#include +#include + +#include "yacreader_global.h" + +class LabelItem; +class SpecialListItem; +class ReadingListItem; +class ReadingListSeparatorItem; + +class ReadingListModelProxy : public QSortFilterProxyModel +{ + Q_OBJECT +public: + explicit ReadingListModelProxy(QObject *parent = 0); +}; + +class ReadingListModel : public QAbstractItemModel +{ + Q_OBJECT +public: + explicit ReadingListModel(QObject *parent = 0); + + //QAbstractItemModel methods + int rowCount(const QModelIndex &parent = QModelIndex()) const; + int columnCount(const QModelIndex &parent = QModelIndex()) const; + QVariant data(const QModelIndex &index, int role) const; + Qt::ItemFlags flags(const QModelIndex &index) const; + QVariant headerData(int section, Qt::Orientation orientation, + int role = Qt::DisplayRole) const; + QModelIndex index(int row, int column, + const QModelIndex &parent = QModelIndex()) const; + QModelIndex parent(const QModelIndex &index) const; + bool canDropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent) const; + bool dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent); + QMimeData *mimeData(const QModelIndexList &indexes) const; + + //Convenience methods + void setupReadingListsData(QString path); + void addNewLabel(const QString & name, YACReader::LabelColors color); + void addReadingList(const QString & name);//top level reading list + void addReadingListAt(const QString & name, const QModelIndex & mi); + bool isEditable(const QModelIndex & mi); + bool isReadingList(const QModelIndex & mi); + bool isReadingSubList(const QModelIndex & mi); + QString name(const QModelIndex & mi); + void rename(const QModelIndex & mi, const QString & name); + void deleteItem(const QModelIndex & mi); + const QList getLabels(); + + enum Roles { + TypeListsRole = Qt::UserRole + 1, + IDRole, + LabelColorRole, + SpecialListTypeRole + }; + + enum TypeList { + SpecialList, + Label, + ReadingList, + Separator + }; + + enum TypeSpecialList { + Reading, + Favorites + }; + +signals: + + void addComicsToFavorites(const QList & comicIds); + void addComicsToLabel(const QList & comicIds, qulonglong labelId); + void addComicsToReadingList(const QList & comicIds, qulonglong readingListId); + +private: + void cleanAll(); + void setupReadingListsData(QSqlQuery &sqlquery, ReadingListItem *parent); + QList setupSpecialLists(QSqlDatabase &db); + void setupLabels(QSqlDatabase &db); + void setupReadingLists(QSqlDatabase &db); + int addLabelIntoList(LabelItem *item); + void reorderingChildren(QList children); + + bool rowIsSpecialList(int row, const QModelIndex & parent = QModelIndex()) const; + bool rowIsLabel(int row, const QModelIndex & parent = QModelIndex()) const; + bool rowIsReadingList(int row, const QModelIndex & parent = QModelIndex()) const; + bool rowIsSeparator(int row, const QModelIndex & parent = QModelIndex()) const; + + bool dropComics(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent); + bool dropSublist(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent); + //Special lists + QList specialLists; + + //Label + QList labels; + + //Reading lists + ReadingListItem * rootItem; // + QMap items; //lists relationship + + //separators + ReadingListSeparatorItem * separator1; + ReadingListSeparatorItem * separator2; + + QString _databasePath; + +}; + +#endif // READING_LIST_MODEL_H diff --git a/YACReaderLibrary/db_helper.cpp b/YACReaderLibrary/db_helper.cpp index 2155ea11..b4753c24 100644 --- a/YACReaderLibrary/db_helper.cpp +++ b/YACReaderLibrary/db_helper.cpp @@ -1,1685 +1,1685 @@ -#include "db_helper.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include "reading_list.h" -#include "library_item.h" -#include "comic_db.h" -#include "data_base_management.h" -#include "folder.h" -#include "yacreader_libraries.h" - -#include "qnaturalsorting.h" - -#include "QsLog.h" -//server - -YACReaderLibraries DBHelper::getLibraries() -{ - YACReaderLibraries libraries; - libraries.load(); - return libraries; -} -QList DBHelper::getFolderSubfoldersFromLibrary(qulonglong libraryId, qulonglong folderId) -{ - QString libraryPath = DBHelper::getLibraries().getPath(libraryId); - QSqlDatabase db = DataBaseManagement::loadDatabase(libraryPath+"/.yacreaderlibrary"); - - QList list = DBHelper::getFoldersFromParent(folderId,db,false); - - db.close(); - QSqlDatabase::removeDatabase(db.connectionName()); - return list; -} -QList DBHelper::getFolderComicsFromLibrary(qulonglong libraryId, qulonglong folderId) -{ - return DBHelper::getFolderComicsFromLibrary(libraryId, folderId, false); -} - -QList DBHelper::getFolderComicsFromLibrary(qulonglong libraryId, qulonglong folderId, bool sort) -{ - QString libraryPath = DBHelper::getLibraries().getPath(libraryId); - QSqlDatabase db = DataBaseManagement::loadDatabase(libraryPath+"/.yacreaderlibrary"); - - QList list = DBHelper::getComicsFromParent(folderId,db,sort); - - db.close(); - QSqlDatabase::removeDatabase(db.connectionName()); - return list; -} - -quint32 DBHelper::getNumChildrenFromFolder(qulonglong libraryId, qulonglong folderId) -{ - QString libraryPath = DBHelper::getLibraries().getPath(libraryId); - QSqlDatabase db = DataBaseManagement::loadDatabase(libraryPath+"/.yacreaderlibrary"); - - quint32 result = 0; - - { - QSqlQuery selectQuery(db); - selectQuery.prepare("SELECT count(*) FROM folder WHERE parentId = :parentId and id <> 1"); - selectQuery.bindValue(":parentId", folderId); - selectQuery.exec(); - - result += selectQuery.record().value(0).toULongLong(); - } - - { - QSqlQuery selectQuery(db); - selectQuery.prepare("SELECT count(*) FROM comic c WHERE c.parentId = :parentId"); - selectQuery.bindValue(":parentId", folderId); - selectQuery.exec(); - - result += selectQuery.record().value(0).toULongLong(); - } - - db.close(); - QSqlDatabase::removeDatabase(db.connectionName()); - - return result; -} - -qulonglong DBHelper::getParentFromComicFolderId(qulonglong libraryId, qulonglong id) -{ - QString libraryPath = DBHelper::getLibraries().getPath(libraryId); - QSqlDatabase db = DataBaseManagement::loadDatabase(libraryPath+"/.yacreaderlibrary"); - - Folder f = DBHelper::loadFolder(id,db); - - db.close(); - QSqlDatabase::removeDatabase(db.connectionName()); - return f.parentId; -} -ComicDB DBHelper::getComicInfo(qulonglong libraryId, qulonglong id) -{ - QString libraryPath = DBHelper::getLibraries().getPath(libraryId); - QSqlDatabase db = DataBaseManagement::loadDatabase(libraryPath+"/.yacreaderlibrary"); - - ComicDB comic = DBHelper::loadComic(id,db); - - db.close(); - QSqlDatabase::removeDatabase(db.connectionName()); - return comic; -} - -QList DBHelper::getSiblings(qulonglong libraryId, qulonglong parentId) -{ - QString libraryPath = DBHelper::getLibraries().getPath(libraryId); - QSqlDatabase db = DataBaseManagement::loadDatabase(libraryPath+"/.yacreaderlibrary"); - - QList comics = DBHelper::getSortedComicsFromParent(parentId,db); - db.close(); - QSqlDatabase::removeDatabase(db.connectionName()); - return comics; -} - -QString DBHelper::getFolderName(qulonglong libraryId, qulonglong id) -{ - QString libraryPath = DBHelper::getLibraries().getPath(libraryId); - QSqlDatabase db = DataBaseManagement::loadDatabase(libraryPath+"/.yacreaderlibrary"); - - QString name=""; - - { - QSqlQuery selectQuery(db); //TODO check - selectQuery.prepare("SELECT name FROM folder WHERE id = :id"); - selectQuery.bindValue(":id", id); - selectQuery.exec(); - - if(selectQuery.next()) - { - name = selectQuery.value(0).toString(); - } - } - - db.close(); - QSqlDatabase::removeDatabase(db.connectionName()); - return name; -} -QList DBHelper::getLibrariesNames() -{ - QStringList names = getLibraries().getNames(); - qSort(names.begin(),names.end(),naturalSortLessThanCI); - return names; -} -QString DBHelper::getLibraryName(int id) -{ - return getLibraries().getName(id); -} - -QList DBHelper::getLabelComics(qulonglong libraryId, qulonglong labelId) -{ - QString libraryPath = DBHelper::getLibraries().getPath(libraryId); - QSqlDatabase db = DataBaseManagement::loadDatabase(libraryPath+"/.yacreaderlibrary"); - - QList list; - - { - QSqlQuery selectQuery(db); - selectQuery.prepare("SELECT c.id,c.fileName,ci.title,ci.currentPage,ci.numPages,ci.hash,ci.read,ci.coverSizeRatio " - "FROM comic c INNER JOIN comic_info ci ON (c.comicInfoId = ci.id) " - "INNER JOIN comic_label cl ON (c.id == cl.comic_id) " - "WHERE cl.label_id = :parentLabelId " - "ORDER BY cl.ordering"); - selectQuery.bindValue(":parentLabelId", labelId); - selectQuery.exec(); - - while (selectQuery.next()) - { - ComicDB comic; - - comic.id = selectQuery.value(0).toULongLong(); - comic.parentId = labelId; - comic.name = selectQuery.value(1).toString(); - comic.info.title = selectQuery.value(2).toString(); - comic.info.currentPage = selectQuery.value(3).toInt(); - comic.info.numPages = selectQuery.value(4).toInt(); - comic.info.hash = selectQuery.value(5).toString(); - comic.info.read = selectQuery.value(6).toBool(); - comic.info.coverSizeRatio = selectQuery.value(7).toFloat(); - - list.append(comic); - } - - db.close(); - } - //TODO ? - //QSqlDatabase::removeDatabase(db.connectionName()); - - return list; -} - -QList DBHelper::getFavorites(qulonglong libraryId) -{ - QString libraryPath = DBHelper::getLibraries().getPath(libraryId); - QSqlDatabase db = DataBaseManagement::loadDatabase(libraryPath+"/.yacreaderlibrary"); - - QList list; - - const int FAV_ID = 1; - - { - QSqlQuery selectQuery(db); - selectQuery.prepare("SELECT c.id,c.fileName,ci.title,ci.currentPage,ci.numPages,ci.hash,ci.read,ci.coverSizeRatio " - "FROM comic c INNER JOIN comic_info ci ON (c.comicInfoId = ci.id) " - "INNER JOIN comic_default_reading_list cdrl ON (c.id == cdrl.comic_id) " - "WHERE cdrl.default_reading_list_id = :parentDefaultListId " - "ORDER BY cdrl.ordering"); - selectQuery.bindValue(":parentDefaultListId", FAV_ID); - selectQuery.exec(); - - while (selectQuery.next()) - { - ComicDB comic; - - comic.id = selectQuery.value(0).toULongLong(); - comic.parentId = FAV_ID; - comic.name = selectQuery.value(1).toString(); - comic.info.title = selectQuery.value(2).toString(); - comic.info.currentPage = selectQuery.value(3).toInt(); - comic.info.numPages = selectQuery.value(4).toInt(); - comic.info.hash = selectQuery.value(5).toString(); - comic.info.read = selectQuery.value(6).toBool(); - comic.info.coverSizeRatio = selectQuery.value(7).toFloat(); - - list.append(comic); - } - - db.close(); - } - //TODO ? - //QSqlDatabase::removeDatabase(db.connectionName()); - - return list; -} - -QList DBHelper::getReading(qulonglong libraryId) -{ - QString libraryPath = DBHelper::getLibraries().getPath(libraryId); - QSqlDatabase db = DataBaseManagement::loadDatabase(libraryPath+"/.yacreaderlibrary"); - - QList list; - - { - QSqlQuery selectQuery(db); - selectQuery.prepare("SELECT c.id,c.parentId,c.fileName,ci.title,ci.currentPage,ci.numPages,ci.hash,ci.read,ci.coverSizeRatio " - "FROM comic c INNER JOIN comic_info ci ON (c.comicInfoId = ci.id) " - "WHERE ci.hasBeenOpened = 1 AND ci.read = 0 " - "ORDER BY ci.lastTimeOpened DESC"); - selectQuery.exec(); - - while (selectQuery.next()) - { - ComicDB comic; - - comic.id = selectQuery.value(0).toULongLong(); - comic.parentId = selectQuery.value(1).toULongLong(); - comic.name = selectQuery.value(2).toString(); - comic.info.title = selectQuery.value(3).toString(); - comic.info.currentPage = selectQuery.value(4).toInt(); - comic.info.numPages = selectQuery.value(5).toInt(); - comic.info.hash = selectQuery.value(6).toString(); - comic.info.read = selectQuery.value(7).toBool(); - comic.info.coverSizeRatio = selectQuery.value(8).toFloat(); - - list.append(comic); - } - - db.close(); - } - //TODO ? - //QSqlDatabase::removeDatabase(db.connectionName()); - - return list; -} - -QList DBHelper::getReadingLists(qulonglong libraryId) -{ - QString libraryPath = DBHelper::getLibraries().getPath(libraryId); - QSqlDatabase db = DataBaseManagement::loadDatabase(libraryPath+"/.yacreaderlibrary"); - - QList list; - - QSqlQuery selectQuery("SELECT * from reading_list WHERE parentId IS NULL ORDER BY name DESC",db); - - selectQuery.exec(); - - QSqlRecord record = selectQuery.record(); - - int name = record.indexOf("name"); - int id = record.indexOf("id"); - int ordering = record.indexOf("ordering"); - - while (selectQuery.next()) - { - ReadingList item(selectQuery.value(name).toString(), selectQuery.value(id).toLongLong(),selectQuery.value(ordering).toInt()); - - if(list.isEmpty()) - { - list.append(item); - } - else - { - int i= 0; - while(i DBHelper::getReadingListFullContent(qulonglong libraryId, qulonglong readingListId) -{ - QString libraryPath = DBHelper::getLibraries().getPath(libraryId); - QSqlDatabase db = DataBaseManagement::loadDatabase(libraryPath+"/.yacreaderlibrary"); - - QList list; - - { - QList ids; - ids << readingListId; - - QSqlQuery subfolders(db); - subfolders.prepare("SELECT id " - "FROM reading_list " - "WHERE parentId = :parentId " - "ORDER BY ordering ASC"); - subfolders.bindValue(":parentId", readingListId); - subfolders.exec(); - while(subfolders.next()) - ids << subfolders.value(0).toULongLong(); - - foreach(qulonglong id, ids) - { - QSqlQuery selectQuery(db); - selectQuery.prepare("SELECT c.id,c.parentId,c.fileName,ci.title,ci.currentPage,ci.numPages,ci.hash,ci.read,ci.coverSizeRatio " - "FROM comic c INNER JOIN comic_info ci ON (c.comicInfoId = ci.id) " - "INNER JOIN comic_reading_list crl ON (c.id == crl.comic_id) " - "WHERE crl.reading_list_id = :parentReadingList " - "ORDER BY crl.ordering"); - selectQuery.bindValue(":parentReadingList", id); - selectQuery.exec(); - - while (selectQuery.next()) - { - ComicDB comic; - - comic.id = selectQuery.value(0).toULongLong(); - comic.parentId = selectQuery.value(1).toULongLong(); - comic.name = selectQuery.value(2).toString(); - comic.info.title = selectQuery.value(3).toString(); - comic.info.currentPage = selectQuery.value(4).toInt(); - comic.info.numPages = selectQuery.value(5).toInt(); - comic.info.hash = selectQuery.value(6).toString(); - comic.info.read = selectQuery.value(7).toBool(); - comic.info.coverSizeRatio = selectQuery.value(8).toFloat(); - - list.append(comic); - } - } - } - - //TODO ? - //QSqlDatabase::removeDatabase(db.connectionName()); - - return list; -} - -//objects management -//deletes -void DBHelper::removeFromDB(LibraryItem * item, QSqlDatabase & db) -{ - if(item->isDir()) - DBHelper::removeFromDB(dynamic_cast(item),db); - else - DBHelper::removeFromDB(dynamic_cast(item),db); -} -void DBHelper::removeFromDB(Folder * folder, QSqlDatabase & db) -{ - QSqlQuery query(db); - query.prepare("DELETE FROM folder WHERE id = :id"); - query.bindValue(":id", folder->id); - query.exec(); -} -void DBHelper::removeFromDB(ComicDB * comic, QSqlDatabase & db) -{ - QSqlQuery query(db); - query.prepare("DELETE FROM comic WHERE id = :id"); - query.bindValue(":id", comic->id); - query.exec(); -} - -void DBHelper::removeLabelFromDB(qulonglong id, QSqlDatabase &db) -{ - QSqlQuery query(db); - query.prepare("DELETE FROM label WHERE id = :id"); - query.bindValue(":id", id); - query.exec(); -} - -void DBHelper::removeListFromDB(qulonglong id, QSqlDatabase &db) -{ - QSqlQuery query(db); - query.prepare("DELETE FROM reading_list WHERE id = :id"); - query.bindValue(":id", id); - query.exec(); -} - -void DBHelper::deleteComicsFromFavorites(const QList &comicsList, QSqlDatabase &db) -{ - db.transaction(); - - QLOG_DEBUG() << "deleteComicsFromFavorites----------------------------------"; - - QSqlQuery query(db); - query.prepare("DELETE FROM comic_default_reading_list WHERE comic_id = :comic_id AND default_reading_list_id = 1"); - foreach(ComicDB comic, comicsList) - { - query.bindValue(":comic_id", comic.id); - query.exec(); - } - - db.commit(); -} - -void DBHelper::deleteComicsFromLabel(const QList &comicsList, qulonglong labelId, QSqlDatabase &db) -{ - db.transaction(); - - QLOG_DEBUG() << "deleteComicsFromLabel----------------------------------"; - - QSqlQuery query(db); - query.prepare("DELETE FROM comic_label WHERE comic_id = :comic_id AND label_id = :label_id"); - foreach(ComicDB comic, comicsList) - { - query.bindValue(":comic_id", comic.id); - query.bindValue(":label_id", labelId); - query.exec(); - - QLOG_DEBUG() << "cid = " << comic.id << "lid = " << labelId; - QLOG_DEBUG() << query.lastError().databaseText() << "-" << query.lastError().driverText(); - } - - db.commit(); -} - -void DBHelper::deleteComicsFromReadingList(const QList &comicsList, qulonglong readingListId, QSqlDatabase &db) -{ - db.transaction(); - - QLOG_DEBUG() << "deleteComicsFromReadingList----------------------------------"; - - QSqlQuery query(db); - query.prepare("DELETE FROM comic_reading_list WHERE comic_id = :comic_id AND reading_list_id = :reading_list_id"); - foreach(ComicDB comic, comicsList) - { - query.bindValue(":comic_id", comic.id); - query.bindValue(":reading_list_id", readingListId); - query.exec(); - } - - db.commit(); -} - -//updates -void DBHelper::update(ComicDB * comic, QSqlDatabase & db) -{ - Q_UNUSED(comic) - Q_UNUSED(db) - //do nothing -} - -void DBHelper::update(qulonglong libraryId, ComicInfo & comicInfo) -{ - QString libraryPath = DBHelper::getLibraries().getPath(libraryId); - QSqlDatabase db = DataBaseManagement::loadDatabase(libraryPath+"/.yacreaderlibrary"); - - DBHelper::update(&comicInfo,db); - - db.close(); - QSqlDatabase::removeDatabase(db.connectionName()); -} - -void DBHelper::update(ComicInfo * comicInfo, QSqlDatabase & db) -{ - if(comicInfo == nullptr) - return; - - QSqlQuery updateComicInfo(db); - updateComicInfo.prepare("UPDATE comic_info SET " - "title = :title," - - "coverPage = :coverPage," - "numPages = :numPages," - - "number = :number," - "isBis = :isBis," - "count = :count," - - "volume = :volume," - "storyArc = :storyArc," - "arcNumber = :arcNumber," - "arcCount = :arcCount," - - "genere = :genere," - - "writer = :writer," - "penciller = :penciller," - "inker = :inker," - "colorist = :colorist," - "letterer = :letterer," - "coverArtist = :coverArtist," - - "date = :date," - "publisher = :publisher," - "format = :format," - "color = :color," - "ageRating = :ageRating," - - "synopsis = :synopsis," - "characters = :characters," - "notes = :notes," - - "read = :read," - "edited = :edited," - //new 7.0 fields - "hasBeenOpened = :hasBeenOpened," - - "currentPage = :currentPage," - "bookmark1 = :bookmark1," - "bookmark2 = :bookmark2," - "bookmark3 = :bookmark3," - "brightness = :brightness," - "contrast = :contrast, " - "gamma = :gamma," - "rating = :rating," - - //new 7.1 fields - "comicVineID = :comicVineID," - - //new 9.5 fields - "lastTimeOpened = :lastTimeOpened," - - "coverSizeRatio = :coverSizeRatio," - "originalCoverSize = :originalCoverSize" - //-- - " WHERE id = :id "); - - updateComicInfo.bindValue(":title",comicInfo->title); - - updateComicInfo.bindValue(":coverPage", comicInfo->coverPage); - updateComicInfo.bindValue(":numPages", comicInfo->numPages); - - updateComicInfo.bindValue(":number", comicInfo->number); - updateComicInfo.bindValue(":isBis", comicInfo->isBis); - updateComicInfo.bindValue(":count", comicInfo->count); - - updateComicInfo.bindValue(":volume", comicInfo->volume); - updateComicInfo.bindValue(":storyArc", comicInfo->storyArc); - updateComicInfo.bindValue(":arcNumber",comicInfo->arcNumber); - updateComicInfo.bindValue(":arcCount",comicInfo->arcCount); - - updateComicInfo.bindValue(":genere",comicInfo->genere); - - updateComicInfo.bindValue(":writer",comicInfo->writer); - updateComicInfo.bindValue(":penciller",comicInfo->penciller); - updateComicInfo.bindValue(":inker",comicInfo->inker); - updateComicInfo.bindValue(":colorist",comicInfo->colorist); - updateComicInfo.bindValue(":letterer",comicInfo->letterer); - updateComicInfo.bindValue(":coverArtist",comicInfo->coverArtist); - - updateComicInfo.bindValue(":date",comicInfo->date); - updateComicInfo.bindValue(":publisher",comicInfo->publisher); - updateComicInfo.bindValue(":format",comicInfo->format); - updateComicInfo.bindValue(":color",comicInfo->color); - updateComicInfo.bindValue(":ageRating",comicInfo->ageRating); - - updateComicInfo.bindValue(":synopsis",comicInfo->synopsis); - updateComicInfo.bindValue(":characters",comicInfo->characters); - updateComicInfo.bindValue(":notes",comicInfo->notes); - - bool read = comicInfo->read || comicInfo->currentPage == comicInfo->numPages.toInt(); //if current page is the las page, the comic is read(completed) - comicInfo->read = read; - updateComicInfo.bindValue(":read", read?1:0); - updateComicInfo.bindValue(":id", comicInfo->id); - updateComicInfo.bindValue(":edited", comicInfo->edited?1:0); - - updateComicInfo.bindValue(":hasBeenOpened", comicInfo->hasBeenOpened?1:0 || comicInfo->currentPage > 1); - updateComicInfo.bindValue(":currentPage", comicInfo->currentPage); - updateComicInfo.bindValue(":bookmark1", comicInfo->bookmark1); - updateComicInfo.bindValue(":bookmark2", comicInfo->bookmark2); - updateComicInfo.bindValue(":bookmark3", comicInfo->bookmark3); - updateComicInfo.bindValue(":brightness", comicInfo->brightness); - updateComicInfo.bindValue(":contrast", comicInfo->contrast); - updateComicInfo.bindValue(":gamma", comicInfo->gamma); - updateComicInfo.bindValue(":rating", comicInfo->rating); - - updateComicInfo.bindValue(":comicVineID", comicInfo->comicVineID); - - updateComicInfo.bindValue(":lastTimeOpened", comicInfo->lastTimeOpened); - - updateComicInfo.bindValue(":coverSizeRatio", comicInfo->coverSizeRatio); - updateComicInfo.bindValue(":originalCoverSize", comicInfo->originalCoverSize); - - updateComicInfo.exec(); -} - -void DBHelper::updateRead(ComicInfo * comicInfo, QSqlDatabase & db) -{ - QSqlQuery updateComicInfo(db); - updateComicInfo.prepare("UPDATE comic_info SET " - "read = :read" - " WHERE id = :id "); - - updateComicInfo.bindValue(":read", comicInfo->read?1:0); - updateComicInfo.bindValue(":id", comicInfo->id); - updateComicInfo.exec(); -} - -void DBHelper::update(const Folder & folder, QSqlDatabase &db) -{ - QSqlQuery updateFolderInfo(db); - updateFolderInfo.prepare("UPDATE folder SET " - "finished = :finished, " - "completed = :completed " - "WHERE id = :id "); - updateFolderInfo.bindValue(":finished", folder.isFinished()?1:0); - updateFolderInfo.bindValue(":completed", folder.isCompleted()?1:0); - updateFolderInfo.bindValue(":id", folder.id); - updateFolderInfo.exec(); -} - -void DBHelper::updateChildrenInfo(const Folder & folder, QSqlDatabase & db) -{ - QSqlQuery updateFolderInfo(db); - updateFolderInfo.prepare("UPDATE folder SET " - "numChildren = :numChildren, " - "firstChildHash = :firstChildHash " - "WHERE id = :id "); - updateFolderInfo.bindValue(":numChildren", folder.getNumChildren()); - updateFolderInfo.bindValue(":firstChildHash", folder.getFirstChildHash()); - updateFolderInfo.bindValue(":id", folder.id); - updateFolderInfo.exec(); -} - -void DBHelper::updateChildrenInfo(qulonglong folderId, QSqlDatabase & db) -{ - QList subfolders = DBHelper::getFoldersFromParent(folderId,db,false); - QList comics = DBHelper::getComicsFromParent(folderId,db,true); - - ComicDB * firstComic = NULL; - if(comics.count() > 0) - firstComic = static_cast(comics.first()); - - QSqlQuery updateFolderInfo(db); - updateFolderInfo.prepare("UPDATE folder SET " - "numChildren = :numChildren, " - "firstChildHash = :firstChildHash " - "WHERE id = :id "); - updateFolderInfo.bindValue(":numChildren", subfolders.count() + comics.count()); - updateFolderInfo.bindValue(":firstChildHash", firstComic != NULL ? firstComic->info.hash : ""); - updateFolderInfo.bindValue(":id", folderId); - updateFolderInfo.exec(); -} - -void DBHelper::updateChildrenInfo(QSqlDatabase & db) -{ - QSqlQuery selectQuery(db); //TODO check - selectQuery.prepare("SELECT id FROM folder"); - selectQuery.exec(); - - while (selectQuery.next()) - { - DBHelper::updateChildrenInfo(selectQuery.value(0).toULongLong(), db); - } -} - -void DBHelper::updateProgress(qulonglong libraryId, const ComicInfo &comicInfo) -{ - QString libraryPath = DBHelper::getLibraries().getPath(libraryId); - QSqlDatabase db = DataBaseManagement::loadDatabase(libraryPath+"/.yacreaderlibrary"); - - ComicDB comic = DBHelper::loadComic(comicInfo.id,db); - 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; - - DBHelper::updateReadingRemoteProgress(comic.info,db); - - db.close(); - QSqlDatabase::removeDatabase(db.connectionName()); -} - -void DBHelper::setComicAsReading(qulonglong libraryId, const ComicInfo &comicInfo) -{ - QString libraryPath = DBHelper::getLibraries().getPath(libraryId); - QSqlDatabase db = DataBaseManagement::loadDatabase(libraryPath+"/.yacreaderlibrary"); - - ComicDB comic = DBHelper::loadComic(comicInfo.id,db); - comic.info.hasBeenOpened = true; - comic.info.read = comic.info.read || comic.info.currentPage == comic.info.numPages; - - DBHelper::updateReadingRemoteProgress(comic.info,db); - - db.close(); - QSqlDatabase::removeDatabase(db.connectionName()); -} - -void DBHelper::updateReadingRemoteProgress(const ComicInfo &comicInfo, QSqlDatabase &db) -{ - QSqlQuery updateComicInfo(db); - updateComicInfo.prepare("UPDATE comic_info SET " - "read = :read, " - "currentPage = :currentPage, " - "hasBeenOpened = :hasBeenOpened, " - "lastTimeOpened = :lastTimeOpened, " - "rating = :rating" - " WHERE id = :id "); - - updateComicInfo.bindValue(":read", comicInfo.read?1:0); - updateComicInfo.bindValue(":currentPage", comicInfo.currentPage); - updateComicInfo.bindValue(":hasBeenOpened", comicInfo.hasBeenOpened?1:0); - updateComicInfo.bindValue(":lastTimeOpened", QDateTime::currentMSecsSinceEpoch() / 1000); - updateComicInfo.bindValue(":id", comicInfo.id); - updateComicInfo.bindValue(":rating", comicInfo.rating); - updateComicInfo.exec(); - - updateComicInfo.clear(); -} - - -void DBHelper::updateFromRemoteClient(qulonglong libraryId,const ComicInfo & comicInfo) -{ - QString libraryPath = DBHelper::getLibraries().getPath(libraryId); - QSqlDatabase db = DataBaseManagement::loadDatabase(libraryPath+"/.yacreaderlibrary"); - - ComicDB comic = DBHelper::loadComic(comicInfo.id,db); - - if(comic.info.hash == comicInfo.hash) - { - if(comicInfo.currentPage > 0) - { - comic.info.currentPage = comicInfo.currentPage; - - if(comic.info.currentPage == comic.info.numPages) - comic.info.read = true; - - comic.info.hasBeenOpened = true; - - if (comic.info.lastTimeOpened.toULongLong() < comicInfo.lastTimeOpened.toULongLong()) - comic.info.lastTimeOpened = comicInfo.lastTimeOpened; - } - - if(comicInfo.rating > 0) - comic.info.rating = comicInfo.rating; - - DBHelper::updateReadingRemoteProgress(comic.info,db); - } - - db.close(); - QSqlDatabase::removeDatabase(db.connectionName()); -} - -void DBHelper::updateFromRemoteClientWithHash(const ComicInfo & comicInfo) -{ - YACReaderLibraries libraries = DBHelper::getLibraries(); - - QStringList names = libraries.getNames(); - - foreach (QString name, names) { - QString libraryPath = DBHelper::getLibraries().getPath(libraries.getId(name)); - - QSqlDatabase db = DataBaseManagement::loadDatabase(libraryPath+"/.yacreaderlibrary"); - - ComicInfo info = loadComicInfo(comicInfo.hash, db); - - if(comicInfo.currentPage > 0) - { - info.currentPage = comicInfo.currentPage; - - if(info.currentPage == info.numPages) - info.read = true; - - info.hasBeenOpened = true; - - if (info.lastTimeOpened.toULongLong() < comicInfo.lastTimeOpened.toULongLong()) - info.lastTimeOpened = comicInfo.lastTimeOpened; - } - - if(comicInfo.rating > 0) - info.rating = comicInfo.rating; - - DBHelper::update(&info, db); - - db.close(); - QSqlDatabase::removeDatabase(db.connectionName()); - } -} - -void DBHelper::renameLabel(qulonglong id, const QString &name, QSqlDatabase &db) -{ - QSqlQuery renameLabelQuery(db); - renameLabelQuery.prepare("UPDATE label SET " - "name = :name " - "WHERE id = :id"); - renameLabelQuery.bindValue(":name", name); - renameLabelQuery.bindValue(":id", id); - renameLabelQuery.exec(); - - QLOG_DEBUG() << renameLabelQuery.lastError().databaseText(); -} - -void DBHelper::renameList(qulonglong id, const QString &name, QSqlDatabase &db) -{ - QSqlQuery renameLabelQuery(db); - renameLabelQuery.prepare("UPDATE reading_list SET " - "name = :name " - "WHERE id = :id"); - renameLabelQuery.bindValue(":name", name); - renameLabelQuery.bindValue(":id", id); - renameLabelQuery.exec(); -} - -void DBHelper::reasignOrderToSublists(QList ids, QSqlDatabase &db) -{ - QSqlQuery updateOrdering(db); - updateOrdering.prepare("UPDATE reading_list SET " - "ordering = :ordering " - "WHERE id = :id"); - db.transaction(); - int order = 0; - foreach(qulonglong id, ids) - { - updateOrdering.bindValue(":ordering",order++); - updateOrdering.bindValue(":id", id); - updateOrdering.exec(); - } - - db.commit(); -} - -void DBHelper::reasignOrderToComicsInFavorites(QList comicIds, QSqlDatabase &db) -{ - QSqlQuery updateOrdering(db); - updateOrdering.prepare("UPDATE comic_default_reading_list SET " - "ordering = :ordering " - "WHERE comic_id = :comic_id AND default_reading_list_id = 1"); - db.transaction(); - int order = 0; - foreach(qulonglong id, comicIds) - { - updateOrdering.bindValue(":ordering",order++); - updateOrdering.bindValue(":comic_id", id); - updateOrdering.exec(); - } - - db.commit(); -} - -void DBHelper::reasignOrderToComicsInLabel(qulonglong labelId, QList comicIds, QSqlDatabase &db) -{ - QSqlQuery updateOrdering(db); - updateOrdering.prepare("UPDATE comic_label SET " - "ordering = :ordering " - "WHERE comic_id = :comic_id AND label_id = :label_id"); - db.transaction(); - int order = 0; - foreach(qulonglong id, comicIds) - { - updateOrdering.bindValue(":ordering",order++); - updateOrdering.bindValue(":comic_id", id); - updateOrdering.bindValue(":label_id", labelId); - updateOrdering.exec(); - } - - db.commit(); -} - -void DBHelper::reasignOrderToComicsInReadingList(qulonglong readingListId, QList comicIds, QSqlDatabase &db) -{ - QSqlQuery updateOrdering(db); - updateOrdering.prepare("UPDATE comic_reading_list SET " - "ordering = :ordering " - "WHERE comic_id = :comic_id AND reading_list_id = :reading_list_id"); - db.transaction(); - int order = 0; - foreach(qulonglong id, comicIds) - { - updateOrdering.bindValue(":ordering",order++); - updateOrdering.bindValue(":comic_id", id); - updateOrdering.bindValue(":reading_list_id", readingListId); - updateOrdering.exec(); - QLOG_TRACE() << updateOrdering.lastError().databaseText() << "-" << updateOrdering.lastError().driverText(); - } - - db.commit(); -} - -//inserts -qulonglong DBHelper::insert(Folder * folder, QSqlDatabase & db) -{ - QSqlQuery query(db); - query.prepare("INSERT INTO folder (parentId, name, path) " - "VALUES (:parentId, :name, :path)"); - query.bindValue(":parentId", folder->parentId); - query.bindValue(":name", folder->name); - query.bindValue(":path", folder->path); - query.exec(); - - return query.lastInsertId().toULongLong(); -} - -qulonglong DBHelper::insert(ComicDB * comic, QSqlDatabase & db) -{ - if(!comic->info.existOnDb) - { - QSqlQuery comicInfoInsert(db); - comicInfoInsert.prepare("INSERT INTO comic_info (hash,numPages,coverSizeRatio,originalCoverSize) " - "VALUES (:hash,:numPages,:coverSizeRatio,:originalCoverSize)"); - comicInfoInsert.bindValue(":hash", comic->info.hash); - comicInfoInsert.bindValue(":numPages", comic->info.numPages); - comicInfoInsert.bindValue(":coverSizeRatio", comic->info.coverSizeRatio); - comicInfoInsert.bindValue(":originalCoverSize", comic->info.originalCoverSize); - comicInfoInsert.exec(); - comic->info.id =comicInfoInsert.lastInsertId().toULongLong(); - comic->_hasCover = false; - } - else - comic->_hasCover = true; - - QSqlQuery query(db); - query.prepare("INSERT INTO comic (parentId, comicInfoId, fileName, path) " - "VALUES (:parentId,:comicInfoId,:name, :path)"); - query.bindValue(":parentId", comic->parentId); - query.bindValue(":comicInfoId", comic->info.id); - query.bindValue(":name", comic->name); - query.bindValue(":path", comic->path); - query.exec(); - - return query.lastInsertId().toULongLong(); -} - -qulonglong DBHelper::insertLabel(const QString &name, YACReader::LabelColors color, QSqlDatabase &db) -{ - QSqlQuery query(db); - query.prepare("INSERT INTO label (name, color, ordering) " - "VALUES (:name, :color, :ordering)"); - query.bindValue(":name", name); - query.bindValue(":color", YACReader::colorToName(color)); - query.bindValue(":ordering", color); - query.exec(); - return query.lastInsertId().toULongLong(); -} - -qulonglong DBHelper::insertReadingList(const QString &name, QSqlDatabase &db) -{ - QSqlQuery query(db); - query.prepare("INSERT INTO reading_list (name) " - "VALUES (:name)"); - query.bindValue(":name", name); - query.exec(); - return query.lastInsertId().toULongLong(); -} - -qulonglong DBHelper::insertReadingSubList(const QString &name, qulonglong parentId, int ordering, QSqlDatabase &db) -{ - QSqlQuery query(db); - query.prepare("INSERT INTO reading_list (name, parentId, ordering) " - "VALUES (:name, :parentId, :ordering)"); - query.bindValue(":name", name); - query.bindValue(":parentId", parentId); - query.bindValue(":ordering", ordering); - query.exec(); - return query.lastInsertId().toULongLong(); -} - -void DBHelper::insertComicsInFavorites(const QList &comicsList, QSqlDatabase &db) -{ - QSqlQuery getNumComicsInFavoritesQuery("SELECT count(*) FROM comic_default_reading_list WHERE default_reading_list_id = 1;",db); - getNumComicsInFavoritesQuery.next(); - - int numComics = getNumComicsInFavoritesQuery.value(0).toInt(); - - db.transaction(); - - QSqlQuery query(db); - query.prepare("INSERT INTO comic_default_reading_list (default_reading_list_id, comic_id, ordering) " - "VALUES (1, :comic_id, :ordering)"); - - foreach(ComicDB comic, comicsList) - { - query.bindValue(":comic_id", comic.id); - query.bindValue(":ordering", numComics++); - query.exec(); - } - - QLOG_TRACE() << query.lastError(); - - db.commit(); -} - -void DBHelper::insertComicsInLabel(const QList &comicsList, qulonglong labelId, QSqlDatabase &db) -{ - QSqlQuery getNumComicsInFavoritesQuery(QString("SELECT count(*) FROM comic_label WHERE label_id = %1;").arg(labelId) ,db); - getNumComicsInFavoritesQuery.next(); - - int numComics = getNumComicsInFavoritesQuery.value(0).toInt(); - - db.transaction(); - - QSqlQuery query(db); - query.prepare("INSERT INTO comic_label (label_id, comic_id, ordering) " - "VALUES (:label_id, :comic_id, :ordering)"); - - foreach(ComicDB comic, comicsList) - { - query.bindValue(":label_id", labelId); - query.bindValue(":comic_id", comic.id); - query.bindValue(":ordering", numComics++); - query.exec(); - } - - QLOG_TRACE() << query.lastError(); - - db.commit(); -} - -void DBHelper::insertComicsInReadingList(const QList &comicsList, qulonglong readingListId, QSqlDatabase &db) -{ - QSqlQuery getNumComicsInFavoritesQuery("SELECT count(*) FROM comic_reading_list;",db); - getNumComicsInFavoritesQuery.next(); - - int numComics = getNumComicsInFavoritesQuery.value(0).toInt(); - - db.transaction(); - - QSqlQuery query(db); - query.prepare("INSERT INTO comic_reading_list (reading_list_id, comic_id, ordering) " - "VALUES (:reading_list_id, :comic_id, :ordering)"); - - foreach(ComicDB comic, comicsList) - { - query.bindValue(":reading_list_id", readingListId); - query.bindValue(":comic_id", comic.id); - query.bindValue(":ordering", numComics++); - query.exec(); - } - - db.commit(); -} -//queries -QList DBHelper::getFoldersFromParent(qulonglong parentId, QSqlDatabase & db, bool sort) -{ - QList list; - - QSqlQuery selectQuery(db); //TODO check - selectQuery.prepare("SELECT * FROM folder WHERE parentId = :parentId and id <> 1"); - selectQuery.bindValue(":parentId", parentId); - selectQuery.exec(); - - QSqlRecord record = selectQuery.record(); - - int name = record.indexOf("name"); - int path = record.indexOf("path"); - int id = record.indexOf("id"); - int numChildren = record.indexOf("numChildren"); - int firstChildHash = record.indexOf("firstChildHash"); - int customImage = record.indexOf("customImage"); - - Folder * currentItem; - while (selectQuery.next()) - { - //TODO sort by sort indicator and name - currentItem = new Folder(selectQuery.value(id).toULongLong(),parentId,selectQuery.value(name).toString(),selectQuery.value(path).toString()); - - if(!selectQuery.value(numChildren).isNull() && selectQuery.value(numChildren).isValid()) - currentItem->setNumChildren(selectQuery.value(numChildren).toInt()); - currentItem->setFirstChildHash(selectQuery.value(firstChildHash).toString()); - currentItem->setCustomImage(selectQuery.value(customImage).toString()); - - int lessThan = 0; - - if(list.isEmpty() || !sort) - list.append(currentItem); - else - { - Folder * last = static_cast(list.back()); - QString nameLast = last->name; - QString nameCurrent = currentItem->name; - QList::iterator i; - i = list.end(); - i--; - while ((0 > (lessThan = naturalCompare(nameCurrent,nameLast,Qt::CaseInsensitive))) && i != list.begin()) - { - i--; - nameLast = (*i)->name; - } - if(lessThan>=0) //si se ha encontrado un elemento menor que current, se inserta justo después - list.insert(++i,currentItem); - else - list.insert(i,currentItem); - } - } - - return list; -} - -QList DBHelper::getSortedComicsFromParent(qulonglong parentId, QSqlDatabase & db) -{ - QList list; - - QSqlQuery selectQuery(db); - - selectQuery.setForwardOnly(true); - selectQuery.prepare("select * from comic c inner join comic_info ci on (c.comicInfoId = ci.id) where c.parentId = :parentId"); - selectQuery.bindValue(":parentId", parentId); - selectQuery.exec(); - - QSqlRecord record = selectQuery.record(); - - int id = record.indexOf("id"); - //int parentIdIndex = record.indexOf("parentId"); - int fileName = record.indexOf("fileName"); - int path = record.indexOf("path"); - - int hash = record.indexOf("hash"); - int comicInfoId = record.indexOf("comicInfoId"); - int read = record.indexOf("read"); - int edited = record.indexOf("edited"); - - //new 7.0 fields - int hasBeenOpened = record.indexOf("hasBeenOpened"); - int currentPage = record.indexOf("currentPage"); - int bookmark1 = record.indexOf("bookmark1"); - int bookmark2 = record.indexOf("bookmark2"); - int bookmark3 = record.indexOf("bookmark3"); - int brightness = record.indexOf("brightness"); - int contrast = record.indexOf("contrast"); - int gamma = record.indexOf("gamma"); - int rating = record.indexOf("rating"); - //-- - - int title = record.indexOf("title"); - int numPages = record.indexOf("numPages"); - - int coverPage = record.indexOf("coverPage"); - - int number = record.indexOf("number"); - int isBis = record.indexOf("isBis"); - int count = record.indexOf("count"); - - int volume = record.indexOf("volume"); - int storyArc = record.indexOf("storyArc"); - int arcNumber = record.indexOf("arcNumber"); - int arcCount = record.indexOf("arcCount"); - - int genere = record.indexOf("genere"); - - int writer = record.indexOf("writer"); - int penciller = record.indexOf("penciller"); - int inker = record.indexOf("inker"); - int colorist = record.indexOf("colorist"); - int letterer = record.indexOf("letterer"); - int coverArtist = record.indexOf("coverArtist"); - - int date = record.indexOf("date"); - int publisher = record.indexOf("publisher"); - int format = record.indexOf("format"); - int color = record.indexOf("color"); - int ageRating = record.indexOf("ageRating"); - - int synopsis = record.indexOf("synopsis"); - int characters = record.indexOf("characters"); - int notes = record.indexOf("notes"); - - int comicVineID = record.indexOf("comicVineID"); - - int lastTimeOpened = record.indexOf("lastTimeOpened"); - - int coverSizeRatio = record.indexOf("coverSizeRatio"); - int originalCoverSize = record.indexOf("originalCoverSize"); - - ComicDB currentItem; - while (selectQuery.next()) - { - currentItem.id = selectQuery.value(id).toULongLong(); - currentItem.parentId = parentId;//selectQuery.value(parentId).toULongLong(); - currentItem.name = selectQuery.value(fileName).toString(); - currentItem.path = selectQuery.value(path).toString(); - - currentItem.info.hash = selectQuery.value(hash).toString(); - currentItem.info.id = selectQuery.value(comicInfoId).toULongLong(); - currentItem.info.read = selectQuery.value(read).toBool(); - currentItem.info.edited = selectQuery.value(edited).toBool(); - - //new 7.0 fields - currentItem.info.hasBeenOpened = selectQuery.value(hasBeenOpened).toBool(); - currentItem.info.currentPage = selectQuery.value(currentPage).toInt(); - currentItem.info.bookmark1 = selectQuery.value(bookmark1).toInt(); - currentItem.info.bookmark2 = selectQuery.value(bookmark2).toInt(); - currentItem.info.bookmark3 = selectQuery.value(bookmark3).toInt(); - currentItem.info.brightness = selectQuery.value(brightness).toInt(); - currentItem.info.contrast = selectQuery.value(contrast).toInt(); - currentItem.info.gamma = selectQuery.value(gamma).toInt(); - currentItem.info.rating = selectQuery.value(rating).toInt(); - //-- - - currentItem.info.title = selectQuery.value(title); - currentItem.info.numPages = selectQuery.value(numPages); - - currentItem.info.coverPage = selectQuery.value(coverPage); - - currentItem.info.number = selectQuery.value(number); - currentItem.info.isBis = selectQuery.value(isBis); - currentItem.info.count = selectQuery.value(count); - - currentItem.info.volume = selectQuery.value(volume); - currentItem.info.storyArc = selectQuery.value(storyArc); - currentItem.info.arcNumber = selectQuery.value(arcNumber); - currentItem.info.arcCount = selectQuery.value(arcCount); - - currentItem.info.genere = selectQuery.value(genere); - - currentItem.info.writer = selectQuery.value(writer); - currentItem.info.penciller = selectQuery.value(penciller); - currentItem.info.inker = selectQuery.value(inker); - currentItem.info.colorist = selectQuery.value(colorist); - currentItem.info.letterer = selectQuery.value(letterer); - currentItem.info.coverArtist = selectQuery.value(coverArtist); - - currentItem.info.date = selectQuery.value(date); - currentItem.info.publisher = selectQuery.value(publisher); - currentItem.info.format = selectQuery.value(format); - currentItem.info.color = selectQuery.value(color); - currentItem.info.ageRating = selectQuery.value(ageRating); - - currentItem.info.synopsis = selectQuery.value(synopsis); - currentItem.info.characters = selectQuery.value(characters); - currentItem.info.notes = selectQuery.value(notes); - - currentItem.info.comicVineID = selectQuery.value(comicVineID); - - currentItem.info.lastTimeOpened = selectQuery.value(lastTimeOpened); - - currentItem.info.coverSizeRatio = selectQuery.value(coverSizeRatio); - currentItem.info.originalCoverSize = selectQuery.value(originalCoverSize); - - currentItem.info.existOnDb = true; - - list.append(currentItem); - } - - std::sort(list.begin(), list.end(), [](const ComicDB&c1, const ComicDB&c2) - { - if(c1.info.number.isNull() && c2.info.number.isNull()) - { - return naturalSortLessThanCI(c1.name, c2.name); - } - else - { - if (c1.info.number.isNull() == false && c2.info.number.isNull() == false) - { - return c1.info.number.toInt() < c2.info.number.toInt(); - } - else - { - return c2.info.number.isNull(); - } - } - }); - - //selectQuery.finish(); - return list; -} -QList DBHelper::getComicsFromParent(qulonglong parentId, QSqlDatabase & db, bool sort) -{ - QList list; - - QSqlQuery selectQuery(db); - selectQuery.prepare("select c.id,c.parentId,c.fileName,c.path,ci.hash from comic c inner join comic_info ci on (c.comicInfoId = ci.id) where c.parentId = :parentId"); - selectQuery.bindValue(":parentId", parentId); - selectQuery.exec(); - - QSqlRecord record = selectQuery.record(); - - int id = record.indexOf("id"); - - ComicDB * currentItem; - while (selectQuery.next()) - { - currentItem = new ComicDB(); - currentItem->id = selectQuery.value(id).toULongLong(); - currentItem->parentId = selectQuery.value(1).toULongLong(); - currentItem->name = selectQuery.value(2).toString(); - currentItem->path = selectQuery.value(3).toString(); - currentItem->info = DBHelper::loadComicInfo(selectQuery.value(4).toString(),db); - - list.append(currentItem); - } - - if (sort) - { - std::sort(list.begin(), list.end(), [](const LibraryItem * c1, const LibraryItem * c2){ - return c1->name.localeAwareCompare(c2->name) < 0; - }); - } - - return list; -} - -QList