Merged luisangelsm/yacreader into default

This commit is contained in:
Felix Kauselmann
2015-08-20 12:28:47 +02:00
parent 3a6b2d9b98
commit 23c33cef61
64 changed files with 1758 additions and 877 deletions

View File

@ -1,3 +1,34 @@
8.0.0
Reading lists
Tags
'Favorites' and 'being read' lists
New search engine, now you can filter folders and comics
New grid view
Add and delete folders
Update a single folder (no need for updating the whole library to rescan a single folder)
Drag and drop for adding new comics and folders
Customizable shorcuts
Manga mode (thank you Felix)
Spread page detection for double page mode (including manga mode)(thank you again Felix :) )
New view for folders not containing comics (only subfolders)
Save selected covers to disk
Comics in Reading Lists and Tags can be sorted by drag&drop
Sublist in Reading Lists can by sorted by drag&drop
Added WebP image format support
The user has to provide its own Comic Vine API key to prevent usage limit errors from Comic Vine
New unarr decompression backend for Linux and Unix systems
Fixed memory and filedescriptor leaks in 7zip wrapper
Dropped support for Qt4
Lots of smaller bugfixes
7.2.0
Added support for the new "remote read" feature in iOS devices.
Improved stability
Fixed broken compatibility with Windows XP
Improved Linux "packageability" (thanks to Felix, Alexander and Yoann)**
German translation (thanks to Gerhard Joeken)
Bug fixes.
7.1.0
A<EFBFBD>adida opci<63>n para resetear el rating de un comics
Corregidos bugs que afectaban a la informaci<63>n de p<>gina.

View File

@ -2,14 +2,57 @@ COMPILATION GUIDE FOR LINUX/UNIX USERS
**********************************
YACReader and YACReaderLibrary are build using qmake. To build and install the program, run:
qmake
qmake-qt5 CONFIG+=[Options]
make
make install
from the source dir. For seperate builds of YACReader or YACReaderLibrary, enter their respective subfolders and run the commands from there.
Build options:
Dependencies:
-----------------------
- Qt >= 5.3 with the following modules:
- declarative
- sql
- script
- multimedia
- imageformats
- opengl
- sql-sqlite
- poppler-qt5
- qrencode
- sqllite
- glu
- a decompression backend, either 7zip or unarr (see below)
Decompression backend:
---------------------------------------
YACReader supports two decompression backends:
- unarr
- p7zip=9.20.1
These can be selected at build time by adding either CONFIG+=unarr or CONFIG+=7zip as an option when running qmake.
If none of these is provided, the build system will default to unarr on Linux/Unix and [p]7zip on Windows and OS X.
The decompression backends have their own dependencies and require additional steps like downloading additional source code
for setup. Please consult the README files provided in the compressed_archive and compressed_archive/unarr folders for details.
If you chose to build YACReader with p7zip as a backend on Linux/Unix, please take notice that this backend has some problems:
- p7zip > 9.20.1 is not supported
- p7zip 9.20.1 has known bugs that are fixed only in the later versions
- a system update that replaces p7zip 9.20.1 with a later version will make YACReader unusable
If your system already ships with p7zip > 9.20.1 you can place 7z.so and the Codecs folder with the Rar29.so from p7zip 9.20.1 in /usr/lib/yacreader
YACReader will check this folder first and can thus continue using 7zip as a backend with p7zip > 9.20.1 installed on your system.
Other build options:
---------------------
You can adjust the installation prefix as well als the path make install uses to install the files.
Use "qmake PREFIX=DIR" to configure YACReader for your systems default prefix (for example "/", "/usr", "/usr/local").
@ -24,7 +67,7 @@ On embedded devices that don't support desktop OpenGL, it is recommended to use
qmake CONFIG+=no_opengl
This will remove any dependency on desktop OpenGL.
This will remove any dependency on desktop OpenGL and hardlock rendering to software.
DO YOU WANT TO HELP YACREADER?

View File

@ -1,164 +0,0 @@
INCLUDEPATH += $$PWD
DEPENDPATH += $$PWD
INCLUDEPATH += .
INCLUDEPATH += $$PWD/../common \
$$PWD/../custom_widgets
CONFIG(legacy_gl_widget) {
INCLUDEPATH += ../common/gl_legacy \
} else {
INCLUDEPATH += ../common/gl \
}
win32 {
LIBS += -L$$PWD/../dependencies/poppler/lib -loleaut32 -lole32
LIBS += -lpoppler-qt5
INCLUDEPATH += ../dependencies/poppler/include/qt5
QMAKE_CXXFLAGS_RELEASE += /MP /Ob2 /Oi /Ot /GT
!CONFIG(no_opengl) {
QMAKE_CXXFLAGS_RELEASE += /GL
}
QMAKE_LFLAGS_RELEASE += /LTCG
CONFIG -= embed_manifest_exe
}
unix:!macx{
INCLUDEPATH += /usr/include/poppler/qt5
LIBS += -L/usr/lib -lpoppler-qt5
!CONFIG(no_opengl) {
LIBS += -lGLU
}
}
macx{
#INCLUDEPATH += "/Volumes/Mac OS X Lion/usr/X11/include"
#isEqual(QT_MAJOR_VERSION, 5) {
#INCLUDEPATH += /usr/local/include/poppler/qt5
#LIBS += -L/usr/local/lib -lpoppler-qt5
#}
#else {
#INCLUDEPATH += /usr/local/include/poppler/qt4
#LIBS += -L/usr/local/lib -lpoppler-qt4
#}
CONFIG += objective_c
QT += macextras gui-private
LIBS += -framework Foundation -framework ApplicationServices -framework AppKit
OBJECTIVE_SOURCES += $$PWD/../common/pdf_comic.mm
HEADERS += $$PWD/../common/pdf_comic.h
}
QT += network widgets core
!CONFIG(no_opengl) {
QT += opengl
}
#CONFIG += release
CONFIG -= flat
QT += multimedia
# Input
HEADERS += $$PWD/../common/comic.h \
$$PWD/configuration.h \
$$PWD/goto_dialog.h \
$$PWD/magnifying_glass.h \
$$PWD/main_window_viewer.h \
$$PWD/viewer.h \
$$PWD/goto_flow.h \
$$PWD/options_dialog.h \
$$PWD/../common/bookmarks.h \
$$PWD/bookmarks_dialog.h \
$$PWD/render.h \
$$PWD/shortcuts_dialog.h \
$$PWD/translator.h \
$$PWD/goto_flow_widget.h \
$$PWD/page_label_widget.h \
$$PWD/goto_flow_toolbar.h \
$$PWD/goto_flow_decorationbar.h \
$$PWD/width_slider.h \
$$PWD/notifications_label_widget.h \
$$PWD/../common/pictureflow.h \
$$PWD/../common/custom_widgets.h \
$$PWD/../common/check_new_version.h \
$$PWD/../common/qnaturalsorting.h \
$$PWD/../common/yacreader_global.h \
$$PWD/../common/onstart_flow_selection_dialog.h \
$$PWD/../common/comic_db.h \
$$PWD/../common/folder.h \
$$PWD/../common/library_item.h \
$$PWD/yacreader_local_client.h \
$$PWD/../common/http_worker.h \
$$PWD/../common/exit_check.h \
$$PWD/../common/scroll_management.h
!CONFIG(no_opengl) {
CONFIG(legacy_gl_widget) {
message("using legacy YACReaderFlowGL (QGLWidget) header")
HEADERS += ../common/gl_legacy/yacreader_flow_gl.h
} else {
HEADERS += ../common/gl/yacreader_flow_gl.h
}
HEADERS += $$PWD/goto_flow_gl.h
}
SOURCES += $$PWD/../common/comic.cpp \
$$PWD/configuration.cpp \
$$PWD/goto_dialog.cpp \
$$PWD/magnifying_glass.cpp \
$$PWD/main_window_viewer.cpp \
$$PWD/viewer.cpp \
$$PWD/goto_flow.cpp \
$$PWD/options_dialog.cpp \
$$PWD/../common/bookmarks.cpp \
$$PWD/bookmarks_dialog.cpp \
$$PWD/render.cpp \
$$PWD/shortcuts_dialog.cpp \
$$PWD/translator.cpp \
$$PWD/goto_flow_widget.cpp \
$$PWD/page_label_widget.cpp \
$$PWD/goto_flow_toolbar.cpp \
$$PWD/goto_flow_decorationbar.cpp \
$$PWD/width_slider.cpp \
$$PWD/notifications_label_widget.cpp \
$$PWD/../common/pictureflow.cpp \
$$PWD/../common/custom_widgets.cpp \
$$PWD/../common/check_new_version.cpp \
$$PWD/../common/qnaturalsorting.cpp \
$$PWD/../common/onstart_flow_selection_dialog.cpp \
$$PWD/../common/comic_db.cpp \
$$PWD/../common/folder.cpp \
$$PWD/../common/library_item.cpp \
$$PWD/yacreader_local_client.cpp \
$$PWD/../common/http_worker.cpp \
$$PWD/../common/yacreader_global.cpp \
$$PWD/../common/exit_check.cpp \
$$PWD/../common/scroll_management.cpp
!CONFIG(no_opengl) {
CONFIG(legacy_gl_widget) {
message("using legacy YACReaderFlowGL (QGLWidget) source code")
SOURCES += ../common/gl_legacy/yacreader_flow_gl.cpp
} else {
SOURCES += ../common/gl/yacreader_flow_gl.cpp
}
SOURCES += $$PWD/goto_flow_gl.cpp
}
include($$PWD/../custom_widgets/custom_widgets_yacreader.pri)
include($$PWD/../compressed_archive/wrapper.pri)
include($$PWD/../shortcuts_management/shortcuts_management.pri)
RESOURCES += $$PWD/yacreader_images.qrc \
$$PWD/yacreader_files.qrc
win32:RESOURCES += $$PWD/yacreader_images_win.qrc
unix:!macx:RESOURCES += $$PWD/yacreader_images_win.qrc
macx:RESOURCES += $$PWD/yacreader_images_osx.qrc

View File

@ -8,41 +8,51 @@ DEPENDPATH += . \
DEFINES += NOMINMAX YACREADER
CONFIG(no_opengl) {
DEFINES += NO_OPENGL
#load default build flags
include (../config.pri)
unix:!macx{
QMAKE_CXXFLAGS += -std=c++11
}
unix:!macx{
QMAKE_CXXFLAGS += -std=c++11
CONFIG(force_angle) {
Release:DESTDIR = ../release_angle
Debug:DESTDIR = ../debug_angle
} else {
Release:DESTDIR = ../release
Debug:DESTDIR = ../debug
}
Release:DESTDIR = ../release
Debug:DESTDIR = ../debug
SOURCES += main.cpp
INCLUDEPATH += ../common \
../custom_widgets
CONFIG(legacy_gl_widget) {
!CONFIG(no_opengl):CONFIG(legacy_gl_widget) {
INCLUDEPATH += ../common/gl_legacy \
} else {
INCLUDEPATH += ../common/gl \
}
#there are going to be two builds for windows, OpenGL based and ANGLE based
win32 {
LIBS += -L../dependencies/poppler/lib -loleaut32 -lole32
CONFIG(force_angle) {
message("using ANGLE")
LIBS += -L../dependencies/poppler/lib -loleaut32 -lole32 -lshell32 -lopengl32 -lglu32 -luser32
#linking extra libs are necesary for a successful compilation, a better approach should be
#to remove any OpenGL (desktop) dependencies
#the OpenGL stuff should be migrated to OpenGL ES
DEFINES += FORCE_ANGLE
} else {
LIBS += -L../dependencies/poppler/lib -loleaut32 -lole32 -lshell32 -lopengl32 -lglu32 -luser32
}
LIBS += -lpoppler-qt5
INCLUDEPATH += ../dependencies/poppler/include/qt5
LIBS += -lpoppler-qt5
INCLUDEPATH += ../dependencies/poppler/include/qt5
QMAKE_CXXFLAGS_RELEASE += /MP /Ob2 /Oi /Ot /GT
!CONFIG(no_opengl) {
QMAKE_CXXFLAGS_RELEASE += /GL
}
QMAKE_LFLAGS_RELEASE += /LTCG
CONFIG -= embed_manifest_exe
QMAKE_CXXFLAGS_RELEASE += /MP /Ob2 /Oi /Ot /GT /GL
QMAKE_LFLAGS_RELEASE += /LTCG
CONFIG -= embed_manifest_exe
}
unix:!macx{
@ -118,7 +128,8 @@ HEADERS += ../common/comic.h \
yacreader_local_client.h \
../common/http_worker.h \
../common/exit_check.h \
../common/scroll_management.h
../common/scroll_management.h \
../common/opengl_checker.h
!CONFIG(no_opengl) {
CONFIG(legacy_gl_widget) {
@ -161,7 +172,8 @@ SOURCES += ../common/comic.cpp \
../common/http_worker.cpp \
../common/yacreader_global.cpp \
../common/exit_check.cpp \
../common/scroll_management.cpp
../common/scroll_management.cpp \
../common/opengl_checker.cpp
!CONFIG(no_opengl) {
CONFIG(legacy_gl_widget) {
@ -174,7 +186,13 @@ SOURCES += ../common/comic.cpp \
}
include(../custom_widgets/custom_widgets_yacreader.pri)
CONFIG(7zip){
include(../compressed_archive/wrapper.pri)
} else:CONFIG(unarr){
include(../compressed_archive/unarr/unarr-wrapper.pri)
} else {
error(No compression backend specified. Did you mess with the build system?)
}
include(../shortcuts_management/shortcuts_management.pri)
RESOURCES += yacreader_images.qrc \
@ -202,24 +220,6 @@ TRANSLATIONS = yacreader_es.ts \
yacreader_de.ts \
yacreader_source.ts
win32 {
!exists (../compressed_archive/lib7zip) {
error(You\'ll need 7zip source code to compile YACReader. \
Please check the compressed_archive folder for further instructions.)
}
}
unix {
exists (../compressed_archive/libp7zip) {
message(Found p7zip source code...)
system(patch -d ../compressed_archive -N -p0 -i libp7zip.patch)
} else {
error(You\'ll need 7zip source code to compile YACReader. \
Please check the compressed_archive folder for further instructions.)
}
}
unix:!macx {
#set install prefix if it's empty
isEmpty(PREFIX) {

View File

@ -59,6 +59,7 @@ class YACReaderApplication: public QApplication
int main(int argc, char * argv[])
{
#if defined(_MSC_VER) && defined(_DEBUG)
_CrtSetDbgFlag ( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF );
#endif
@ -78,9 +79,13 @@ int main(int argc, char * argv[])
QApplication app(argc, argv);
#endif
#ifdef FORCE_ANGLE
app.setAttribute(Qt::AA_UseOpenGLES);
#endif
app.setApplicationName("YACReader");
app.setOrganizationName("YACReader");
qApp->setAttribute(Qt::AA_UseHighDpiPixmaps);
app.setAttribute(Qt::AA_UseHighDpiPixmaps);
//simple command line parser
//will be replaced by QCommandLineParser in the future
QStringList optlist;

View File

@ -354,7 +354,7 @@ void MainWindowViewer::createActions()
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(setBookmarkAction(bool)));
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)));
@ -578,7 +578,7 @@ void MainWindowViewer::createToolBars()
#ifdef Q_OS_MAC
comicToolBar->addStretch();
#else
comicToolBar->addWidget(new QToolBarStretch());
comicToolBar->addWidget(new YACReaderToolBarStretch());
#endif
@ -671,7 +671,11 @@ void MainWindowViewer::reloadOptions()
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);
@ -1315,7 +1319,11 @@ 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);

View File

@ -431,9 +431,9 @@ Render::~Render()
delete pr;
}
}
//Este m<EFBFBD>todo se encarga de forzar el renderizado de las p<EFBFBD>ginas.
//Actualiza el buffer seg<EFBFBD>n es necesario.
//si la pagina actual no est<EFBFBD> renderizada, se lanza un hilo que la renderize (double or single page mode) y se emite una se<EFBFBD>al que indica que se est<EFBFBD> renderizando.
//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();
@ -446,30 +446,30 @@ void Render::render()
pageRenders[currentPageBufferedIndex] = new PageRender(this,currentIndex,comic->getRawData()->at(currentIndex),buffer[currentPageBufferedIndex],imageRotation,filters);
}
else
//las p<EFBFBD>ginas no est<EFBFBD>n listas, y se est<EFBFBD>n cargando en el c<EFBFBD>mic
emit processingPage(); //para evitar confusiones esta se<EFBFBD>al deber<EFBFBD>a llamarse de otra forma
//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<EFBFBD>gina actual, se arranca
//si se ha creado un hilo para renderizar la página actual, se arranca
if(pageRenders[currentPageBufferedIndex]!=0)
{
//se conecta la se<EFBFBD>al pageReady del hilo, con el SLOT prepareAvailablePage
//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<EFBFBD>al de procesando, debido a que los hilos se arrancan aqu<EFBFBD>
//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<EFBFBD> caso ser<EFBFBD>a necesario hacer esto??? //TODO: IMPORTANTE, puede que no sea necesario.
//en qué caso sería necesario hacer esto??? //TODO: IMPORTANTE, puede que no sea necesario.
emit processingPage();
}
else
//no hay ninguna p<EFBFBD>gina lista para ser renderizada, es necesario esperar.
//no hay ninguna página lista para ser renderizada, es necesario esperar.
emit processingPage();
}
else
// la p<EFBFBD>gina actual est<EFBFBD> lista
// la página actual está lista
{
//emit currentPageReady();
//make prepareAvailablePage the only function that emits currentPageReady()
@ -768,7 +768,7 @@ void Render::createComic(const QString & path)
comic = FactoryComic::newComic(path);
if(comic == NULL)//archivo no encontrado o no v<EFBFBD>lido
if(comic == NULL)//archivo no encontrado o no válido
{
emit errorOpening();
reset();
@ -788,7 +788,6 @@ void Render::createComic(const QString & path)
connect(comic,SIGNAL(numPages(unsigned int)),this,SLOT(setNumPages(unsigned int)));
connect(comic,SIGNAL(imageLoaded(int,QByteArray)),this,SIGNAL(imageLoaded(int,QByteArray)));
connect(comic,SIGNAL(isBookmark(bool)),this,SIGNAL(currentPageIsBookmark(bool)));
connect(comic,SIGNAL(isBookmark(bool)),this,SLOT(pageIsBookmark(bool)));
connect(comic,SIGNAL(bookmarksUpdated()),this,SIGNAL(bookmarksUpdated()));
@ -814,6 +813,9 @@ void Render::startLoad()
comic->moveToThread(thread);
connect(comic, SIGNAL(errorOpening()), thread, SLOT(quit()));
connect(comic, SIGNAL(errorOpening(QString)), thread, SLOT(quit()));
connect(comic, SIGNAL(imagesLoaded()), thread, SLOT(quit()));
connect(thread, SIGNAL(started()), comic, SLOT(process()));
connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater()));
@ -836,13 +838,13 @@ void Render::reset()
loadedComic = false;
invalidate();
}
//si se solicita la siguiente p<EFBFBD>gina, se calcula cu<EFBFBD>l debe ser en funci<EFBFBD>n de si se lee en modo a doble p<EFBFBD>gina o no.
//la p<EFBFBD>gina s<EFBFBD>lo se renderiza, si realmente ha cambiado.
//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<EFBFBD>l ser<EFBFBD> la pr<EFBFBD>xima p<EFBFBD>gina
int nextPage; //indica cuál será la próxima página
nextPage = comic->nextPage();
//se fuerza renderizado si la p<EFBFBD>gina ha cambiado
//se fuerza renderizado si la página ha cambiado
if(currentIndex != nextPage)
{
previousIndex = currentIndex;
@ -880,14 +882,14 @@ void Render::nextDoublePage()
}
}
//si se solicita la p<EFBFBD>gina anterior, se calcula cu<EFBFBD>l debe ser en funci<EFBFBD>n de si se lee en modo a doble p<EFBFBD>gina o no.
//la p<EFBFBD>gina s<EFBFBD>lo se renderiza, si realmente ha cambiado.
//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<EFBFBD>l ser<EFBFBD> la pr<EFBFBD>xima p<EFBFBD>gina
int previousPage; //indica cuál será la próxima página
previousPage = comic->previousPage();
//se fuerza renderizado si la p<EFBFBD>gina ha cambiado
//se fuerza renderizado si la página ha cambiado
if(currentIndex != previousPage)
{
previousIndex = currentIndex;
@ -903,7 +905,7 @@ void Render::previousPage()
void Render::previousDoublePage()
{
int previousPage; //indica cu<EFBFBD>l ser<EFBFBD> la pr<EFBFBD>xima p<EFBFBD>gina
int previousPage; //indica cuál será la próxima página
previousPage = qMax(currentIndex-2,0);
if(currentIndex != previousPage)
{
@ -965,7 +967,7 @@ void Render::pageRawDataReady(int page)
}
}
//s<EFBFBD>lo se renderiza la p<EFBFBD>gina, si ha habido un cambio de p<EFBFBD>gina
//sólo se renderiza la página, si ha habido un cambio de página
void Render::goTo(int index)
{
@ -993,9 +995,9 @@ void Render::rotateLeft()
reload();
}
//Actualiza el buffer, a<EFBFBD>adiendo las im<EFBFBD>genes (vac<EFBFBD>as) necesarias para su posterior renderizado y
//eliminado aquellas que ya no sean necesarias. Tambi<EFBFBD>n libera los hilos (no estoy seguro de que sea responsabilidad suya)
//Calcula el n<EFBFBD>mero de nuevas p<EFBFBD>ginas que hay que buferear y si debe hacerlo por la izquierda o la derecha (seg<EFBFBD>n sea el sentido de la lectura)
//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);
@ -1081,8 +1083,8 @@ void Render::fillBuffer()
}
//M<EFBFBD>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<EFBFBD>n y se libera la memoria (de hilos e im<EFBFBD>genes)
//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;i<pageRenders.size();i++)

View File

@ -18,6 +18,8 @@
#include "comic_db.h"
#include "shortcuts_manager.h"
#include "opengl_checker.h"
#include <QFile>
@ -72,10 +74,15 @@ shouldOpenPrevious(false)
//CONFIG GOTO_FLOW--------------------------------------------------------
#ifndef NO_OPENGL
if(!settings->contains(USE_OPEN_GL))
{
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());

View File

@ -15,9 +15,8 @@ INCLUDEPATH += ../common \
DEFINES += SERVER_RELEASE NOMINMAX YACREADER_LIBRARY
CONFIG(no_opengl) {
DEFINES += NO_OPENGL
}
#load default build flags
include (../config.pri)
CONFIG(legacy_gl_widget) {
INCLUDEPATH += ../common/gl_legacy \
@ -25,19 +24,25 @@ CONFIG(legacy_gl_widget) {
INCLUDEPATH += ../common/gl \
}
#there are going to be two builds for windows, OpenGL based and ANGLE based
win32 {
CONFIG(force_angle) {
message("using ANGLE")
LIBS += -L../dependencies/poppler/lib -loleaut32 -lole32 -lshell32 -lopengl32 -lglu32 -luser32
#linking extra libs are necesary for a successful compilation, a better approach should be
#to remove any OpenGL (desktop) dependencies
#the OpenGL stuff should be migrated to OpenGL ES
DEFINES += FORCE_ANGLE
} else {
LIBS += -L../dependencies/poppler/lib -loleaut32 -lole32 -lshell32 -lopengl32 -lglu32 -luser32
}
LIBS += -L../dependencies/poppler/lib -loleaut32 -lole32 -lshell32
LIBS += -lpoppler-qt5
INCLUDEPATH += ../dependencies/poppler/include/qt5
LIBS += -lpoppler-qt5
INCLUDEPATH += ../dependencies/poppler/include/qt5
QMAKE_CXXFLAGS_RELEASE += /MP /Ob2 /Oi /Ot /GT
!CONFIG(no_opengl) {
QMAKE_CXXFLAGS_RELEASE += /GL
}
QMAKE_LFLAGS_RELEASE += /LTCG
CONFIG -= embed_manifest_exe
QMAKE_CXXFLAGS_RELEASE += /MP /Ob2 /Oi /Ot /GT /GL
QMAKE_LFLAGS_RELEASE += /LTCG
CONFIG -= embed_manifest_exe
}
unix:!macx{
@ -71,7 +76,7 @@ QT += macextras gui-private
}
unix{
QMAKE_CXXFLAGS += -std=c++11
CONFIG += c++11
}
#CONFIG += release
@ -138,7 +143,8 @@ HEADERS += comic_flow.h \
empty_container_info.h \
empty_special_list.h \
empty_reading_list_widget.h \
../common/scroll_management.h
../common/scroll_management.h \
../common/opengl_checker.h
!CONFIG(no_opengl) {
CONFIG(legacy_gl_widget) {
@ -206,7 +212,8 @@ SOURCES += comic_flow.cpp \
empty_container_info.cpp \
empty_special_list.cpp \
empty_reading_list_widget.cpp \
../common/scroll_management.cpp
../common/scroll_management.cpp \
../common/opengl_checker.cpp
!CONFIG(no_opengl) {
CONFIG(legacy_gl_widget) {
@ -220,7 +227,14 @@ SOURCES += comic_flow.cpp \
include(./server/server.pri)
include(../custom_widgets/custom_widgets_yacreaderlibrary.pri)
CONFIG(7zip){
include(../compressed_archive/wrapper.pri)
} else:CONFIG(unarr) {
include(../compressed_archive/unarr/unarr-wrapper.pri)
} else {
error(No compression backend specified. Did you mess with the build system?)
}
include(./comic_vine/comic_vine.pri)
include(../QsLog/QsLog.pri)
include(../shortcuts_management/shortcuts_management.pri)
@ -245,9 +259,13 @@ TRANSLATIONS = yacreaderlibrary_es.ts \
yacreaderlibrary_de.ts \
yacreaderlibrary_source.ts
Release:DESTDIR = ../release
Debug:DESTDIR = ../debug
CONFIG(force_angle) {
Release:DESTDIR = ../release_angle
Debug:DESTDIR = ../debug_angle
} else {
Release:DESTDIR = ../release
Debug:DESTDIR = ../debug
}
#QML/GridView
QT += quick qml
@ -263,23 +281,6 @@ win32:RESOURCES += qml_win.qrc
unix:!macx:RESOURCES += qml_win.qrc
macx:RESOURCES += qml_osx.qrc
win32 {
!exists(../compressed_archive/lib7zip){
error(You\'ll need 7zip source code to compile YACReader. \
Please check the compressed_archive folder for further instructions.)
}
}
unix {
exists (../compressed_archive/libp7zip) {
message(Found p7zip source code...)
system(patch -d ../compressed_archive -N -p0 -i libp7zip.patch)
} else {
error(You\'ll need 7zip source code to compile YACReader. \
Please check the compressed_archive folder for further instructions.)
}
}
unix:!macx {
#set install prefix if it's empty
isEmpty(PREFIX) {

View File

@ -1,11 +1,12 @@
#include "classic_comics_view.h"
#include "yacreader_table_view.h"
#include "QStackedWidget"
#include "comic_flow_widget.h"
#include "QsLog.h"
#include "QStackedWidget"
#include "shortcuts_manager.h"
#include "yacreader_table_view.h"
#include "yacreader_tool_bar_stretch.h"
ClassicComicsView::ClassicComicsView(QWidget *parent)
:ComicsView(parent),searching(false)
@ -16,6 +17,7 @@ ClassicComicsView::ClassicComicsView(QWidget *parent)
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);
@ -70,6 +72,7 @@ ClassicComicsView::ClassicComicsView(QWidget *parent)
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);
@ -83,11 +86,49 @@ ClassicComicsView::ClassicComicsView(QWidget *parent)
if(settings->contains(COMICS_VIEW_FLOW_SPLITTER_STATUS))
sVertical->restoreState(settings->value(COMICS_VIEW_FLOW_SPLITTER_STATUS).toByteArray());
//hide flow widgets
toolBarStretch = new YACReaderToolBarStretch(this);
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/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<int> sizes;
sizes.append(0);
int total = sVertical->sizes().at(0) + sVertical->sizes().at(1);
sizes.append(total);
sVertical->setSizes(sizes);
}
else
{
QList<int> 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<QVBoxLayout *>(comics->layout())->insertWidget(0,toolBar);
this->toolbar = toolBar;
toolBarStretchAction = toolBar->addWidget(toolBarStretch);
toolBar->addAction(hideFlowViewAction);
}
void ClassicComicsView::setModel(ComicModel *model)
@ -118,23 +159,25 @@ void ClassicComicsView::setModel(ComicModel *model)
tableView->horizontalHeader()->setMovable(true);
#endif
//TODO parametrizar la configuración de las columnas
for(int i = 0;i<tableView->horizontalHeader()->count();i++)
tableView->horizontalHeader()->hideSection(i);
/*if(!settings->contains(COMICS_VIEW_HEADERS))
{*/
for(int i = 0;i<tableView->horizontalHeader()->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);
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))
tableView->resizeColumnsToContents();
tableView->horizontalHeader()->setStretchLastSection(true);
QStringList paths = model->getPaths(model->getCurrentPath());//TODO ComicsView: get currentpath from somewhere currentPath());
comicFlow->setImagePaths(paths);
@ -143,6 +186,10 @@ void ClassicComicsView::setModel(ComicModel *model)
if(settings->contains(COMICS_VIEW_HEADERS))
tableView->horizontalHeader()->restoreState(settings->value(COMICS_VIEW_HEADERS).toByteArray());
tableView->resizeColumnsToContents();
tableView->horizontalHeader()->setStretchLastSection(true);
}
}
@ -264,8 +311,10 @@ void ClassicComicsView::saveTableHeadersStatus()
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<int> &roles)
@ -291,6 +340,9 @@ void ClassicComicsView::closeEvent(QCloseEvent *event)
saveTableHeadersStatus();
saveSplitterStatus();
ComicsView::closeEvent(event);
toolbar->removeAction(toolBarStretchAction);
toolbar->removeAction(hideFlowViewAction);
}
void ClassicComicsView::setupSearchingIcon()

View File

@ -6,12 +6,14 @@
#include <QModelIndex>
#include <QModelIndexList>
class YACReaderTableView;
class QSplitter;
class ComicFlowWidget;
class QToolBar;
class ComicModel;
class QStackedWidget;
class QToolBar;
class ComicFlowWidget;
class ComicModel;
class YACReaderTableView;
class YACReaderToolBarStretch;
class ClassicComicsView : public ComicsView
{
@ -44,16 +46,22 @@ public slots:
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;
@ -64,6 +72,8 @@ private:
void showSearchingIcon();
void hideSearchingIcon();
void updateSearchingIconPosition();
QMutex settingsMutex;
};
#endif // CLASSIC_COMICS_VIEW_H

View File

@ -169,10 +169,12 @@ void SortVolumeComics::moveDownCL()
QList<QModelIndex> selection = tableFiles->selectionModel()->selectedIndexes();
if(selection.count() > 0)
{
localComicsModel->moveSelectionDown(selection);
selection = tableFiles->selectionModel()->selectedIndexes();
tableFiles->scrollTo(selection.last());
selection = tableFiles->selectionModel()->selectedIndexes();
tableFiles->scrollTo(selection.last());
}
}
void SortVolumeComics::moveUpIL()

View File

@ -47,7 +47,7 @@ bool ComicModel::canDropMimeData(const QMimeData *data, Qt::DropAction action, i
return data->formats().contains(YACReader::YACReaderLibrarComiscSelectionMimeDataFormat);
}
//TODO: optimize this method
//TODO: optimize this method (seriously)
bool ComicModel::dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent)
{
@ -118,9 +118,26 @@ bool ComicModel::dropMimeData(const QMimeData *data, Qt::DropAction action, int
QLOG_INFO() << newSorting;
if(!beginMoveRows(parent,currentIndexes.first(),currentIndexes.last(),parent,row))
return false;
_data = resortedData;
int tempRow = row;
foreach(qulonglong id, comicIds)
{
int i = 0;
foreach (ComicItem *item, _data) {
if(item->data(Id) == id)
{
beginMoveRows(parent,i,i,parent,tempRow);
_data.removeAll(item);
_data.insert(tempRow++, item);
endMoveRows();
break;
}
i++;
}
}
/*if(!beginMoveRows(parent,currentIndexes.first(),currentIndexes.last(),parent,row))
return false;*/
_data = resortedData; //TODO No longer needed
//TODO emit signals
@ -145,7 +162,7 @@ bool ComicModel::dropMimeData(const QMimeData *data, Qt::DropAction action, int
QSqlDatabase::removeDatabase(_databasePath);
endMoveRows();
//endMoveRows();
emit resortedIndexes(newSorting);
int destSelectedIndex = row<0?_data.length():row;
@ -262,7 +279,7 @@ QVariant ComicModel::data(const QModelIndex &index, int role) const
else if (role == RatingRole)
return item->data(Rating);
else if (role == CoverPathRole)
return "file:///"+_databasePath+"/covers/"+item->data(Hash).toString()+".jpg";
return QUrl("file:"+_databasePath+"/covers/"+item->data(Hash).toString()+".jpg");
else if (role == NumPagesRole)
return item->data(NumPages);
else if (role == CurrentPageRole)
@ -361,11 +378,13 @@ QVariant ComicModel::headerData(int section, Qt::Orientation orientation,
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"));
else if (ext.compare("cb7",Qt::CaseInsensitive) == 0)
#endif
else if (ext.compare("cbt",Qt::CaseInsensitive) == 0)
return QVariant(QIcon(":/images/comicTar.png"));
}

View File

@ -348,7 +348,7 @@ void DBHelper::update(ComicInfo * comicInfo, QSqlDatabase & db)
updateComicInfo.bindValue(":comicVineID", comicInfo->comicVineID);
updateComicInfo.exec();
updateComicInfo.exec();
}
void DBHelper::updateRead(ComicInfo * comicInfo, QSqlDatabase & db)
@ -391,6 +391,44 @@ void DBHelper::updateProgress(qulonglong libraryId, const ComicInfo &comicInfo)
QSqlDatabase::removeDatabase(libraryPath);
}
void DBHelper::updateReadingRemoteProgress(const ComicInfo &comicInfo, QSqlDatabase &db)
{
QSqlQuery updateComicInfo(db);
updateComicInfo.prepare("UPDATE comic_info SET "
"read = :read, "
"currentPage = :currentPage, "
"hasBeenOpened = :hasBeenOpened"
" WHERE id = :id ");
updateComicInfo.bindValue(":read", comicInfo.read?1:0);
updateComicInfo.bindValue(":currentPage", comicInfo.currentPage);
updateComicInfo.bindValue(":hasBeenOpened", comicInfo.hasBeenOpened?1:0);
updateComicInfo.bindValue(":id", comicInfo.id);
updateComicInfo.exec();
}
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(comic.info.currentPage == comic.info.numPages)
comic.info.read = true;
comic.info.currentPage = comicInfo.currentPage;
comic.info.hasBeenOpened = true;
DBHelper::updateReadingRemoteProgress(comic.info,db);
}
db.close();
QSqlDatabase::removeDatabase(libraryPath);
}
void DBHelper::renameLabel(qulonglong id, const QString &name, QSqlDatabase &db)
{
QSqlQuery renameLabelQuery(db);
@ -566,16 +604,21 @@ qulonglong DBHelper::insertReadingSubList(const QString &name, qulonglong parent
void DBHelper::insertComicsInFavorites(const QList<ComicDB> &comicsList, QSqlDatabase &db)
{
QSqlQuery getNumComicsInFavoritesQuery("SELECT count(*) FROM comic_default_reading_list WHERE default_reading_list_id = 1;",db);
getNumComicsInFavoritesQuery.next();
QSqlRecord record = getNumComicsInFavoritesQuery.record();
int numComics = record.value(0).toInt();
db.transaction();
QSqlQuery query(db);
query.prepare("INSERT INTO comic_default_reading_list (default_reading_list_id, comic_id) "
"VALUES (1, :comic_id)");
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(":order", numComics++);
query.bindValue(":ordering", numComics++);
query.exec();
}
@ -584,16 +627,22 @@ void DBHelper::insertComicsInFavorites(const QList<ComicDB> &comicsList, QSqlDat
void DBHelper::insertComicsInLabel(const QList<ComicDB> &comicsList, qulonglong labelId, QSqlDatabase &db)
{
QSqlQuery getNumComicsInFavoritesQuery(QString("SELECT count(*) FROM comic_label WHERE label_id = %1;").arg(labelId) ,db);
getNumComicsInFavoritesQuery.next();
QSqlRecord record = getNumComicsInFavoritesQuery.record();
int numComics = record.value(0).toInt();
db.transaction();
QSqlQuery query(db);
query.prepare("INSERT INTO comic_label (label_id, comic_id) "
"VALUES (:label_id, :comic_id)");
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();
}
@ -602,7 +651,7 @@ void DBHelper::insertComicsInLabel(const QList<ComicDB> &comicsList, qulonglong
void DBHelper::insertComicsInReadingList(const QList<ComicDB> &comicsList, qulonglong readingListId, QSqlDatabase &db)
{
QSqlQuery getNumComicsInFavoritesQuery("SELECT count(*) from comic_reading_list;",db);
QSqlQuery getNumComicsInFavoritesQuery("SELECT count(*) FROM comic_reading_list;",db);
getNumComicsInFavoritesQuery.next();
QSqlRecord record = getNumComicsInFavoritesQuery.record();
int numComics = record.value(0).toInt();

View File

@ -57,6 +57,8 @@ public:
static void updateRead(ComicInfo * comicInfo, QSqlDatabase & db);
static void update(const Folder & folder, QSqlDatabase & db);
static void updateProgress(qulonglong libraryId,const ComicInfo & comicInfo);
static void updateReadingRemoteProgress(const ComicInfo & comicInfo, QSqlDatabase & db);
static void updateFromRemoteClient(qulonglong libraryId,const ComicInfo & comicInfo);
static void renameLabel(qulonglong id, const QString & name, QSqlDatabase & db);
static void renameList(qulonglong id, const QString & name, QSqlDatabase & db);
static void reasignOrderToSublists(QList<qulonglong> ids, QSqlDatabase & db);

View File

@ -84,7 +84,7 @@ void GridComicsView::setModel(ComicModel *model)
ctxt->setContextProperty("textColor", "#636363");
//fonts settings
ctxt->setContextProperty("fontSize", 11);
ctxt->setContextProperty("fontFamily", "none");
ctxt->setContextProperty("fontFamily", QApplication::font().family());
ctxt->setContextProperty("fontSpacing", 0.5);
#else
@ -93,12 +93,15 @@ void GridComicsView::setModel(ComicModel *model)
ctxt->setContextProperty("selectedColor", "#121212");
ctxt->setContextProperty("selectedBorderColor", "#121212");
ctxt->setContextProperty("borderColor", "#121212");
ctxt->setContextProperty("titleColor", "#E6E6E6");
ctxt->setContextProperty("textColor", "#E6E6E6");
ctxt->setContextProperty("titleColor", "#FFFFFF");
ctxt->setContextProperty("textColor", "#A8A8A8");
ctxt->setContextProperty("dropShadow",false);
//fonts settings
ctxt->setContextProperty("fontSize", "none");
ctxt->setContextProperty("fontFamily", "none");
int fontSize = QApplication::font().pointSize();
if(fontSize == -1)
fontSize = QApplication::font().pixelSize();
ctxt->setContextProperty("fontSize", fontSize);
ctxt->setContextProperty("fontFamily", QApplication::font().family());
ctxt->setContextProperty("fontSpacing", 0.5);
#endif

View File

@ -127,11 +127,14 @@ ImportWidget::ImportWidget(QWidget *parent) :
coversView->setMaximumHeight(300);
coversView->setStyleSheet("QGraphicsView {background-color: #E6E6E6;border:none;}");
coversScene = new QGraphicsScene();
coversScene->setSceneRect(0,0,coversView->width(),coversView->height());
coversScene = new QGraphicsScene();
coversView->setAlignment(Qt::AlignLeft);
coversView->setScene(coversScene);
coversView->setScene(coversScene);
coversView->setFixedHeight(300);
coversView->setInteractive(false);
scrollAnimation = new QPropertyAnimation(coversView->horizontalScrollBar(), "value");
QLabel * topDecorator = new QLabel();
QLabel * bottomDecorator = new QLabel();
@ -208,7 +211,7 @@ ImportWidget::ImportWidget(QWidget *parent) :
connect(stop,SIGNAL(clicked()),this,SIGNAL(stop()));
//connect(stop,SIGNAL(clicked()),this,SLOT(addCoverTest()));
previousWidth = 10;
previousWidth = 0;
updatingCovers = false;
elapsedTimer = new QElapsedTimer();
elapsedTimer->start();
@ -216,70 +219,49 @@ ImportWidget::ImportWidget(QWidget *parent) :
void ImportWidget::newComic(const QString & path, const QString & coverPath)
{
currentComicLabel->setText("<font color=\"#565959\">"+path+"</font>");
if(!this->isVisible())
return;
if(((elapsedTimer->elapsed()>=1000) || ((previousWidth < coversView->width()) && (elapsedTimer->elapsed()>=500))) && !updatingCovers)//todo elapsed time
{
currentComicLabel->setText("<font color=\"#565959\">"+path+"</font>");
QPixmap p(coverPath);
p = p.scaledToHeight(300,Qt::SmoothTransformation);
QGraphicsPixmapItem * item = new QGraphicsPixmapItem(p);
item->setPos(previousWidth,0);
item->setZValue(i/10000.0);
previousWidth += 10 + p.width();
coversScene->addItem(item);
if( ((elapsedTimer->elapsed()>=1100) || ((previousWidth < coversView->width()) && (elapsedTimer->elapsed()>=500))) && scrollAnimation->state() != QAbstractAnimation::Running)//todo elapsed time
{
updatingCovers = true;
elapsedTimer->start();
elapsedTimer->start();
if(previousWidth >= coversView->width()+200 && !updatingCovers)
{
updatingCovers = true;
QPixmap p(coverPath);
p = p.scaledToHeight(300,Qt::SmoothTransformation);
foreach(QGraphicsItem * itemToRemove, coversScene->items())
{
QGraphicsPixmapItem * last = dynamic_cast<QGraphicsPixmapItem *>(itemToRemove);
QGraphicsPixmapItem * item = new QGraphicsPixmapItem(p);
item->setPos(previousWidth, 0);
coversScene->addItem(item);
if((last->pos().x()+last->pixmap().width())<=0)
{
coversScene->removeItem(last);
delete last;
}
//else
// break;
}
previousWidth += 10 + p.width();
int width = p.width();
foreach(QGraphicsItem * itemToRemove, coversScene->items())
{
QGraphicsPixmapItem * last = dynamic_cast<QGraphicsPixmapItem *>(itemToRemove);
foreach(QGraphicsItem * itemToMove, coversScene->items())
{
QTimeLine *timer = new QTimeLine(400);
timer->setFrameRange(0, 24);
timer->setUpdateInterval(17);
if((last->pos().x()+last->pixmap().width()) < coversView->horizontalScrollBar()->value()) //TODO check this
{
coversScene->removeItem(last);
delete last;
}
}
QGraphicsItemAnimation *animation = new QGraphicsItemAnimation;
animation->setItem(itemToMove);
animation->setTimeLine(timer);
QScrollBar * scrollBar = coversView->horizontalScrollBar();
QPointF point = itemToMove->scenePos();
float step = (width+10)/24.0;
for (int i = 0; i < 24; ++i)
animation->setPosAt(i / 24.0, QPointF(point.x()-((i+1)*step), point.y()));
float speedFactor = 2.5;
int origin = scrollBar->value();
int dest = origin + 10 + p.width();
timer->start();
connect(timer,SIGNAL(finished()),timer,SLOT(deleteLater()));
connect(timer,SIGNAL(finished()),animation,SLOT(deleteLater()));
}
QTimer::singleShot(400,this,SLOT(finishedUpdatingCover()));
previousWidth -= 10+width;
}
}
}
void ImportWidget::finishedUpdatingCover()
{
updatingCovers = false;
scrollAnimation->setDuration((dest-origin)*speedFactor);
scrollAnimation->setStartValue(origin);
scrollAnimation->setEndValue(dest);
QEasingCurve easing(QEasingCurve::OutQuad);
scrollAnimation->setEasingCurve(easing);
scrollAnimation->start();
}
}
void ImportWidget::newCover(const QPixmap & image)
@ -335,7 +317,7 @@ void ImportWidget::addCoverTest()
void ImportWidget::clear()
{
previousWidth = 10;
previousWidth = 0;
//nos aseguramos de que las animaciones han finalizado antes de borrar
QList<QGraphicsItem*> all = coversScene->items();
@ -347,7 +329,12 @@ void ImportWidget::clear()
}
coversScene->clear();
updatingCovers = false;
delete coversScene;
coversScene = new QGraphicsScene;
coversView->setScene(coversScene);
updatingCovers = false;
currentComicLabel->setText("<font color=\"#565959\">...</font>");
@ -377,7 +364,7 @@ void ImportWidget::clearScene()
void ImportWidget::showCovers(bool hide)
{
portadasLabel->setHidden(hide);
coversViewContainer->setHidden(hide);
coversViewContainer->setHidden(hide);
}
void ImportWidget::resizeEvent(QResizeEvent * event)

View File

@ -10,42 +10,45 @@ class QElapsedTimer;
class QVBoxLayout;
class QToolButton;
class QResizeEvent;
class QPropertyAnimation;
class ImportWidget : public QWidget
{
Q_OBJECT
Q_OBJECT
public:
explicit ImportWidget(QWidget *parent = 0);
explicit ImportWidget(QWidget *parent = 0);
signals:
void stop();
void stop();
public slots:
void newComic(const QString & path, const QString & coverPath);
void newCover(const QPixmap & image);
void clear();
void addCoverTest();
void finishedUpdatingCover();
void clearScene();
void setImportLook();
void setUpdateLook();
void showCovers(bool hide);
void newComic(const QString & path, const QString & coverPath);
void newCover(const QPixmap & image);
void clear();
void addCoverTest();
void clearScene();
void setImportLook();
void setUpdateLook();
void showCovers(bool hide);
private:
QLabel * currentComicLabel;
QLabel * portadasLabel;
QLabel * iconLabel;
QLabel * text;
QLabel * textDescription;
QWidget * coversViewContainer;
QGraphicsView * coversView;
QGraphicsScene * coversScene;
int previousWidth;
bool updatingCovers;
QElapsedTimer * elapsedTimer;
quint64 i;
QLabel * currentComicLabel;
QLabel * portadasLabel;
QLabel * iconLabel;
QLabel * text;
QLabel * textDescription;
QWidget * coversViewContainer;
QGraphicsView * coversView;
QGraphicsScene * coversScene;
QPropertyAnimation * scrollAnimation;
QToolButton * hideButton;
int previousWidth;
bool updatingCovers;
QElapsedTimer * elapsedTimer;
quint64 i;
void resizeEvent(QResizeEvent * event);
QToolButton * hideButton;
void resizeEvent(QResizeEvent * event);
};

View File

@ -122,8 +122,8 @@ void LibraryCreator::processLibrary(const QString & source, const QString & targ
void LibraryCreator::run()
{
stopRunning = false;
//check for 7z lib
#ifndef use_unarr
//check for 7z lib
#if defined Q_OS_UNIX && !defined Q_OS_MAC
QLibrary *sevenzLib = new QLibrary(QString(LIBDIR)+"/p7zip/7z.so");
#else
@ -137,7 +137,7 @@ void LibraryCreator::run()
exit();
}
sevenzLib->deleteLater();
#endif
if(_mode == CREATOR)
{
QLOG_INFO() << "Starting to create new library ( " << _source << "," << _target << ")";

View File

@ -86,6 +86,7 @@
#include "db_helper.h"
#include "reading_list_item.h"
#include "opengl_checker.h"
#include "QsLog.h"
@ -187,10 +188,15 @@ void LibraryWindow::doLayout()
#ifndef NO_OPENGL
//FLOW-----------------------------------------------------------------------
//---------------------------------------------------------------------------
if(QGLFormat::hasOpenGL() && !settings->contains(USE_OPEN_GL))
{
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);
#endif
//FOLDERS FILTER-------------------------------------------------------------
//---------------------------------------------------------------------------
@ -245,7 +251,6 @@ void LibraryWindow::doLayout()
doComicsViewConnections();
comicsView->setToolBar(editInfoToolBar);
comicsViewStack->addWidget(comicsViewTransition = new ComicsViewTransition());
comicsViewStack->addWidget(emptyFolderWidget = new EmptyFolderWidget());
comicsViewStack->addWidget(emptyLabelWidget = new EmptyLabelWidget());
@ -413,8 +418,7 @@ void LibraryWindow::setUpShortcutsManagement()
#ifndef Q_OS_MAC
<< toggleFullScreenAction
#endif
<< toggleComicsViewAction
<< hideComicViewAction);
<< toggleComicsViewAction);
allActions << tmpList;
@ -570,7 +574,7 @@ void LibraryWindow::createActions()
setAllAsNonReadAction->setIcon(QIcon(":/images/setAllUnread.png"));*/
showHideMarksAction = new QAction(tr("Show/Hide marks"),this);
showHideMarksAction->setToolTip(tr("Show or hide readed marks"));
showHideMarksAction->setToolTip(tr("Show or hide read marks"));
showHideMarksAction->setData(SHOW_HIDE_MARKS_ACTION_YL);
showHideMarksAction->setShortcut(ShortcutsManager::getShortcutsManager().getShortcut(SHOW_HIDE_MARKS_ACTION_YL));
showHideMarksAction->setCheckable(true);
@ -719,14 +723,6 @@ void LibraryWindow::createActions()
deleteComicsAction->setShortcut(ShortcutsManager::getShortcutsManager().getShortcut(DELETE_COMICS_ACTION_YL));
deleteComicsAction->setIcon(QIcon(":/images/trash.png"));
hideComicViewAction = new QAction(this);
hideComicViewAction->setText(tr("Hide comic flow"));
hideComicViewAction->setData(HIDE_COMIC_VIEW_ACTION_YL);
hideComicViewAction->setShortcut(ShortcutsManager::getShortcutsManager().getShortcut(HIDE_COMIC_VIEW_ACTION_YL));
hideComicViewAction->setIcon(QIcon(":/images/hideComicFlow.png"));
hideComicViewAction->setCheckable(true);
hideComicViewAction->setChecked(false);
getInfoAction = new QAction(this);
getInfoAction->setData(GET_INFO_ACTION_YL);
getInfoAction->setShortcut(ShortcutsManager::getShortcutsManager().getShortcut(GET_INFO_ACTION_YL));
@ -932,8 +928,8 @@ void LibraryWindow::createToolBars()
editInfoToolBar->addAction(deleteComicsAction);
/*editInfoToolBar->addWidget(new QToolBarStretch());
editInfoToolBar->addAction(hideComicViewAction);*/
comicsView->setToolBar(editInfoToolBar);
}
void LibraryWindow::createMenus()
@ -1142,8 +1138,6 @@ void LibraryWindow::createConnections()
connect(deleteComicsAction,SIGNAL(triggered()),this,SLOT(deleteComics()));
connect(hideComicViewAction, SIGNAL(toggled(bool)),this, SLOT(hideComicFlow(bool)));
connect(getInfoAction,SIGNAL(triggered()),this,SLOT(showComicVineScraper()));
//connect(socialAction,SIGNAL(triggered()),this,SLOT(showSocial()));
@ -2458,30 +2452,6 @@ QString LibraryWindow::currentFolderPath()
return QDir::cleanPath(currentPath()+path);
}
//TODO ComicsView: some actions in the comics toolbar can be relative to a certain view
//show/hide actions on show/hide widget
void LibraryWindow::hideComicFlow(bool hide)
{
/*
if(hide)
{
QList<int> sizes;
sizes.append(0);
int total = sVertical->sizes().at(0) + sVertical->sizes().at(1);
sizes.append(total);
sVertical->setSizes(sizes);
}
else
{
QList<int> sizes;
int total = sVertical->sizes().at(0) + sVertical->sizes().at(1);
sizes.append(2*total/3);
sizes.append(total/3);
sVertical->setSizes(sizes);
}
*/
}
void LibraryWindow::showExportComicsInfo()
{
exportComicsInfoDialog->source = currentPath() + "/.yacreaderlibrary/library.ydb";

View File

@ -205,7 +205,6 @@ private:
QAction * asignOrderAction;
QAction * forceCoverExtractedAction;
QAction * deleteComicsAction;
QAction * hideComicViewAction;
QAction *showEditShortcutsAction;
@ -339,7 +338,6 @@ public slots:
void setCurrentComicsStatusReaded(YACReaderComicReadStatus readStatus);
void setCurrentComicReaded();
void setCurrentComicUnreaded();
void hideComicFlow(bool hide);
void showExportComicsInfo();
void showImportComicsInfo();
void asignNumbers();

View File

@ -19,6 +19,7 @@
#include "db_helper.h"
#include "yacreader_libraries.h"
#include "exit_check.h"
#include "opengl_checker.h"
#include "QsLog.h"
#include "QsLogDest.h"
@ -92,6 +93,7 @@ void logSystemAndConfig()
QLOG_INFO() << "SO : Unknown";
#endif
#ifndef use_unarr
#ifdef Q_OS_WIN
if(QLibrary::isLibrary(QApplication::applicationDirPath()+"/utils/7z.dll"))
#elif defined Q_OS_UNIX && !defined Q_OS_MAC
@ -102,6 +104,9 @@ void logSystemAndConfig()
QLOG_INFO() << "7z : found";
else
QLOG_ERROR() << "7z : not found";
#else
QLOG_INFO() << "using unarr decompression backend";
#endif
#if defined Q_OS_UNIX && !defined Q_OS_MAC
if(QFileInfo(QString(BINDIR)+"/qrencode").exists())
#else
@ -123,12 +128,16 @@ void logSystemAndConfig()
else
QLOG_INFO() << "OpenGL : disabled";
OpenGLChecker checker;
QLOG_INFO() << "OpenGL version : " << checker.textVersionDescription();
QLOG_INFO() << "Libraries: " << DBHelper::getLibraries().getLibraries();
QLOG_INFO() << "--------------------------------------------";
}
int main( int argc, char ** argv )
{
//fix for misplaced text in Qt4.8 and Mavericks
#ifdef Q_OS_MAC
#if QT_VERSION < 0x050000
@ -140,9 +149,13 @@ int main( int argc, char ** argv )
QApplication app( argc, argv );
#ifdef FORCE_ANGLE
app.setAttribute(Qt::AA_UseOpenGLES);
#endif
app.setApplicationName("YACReaderLibrary");
app.setOrganizationName("YACReader");
qApp->setAttribute(Qt::AA_UseHighDpiPixmaps);
app.setAttribute(Qt::AA_UseHighDpiPixmaps);
//simple command line parser
//will be replaced by QCommandLineParser in the future
//TODO: --headless, --server=[on|off], support for file and directory arguments
@ -208,7 +221,6 @@ int main( int argc, char ** argv )
if(settings->value(SERVER_ON,true).toBool())
{
s->start();
}
#endif

View File

@ -150,11 +150,14 @@ Rectangle {
}
onReleased: {
/*if(mouse.button != Qt.RightButton && !(mouse.modifiers & Qt.ControlModifier || mouse.modifiers & Qt.ShiftModifier))
if(mouse.button == Qt.LeftButton && !(mouse.modifiers & Qt.ControlModifier || mouse.modifiers & Qt.ShiftModifier))
{
comicsSelectionHelper.setCurrentIndex(index)
grid.currentIndex = index;
}*/
if(comicsSelectionHelper.isSelectedIndex(index))
{
comicsSelectionHelper.setCurrentIndex(index)
grid.currentIndex = index;
}
}
}
}
@ -166,30 +169,44 @@ Rectangle {
//cover
Image {
id: coverElement
width: 148
height: 224
anchors {horizontalCenter: parent.horizontalCenter; top: realCell.top; topMargin: 4}
width: 156
height: 236
anchors {horizontalCenter: parent.horizontalCenter; top: realCell.top; topMargin: 0}
source: cover_path
fillMode: Image.PreserveAspectCrop
smooth: true
mipmap: true
asynchronous : true
cache: false //TODO clear cache only when it is neede
cache: false //TODO clear cache only when it is needed
}
//border
Rectangle {
width: 156
height: 236
anchors {horizontalCenter: parent.horizontalCenter; top: realCell.top; topMargin: 0}
color: "transparent"
border {
color: "#20FFFFFF"
width: 1
}
}
//mark
Image {
id: mark
width: 23
height: 23
source: read_column&&show_marks?"tick.png":has_been_opened&&show_marks?"reading.png":""
anchors {right: coverElement.right; top: coverElement.top; topMargin: 11; rightMargin: 11}
anchors {right: coverElement.right; top: coverElement.top; topMargin: 9; rightMargin: 9}
asynchronous : true
}
//title
Text {
id : titleText
anchors { top: realCell.top; left: realCell.left; leftMargin: 4; rightMargin: 4; topMargin: 234; }
anchors { top: realCell.top; left: realCell.left; leftMargin: 4; rightMargin: 4; topMargin: 238; }
width: 148
maximumLineCount: 2
wrapMode: Text.WordWrap
@ -339,6 +356,12 @@ Rectangle {
currentIndex: 0
cacheBuffer: 0
footer: Rectangle { //fix for the scroll issue, TODO find what causes the issue (some times the bottoms cells are hidden for the toolbar, no full scroll)
height : 25
width : parent.width
color : backgroundColor
}
move: Transition {
NumberAnimation { properties: "x,y"; duration: 250 }
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 155 B

After

Width:  |  Height:  |  Size: 163 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 242 B

After

Width:  |  Height:  |  Size: 288 B

View File

@ -56,6 +56,9 @@ void ComicController::service(HttpRequest& request, HttpResponse& response)
comicFile->moveToThread(thread);
connect(comicFile, SIGNAL(errorOpening()), thread, SLOT(quit()));
connect(comicFile, SIGNAL(errorOpening(QString)), thread, SLOT(quit()));
connect(comicFile, SIGNAL(imagesLoaded()), thread, SLOT(quit()));
connect(thread, SIGNAL(started()), comicFile, SLOT(process()));
connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater()));

View File

@ -10,6 +10,8 @@ ComicDownloadInfoController::ComicDownloadInfoController() {}
void ComicDownloadInfoController::service(HttpRequest& request, HttpResponse& response)
{
response.setHeader("Content-Type", "plain/text; charset=utf-8");
QString path = QUrl::fromPercentEncoding(request.getPath()).toUtf8();
QStringList pathElements = path.split('/');

View File

@ -51,7 +51,7 @@ void FolderController::service(HttpRequest& request, HttpResponse& response)
}
if(folderId!=1)
t.setVariable("folder.name",folderName);
t.setVariable("folder.name",folderName);
else
t.setVariable("folder.name",libraryName);
QList<LibraryItem *> folderContent = DBHelper::getFolderSubfoldersFromLibrary(libraryId,folderId);
@ -155,75 +155,81 @@ void FolderController::service(HttpRequest& request, HttpResponse& response)
t.setVariable(QString("path%1.name").arg(i-1),DBHelper::getFolderName(libraryId,foldersPath[i].first));
}
t.loop("element",numFoldersAtCurrentPage);
int i = 0;
while(i<numFoldersAtCurrentPage)
{
LibraryItem * item = folderContent.at(i + (page*elementsPerPage));
t.setVariable(QString("element%1.name").arg(i),folderContent.at(i + (page*elementsPerPage))->name);
if(item->isDir())
{
t.setVariable(QString("element%1.class").arg(i),"folder");
QList<LibraryItem *> children = DBHelper::getFolderComicsFromLibrary(libraryId, item->id);
if(children.length()>0)
if(folderContent.length() > 0)
{
t.loop("element",numFoldersAtCurrentPage);
int i = 0;
while(i<numFoldersAtCurrentPage)
{
LibraryItem * item = folderContent.at(i + (page*elementsPerPage));
t.setVariable(QString("element%1.name").arg(i),folderContent.at(i + (page*elementsPerPage))->name);
if(item->isDir())
{
const ComicDB * comic = static_cast<ComicDB*>(children.at(0));
t.setVariable(QString("element%1.image.url").arg(i),QString("/library/%1/cover/%2.jpg?folderCover=true").arg(libraryId).arg(comic->info.hash));
t.setVariable(QString("element%1.class").arg(i),"folder");
QList<LibraryItem *> children = DBHelper::getFolderComicsFromLibrary(libraryId, item->id);
if(children.length()>0)
{
const ComicDB * comic = static_cast<ComicDB*>(children.at(0));
t.setVariable(QString("element%1.image.url").arg(i),QString("/library/%1/cover/%2.jpg?folderCover=true").arg(libraryId).arg(comic->info.hash));
}
else
t.setVariable(QString("element%1.image.url").arg(i),"/images/f.png");
t.setVariable(QString("element%1.browse").arg(i),QString("<a class =\"browseButton\" href=\"%1\">BROWSE</a>").arg(QString("/library/%1/folder/%2").arg(libraryId).arg(item->id)));
t.setVariable(QString("element%1.cover.browse").arg(i),QString("<a href=\"%1\">").arg(QString("/library/%1/folder/%2").arg(libraryId).arg(item->id)));
t.setVariable(QString("element%1.cover.browse.end").arg(i),"</a>");
//t.setVariable(QString("element%1.url").arg(i),"/library/"+libraryName+"/folder/"+QString("%1").arg(folderContent.at(i + (page*10))->id));
//t.setVariable(QString("element%1.downloadurl").arg(i),"/library/"+libraryName+"/folder/"+QString("%1/info").arg(folderContent.at(i + (page*elementsPerPage))->id));
t.setVariable(QString("element%1.download").arg(i),QString("<a onclick=\"this.innerHTML='IMPORTING';this.className='importedButton';\" class =\"importButton\" href=\"%1\">IMPORT</a>").arg("/library/"+QString::number(libraryId)+"/folder/"+QString("%1/info").arg(folderContent.at(i + (page*elementsPerPage))->id)));
t.setVariable(QString("element%1.read").arg(i),"");
t.setVariable(QString("element%1.size").arg(i),"");
t.setVariable(QString("element%1.pages").arg(i),"");
t.setVariable(QString("element%1.status").arg(i),"");
}
else
t.setVariable(QString("element%1.image.url").arg(i),"/images/f.png");
t.setVariable(QString("element%1.browse").arg(i),QString("<a class =\"browseButton\" href=\"%1\">BROWSE</a>").arg(QString("/library/%1/folder/%2").arg(libraryId).arg(item->id)));
t.setVariable(QString("element%1.cover.browse").arg(i),QString("<a href=\"%1\">").arg(QString("/library/%1/folder/%2").arg(libraryId).arg(item->id)));
t.setVariable(QString("element%1.cover.browse.end").arg(i),"</a>");
//t.setVariable(QString("element%1.url").arg(i),"/library/"+libraryName+"/folder/"+QString("%1").arg(folderContent.at(i + (page*10))->id));
//t.setVariable(QString("element%1.downloadurl").arg(i),"/library/"+libraryName+"/folder/"+QString("%1/info").arg(folderContent.at(i + (page*elementsPerPage))->id));
t.setVariable(QString("element%1.download").arg(i),QString("<a onclick=\"this.innerHTML='IMPORTING';this.className='importedButton';\" class =\"importButton\" href=\"%1\">IMPORT</a>").arg("/library/"+QString::number(libraryId)+"/folder/"+QString("%1/info").arg(folderContent.at(i + (page*elementsPerPage))->id)));
t.setVariable(QString("element%1.read").arg(i),"");
t.setVariable(QString("element%1.size").arg(i),"");
t.setVariable(QString("element%1.pages").arg(i),"");
t.setVariable(QString("element%1.status").arg(i),"");
}
else
{
t.setVariable(QString("element%1.class").arg(i),"cover");
const ComicDB * comic = (ComicDB *)item;
t.setVariable(QString("element%1.browse").arg(i),"");
//t.setVariable(QString("element%1.downloadurl").arg(i),"/library/"+libraryName+"/comic/"+QString("%1").arg(comic->id));
if(!session.isComicOnDevice(comic->info.hash) && !session.isComicDownloaded(comic->info.hash))
t.setVariable(QString("element%1.download").arg(i),QString("<a onclick=\"this.innerHTML='IMPORTING';this.className='importedButton';\" class =\"importButton\" href=\"%1\">IMPORT</a>").arg("/library/"+QString::number(libraryId)+"/comic/"+QString("%1").arg(comic->id)));
else if (session.isComicOnDevice(comic->info.hash))
{
t.setVariable(QString("element%1.class").arg(i),"cover");
const ComicDB * comic = (ComicDB *)item;
t.setVariable(QString("element%1.browse").arg(i),"");
//t.setVariable(QString("element%1.downloadurl").arg(i),"/library/"+libraryName+"/comic/"+QString("%1").arg(comic->id));
if(!session.isComicOnDevice(comic->info.hash) && !session.isComicDownloaded(comic->info.hash))
t.setVariable(QString("element%1.download").arg(i),QString("<a onclick=\"this.innerHTML='IMPORTING';this.className='importedButton';\" class =\"importButton\" href=\"%1\">IMPORT</a>").arg("/library/"+QString::number(libraryId)+"/comic/"+QString("%1").arg(comic->id)));
else if (session.isComicOnDevice(comic->info.hash))
t.setVariable(QString("element%1.download").arg(i),QString("<div class=\"importedButton\">IMPORTED</div>"));
else
t.setVariable(QString("element%1.download").arg(i),QString("<div class=\"importedButton\">IMPORTING</div>"));
else
t.setVariable(QString("element%1.download").arg(i),QString("<div class=\"importedButton\">IMPORTING</div>"));
//t.setVariable(QString("element%1.image.url").arg(i),"/images/f.png");
//t.setVariable(QString("element%1.image.url").arg(i),"/images/f.png");
t.setVariable(QString("element%1.read").arg(i),QString("<a class =\"readButton\" href=\"%1\">READ</a>").arg("/library/"+QString::number(libraryId)+"/comic/"+QString("%1").arg(comic->id)+"/remote"));
t.setVariable(QString("element%1.read").arg(i),QString("<a class =\"readButton\" href=\"%1\">READ</a>").arg("/library/"+QString::number(libraryId)+"/comic/"+QString("%1").arg(comic->id)+"/remote"));
t.setVariable(QString("element%1.image.url").arg(i),QString("/library/%1/cover/%2.jpg").arg(libraryId).arg(comic->info.hash));
t.setVariable(QString("element%1.image.url").arg(i),QString("/library/%1/cover/%2.jpg").arg(libraryId).arg(comic->info.hash));
t.setVariable(QString("element%1.size").arg(i),"<span class=\"comicSize\">" + QString::number(comic->info.hash.right(comic->info.hash.length()-40).toInt()/1024.0/1024.0,'f',2)+"Mb</span>");
if(comic->info.hasBeenOpened)
t.setVariable(QString("element%1.pages").arg(i),QString("<span class=\"numPages\">%1/%2 pages</span>").arg(comic->info.currentPage).arg(comic->info.numPages.toInt()));
else
t.setVariable(QString("element%1.pages").arg(i),QString("<span class=\"numPages\">%1 pages</span>").arg(comic->info.numPages.toInt()));
t.setVariable(QString("element%1.size").arg(i),"<span class=\"comicSize\">" + QString::number(comic->info.hash.right(comic->info.hash.length()-40).toInt()/1024.0/1024.0,'f',2)+"Mb</span>");
if(comic->info.hasBeenOpened)
t.setVariable(QString("element%1.pages").arg(i),QString("<span class=\"numPages\">%1/%2 pages</span>").arg(comic->info.currentPage).arg(comic->info.numPages.toInt()));
else
t.setVariable(QString("element%1.pages").arg(i),QString("<span class=\"numPages\">%1 pages</span>").arg(comic->info.numPages.toInt()));
if(comic->info.read)
t.setVariable(QString("element%1.status").arg(i), QString("<div class=\"mark\"><img src=\"/images/readMark.png\" style = \"width: 15px\"/> </div>"));
else if(comic->info.hasBeenOpened)
t.setVariable(QString("element%1.status").arg(i), QString("<div class=\"mark\"><img src=\"/images/readingMark.png\" style = \"width: 15px\"/> </div>"));
else
t.setVariable(QString("element%1.status").arg(i),"");
if(comic->info.read)
t.setVariable(QString("element%1.status").arg(i), QString("<div class=\"mark\"><img src=\"/images/readMark.png\" style = \"width: 15px\"/> </div>"));
else if(comic->info.hasBeenOpened)
t.setVariable(QString("element%1.status").arg(i), QString("<div class=\"mark\"><img src=\"/images/readingMark.png\" style = \"width: 15px\"/> </div>"));
else
t.setVariable(QString("element%1.status").arg(i),"");
t.setVariable(QString("element%1.cover.browse").arg(i),"");
t.setVariable(QString("element%1.cover.browse.end").arg(i),"");
}
i++;
}
t.setVariable(QString("element%1.cover.browse").arg(i),"");
t.setVariable(QString("element%1.cover.browse.end").arg(i),"");
}
i++;
}
} else
{
t.loop("element",0);
}
if(numPages > 1)
{

View File

@ -0,0 +1,55 @@
#include "synccontroller.h"
#include "QsLog.h"
#include <QUrl>
#include "comic_db.h"
#include "db_helper.h"
SyncController::SyncController()
{
}
void SyncController::service(HttpRequest &request, HttpResponse &response)
{
QString postData = QString::fromUtf8(request.getBody());
QLOG_INFO() << "POST DATA: " << postData;
if(postData.length()>0) {
QList<QString> data = postData.split("\n");
qulonglong libraryId;
qulonglong comicId;
int currentPage;
QString hash;
foreach(QString comicInfo, data)
{
QList<QString> comicInfoProgress = comicInfo.split("\t");
if(comicInfoProgress.length() == 4)
{
libraryId = comicInfoProgress.at(0).toULongLong();
comicId = comicInfoProgress.at(1).toULongLong();
hash = comicInfoProgress.at(2);
currentPage = comicInfoProgress.at(3).toInt();
ComicInfo info;
info.currentPage = currentPage;
info.hash = hash; //TODO remove the hash check and add UUIDs for libraries
info.id = comicId;
DBHelper::updateFromRemoteClient(libraryId,info);
}
}
}
else
{
response.setStatus(412,"No comic info received");
response.writeText("",true);
return;
}
response.write("OK",true);
}

View File

@ -0,0 +1,21 @@
#ifndef SYNCCONTROLLER_H
#define SYNCCONTROLLER_H
#include <QObject>
#include "httprequest.h"
#include "httpresponse.h"
#include "httprequesthandler.h"
class SyncController : public HttpRequestHandler {
Q_OBJECT
Q_DISABLE_COPY(SyncController);
public:
/** Constructor */
SyncController();
/** Generates the response */
void service(HttpRequest& request, HttpResponse& response);
};
#endif // SYNCCONTROLLER_H

View File

@ -99,66 +99,72 @@ void HttpConnectionHandler::disconnected() {
}
void HttpConnectionHandler::read() {
while (socket.bytesAvailable()) {
#ifdef SUPERVERBOSE
qDebug("HttpConnectionHandler (%p): read input",this);
qDebug("HttpConnectionHandler (%p): read input",this);
#endif
// Create new HttpRequest object if necessary
if (!currentRequest) {
currentRequest=new HttpRequest(settings);
}
// Collect data for the request object
while (socket.bytesAvailable() && currentRequest->getStatus()!=HttpRequest::complete && currentRequest->getStatus()!=HttpRequest::abort) {
currentRequest->readFromSocket(socket);
if (currentRequest->getStatus()==HttpRequest::waitForBody) {
// Restart timer for read timeout, otherwise it would
// expire during large file uploads.
int readTimeout=settings->value("readTimeout",10000).toInt();
readTimer.start(readTimeout);
}
}
// If the request is aborted, return error message and close the connection
if (currentRequest->getStatus()==HttpRequest::abort) {
socket.write("HTTP/1.1 413 entity too large\r\nConnection: close\r\n\r\n413 Entity too large\r\n");
socket.disconnectFromHost();
delete currentRequest;
currentRequest=0;
return;
}
// If the request is complete, let the request mapper dispatch it
if (currentRequest->getStatus()==HttpRequest::complete) {
readTimer.stop();
qDebug("HttpConnectionHandler (%p): received request",this);
HttpResponse response(&socket);
//response.setHeader("Connection","close"); No funciona bien con NSURLConnection
try {
requestHandler->service(*currentRequest, response);
}
catch (...) {
qCritical("HttpConnectionHandler (%p): An uncatched exception occured in the request handler",this);
// Create new HttpRequest object if necessary
if (!currentRequest) {
currentRequest=new HttpRequest(settings);
}
// Finalize sending the response if not already done
if (!response.hasSentLastPart()) {
response.write(QByteArray(),true);
// Collect data for the request object
while (socket.bytesAvailable() && currentRequest->getStatus()!=HttpRequest::complete && currentRequest->getStatus()!=HttpRequest::abort) {
currentRequest->readFromSocket(socket);
if (currentRequest->getStatus()==HttpRequest::waitForBody) {
// Restart timer for read timeout, otherwise it would
// expire during large file uploads.
int readTimeout=settings->value("readTimeout",10000).toInt();
readTimer.start(readTimeout);
}
}
socket.disconnectFromHost(); //CAMBIADO s<>lo se van a soportar conexiones NO persistentes
// If the request is aborted, return error message and close the connection
if (currentRequest->getStatus()==HttpRequest::abort) {
socket.write("HTTP/1.1 413 entity too large\r\nConnection: close\r\n\r\n413 Entity too large\r\n");
socket.disconnectFromHost();
delete currentRequest;
currentRequest=0;
return;
}
// Close the connection after delivering the response, if requested
//if (QString::compare(currentRequest->getHeader("Connection"),"close",Qt::CaseInsensitive)==0) {
// socket.disconnectFromHost();
//}
//else {
// // Start timer for next request
// int readTimeout=settings->value("readTimeout",10000).toInt();
// readTimer.start(readTimeout);
//}
// Prepare for next request
delete currentRequest;
currentRequest=0;
// If the request is complete, let the request mapper dispatch it
if (currentRequest->getStatus()==HttpRequest::complete) {
readTimer.stop();
qDebug("HttpConnectionHandler (%p): received request",this);
HttpResponse response(&socket);
//response.setHeader("Connection","close"); No funciona bien con NSURLConnection
try {
requestHandler->service(*currentRequest, response);
}
catch (...) {
qCritical("HttpConnectionHandler (%p): An uncatched exception occured in the request handler",this);
}
// Finalize sending the response if not already done
if (!response.hasSentLastPart()) {
response.write(QByteArray(),true);
}
//socket.disconnectFromHost(); //CAMBIADO s<>lo se van a soportar conexiones NO persistentes
// Close the connection after delivering the response, if requested
if (QString::compare(currentRequest->getHeader("Connection"),"close",Qt::CaseInsensitive)==0) {
socket.disconnectFromHost();
}
else {
// Start timer for next request
int readTimeout=settings->value("readTimeout",10000).toInt();
readTimer.start(readTimeout);
}
// Prepare for next request
delete currentRequest;
currentRequest=0;
}
else
{
qDebug("HttpConnectionHandler (%p): received request",this);
}
}
}

View File

@ -14,7 +14,7 @@ HttpSessionStore::HttpSessionStore(QSettings* settings, QObject* parent)
connect(&cleanupTimer,SIGNAL(timeout()),this,SLOT(timerEvent()));
cleanupTimer.start(60000);
cookieName=settings->value("cookieName","sessionid").toByteArray();
expirationTime=settings->value("expirationTime",86400000).toInt();
expirationTime=settings->value("expirationTime",864000000).toInt();
qDebug("HttpSessionStore: Sessions expire after %i milliseconds",expirationTime);
}
@ -90,7 +90,9 @@ void HttpSessionStore::timerEvent() {
++i;
HttpSession session=prev.value();
qint64 lastAccess=session.getLastAccess();
if (now-lastAccess>expirationTime) {
if (now-lastAccess>expirationTime) { //TODO cleaning up will cause current opened comic to be deleted, so clients won't be able to download it
//If the cleaning occurs in the midle of a download it going to cause issues
//Temporal fix: use a big expirationTime = 10 days
qDebug("HttpSessionStore: session %s expired",session.getId().data());
sessions.erase(prev);
}

View File

@ -6,6 +6,8 @@
#ifndef LOGGER_H
#define LOGGER_H
#include <QObject>
#include <QtGlobal>
#include <QThreadStorage>
#include <QHash>

View File

@ -21,6 +21,7 @@
#include "controllers/updatecomiccontroller.h"
#include "controllers/errorcontroller.h"
#include "controllers/comicdownloadinfocontroller.h"
#include "controllers/synccontroller.h"
#include "db_helper.h"
#include "yacreader_libraries.h"
@ -91,81 +92,86 @@ void RequestMapper::loadSession(HttpRequest & request, HttpResponse& response)
}
void RequestMapper::service(HttpRequest& request, HttpResponse& response) {
QByteArray path=request.getPath();
qDebug("RequestMapper: path=%s",path.data());
QByteArray path=request.getPath();
qDebug("RequestMapper: path=%s",path.data());
QRegExp folder("/library/.+/folder/[0-9]+/?");//get comic content
QRegExp folderInfo("/library/.+/folder/[0-9]+/info/?"); //get folder info
QRegExp folder("/library/.+/folder/[0-9]+/?");//get comic content
QRegExp folderInfo("/library/.+/folder/[0-9]+/info/?"); //get folder info
QRegExp comicDownloadInfo("/library/.+/comic/[0-9]+/?"); //get comic info (basic/download info)
QRegExp comicFullInfo("/library/.+/comic/[0-9]+/info/?"); //get comic info (full info)
QRegExp comicOpen("/library/.+/comic/[0-9]+/remote/?"); //the server will open for reading the comic
QRegExp comicUpdate("/library/.+/comic/[0-9]+/update/?"); //get comic info
QRegExp comicClose("/library/.+/comic/[0-9]+/close/?"); //the server will close the comic and free memory
QRegExp cover("/library/.+/cover/[0-9a-f]+.jpg"); //get comic cover (navigation)
QRegExp comicPage("/library/.+/comic/[0-9]+/page/[0-9]+/?"); //get comic page
QRegExp comicClose("/library/.+/comic/[0-9]+/close/?"); //the server will close the comic and free memory
QRegExp cover("/library/.+/cover/[0-9a-f]+.jpg"); //get comic cover (navigation)
QRegExp comicPage("/library/.+/comic/[0-9]+/page/[0-9]+/?"); //get comic page
QRegExp comicPageRemote("/library/.+/comic/[0-9]+/page/[0-9]+/remote?"); //get comic page (remote reading)
QRegExp sync("/sync");
QRegExp library("/library/([0-9]+)/.+"); //permite verificar que la biblioteca solicitada existe
path = QUrl::fromPercentEncoding(path).toUtf8();
loadSession(request, response);
if(!sync.exactMatch(path)) //no session is needed for syncback info, until security will be added
loadSession(request, response);
//primera petición, se ha hecho un post, se sirven las bibliotecas si la seguridad mediante login no está habilitada
//primera petición, se ha hecho un post, se sirven las bibliotecas si la seguridad mediante login no está habilitada
if(path == "/") //Don't send data to the server using '/' !!!!
{
LibrariesController().service(request, response);
}
else
{
//se comprueba que la sesión sea la correcta con el fin de evitar accesos no autorizados
HttpSession session=Static::sessionStore->getSession(request,response,false);
if(!session.isNull() && session.contains("ySession"))
LibrariesController().service(request, response);
}
else
{
if(sync.exactMatch(path))
SyncController().service(request, response);
else
{
if(library.indexIn(path)!=-1 && DBHelper::getLibraries().contains(library.cap(1).toInt()) )
{
//listar el contenido del folder
if(folder.exactMatch(path))
{
FolderController().service(request, response);
}
else if (folderInfo.exactMatch(path))
{
FolderInfoController().service(request, response);
}
else if(cover.exactMatch(path))
{
CoverController().service(request, response);
}
else if(comicDownloadInfo.exactMatch(path))
//se comprueba que la sesión sea la correcta con el fin de evitar accesos no autorizados
HttpSession session=Static::sessionStore->getSession(request,response,false);
if(!session.isNull() && session.contains("ySession"))
{
if(library.indexIn(path)!=-1 && DBHelper::getLibraries().contains(library.cap(1).toInt()) )
{
ComicDownloadInfoController().service(request, response);
//listar el contenido del folder
if(folder.exactMatch(path))
{
FolderController().service(request, response);
}
else if (folderInfo.exactMatch(path))
{
FolderInfoController().service(request, response);
}
else if(cover.exactMatch(path))
{
CoverController().service(request, response);
}
else if(comicDownloadInfo.exactMatch(path))
{
ComicDownloadInfoController().service(request, response);
}
else if(comicFullInfo.exactMatch(path) || comicOpen.exactMatch(path))//start download or start remote reading
{
ComicController().service(request, response);
}
else if(comicPage.exactMatch(path) || comicPageRemote.exactMatch(path))
{
PageController().service(request,response);
}
else if(comicUpdate.exactMatch(path))
{
UpdateComicController().service(request, response);
}
}
else if(comicFullInfo.exactMatch(path) || comicOpen.exactMatch(path))//start download or start remote reading
{
ComicController().service(request, response);
}
else if(comicPage.exactMatch(path) || comicPageRemote.exactMatch(path))
{
PageController().service(request,response);
}
else if(comicUpdate.exactMatch(path))
else
{
UpdateComicController().service(request, response);
//response.writeText(library.cap(1));
Static::staticFileController->service(request, response);
}
}
else
{
//response.writeText(library.cap(1));
Static::staticFileController->service(request, response);
}
}
else //acceso no autorizado, redirección
{
ErrorController(300).service(request,response);
}
}
else //acceso no autorizado, redirección
{
ErrorController(300).service(request,response);
}
}
}
}

View File

@ -5,31 +5,33 @@ HEADERS += \
$$PWD/static.h \
$$PWD/startup.h \
$$PWD/requestmapper.h \
$$PWD/controllers/comiccontroller.h \
$$PWD/controllers/errorcontroller.h \
$$PWD/controllers/foldercontroller.h \
$$PWD/controllers/folderinfocontroller.h \
$$PWD/controllers/librariescontroller.h \
$$PWD/controllers/pagecontroller.h \
$$PWD/controllers/sessionmanager.h \
$$PWD/controllers/covercontroller.h \
server/controllers/updatecomiccontroller.h \
server/controllers/comicdownloadinfocontroller.h
$$PWD/controllers/comiccontroller.h \
$$PWD/controllers/errorcontroller.h \
$$PWD/controllers/foldercontroller.h \
$$PWD/controllers/folderinfocontroller.h \
$$PWD/controllers/librariescontroller.h \
$$PWD/controllers/pagecontroller.h \
$$PWD/controllers/sessionmanager.h \
$$PWD/controllers/covercontroller.h \
$$PWD/controllers/updatecomiccontroller.h \
$$PWD/controllers/comicdownloadinfocontroller.h \
$$PWD/controllers/synccontroller.h
SOURCES += \
$$PWD/static.cpp \
$$PWD/startup.cpp \
$$PWD/requestmapper.cpp \
$$PWD/controllers/comiccontroller.cpp \
$$PWD/controllers/errorcontroller.cpp \
$$PWD/controllers/foldercontroller.cpp \
$$PWD/controllers/folderinfocontroller.cpp \
$$PWD/controllers/librariescontroller.cpp \
$$PWD/controllers/pagecontroller.cpp \
$$PWD/controllers/sessionmanager.cpp \
$$PWD/controllers/covercontroller.cpp \
server/controllers/updatecomiccontroller.cpp \
server/controllers/comicdownloadinfocontroller.cpp
$$PWD/controllers/comiccontroller.cpp \
$$PWD/controllers/errorcontroller.cpp \
$$PWD/controllers/foldercontroller.cpp \
$$PWD/controllers/folderinfocontroller.cpp \
$$PWD/controllers/librariescontroller.cpp \
$$PWD/controllers/pagecontroller.cpp \
$$PWD/controllers/sessionmanager.cpp \
$$PWD/controllers/covercontroller.cpp \
$$PWD/controllers/updatecomiccontroller.cpp \
$$PWD/controllers/comicdownloadinfocontroller.cpp \
$$PWD/controllers/synccontroller.cpp
include(lib/bfLogging/bfLogging.pri)
include(lib/bfHttpServer/bfHttpServer.pri)

View File

@ -1,4 +1,4 @@
#include "comic.h"
#include "comic.h"
#include <QPixmap>
#include <QRegExp>
@ -18,9 +18,13 @@
const QStringList Comic::imageExtensions = QStringList() << "*.jpg" << "*.jpeg" << "*.png" << "*.gif" << "*.tiff" << "*.tif" << "*.bmp" << "*.webp";
const QStringList Comic::literalImageExtensions = QStringList() << "jpg" << "jpeg" << "png" << "gif" << "tiff" << "tif" << "bmp" << "webp";
#ifndef use_unarr
const QStringList Comic::comicExtensions = QStringList() << "*.cbr" << "*.cbz" << "*.rar" << "*.zip" << "*.tar" << "*.pdf" << "*.7z" << "*.cb7" << "*.arj" << "*.cbt";
const QStringList Comic::literalComicExtensions = QStringList() << "cbr" << "cbz" << "rar" << "zip" << "tar" << "pdf" << "7z" << "cb7" << "arj" << "cbt";
#else
const QStringList Comic::comicExtensions = QStringList() << "*.cbr" << "*.cbz" << "*.rar" << "*.zip" << "*.tar" << "*.pdf" << "*.cbt";
const QStringList Comic::literalComicExtensions = QStringList() << "cbr" << "cbz" << "rar" << "zip" << "tar" << "pdf" << "cbt";
#endif
//-----------------------------------------------------------------------------
Comic::Comic()
:_pages(),_index(0),_path(),_loaded(false),bm(new Bookmarks()),_loadedPages(),_isPDF(false)
@ -305,6 +309,7 @@ bool FileComic::load(const QString & path, const ComicDB & comic)
else
{
//QMessageBox::critical(NULL,tr("Not found"),tr("Comic not found")+" : " + path);
moveToThread(QApplication::instance()->thread());
emit errorOpening();
return false;
}
@ -471,12 +476,14 @@ void FileComic::process()
CompressedArchive archive(_path);
if(!archive.toolsLoaded())
{
moveToThread(QApplication::instance()->thread());
emit errorOpening(tr("7z not found"));
return;
}
if(!archive.isValid())
{
moveToThread(QApplication::instance()->thread());
emit errorOpening(tr("Format not supported"));
return;
}
@ -488,6 +495,7 @@ void FileComic::process()
if(_fileNames.size()==0)
{
//QMessageBox::critical(NULL,tr("File error"),tr("File not found or not images in file"));
moveToThread(QApplication::instance()->thread());
emit errorOpening();
return;
}
@ -507,6 +515,10 @@ void FileComic::process()
if(_firstPage == -1)
_firstPage = bm->getLastPage();
if(_firstPage >= _pages.length())
_firstPage = 0;
_index = _firstPage;
emit(openAt(_index));
@ -527,9 +539,8 @@ void FileComic::process()
emit imageLoaded(sortedIndex);
emit imageLoaded(sortedIndex,_pages[sortedIndex]);
}*/
moveToThread(QApplication::instance()->thread());
emit imagesLoaded();
//moveToThread(QApplication::instance()->thread());
}
@ -587,6 +598,7 @@ void FolderComic::process()
{
//TODO emitir este mensaje en otro sitio
//QMessageBox::critical(NULL,QObject::tr("No images found"),QObject::tr("There are not images on the selected folder"));
moveToThread(QApplication::instance()->thread());
emit errorOpening();
}
else
@ -594,6 +606,9 @@ void FolderComic::process()
if(_firstPage == -1)
_firstPage = bm->getLastPage();
if(_firstPage >= _pages.length())
_firstPage = 0;
_index = _firstPage;
emit(openAt(_index));
@ -617,8 +632,8 @@ void FolderComic::process()
count++;
}
}
moveToThread(QApplication::instance()->thread());
emit imagesLoaded();
moveToThread(QApplication::instance()->thread());
}
////////////////////////////////////////////////////////////////////////////////
@ -660,6 +675,7 @@ bool PDFComic::load(const QString & path, int atPage)
}
else
{
moveToThread(QApplication::instance()->thread());
emit errorOpening();
return false;
}
@ -682,6 +698,7 @@ bool PDFComic::load(const QString & path, const ComicDB & comic)
else
{
//QMessageBox::critical(NULL,tr("Not found"),tr("Comic not found")+" : " + path);
moveToThread(QApplication::instance()->thread());
emit errorOpening();
return false;
}
@ -705,11 +722,13 @@ void PDFComic::process()
{
//delete pdfComic;
//pdfComic = 0;
moveToThread(QApplication::instance()->thread());
emit errorOpening();
return;
}
if (pdfComic->isLocked())
{
moveToThread(QApplication::instance()->thread());
emit errorOpening();
return;
}
@ -730,6 +749,10 @@ void PDFComic::process()
if(_firstPage == -1)
_firstPage = bm->getLastPage();
if(_firstPage >= _pages.length())
_firstPage = 0;
_index = _firstPage;
emit(openAt(_index));
@ -741,8 +764,8 @@ void PDFComic::process()
renderPage(i);
delete pdfComic;
moveToThread(QApplication::instance()->thread());
emit imagesLoaded();
moveToThread(QApplication::instance()->thread());
}
void PDFComic::renderPage(int page)

View File

@ -355,7 +355,8 @@ void YACReaderFlowGL::paintGL()
void YACReaderFlowGL::resizeGL(int width, int height)
{
fontSize = (width + height) * 0.010;
float pixelRatio = devicePixelRatio();
fontSize = (width + height) * 0.010 * pixelRatio;
if(fontSize < 10)
fontSize = 10;
@ -368,12 +369,13 @@ void YACReaderFlowGL::resizeGL(int width, int height)
void YACReaderFlowGL::udpatePerspective(int width, int height)
{
glViewport(0, 0, width, height);
float pixelRatio = devicePixelRatio();
glViewport(0, 0, width*pixelRatio, height*pixelRatio);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(20.0, GLdouble(width) / (float)height, 1.0, 200.0);
gluPerspective(20.0, GLdouble(width) / (float)height, 1.0, 200.0);
glMatrixMode(GL_MODELVIEW);
}
@ -384,7 +386,7 @@ void YACReaderFlowGL::calcPos(YACReader3DImage & image, int pos)
{
if(pos == 0){
image.current = centerPos;
}else{
}else{
if(pos > 0){
image.current.x = (config.centerDistance)+(config.xDistance*pos);
image.current.y = config.yDistance*pos*-1;
@ -804,6 +806,8 @@ void YACReaderFlowGL::populate(int n)
void YACReaderFlowGL::reset()
{
makeCurrent();
startAnimationTimer();
currentSelected = 0;
@ -819,6 +823,8 @@ void YACReaderFlowGL::reset()
if(!hasBeenInitialized)
lazyPopulateObjects = -1;
doneCurrent();
}
void YACReaderFlowGL::reload()
@ -1101,8 +1107,9 @@ void YACReaderFlowGL::mousePressEvent(QMouseEvent *event)
if(event->button() == Qt::LeftButton)
{
float x,y;
x = event->x();
y = event->y();
float pixelRatio = devicePixelRatio();
x = event->x()*pixelRatio;
y = event->y()*pixelRatio;
GLint viewport[4];
GLdouble modelview[16];
GLdouble projection[16];
@ -1139,8 +1146,9 @@ void YACReaderFlowGL::mouseDoubleClickEvent(QMouseEvent* event)
{
makeCurrent();
float x,y;
x = event->x();
y = event->y();
float pixelRatio = devicePixelRatio();
x = event->x()*pixelRatio;
y = event->y()*pixelRatio;
GLint viewport[4];
GLdouble modelview[16];
GLdouble projection[16];
@ -1269,6 +1277,8 @@ void YACReaderComicFlowGL::updateImageData()
return;
}
}
delete[] indexes;
}
void YACReaderComicFlowGL::remove(int item)
@ -1405,6 +1415,8 @@ void YACReaderPageFlowGL::updateImageData()
return;
}
}
delete[] indexes;
}
void YACReaderPageFlowGL::populate(int n)

View File

@ -238,10 +238,10 @@ YACReaderFlowGL::YACReaderFlowGL(QWidget *parent,struct Preset p)
loaderThread->start();*/
QGLFormat f = format();
/*QGLFormat f = format();
f.setVersion(2, 1);
f.setSwapInterval(0);
setFormat(f);
f.setSwapInterval(0);
setFormat(f);*/
timerId = startTimer(updateInterval);
@ -325,8 +325,8 @@ void YACReaderFlowGL::paintGL()
void YACReaderFlowGL::resizeGL(int width, int height)
{
fontSize = (width + height) * 0.010;
float pixelRatio = devicePixelRatio();
fontSize = (width + height) * 0.010 * pixelRatio;
if(fontSize < 10)
fontSize = 10;
@ -339,7 +339,8 @@ void YACReaderFlowGL::resizeGL(int width, int height)
void YACReaderFlowGL::udpatePerspective(int width, int height)
{
glViewport(0, 0, width, height);
float pixelRatio = devicePixelRatio();
glViewport(0, 0, width*pixelRatio, height*pixelRatio);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
@ -938,26 +939,25 @@ void YACReaderFlowGL::setPerformance(Performance performance)
}
void YACReaderFlowGL::useVSync(bool b)
{
if(bUseVSync != b)
{/*if(bUseVSync != b)
{
bUseVSync = b;
if(b)
{
QGLFormat f = format();
f.setVersion(2, 1);
//f.setVersion(2, 1);
f.setSwapInterval(1);
setFormat(f);
}
else
{
QGLFormat f = format();
f.setVersion(2, 1);
//f.setVersion(2, 1);
f.setSwapInterval(0);
setFormat(f);
}
reset();
}
reset();
}*/
}
void YACReaderFlowGL::setShowMarks(bool value)
{
@ -1079,8 +1079,9 @@ void YACReaderFlowGL::mousePressEvent(QMouseEvent *event)
if(event->button() == Qt::LeftButton)
{
float x,y;
x = event->x();
y = event->y();
float pixelRatio = devicePixelRatio();
x = event->x()*pixelRatio;
y = event->y()*pixelRatio;
GLint viewport[4];
GLdouble modelview[16];
GLdouble projection[16];
@ -1114,8 +1115,9 @@ void YACReaderFlowGL::mousePressEvent(QMouseEvent *event)
void YACReaderFlowGL::mouseDoubleClickEvent(QMouseEvent* event)
{
float x,y;
x = event->x();
y = event->y();
float pixelRatio = devicePixelRatio();
x = event->x()*pixelRatio;
y = event->y()*pixelRatio;
GLint viewport[4];
GLdouble modelview[16];
GLdouble projection[16];
@ -1243,6 +1245,7 @@ void YACReaderComicFlowGL::updateImageData()
return;
}
}
delete[] indexes;
}
void YACReaderComicFlowGL::remove(int item)
@ -1369,6 +1372,7 @@ void YACReaderPageFlowGL::updateImageData()
return;
}
}
delete[] indexes;
}
void YACReaderPageFlowGL::populate(int n)

69
common/opengl_checker.cpp Normal file
View File

@ -0,0 +1,69 @@
#include "opengl_checker.h"
#include "QsLog.h"
OpenGLChecker::OpenGLChecker()
:compatibleOpenGLVersion(true)
{
QOpenGLContext * openGLContext = new QOpenGLContext();
openGLContext->create();
if(!openGLContext->isValid())
{
compatibleOpenGLVersion = false;
description = "unable to create QOpenGLContext";
}
QSurfaceFormat format = openGLContext->format();
int majorVersion = format.majorVersion();
int minorVersion = format.minorVersion();
QString type;
switch (format.renderableType()) {
case QSurfaceFormat::OpenGL:
type = "desktop";
break;
case QSurfaceFormat::OpenGLES:
type = "OpenGL ES";
break;
case QSurfaceFormat::OpenVG:
type = "OpenVG";
default: case QSurfaceFormat::DefaultRenderableType:
type = "unknown";
break;
}
delete openGLContext;
description = QString("%1.%2 %3").arg(majorVersion).arg(minorVersion).arg(type);
if(format.renderableType() != QSurfaceFormat::OpenGL) //Desktop OpenGL
compatibleOpenGLVersion = false;
#ifdef Q_OS_WIN //TODO check Qt version, and set this values depending on the use of QOpenGLWidget or QGLWidget
static const int majorTargetVersion = 1;
static const int minorTargetVersion = 4;
#else
static const int majorTargetVersion = 2;
static const int minorTargetVersion = 0;
#endif
if(majorVersion < majorTargetVersion)
compatibleOpenGLVersion = false;
if(majorVersion == majorTargetVersion && minorVersion < minorTargetVersion)
compatibleOpenGLVersion = false;
}
QString OpenGLChecker::textVersionDescription()
{
return description;
}
bool OpenGLChecker::hasCompatibleOpenGLVersion()
{
return compatibleOpenGLVersion;
}

17
common/opengl_checker.h Normal file
View File

@ -0,0 +1,17 @@
#ifndef OPENGL_CHECKER_H
#define OPENGL_CHECKER_H
#include <QOpenGLContext>
class OpenGLChecker
{
public:
OpenGLChecker();
bool hasCompatibleOpenGLVersion();
QString textVersionDescription();
private:
QString description;
bool compatibleOpenGLVersion;
};
#endif // OPENGL_CHECKER_H

View File

@ -5,14 +5,14 @@ fi
echo "Compiling YACReader"
cd ./YACReader
/Users/luisangel/Qt/5.4/clang_64/bin/qmake -spec macx-clang "CONFIG+=release"
/Users/luisangel/my_dev/Qt5.5.0/5.5/clang_64/bin/qmake -spec macx-clang "CONFIG+=release"
#qmake -spec macx-g++ "CONFIG+=release"
make
cd ..
echo "Compiling YACReaderLibrary"
cd ./YACReaderLibrary
/Users/luisangel/Qt/5.4/clang_64/bin/qmake -spec macx-clang "CONFIG+=release"
/Users/luisangel/my_dev/Qt5.5.0/5.5/clang_64/bin/qmake -spec macx-clang "CONFIG+=release"
#qmake -spec macx-g++ "CONFIG+=release"
make
cd ..

View File

@ -1,7 +1,13 @@
If you are trying to compile YACReader, you need to donwload de source code of 7zip (Windows) or p7zip (Linux/MacOSX).
If you are trying to compile YACReader with a 7zip decompression backend, you need to download de source code of 7zip (Windows) or p7zip (Linux/MacOSX).
Please, extract it and rename the folder to lib7zip (Windows) or libp7zip (Linux/MacOSX), then copy it to $YACREADER_SRC/compressed_archive/ (this
folder). If you are using a 64 bit Linux-System, please apply libp7zip.patch for successfull compilation or use compileX11.sh.
Please extract it and rename the folder to lib7zip (Windows) or libp7zip (Linux/MacOSX), then copy it to $YACREADER_SRC/compressed_archive/ (this
folder).
YACReader is compiled using 7zip/p7zip 9.20.1
YACReader is compiled using 7zip/p7zip 9.20.1 and will not work with newer versions.
On Linux/Unix this means your YACReader installation will stop working if you update your installation of p7zip to a newer version. If you wish to keep using
p7zip with YACReader, you can copy 7z.so and Codecs/Rar29.so from p7zip 9.20.1 to "/usr/lib/yacreader/". YACReader will then detect these files and use
them instead of the system provided p7zip files which allows you to keep both YACReader and an up to date p7zip installation.
Please keep in mind this is only a workaround that is provided for backwards compatibility and not intended as a long time solution.
It is recommended that you switch to unarr as a decompression backend instead (see README.txt in compressed_archive/unarr).

View File

@ -18,7 +18,9 @@ DEFINE_GUID(CLSID_CFormatRar, 0x23170f69, 0x40c1, 0x278a, 0x10, 0x00, 0x00,
DEFINE_GUID(CLSID_CFormatZip, 0x23170f69, 0x40c1, 0x278a, 0x10, 0x00, 0x00, 0x01, 0x10, 0x01, 0x00, 0x00);
DEFINE_GUID(CLSID_CFormatTar, 0x23170f69, 0x40c1, 0x278a, 0x10, 0x00, 0x00, 0x01, 0x10, 0xee, 0x00, 0x00);
DEFINE_GUID(CLSID_CFormatArj, 0x23170f69, 0x40c1, 0x278a, 0x10, 0x00, 0x00, 0x01, 0x10, 0x04, 0x00, 0x00);
DEFINE_GUID(CLSID_CFormatBZip2, 0x23170f69, 0x40c1, 0x278a, 0x10, 0x00, 0x00, 0x01, 0x10, 0x02, 0x00, 0x00);
//unused Formats
/*DEFINE_GUID(CLSID_CFormatBZip2, 0x23170f69, 0x40c1, 0x278a, 0x10, 0x00, 0x00, 0x01, 0x10, 0x02, 0x00, 0x00);
DEFINE_GUID(CLSID_CFormatCab, 0x23170f69, 0x40c1, 0x278a, 0x10, 0x00, 0x00, 0x01, 0x10, 0x08, 0x00, 0x00);
DEFINE_GUID(CLSID_CFormatChm, 0x23170f69, 0x40c1, 0x278a, 0x10, 0x00, 0x00, 0x01, 0x10, 0xe9, 0x00, 0x00);
DEFINE_GUID(CLSID_CFormatCompound,0x23170f69, 0x40c1, 0x278a, 0x10, 0x00, 0x00, 0x01, 0x10, 0xe5, 0x00, 0x00);
@ -32,7 +34,7 @@ DEFINE_GUID(CLSID_CFormatNsis, 0x23170f69, 0x40c1, 0x278a, 0x10, 0x00, 0x00,
DEFINE_GUID(CLSID_CFormatRpm, 0x23170f69, 0x40c1, 0x278a, 0x10, 0x00, 0x00, 0x01, 0x10, 0xeb, 0x00, 0x00);
DEFINE_GUID(CLSID_CFormatSplit, 0x23170f69, 0x40c1, 0x278a, 0x10, 0x00, 0x00, 0x01, 0x10, 0xea, 0x00, 0x00);
DEFINE_GUID(CLSID_CFormatWim, 0x23170f69, 0x40c1, 0x278a, 0x10, 0x00, 0x00, 0x01, 0x10, 0xe6, 0x00, 0x00);
DEFINE_GUID(CLSID_CFormatZ, 0x23170f69, 0x40c1, 0x278a, 0x10, 0x00, 0x00, 0x01, 0x10, 0x05, 0x00, 0x00);
DEFINE_GUID(CLSID_CFormatZ, 0x23170f69, 0x40c1, 0x278a, 0x10, 0x00, 0x00, 0x01, 0x10, 0x05, 0x00, 0x00);*/
#ifdef Q_OS_WIN
GUID _supportedFileFormats[] = {CLSID_CFormatRar,CLSID_CFormatZip,CLSID_CFormatTar,CLSID_CFormat7z,CLSID_CFormatArj};
@ -71,6 +73,13 @@ struct SevenZipInterface {
//SevenZipInterface * szInterface;
const char rar[7]={static_cast<char>(0x52), static_cast<char>(0x61), static_cast<char>(0x72), static_cast<char>(0x21), static_cast<char>(0x1A), static_cast<char>(0x07), static_cast<char>(0x00)};
const char rar5[8]={static_cast<char>(0x52), static_cast<char>(0x61), static_cast<char>(0x72), static_cast<char>(0x21), static_cast<char>(0x1A), static_cast<char>(0x07), static_cast<char>(0x01), static_cast<char>(0x00)};
const char zip[2]={static_cast<char>(0x50), static_cast<char>(0x4B)};
const char sevenz[6]={static_cast<char>(0x37), static_cast<char>(0x7A), static_cast<char>(0xBC), static_cast<char>(0xAF), static_cast<char>(0x27), static_cast<char>(0x1C)};
const char tar[6]="ustar";
const char arj[2]={static_cast<char>(0x60), static_cast<char>(0xEA)};
CompressedArchive::CompressedArchive(const QString & filePath, QObject *parent) :
QObject(parent),sevenzLib(0),valid(false),tools(false)
#ifdef Q_OS_UNIX
@ -98,62 +107,144 @@ CompressedArchive::CompressedArchive(const QString & filePath, QObject *parent)
// openCallbackSpec->PasswordIsDefined = true;
// openCallbackSpec->Password = L"1";
for(unsigned int i=0;i<supportedFileFormats.size();i++)
//get file type from suffix
int i=-1;
QFile filex(filePath);
if (!filex.open(QIODevice::ReadOnly))
return;
QByteArray magicNumber=filex.read(8); //read first 8 bytes
//if (memcmp(magicNumber,rar5,8)==0)
//return; //rar5 is not supported
//qDebug() << memcmp(magicNumber,rar,7);
//TODO: this suffix matching is rather primitive - better approach?
#ifdef Q_OS_UNIX
if (memcmp(magicNumber,rar,6) != 0)
{
//match suffix to GUID list
if (memcmp(magicNumber,zip,2)==0)
i=0;
else if (memcmp(magicNumber,sevenz,6)==0)
i=2;
else if (memcmp(magicNumber,arj,2)==0)
i=3;
else
{
filex.seek(257);
magicNumber=filex.read(8);
if (memcmp(magicNumber,tar,5)==0)
i=1;
}
if (i==-1) //fallback code
{
QFileInfo fileinfo(filePath);
if (fileinfo.suffix() == "zip" || fileinfo.suffix() == "cbz")
{
i=0;
}
else
{
return;
}
}
#else
if (memcmp(magicNumber,rar,6) == 0)
if (memcmp(magicNumber,rar5,7) == 0)
return;
else
i=0;
else if (memcmp(magicNumber,zip,2)==0)
i=1;
else if (memcmp(magicNumber,sevenz,6)==0)
i=3;
else if (memcmp(magicNumber,arj,2)==0)
i=4;
else {
filex.seek(257);
magicNumber=filex.read(8);
if (memcmp(magicNumber,tar,5)==0)
i=2;
}
if (i==-1) //fallback code
{
QFileInfo fileinfo(filePath);
if (fileinfo.suffix() == "zip" || fileinfo.suffix() == "cbz")
{
i=1;
}
else
{
return;
}
}
#endif
#ifdef UNICODE
if (!fileSpec->Open((LPCTSTR)filePath.toStdWString().c_str()))
#else
if (!fileSpec->Open((LPCTSTR)filePath.toStdString().c_str()))
#endif
{
qDebug() << "unable to load" + filePath;
return;
}
//GUID uuid = supportedFileFormats[i];
//qDebug() << "trying : " << uuid << endl;
if (szInterface->createObjectFunc(&supportedFileFormats[i], &IID_InArchive, (void **)&szInterface->archive) != S_OK)
{
qDebug() << "wrong format";
continue;
}
#ifdef UNICODE
if (!fileSpec->Open((LPCTSTR)filePath.toStdWString().c_str()))
#else
if (!fileSpec->Open((LPCTSTR)filePath.toStdString().c_str()))
#endif
{
qDebug() << "unable to load" + filePath;
continue;
}
//qDebug() << "Can not open archive file : " + filePath << endl;
if (szInterface->createObjectFunc(&supportedFileFormats[i], &IID_InArchive, (void **)&szInterface->archive) == S_OK)
{
//qDebug() << "Can not open archive file : " + filePath << endl;
if (szInterface->archive->Open(file, 0, openCallback) == S_OK)
{
valid = formatFound = true;
break;
}
else
qDebug() << "Can not open archive file : " + filePath << endl;
{
valid = formatFound = true;
qDebug() << "Opened archive file : " + filePath << endl;
setupFilesNames();
return;
}
}
if(!formatFound)
{
#ifdef Q_OS_WIN
if(!formatFound)
{
qDebug() << "Can not open archive" << endl;
}
}
}
#else
}
else
{
if (memcmp(magicNumber,rar5,7) == 0)
return;//we don't support rar5
isRar=true; //tell the destructor we *tried* to open a rar file!
if (szInterface->createObjectFunc(&CLSID_CFormatRar, &IID_InArchive, (void **)&szInterface->archive) != S_OK)
{
qDebug() << "Error creating rar archive :" + filePath;
return;
}
CMyComPtr<ISetCompressCodecsInfo> codecsInfo;
CMyComPtr<ISetCompressCodecsInfo> codecsInfo;
if (szInterface->archive->QueryInterface(IID_ISetCompressCodecsInfo,(void **)&codecsInfo) != S_OK)
{
qDebug() << "Error getting rar codec :" + filePath;
return;
}
if (codecsInfo->SetCompressCodecsInfo(this) != S_OK)
{
qDebug() << "Error setting rar codec";
return;
return;
}
#ifdef UNICODE
if (!fileSpec->Open((LPCTSTR)filePath.toStdWString().data()))
if (!fileSpec->Open((LPCTSTR)filePath.toStdWString().c_str()))
#else
if (!fileSpec->Open((LPCTSTR)filePath.toStdString().data()))
if (!fileSpec->Open((LPCTSTR)filePath.toStdString().c_str()))
#endif
{
qDebug() << "Error opening rar file :" + filePath;
@ -164,25 +255,31 @@ CompressedArchive::CompressedArchive(const QString & filePath, QObject *parent)
if (szInterface->archive->Open(file, 0, openCallback) == S_OK)
{
valid = formatFound = true;
isRar = true;
setupFilesNames();
//isRar = true;
}
else
qDebug() << "Error opening rar archive";
#endif
}
}
}
#endif
CompressedArchive::~CompressedArchive()
{
//always close the archive!
if (szInterface->archive)
{
szInterface->archive->Close();
}
#ifdef Q_OS_UNIX
if(isRar) //TODO: fix this!!! Possible memory leak. If AddRef is not used, a crash occurs in "delete szInterface"
if(isRar) //TODO: Memory leak!!!! If AddRef is not used, a crash occurs in "delete szInterface"
{
szInterface->archive->AddRef();
}
#endif
if(valid) //TODO: fix this!!! Memory leak.
delete szInterface;
delete szInterface;
#ifdef Q_OS_UNIX
delete rarLib;
#endif
@ -191,27 +288,27 @@ CompressedArchive::~CompressedArchive()
bool CompressedArchive::loadFunctions()
{
//LOAD library
//TODO check if this works in OSX (7z.so instead of 7z.dylib)
// fix1: try to load "7z.so"
// fix2: rename 7z.so to 7z.dylib
if(sevenzLib == 0)
//LOAD library
//TODO check if this works in OSX (7z.so instead of 7z.dylib)
// fix1: try to load "7z.so"
// fix2: rename 7z.so to 7z.dylib
if(sevenzLib == 0)
{
#if defined Q_OS_UNIX
#if defined Q_OS_MAC
#if defined Q_OS_MAC
rarLib = new QLibrary(QCoreApplication::applicationDirPath()+"/utils/Codecs/Rar29");
#else
//check if a yacreader specific version of p7zip exists on the system
QFileInfo rarCodec(QString(LIBDIR)+"/yacreader/Codecs/Rar29.so");
if (rarCodec.exists())
{
rarLib = new QLibrary(rarCodec.absoluteFilePath());
}
else
{
rarLib = new QLibrary(QString(LIBDIR)+"/p7zip/Codecs/Rar29.so");
}
#endif
#else
//check if a yacreader specific version of p7zip exists on the system
QFileInfo rarCodec(QString(LIBDIR)+"/yacreader/Codecs/Rar29.so");
if (rarCodec.exists())
{
rarLib = new QLibrary(rarCodec.absoluteFilePath());
}
else
{
rarLib = new QLibrary(QString(LIBDIR)+"/p7zip/Codecs/Rar29.so");
}
#endif
if(!rarLib->load())
{
qDebug() << "Error Loading Rar29.so : " + rarLib->errorString() << endl;
@ -220,43 +317,43 @@ bool CompressedArchive::loadFunctions()
}
#endif
#if defined Q_OS_UNIX && !defined Q_OS_MAC
QFileInfo sevenzlibrary(QString(LIBDIR)+"/yacreader/7z.so");
if (sevenzlibrary.exists())
{
sevenzLib = new QLibrary(sevenzlibrary.absoluteFilePath());
}
else
{
sevenzLib = new QLibrary(QString(LIBDIR)+"/p7zip/7z.so");
}
QFileInfo sevenzlibrary(QString(LIBDIR)+"/yacreader/7z.so");
if (sevenzlibrary.exists())
{
sevenzLib = new QLibrary(sevenzlibrary.absoluteFilePath());
}
else
{
sevenzLib = new QLibrary(QString(LIBDIR)+"/p7zip/7z.so");
}
#else
sevenzLib = new QLibrary(QCoreApplication::applicationDirPath()+"/utils/7z");
#endif
}
if(!sevenzLib->load())
{
if(!sevenzLib->load())
{
qDebug() << "Error Loading 7z.dll : " + sevenzLib->errorString() << endl;
QCoreApplication::exit(700); //TODO yacreader_global can't be used here, it is GUI dependant, YACReader::SevenZNotFound
return false;
}
else
{
qDebug() << "Loading functions" << endl;
return false;
}
else
{
qDebug() << "Loading functions" << endl;
if((szInterface->createObjectFunc = (CreateObjectFunc)sevenzLib->resolve("CreateObject")) == 0)
qDebug() << "fail loading function : CreateObject" << endl;
if((szInterface->getMethodPropertyFunc = (GetMethodPropertyFunc)sevenzLib->resolve("GetMethodProperty")) == 0)
qDebug() << "fail loading function : GetMethodProperty" << endl;
if((szInterface->getNumberOfMethodsFunc = (GetNumberOfMethodsFunc)sevenzLib->resolve("GetNumberOfMethods")) == 0)
qDebug() << "fail loading function : GetNumberOfMethods" << endl;
if((szInterface->getNumberOfFormatsFunc = (GetNumberOfFormatsFunc)sevenzLib->resolve("GetNumberOfFormats")) == 0)
qDebug() << "fail loading function : GetNumberOfFormats" << endl;
if((szInterface->getHandlerPropertyFunc = (GetHandlerPropertyFunc)sevenzLib->resolve("GetHandlerProperty")) == 0)
qDebug() << "fail loading function : GetHandlerProperty" << endl;
if((szInterface->getHandlerPropertyFunc2 = (GetHandlerPropertyFunc2)sevenzLib->resolve("GetHandlerProperty2")) == 0)
qDebug() << "fail loading function : GetHandlerProperty2" << endl;
if((szInterface->setLargePageModeFunc = (SetLargePageModeFunc)sevenzLib->resolve("SetLargePageMode")) == 0)
qDebug() << "fail loading function : SetLargePageMode" << endl;
if((szInterface->createObjectFunc = (CreateObjectFunc)sevenzLib->resolve("CreateObject")) == 0)
qDebug() << "fail loading function : CreateObject" << endl;
if((szInterface->getMethodPropertyFunc = (GetMethodPropertyFunc)sevenzLib->resolve("GetMethodProperty")) == 0)
qDebug() << "fail loading function : GetMethodProperty" << endl;
if((szInterface->getNumberOfMethodsFunc = (GetNumberOfMethodsFunc)sevenzLib->resolve("GetNumberOfMethods")) == 0)
qDebug() << "fail loading function : GetNumberOfMethods" << endl;
if((szInterface->getNumberOfFormatsFunc = (GetNumberOfFormatsFunc)sevenzLib->resolve("GetNumberOfFormats")) == 0)
qDebug() << "fail loading function : GetNumberOfFormats" << endl;
if((szInterface->getHandlerPropertyFunc = (GetHandlerPropertyFunc)sevenzLib->resolve("GetHandlerProperty")) == 0)
qDebug() << "fail loading function : GetHandlerProperty" << endl;
if((szInterface->getHandlerPropertyFunc2 = (GetHandlerPropertyFunc2)sevenzLib->resolve("GetHandlerProperty2")) == 0)
qDebug() << "fail loading function : GetHandlerProperty2" << endl;
if((szInterface->setLargePageModeFunc = (SetLargePageModeFunc)sevenzLib->resolve("SetLargePageMode")) == 0)
qDebug() << "fail loading function : SetLargePageMode" << endl;
#ifdef Q_OS_UNIX
if((szInterface->createObjectFuncRar = (CreateObjectFunc)rarLib->resolve("CreateObject")) == 0)
@ -266,95 +363,127 @@ bool CompressedArchive::loadFunctions()
if((szInterface->getNumberOfMethodsFuncRar = (GetNumberOfMethodsFunc)rarLib->resolve("GetNumberOfMethods")) == 0)
qDebug() << "fail loading function (rar) : GetNumberOfMethods" << endl;
#endif
}
}
return true;
return true;
}
void CompressedArchive::setupFilesNames()
{
quint32 numItems = getNumEntries();
quint32 p = 0;
for (quint32 i = 0; i < numItems; i++)
{
// Get name of file
NWindows::NCOM::CPropVariant prop;
szInterface->archive->GetProperty(i, kpidIsDir, &prop);
bool isDir;
if (prop.vt == VT_BOOL)
isDir = VARIANT_BOOLToBool(prop.boolVal);
else if (prop.vt == VT_EMPTY)
isDir = false;
if(!isDir)
{
szInterface->archive->GetProperty(i, kpidPath, &prop);
UString s = ConvertPropVariantToString(prop);
const wchar_t * chars = s.operator const wchar_t *();
files.append(QString::fromWCharArray(chars));
offsets.append(i);
indexesToPages.insert(i,p);
p++;
}
}
}
QVector<quint32> CompressedArchive::translateIndexes(const QVector<quint32> & indexes)
{
QVector<quint32> translatedIndexes;
foreach(quint32 i, indexes)
{
if(i < offsets.length())
translatedIndexes.append(offsets.at(i));
}
return translatedIndexes;
}
QList<QString> CompressedArchive::getFileNames()
{
QList<QString> files;
quint32 numItems = getNumFiles();
for (quint32 i = 0; i < numItems; i++)
{
{
// Get name of file
NWindows::NCOM::CPropVariant prop;
/*szInterface->archive->GetProperty(i, kpidIsDir, &prop);
bool isDir;
if (prop.vt == VT_BOOL)
isDir = VARIANT_BOOLToBool(prop.boolVal);
else if (prop.vt == VT_EMPTY)
isDir = false;
if(!isDir)
{*/
szInterface->archive->GetProperty(i, kpidPath, &prop);
UString s = ConvertPropVariantToString(prop);
const wchar_t * chars = s.operator const wchar_t *();
files.append(QString::fromWCharArray(chars));
//}
}
}
return files;
return files;
}
bool CompressedArchive::isValid()
{
return valid;
return valid;
}
bool CompressedArchive::toolsLoaded()
{
return tools;
return tools;
}
int CompressedArchive::getNumFiles()
{
quint32 numItems = 0;
szInterface->archive->GetNumberOfItems(&numItems);
return numItems;
return files.length();
}
int CompressedArchive::getNumEntries()
{
quint32 numItems = 0;
szInterface->archive->GetNumberOfItems(&numItems);
return numItems;
}
QList<QByteArray> CompressedArchive::getAllData(const QVector<quint32> & indexes, ExtractDelegate * delegate)
{
CArchiveExtractCallback *extractCallbackSpec = new CArchiveExtractCallback(true,delegate);
CMyComPtr<IArchiveExtractCallback> extractCallback(extractCallbackSpec);
extractCallbackSpec->Init(szInterface->archive, L""); // second parameter is output folder path
extractCallbackSpec->PasswordIsDefined = false;
CArchiveExtractCallback *extractCallbackSpec = new CArchiveExtractCallback(indexesToPages, true, delegate);
CMyComPtr<IArchiveExtractCallback> extractCallback(extractCallbackSpec);
extractCallbackSpec->Init(szInterface->archive, L""); // second parameter is output folder path
extractCallbackSpec->PasswordIsDefined = false;
HRESULT result;
if(indexes.isEmpty())
result = szInterface->archive->Extract(NULL, -1, false, extractCallback);
else
result = szInterface->archive->Extract(indexes.data(), indexes.count(), false, extractCallback);
if (result != S_OK)
{
qDebug() << "Extract Error" << endl;
}
QVector<quint32> currentIndexes = translateIndexes(indexes);
return extractCallbackSpec->allFiles;
HRESULT result;
if(indexes.isEmpty())
result = szInterface->archive->Extract(NULL, -1, false, extractCallback);
else
result = szInterface->archive->Extract(currentIndexes.data(), currentIndexes.count(), false, extractCallback);
if (result != S_OK)
{
qDebug() << "Extract Error" << endl;
}
return extractCallbackSpec->allFiles;
}
QByteArray CompressedArchive::getRawDataAtIndex(int index)
{
if(index>=0 && index < getNumFiles())
{
CArchiveExtractCallback *extractCallbackSpec = new CArchiveExtractCallback;
CMyComPtr<IArchiveExtractCallback> extractCallback(extractCallbackSpec);
extractCallbackSpec->Init(szInterface->archive, L""); // second parameter is output folder path
extractCallbackSpec->PasswordIsDefined = false;
if(index>=0 && index < getNumFiles())
{
CArchiveExtractCallback *extractCallbackSpec = new CArchiveExtractCallback(indexesToPages);
CMyComPtr<IArchiveExtractCallback> extractCallback(extractCallbackSpec);
extractCallbackSpec->Init(szInterface->archive, L""); // second parameter is output folder path
extractCallbackSpec->PasswordIsDefined = false;
UInt32 indices[1];
indices[0] = index;
HRESULT result = szInterface->archive->Extract(indices, 1, false, extractCallback);
if (result != S_OK)
{
qDebug() << "Extract Error" << endl;
}
UInt32 indices[1];
return QByteArray((char *)extractCallbackSpec->data,extractCallbackSpec->newFileSize);
}
if(index < offsets.length())
indices[0] = offsets.at(index);
else
indices[0] = index;
HRESULT result = szInterface->archive->Extract(indices, 1, false, extractCallback);
if (result != S_OK)
{
qDebug() << "Extract Error" << endl;
}
return QByteArray((char *)extractCallbackSpec->data,extractCallbackSpec->newFileSize);
}
return QByteArray();
}
@ -384,5 +513,3 @@ STDMETHODIMP CompressedArchive::CreateEncoder(UInt32 index, const GUID *interfac
}
#endif

View File

@ -28,6 +28,7 @@ typedef quint32 (_MY_WINAPI *SetLargePageModeFunc)();
class QLibrary;
#include <QString>
#include <QList>
#include <QMap>
struct SevenZipInterface;
@ -59,6 +60,7 @@ signals:
public slots:
int getNumFiles();
int getNumEntries();
QList<QByteArray> getAllData(const QVector<quint32> & indexes, ExtractDelegate * delegate = 0);
QByteArray getRawDataAtIndex(int index);
QList<QString> getFileNames();
@ -66,6 +68,7 @@ public slots:
bool toolsLoaded();
private:
SevenZipInterface * szInterface;
QLibrary * sevenzLib;
#ifdef Q_OS_UNIX
QLibrary * rarLib;
@ -73,6 +76,12 @@ private:
bool loadFunctions();
bool tools;
bool valid;
QList<QString> files;
QList<qint32> offsets;
QMap<qint32, qint32> indexesToPages;
void setupFilesNames();
QVector<quint32> translateIndexes(const QVector<quint32> &indexes);
friend class MyCodecs;
};

View File

@ -90,8 +90,9 @@ public:
UString Password;
Byte * data;
UInt64 newFileSize;
QMap<qint32, qint32> indexesToPages;
CArchiveExtractCallback(bool c = false,ExtractDelegate * d = 0) : PasswordIsDefined(false),all(c),delegate(d) {}
CArchiveExtractCallback(const QMap<qint32, qint32> & indexesToPages ,bool c = false,ExtractDelegate * d = 0) : PasswordIsDefined(false),all(c),delegate(d),indexesToPages(indexesToPages) {}
~CArchiveExtractCallback() {MidFree(data);}
};
@ -117,7 +118,11 @@ STDMETHODIMP CArchiveExtractCallback::GetStream(UInt32 index,
{
*outStream = 0;
_outFileStream.Release();
_index = index;
if(indexesToPages.isEmpty())
_index = index;
else
_index = indexesToPages.value(index);
{
// Get Name

View File

@ -0,0 +1,6 @@
To use unarr as a decompression engine when building YACReader, download https://github.com/zeniko/unarr/archive/master.zip and extract it in this folder.
This will build unarr as a part of YACReader (static build).
If you're on a Linux/Unix system and prefer to use unarr as a shared library, have a look at https://github.com/selmf/unarr/
This fork of unarr includes a CMake based build system that allows you to build and install unarr as a shared library. YACReader will detect and use
the installed library at build time if it is installed.

View File

@ -0,0 +1,127 @@
#include "compressed_archive.h"
#include <QFileInfo>
#include <QDebug>
#include "extract_delegate.h"
extern"C" {
#include "unarr.h"
}
CompressedArchive::CompressedArchive(const QString & filePath, QObject *parent) :
QObject(parent),valid(false),tools(true),numFiles(0),ar(NULL),stream(NULL)
{
//open file
stream = ar_open_file(filePath.toStdString().c_str());
if (!stream)
{
return;
}
//open archive
ar = ar_open_rar_archive(stream);
//TODO: build unarr with 7z support and test this!
//if (!ar) ar = ar_open_7z_archive(stream);
if (!ar) ar = ar_open_tar_archive(stream);
//zip detection is costly, so it comes last...
if (!ar) ar = ar_open_zip_archive(stream, false);
if (!ar)
{
return;
}
//initial parse
while (ar_parse_entry(ar))
{
//make sure we really got a file header
if (ar_entry_get_size(ar) > 0)
{
fileNames.append(ar_entry_get_name(ar));
offsets.append(ar_entry_get_offset(ar));
numFiles++;
}
}
if (!ar_at_eof(ar))
{
//fail if the initial parse didn't reach EOF
//this might be a bit too drastic
qDebug() << "Error while parsing archive";
return;
}
if (numFiles > 0)
{
valid = true;
}
}
CompressedArchive::~CompressedArchive()
{
ar_close_archive(ar);
ar_close(stream);
}
QList<QString> CompressedArchive::getFileNames()
{
return fileNames;
}
bool CompressedArchive::isValid()
{
return valid;
}
bool CompressedArchive::toolsLoaded()
{
//for backwards compatibilty
return tools;
}
int CompressedArchive::getNumFiles()
{
return numFiles;
}
void CompressedArchive::getAllData(const QVector<quint32> & indexes, ExtractDelegate * delegate)
{
if (indexes.isEmpty())
return;
QByteArray buffer;
int i=0;
while (i < indexes.count())
{
//use the offset list so we generated so we're not getting any non-page files
ar_parse_entry_at(ar, offsets.at(indexes.at(i))); //set ar_entry to start of indexes
buffer.resize(ar_entry_get_size(ar));
if (ar_entry_uncompress(ar, buffer.data(), buffer.size())) //did we extract it?
{
delegate->fileExtracted(indexes.at(i), buffer); //return extracted file
}
else
{
delegate->crcError(indexes.at(i)); //we could not extract it...
}
i++;
}
}
QByteArray CompressedArchive::getRawDataAtIndex(int index)
{
QByteArray buffer;
if(index >= 0 && index < getNumFiles())
{
ar_parse_entry_at(ar, offsets.at(index));
buffer.resize(ar_entry_get_size(ar));
if(ar_entry_uncompress(ar, buffer.data(), buffer.size()))
{
return buffer;
}
else
{
return QByteArray();
}
}
return buffer;
}

View File

@ -0,0 +1,37 @@
#ifndef COMPRESSED_ARCHIVE_H
#define COMPRESSED_ARCHIVE_H
#include <QObject>
#include "extract_delegate.h"
extern"C" {
#include "unarr.h"
}
class CompressedArchive : public QObject
{
Q_OBJECT
public:
explicit CompressedArchive(const QString & filePath, QObject *parent = 0);
~CompressedArchive();
signals:
public slots:
int getNumFiles();
void getAllData(const QVector<quint32> & indexes, ExtractDelegate * delegate=0);
QByteArray getRawDataAtIndex(int index);
QList<QString> getFileNames();
bool isValid();
bool toolsLoaded();
private:
bool tools;
bool valid;
QList<QString> fileNames;
int numFiles;
ar_archive *ar;
ar_stream *stream;
QList<qint64> offsets;
};
#endif // COMPRESSED_ARCHIVE_H

View File

@ -0,0 +1,14 @@
#ifndef EXTRACT_DELEGATE_H
#define EXTRACT_DELEGATE_H
#include <QByteArray>
class ExtractDelegate
{
public:
virtual void fileExtracted(int index, const QByteArray & rawData) = 0;
virtual void crcError(int index) = 0;
virtual void unknownError(int index) = 0;
};
#endif //EXTRACT_DELEGATE_H

View File

@ -0,0 +1,36 @@
INCLUDEPATH += $$PWD
DEPENDPATH += $$PWD
HEADERS += $$PWD/extract_delegate.h \
$$PWD/compressed_archive.h \
SOURCES += $$PWD/compressed_archive.cpp \
unix:!macx:exists (/usr/include/unarr.h) {
message(Using system provided unarr installation)
LIBS+=-lunarr
DEFINES+=use_unarr
}
else:macx:exists (../../dependencies/unarr/libunarr.dynlib) {
LIBS += -L../../dependencies/unarr/ -lunarr
DEFINES+=use_unarr
}
else:win32:exists (../../dependencies/unarr/unarr.dll) {
LIBS += -L../../dependencies/unarr/ -lunarr
DEFINES+=use_unarr
}
else:exists ($$PWD/unarr-master) {
message(Found unarr source-code)
message(Unarr will be build as a part of YACReader)
#qmake based unarr build system
#this should only be used for testing or as a last resort
include(unarr.pro)
DEFINES+=use_unarr
}
else {
error(Missing dependency: unarr decrompression backend. Please install libunarr on your system\
or provide a copy of the unarr source code in compressed_archive/unarr/unarr-master)
}

View File

@ -0,0 +1,51 @@
INCLUDEPATH += $$PWD/unarr-master/
DEPENDPATH += $$PWD/unarr-master/
HEADERS+=$$PWD/unarr-master/common/allocator.h\
$$PWD/unarr-master/common/unarr-imp.h\
$$PWD/unarr-master/lzmasdk/CpuArch.h\
$$PWD/unarr-master/lzmasdk/Ppmd7.h\
$$PWD/unarr-master/lzmasdk/Ppmd.h\
$$PWD/unarr-master/lzmasdk/LzmaDec.h\
$$PWD/unarr-master/lzmasdk/Ppmd8.h\
$$PWD/unarr-master/lzmasdk/Types.h\
$$PWD/unarr-master/lzmasdk/CpuArch.h\
$$PWD/unarr-master/lzmasdk/Ppmd7.h\
$$PWD/unarr-master/lzmasdk/Ppmd.h\
$$PWD/unarr-master/lzmasdk/LzmaDec.h\
$$PWD/unarr-master/lzmasdk/Ppmd8.h\
$$PWD/unarr-master/lzmasdk/Types.h\
$$PWD/unarr-master/lzmasdk/CpuArch.h\
$$PWD/unarr-master/lzmasdk/Ppmd7.h\
$$PWD/unarr-master/lzmasdk/Ppmd.h\
$$PWD/unarr-master/lzmasdk/LzmaDec.h\
$$PWD/unarr-master/lzmasdk/Ppmd8.h\
$$PWD/unarr-master/lzmasdk/Types.h\
$$PWD/unarr-master/tar/tar.h\
$$PWD/unarr-master/_7z/_7z.h\
$$PWD/unarr-master/unarr.h
SOURCES+=$$PWD/unarr-master/common/conv.c\
$$PWD/unarr-master/common/custalloc.c\
$$PWD/unarr-master/common/unarr.c\
$$PWD/unarr-master/common/crc32.c\
$$PWD/unarr-master/common/stream.c\
$$PWD/unarr-master/lzmasdk/CpuArch.c\
$$PWD/unarr-master/lzmasdk/Ppmd7.c\
$$PWD/unarr-master/lzmasdk/Ppmd8.c\
$$PWD/unarr-master/lzmasdk/LzmaDec.c\
$$PWD/unarr-master/lzmasdk/Ppmd7Dec.c\
$$PWD/unarr-master/lzmasdk/Ppmd8Dec.c\
$$PWD/unarr-master/zip/inflate.c\
$$PWD/unarr-master/zip/parse-zip.c\
$$PWD/unarr-master/zip/uncompress-zip.c\
$$PWD/unarr-master/zip/zip.c\
$$PWD/unarr-master/rar/filter-rar.c\
$$PWD/unarr-master/rar/parse-rar.c\
$$PWD/unarr-master/rar/rarvm.c\
$$PWD/unarr-master/rar/huffman-rar.c\
$$PWD/unarr-master/rar/rar.c\
$$PWD/unarr-master/rar/uncompress-rar.c\
$$PWD/unarr-master/tar/parse-tar.c\
$$PWD/unarr-master/tar/tar.c\
$$PWD/unarr-master/_7z/_7z.c

View File

@ -1,6 +1,23 @@
INCLUDEPATH += $$PWD
DEPENDPATH += $$PWD
win32 {
!exists (../compressed_archive/lib7zip) {
error(You\'ll need 7zip source code to compile YACReader. \
Please check the compressed_archive folder for further instructions.)
}
}
unix {
exists (../compressed_archive/libp7zip) {
message(Found p7zip source code...)
system(patch -N -p0 -i libp7zip.patch)
} else {
error(You\'ll need 7zip source code to compile YACReader. \
Please check the compressed_archive folder for further instructions.)
}
}
CONFIG += precompile_header
win32 {PRECOMPILED_HEADER = $$PWD/StdAfx.h}

40
config.pri Normal file
View File

@ -0,0 +1,40 @@
#functions to automatically initialize some of YACReader's build options to
#default values if they're not set on build time
#for a more detailed description, see INSTALL.TXT
#check Qt version
QT_VERSION = $$[QT_VERSION]
QT_VERSION = $$split(QT_VERSION, ".")
QT_VER_MAJ = $$member(QT_VERSION, 0)
QT_VER_MIN = $$member(QT_VERSION, 1)
lessThan(QT_VER_MAJ, 5) {
error(YACReader requires Qt 5 or newer but Qt $$[QT_VERSION] was detected.)
}
lessThan(QT_VER_MIN, 4):!CONFIG(no_opengl) {
CONFIG += legacy_gl_widget
message ("Qt < 5.4 detected. Using QGLWidget for coverflow.")
}
lessThan(QT_VER_MIN, 3){
error ("You need at least Qt 5.3 to build YACReader or YACReaderLibrary")
}
#build without opengl widget support
CONFIG(no_opengl) {
DEFINES += NO_OPENGL
}
!CONFIG(unarr):!CONFIG(7zip) {
unix {
!macx {
CONFIG+=unarr
}
else {
CONFIG+=7zip
}
}
win32 {
CONFIG+=7zip
}
}

View File

@ -175,7 +175,7 @@ YACReaderMacOSXToolbar::YACReaderMacOSXToolbar(QObject *parent)
{
yosemite = true;
//TODO yosemite new constants are not found in compilation time
[nswindow setTitleVisibility:1]; //NSWindowTitleHidden
[nswindow setTitleVisibility:NSWindowTitleHidden];
//TODO NSFullSizeContentViewWindowMask produces an offset in the windows' content
//nswindow.styleMask |= 1 << 15; // NSFullSizeContentViewWindowMask;
[nativeToolBar setSizeMode:NSToolbarSizeModeSmall]; //TODO figure out how to load specific images in Yosemite
@ -215,7 +215,7 @@ void YACReaderMacOSXToolbar::addSpace(int size)
QMacToolBarItem *toolBarItem = addItem(QIcon(),"");
NSToolbarItem * nativeItem = toolBarItem->nativeToolBarItem();
static const NSRect frameRect = { { 0.0, 0.0 }, { size, 16.0 } };
static const NSRect frameRect = { { 0.0, 0.0 }, { CGFloat(size), 16.0 } };
NSView *view = [[NSView alloc] initWithFrame:frameRect];
[nativeItem setView:view];

View File

@ -46,6 +46,9 @@ YACReaderOptionsDialog::YACReaderOptionsDialog(QWidget * parent)
#ifndef NO_OPENGL
useGL = new QCheckBox(tr("Use hardware acceleration (restart needed)"));
connect(useGL,SIGNAL(stateChanged(int)),this,SLOT(saveUseGL(int)));
#endif
#ifdef FORCE_ANGLE
useGL->setHidden(true);
#endif
//sw CONNECTIONS
connect(sw->radio1,SIGNAL(toggled(bool)),this,SLOT(setClassicConfigSW()));

View File

@ -85,9 +85,9 @@ YACReaderTitledToolBar::YACReaderTitledToolBar(const QString & title, QWidget *p
setLayout(mainLayout);
setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Minimum);
setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Minimum);
setMinimumHeight(25);
setMinimumHeight(25);
}
@ -97,9 +97,9 @@ void YACReaderTitledToolBar::addAction(QAction * action)
QToolButton * tb = new QToolButton(this);
tb->setCursor(QCursor(Qt::ArrowCursor));
tb->setDefaultAction(action);
tb->setIconSize(QSize(16,16));
tb->setSizePolicy(QSizePolicy::Minimum,QSizePolicy::Minimum);
tb->setDefaultAction(action);
tb->setIconSize(QSize(16,16));
tb->setSizePolicy(QSizePolicy::Minimum,QSizePolicy::Minimum);
//tb->setStyleSheet("QToolButton:hover {background-color:#C5C5C5;}");
mainLayout->addWidget(tb);

View File

@ -4,10 +4,10 @@
#include <QWidget>
#include <QHBoxLayout>
class QToolBarStretch : public QWidget
class YACReaderToolBarStretch : public QWidget
{
public:
QToolBarStretch(QWidget * parent=0):QWidget(parent)
YACReaderToolBarStretch(QWidget * parent=0):QWidget(parent)
{
QHBoxLayout * l= new QHBoxLayout();
l->addStretch();

View File

@ -2,7 +2,7 @@
#Script to create a source tarball for YACReader distribution and packaging
#This should be run from YACReaders top source directory
YACVERSION=7.2.0
YACVERSION=8.0
if [ -f Makefile ]
then
make distclean
@ -17,6 +17,6 @@ fi
#Use tar's --exclude feature to make sure we get a pristine tar for distribution.
#Exclude all version control system related files and rename the top directory in the tarball using --transform.
tar cfJ yacreader-${YACVERSION}-src.tar.xz --exclude '*.rej' --exclude '*.orig' --exclude '*.gch' --exclude 'dependencies' --exclude '*.o' \
--exclude 'yacreader*tar*' --exclude '.hg*' --exclude 'lib7zip' --exclude 'libp7zip' --exclude-vcs ./* --transform s/./yacreader-${YACVERSION}/
--exclude 'yacreader*tar*' --exclude '.hg*' --exclude 'lib7zip' --exclude 'libp7zip' --exclude 'unarr-master' --exclude-vcs ./* --transform s/./yacreader-${YACVERSION}/
#Calculate checksum to enable packagers to verify whether they are using the original tarball.
md5sum yacreader-${YACVERSION}-src.tar.xz > yacreader-${YACVERSION}-src.tar.xz.md5sum

View File

@ -5,7 +5,7 @@ body{
/* libraries */
#contentLibraries{
width: 300px;
width: 400px;
border: 1px solid #C6C6C6;
background-color: white;
margin-left: auto;
@ -36,7 +36,7 @@ body{
#contentLibraries .library-link
{
width: 211px;
width: 311px;
height: 28px;
border: none;
padding: 11px 0 0 0px;
@ -47,6 +47,7 @@ body{
font-size: 16px;
text-decoration: none;
color: #525252 ;
overflow: hidden;
}
#contentLibraries a

View File

@ -5,11 +5,10 @@ body{
/* libraries */
#contentLibraries{
width: 300px;
border: 1px solid #C6C6C6;
background-color: white;
margin-left: auto;
margin-right: auto;
margin-left: 20px;
margin-right: 20px;
margin-top: 9px;
}
@ -36,7 +35,7 @@ body{
#contentLibraries .library-link
{
width: 211px;
width: 65%;
height: 28px;
border: none;
padding: 11px 0 0 0px;
@ -47,6 +46,7 @@ body{
font-size: 16px;
text-decoration: none;
color: #525252 ;
overflow: hidden;
}
#contentLibraries a
@ -62,7 +62,7 @@ body{
#contentLibraries .library-indicator
{
float: left;
float: right;
background-color: white;
height: 8px;
padding: 16px 16px 15px 16px;
@ -181,10 +181,10 @@ body{
#itemContainer li
{
width: 300px;
height: 120px;
border: 1px solid #E2E2E2;
margin: 9px auto 0px auto;
margin: 9px 10px 0px 10px;
background-color: white;
overflow: hidden;
position: relative;
@ -218,22 +218,22 @@ overflow: hidden;
.info
{
padding: 8px 0px 0px 0px;
float: left;
position: relative;
height: 115px;
width: 212px;
padding-left: 82px;
}
.buttons
{
position:absolute;
bottom:0px;
left:0px;
left:80px;
right: 0px;
border-top: 1px solid #e2e2e2;
padding-top: 3px;
height: 25px;
width: 220px;
font-family: Arial;
color: #6e6e6e;
font-size: 10px;
@ -245,7 +245,7 @@ width: 212px;
bottom:24px;
padding-top: 3px;
height: 25px;
width: 220px;
width: 100%;
font-family: Arial;
color: #adadad;
font-size: 10px;

View File

@ -1,7 +1,7 @@
#!/bin/bash
/Users/luisangel/Qt/5.4/clang_64/bin/macdeployqt YACReader.app
/Users/luisangel/Qt/5.4/clang_64/bin/macdeployqt YACReaderLibrary.app -qmldir=./YACReaderLibrary/qml
/Users/luisangel/my_dev/Qt5.5.0/5.5/clang_64/bin/macdeployqt YACReader.app
/Users/luisangel/my_dev/Qt5.5.0/5.5/clang_64/bin/macdeployqt YACReaderLibrary.app -qmldir=./YACReaderLibrary/qml
#macdeployqt YACReader.app
#macdeployqt YACReaderLibrary.app

View File

@ -0,0 +1,23 @@
TEMPLATE = app
CONFIG += console
SOURCES += \
main.cpp \
QT += core
win32 {
LIBS += -loleaut32 -lole32
QMAKE_CXXFLAGS_RELEASE += /MP /Ob2 /Oi /Ot /GT
QMAKE_LFLAGS_RELEASE += /LTCG
CONFIG -= embed_manifest_exe
}
!CONFIG(unarr){
include(../../compressed_archive/wrapper.pri)
} else {
include(../../compressed_archive/unarr/unarr-wrapper.pri)
}

View File

@ -0,0 +1,86 @@
#include <QtCore/QCoreApplication>
#include <QDir>
#include <QElapsedTimer>
#include "compressed_archive.h"
#include <iostream>
using namespace std;
//This program uses PROTOS Genome Test Suite c10-archive [0] for testing the CompressedArchive wrapper files support
//It tests the following formats: RAR, ZIP, TAR
//Arter downloading c10-archive-r1.iso, open it and full extract RAR_TAR.BZ2, ZIP_TAR.BZ2, TAR_TAR.BZ2 files into a folder
//This program takes the path to that folder as an argument
//
// [0] https://www.ee.oulu.fi/research/ouspg/PROTOS_Test-Suite_c10-archive#Download
//
int main(int argc, char *argv[])
{
if(argc < 2)
{
cout << "Usage: compressed_archive_test PATH" << endl;
return 0;
}
//QCoreApplication app(argc, argv);
QString s(argv[1]);
QStringList supportedFormats;
supportedFormats << "rar"<< "zip" << "tar";
QElapsedTimer timer;
timer.start();
quint32 totalFiles = 0;
foreach (QString format, supportedFormats) {
QDir rootDir(s);
if(!rootDir.cd(format))
{
cout << "Folder for format '" << format.toStdString() << "' not found" << endl;
continue;
}
rootDir.setFilter(QDir::Files | QDir::NoDotAndDotDot);
QFileInfoList files = rootDir.entryInfoList();
quint32 totalFormat = 0;
quint32 errors = 0;
quint64 init = timer.elapsed();
foreach(QFileInfo fileInfo, files)
{
totalFiles++;
totalFormat++;
CompressedArchive archive(fileInfo.filePath());
if(!archive.isValid())
errors++;
else
{
int i = archive.getNumFiles();
cerr << i;
QList<QString> filenames = archive.getFileNames();
if (!filenames.isEmpty())
{
cerr << archive.getFileNames().at(0).toStdString();
}
}
}
quint64 end = timer.elapsed();
cout << "Format '" << format.toStdString() <<"'" << endl;
cout << "Total files : " << totalFormat << endl;
cout << "Errors : " << errors << endl;
cout << "Elapsed time : " << (end - init) / 1000 <<"s" << endl;
cout << endl;
}
cout << endl;
cout << "Total time : " << timer.elapsed() / 1000 <<"s" <<endl;
cout << endl;
//return app.exec();
}