mirror of
https://github.com/YACReader/yacreader
synced 2025-05-27 10:50:27 -04:00
Merge
This commit is contained in:
commit
b41884d5db
@ -1683,6 +1683,7 @@ void MainWindowViewer::sendComic()
|
||||
{
|
||||
YACReaderLocalClient * client = new YACReaderLocalClient;
|
||||
currentComicDB.info.hasBeenOpened = true;
|
||||
currentComicDB.info.lastTimeOpened = QDateTime::currentSecsSinceEpoch();
|
||||
viewer->updateComic(currentComicDB);
|
||||
int retries = 1;
|
||||
while(!client->sendComicInfo(libraryId,currentComicDB) && retries!=0)
|
||||
|
@ -1,317 +1,319 @@
|
||||
TEMPLATE = app
|
||||
TARGET = YACReaderLibrary
|
||||
|
||||
QMAKE_TARGET_BUNDLE_PREFIX = "com.yacreader"
|
||||
|
||||
DEPENDPATH += .
|
||||
INCLUDEPATH += . \
|
||||
../common \
|
||||
./server \
|
||||
./db \
|
||||
../custom_widgets \
|
||||
./comic_vine \
|
||||
./comic_vine/model
|
||||
|
||||
DEFINES += SERVER_RELEASE NOMINMAX YACREADER_LIBRARY
|
||||
QMAKE_MAC_SDK = macosx10.12
|
||||
|
||||
# load default build flags
|
||||
include (../config.pri)
|
||||
include (../dependencies/pdf_backend.pri)
|
||||
|
||||
unix:haiku {
|
||||
DEFINES += _BSD_SOURCE
|
||||
LIBS += -lnetwork -lbsd
|
||||
}
|
||||
|
||||
INCLUDEPATH += ../common/gl
|
||||
|
||||
# there are two builds for Windows, Desktop OpenGL based and ANGLE OpenGL ES based
|
||||
win32 {
|
||||
CONFIG(force_angle) {
|
||||
message("using ANGLE")
|
||||
LIBS += -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 += -loleaut32 -lole32 -lshell32 -lopengl32 -lglu32 -luser32
|
||||
}
|
||||
|
||||
QMAKE_CXXFLAGS_RELEASE += /MP /Ob2 /Oi /Ot /GT /GL
|
||||
QMAKE_LFLAGS_RELEASE += /LTCG
|
||||
CONFIG -= embed_manifest_exe
|
||||
}
|
||||
|
||||
CONFIG(force_angle) {
|
||||
contains(QMAKE_TARGET.arch, x86_64) {
|
||||
Release:DESTDIR = ../release64_angle
|
||||
Debug:DESTDIR = ../debug64_angle
|
||||
} else {
|
||||
Release:DESTDIR = ../release_angle
|
||||
Debug:DESTDIR = ../debug_angle
|
||||
}
|
||||
} else {
|
||||
contains(QMAKE_TARGET.arch, x86_64) {
|
||||
Release:DESTDIR = ../release64
|
||||
Debug:DESTDIR = ../debug64
|
||||
} else {
|
||||
Release:DESTDIR = ../release
|
||||
Debug:DESTDIR = ../debug
|
||||
}
|
||||
}
|
||||
|
||||
unix:!macx:!CONFIG(no_opengl) {
|
||||
LIBS += -lGLU
|
||||
}
|
||||
|
||||
macx {
|
||||
LIBS += -framework Foundation -framework ApplicationServices -framework AppKit
|
||||
CONFIG += objective_c
|
||||
QT += macextras gui-private
|
||||
}
|
||||
|
||||
unix:!macx {
|
||||
CONFIG += c++11
|
||||
}
|
||||
|
||||
#CONFIG += release
|
||||
CONFIG -= flat
|
||||
QT += sql network widgets script
|
||||
!CONFIG(no_opengl) {
|
||||
QT += opengl
|
||||
}
|
||||
|
||||
# Input
|
||||
HEADERS += comic_flow.h \
|
||||
create_library_dialog.h \
|
||||
library_creator.h \
|
||||
library_window.h \
|
||||
add_library_dialog.h \
|
||||
rename_library_dialog.h \
|
||||
properties_dialog.h \
|
||||
options_dialog.h \
|
||||
export_library_dialog.h \
|
||||
import_library_dialog.h \
|
||||
package_manager.h \
|
||||
bundle_creator.h \
|
||||
export_comics_info_dialog.h \
|
||||
import_comics_info_dialog.h \
|
||||
server_config_dialog.h \
|
||||
comic_flow_widget.h \
|
||||
db_helper.h \
|
||||
./db/data_base_management.h \
|
||||
./db/folder_item.h \
|
||||
./db/folder_model.h \
|
||||
./db/comic_model.h \
|
||||
./db/comic_item.h \
|
||||
../common/comic_db.h \
|
||||
../common/folder.h \
|
||||
../common/library_item.h \
|
||||
../common/comic.h \
|
||||
../common/bookmarks.h \
|
||||
../common/pictureflow.h \
|
||||
../common/custom_widgets.h \
|
||||
../common/qnaturalsorting.h \
|
||||
../common/yacreader_global.h \
|
||||
../common/yacreader_global_gui.h \
|
||||
../common/onstart_flow_selection_dialog.h \
|
||||
../common/pdf_comic.h \
|
||||
no_libraries_widget.h \
|
||||
import_widget.h \
|
||||
yacreader_local_server.h \
|
||||
yacreader_main_toolbar.h \
|
||||
comics_remover.h \
|
||||
../common/http_worker.h \
|
||||
yacreader_libraries.h \
|
||||
../common/exit_check.h \
|
||||
comics_view.h \
|
||||
classic_comics_view.h \
|
||||
empty_folder_widget.h \
|
||||
no_search_results_widget.h \
|
||||
comic_files_manager.h \
|
||||
db/reading_list_model.h \
|
||||
db/reading_list_item.h \
|
||||
yacreader_folders_view.h \
|
||||
yacreader_reading_lists_view.h \
|
||||
add_label_dialog.h \
|
||||
yacreader_history_controller.h \
|
||||
yacreader_navigation_controller.h \
|
||||
empty_label_widget.h \
|
||||
empty_container_info.h \
|
||||
empty_special_list.h \
|
||||
empty_reading_list_widget.h \
|
||||
../common/scroll_management.h \
|
||||
../common/opengl_checker.h \
|
||||
yacreader_comics_views_manager.h \
|
||||
info_comics_view.h \
|
||||
yacreader_comics_selection_helper.h \
|
||||
yacreader_comic_info_helper.h
|
||||
|
||||
!CONFIG(no_opengl) {
|
||||
HEADERS += ../common/gl/yacreader_flow_gl.h
|
||||
}
|
||||
|
||||
SOURCES += comic_flow.cpp \
|
||||
create_library_dialog.cpp \
|
||||
library_creator.cpp \
|
||||
library_window.cpp \
|
||||
main.cpp \
|
||||
add_library_dialog.cpp \
|
||||
rename_library_dialog.cpp \
|
||||
properties_dialog.cpp \
|
||||
options_dialog.cpp \
|
||||
export_library_dialog.cpp \
|
||||
import_library_dialog.cpp \
|
||||
package_manager.cpp \
|
||||
bundle_creator.cpp \
|
||||
export_comics_info_dialog.cpp \
|
||||
import_comics_info_dialog.cpp \
|
||||
server_config_dialog.cpp \
|
||||
comic_flow_widget.cpp \
|
||||
db_helper.cpp \
|
||||
./db/data_base_management.cpp \
|
||||
./db/folder_item.cpp \
|
||||
./db/folder_model.cpp \
|
||||
./db/comic_model.cpp \
|
||||
./db/comic_item.cpp \
|
||||
../common/comic_db.cpp \
|
||||
../common/folder.cpp \
|
||||
../common/library_item.cpp \
|
||||
../common/comic.cpp \
|
||||
../common/bookmarks.cpp \
|
||||
../common/pictureflow.cpp \
|
||||
../common/custom_widgets.cpp \
|
||||
../common/qnaturalsorting.cpp \
|
||||
../common/onstart_flow_selection_dialog.cpp \
|
||||
no_libraries_widget.cpp \
|
||||
import_widget.cpp \
|
||||
yacreader_local_server.cpp \
|
||||
yacreader_main_toolbar.cpp \
|
||||
comics_remover.cpp \
|
||||
../common/http_worker.cpp \
|
||||
../common/yacreader_global.cpp \
|
||||
../common/yacreader_global_gui.cpp \
|
||||
yacreader_libraries.cpp \
|
||||
../common/exit_check.cpp \
|
||||
comics_view.cpp \
|
||||
classic_comics_view.cpp \
|
||||
empty_folder_widget.cpp \
|
||||
no_search_results_widget.cpp \
|
||||
comic_files_manager.cpp \
|
||||
db/reading_list_model.cpp \
|
||||
db/reading_list_item.cpp \
|
||||
yacreader_folders_view.cpp \
|
||||
yacreader_reading_lists_view.cpp \
|
||||
add_label_dialog.cpp \
|
||||
yacreader_history_controller.cpp \
|
||||
yacreader_navigation_controller.cpp \
|
||||
empty_label_widget.cpp \
|
||||
empty_container_info.cpp \
|
||||
empty_special_list.cpp \
|
||||
empty_reading_list_widget.cpp \
|
||||
../common/scroll_management.cpp \
|
||||
../common/opengl_checker.cpp \
|
||||
yacreader_comics_views_manager.cpp \
|
||||
info_comics_view.cpp \
|
||||
yacreader_comics_selection_helper.cpp \
|
||||
yacreader_comic_info_helper.cpp
|
||||
|
||||
!CONFIG(no_opengl) {
|
||||
SOURCES += ../common/gl/yacreader_flow_gl.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)
|
||||
|
||||
RESOURCES += images.qrc files.qrc
|
||||
win32:RESOURCES += images_win.qrc
|
||||
unix:!macx:RESOURCES += images_win.qrc
|
||||
macx:RESOURCES += images_osx.qrc
|
||||
|
||||
RC_FILE = icon.rc
|
||||
|
||||
macx {
|
||||
ICON = YACReaderLibrary.icns
|
||||
}
|
||||
|
||||
TRANSLATIONS = yacreaderlibrary_es.ts \
|
||||
yacreaderlibrary_ru.ts \
|
||||
yacreaderlibrary_pt.ts \
|
||||
yacreaderlibrary_fr.ts \
|
||||
yacreaderlibrary_nl.ts \
|
||||
yacreaderlibrary_tr.ts \
|
||||
yacreaderlibrary_de.ts \
|
||||
yacreaderlibrary_source.ts
|
||||
|
||||
#QML/GridView
|
||||
QT += quick qml
|
||||
|
||||
HEADERS += grid_comics_view.h \
|
||||
comics_view_transition.h
|
||||
|
||||
SOURCES += grid_comics_view.cpp \
|
||||
comics_view_transition.cpp
|
||||
|
||||
RESOURCES += qml.qrc
|
||||
win32:RESOURCES += qml_win.qrc
|
||||
unix:!macx:RESOURCES += qml_win.qrc
|
||||
macx:RESOURCES += qml_osx.qrc
|
||||
|
||||
unix:!macx {
|
||||
#set install prefix if it's empty
|
||||
isEmpty(PREFIX) {
|
||||
PREFIX = /usr
|
||||
}
|
||||
isEmpty(BINDIR) {
|
||||
BINDIR = $$PREFIX/bin
|
||||
}
|
||||
isEmpty(LIBDIR) {
|
||||
LIBDIR = $$PREFIX/lib
|
||||
}
|
||||
isEmpty(DATADIR) {
|
||||
DATADIR = $$PREFIX/share
|
||||
}
|
||||
|
||||
DEFINES += "LIBDIR=\\\"$$LIBDIR\\\"" "DATADIR=\\\"$$DATADIR\\\""
|
||||
|
||||
DEFINES += "LIBDIR=\\\"$$LIBDIR\\\"" "DATADIR=\\\"$$DATADIR\\\"" "BINDIR=\\\"$$BINDIR\\\""
|
||||
|
||||
#MAKE INSTALL
|
||||
INSTALLS += bin icon desktop server translation manpage
|
||||
|
||||
bin.path = $$BINDIR
|
||||
isEmpty(DESTDIR) {
|
||||
bin.files = YACReaderLibrary
|
||||
} else {
|
||||
bin.files = $$DESTDIR/YACReaderLibrary
|
||||
}
|
||||
|
||||
server.path = $$DATADIR/yacreader
|
||||
server.files = ../release/server
|
||||
|
||||
icon.path = $$DATADIR/icons/hicolor/scalable/apps
|
||||
icon.files = ../YACReaderLibrary.svg
|
||||
|
||||
desktop.path = $$DATADIR/applications
|
||||
desktop.files = ../YACReaderLibrary.desktop
|
||||
|
||||
translation.path = $$DATADIR/yacreader/languages
|
||||
translation.files = ../release/languages/yacreaderlibrary_*
|
||||
|
||||
manpage.path = $$DATADIR/man/man1
|
||||
manpage.files = ../YACReaderLibrary.1
|
||||
}
|
||||
TEMPLATE = app
|
||||
TARGET = YACReaderLibrary
|
||||
|
||||
QMAKE_TARGET_BUNDLE_PREFIX = "com.yacreader"
|
||||
|
||||
DEPENDPATH += .
|
||||
INCLUDEPATH += . \
|
||||
../common \
|
||||
./server \
|
||||
./db \
|
||||
../custom_widgets \
|
||||
./comic_vine \
|
||||
./comic_vine/model
|
||||
|
||||
DEFINES += SERVER_RELEASE NOMINMAX YACREADER_LIBRARY
|
||||
QMAKE_MAC_SDK = macosx10.12
|
||||
|
||||
# load default build flags
|
||||
include (../config.pri)
|
||||
include (../dependencies/pdf_backend.pri)
|
||||
|
||||
unix:haiku {
|
||||
DEFINES += _BSD_SOURCE
|
||||
LIBS += -lnetwork -lbsd
|
||||
}
|
||||
|
||||
INCLUDEPATH += ../common/gl
|
||||
|
||||
# there are two builds for Windows, Desktop OpenGL based and ANGLE OpenGL ES based
|
||||
win32 {
|
||||
CONFIG(force_angle) {
|
||||
message("using ANGLE")
|
||||
LIBS += -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 += -loleaut32 -lole32 -lshell32 -lopengl32 -lglu32 -luser32
|
||||
}
|
||||
|
||||
QMAKE_CXXFLAGS_RELEASE += /MP /Ob2 /Oi /Ot /GT /GL
|
||||
QMAKE_LFLAGS_RELEASE += /LTCG
|
||||
CONFIG -= embed_manifest_exe
|
||||
}
|
||||
|
||||
CONFIG(force_angle) {
|
||||
contains(QMAKE_TARGET.arch, x86_64) {
|
||||
Release:DESTDIR = ../release64_angle
|
||||
Debug:DESTDIR = ../debug64_angle
|
||||
} else {
|
||||
Release:DESTDIR = ../release_angle
|
||||
Debug:DESTDIR = ../debug_angle
|
||||
}
|
||||
} else {
|
||||
contains(QMAKE_TARGET.arch, x86_64) {
|
||||
Release:DESTDIR = ../release64
|
||||
Debug:DESTDIR = ../debug64
|
||||
} else {
|
||||
Release:DESTDIR = ../release
|
||||
Debug:DESTDIR = ../debug
|
||||
}
|
||||
}
|
||||
|
||||
unix:!macx:!CONFIG(no_opengl) {
|
||||
LIBS += -lGLU
|
||||
}
|
||||
|
||||
macx {
|
||||
LIBS += -framework Foundation -framework ApplicationServices -framework AppKit
|
||||
CONFIG += objective_c
|
||||
QT += macextras gui-private
|
||||
}
|
||||
|
||||
unix:!macx {
|
||||
CONFIG += c++11
|
||||
}
|
||||
|
||||
#CONFIG += release
|
||||
CONFIG -= flat
|
||||
QT += sql network widgets script
|
||||
!CONFIG(no_opengl) {
|
||||
QT += opengl
|
||||
}
|
||||
|
||||
# Input
|
||||
HEADERS += comic_flow.h \
|
||||
create_library_dialog.h \
|
||||
library_creator.h \
|
||||
library_window.h \
|
||||
add_library_dialog.h \
|
||||
rename_library_dialog.h \
|
||||
properties_dialog.h \
|
||||
options_dialog.h \
|
||||
export_library_dialog.h \
|
||||
import_library_dialog.h \
|
||||
package_manager.h \
|
||||
bundle_creator.h \
|
||||
export_comics_info_dialog.h \
|
||||
import_comics_info_dialog.h \
|
||||
server_config_dialog.h \
|
||||
comic_flow_widget.h \
|
||||
db_helper.h \
|
||||
./db/data_base_management.h \
|
||||
./db/folder_item.h \
|
||||
./db/folder_model.h \
|
||||
./db/comic_model.h \
|
||||
./db/comic_item.h \
|
||||
../common/comic_db.h \
|
||||
../common/folder.h \
|
||||
../common/library_item.h \
|
||||
../common/comic.h \
|
||||
../common/bookmarks.h \
|
||||
../common/pictureflow.h \
|
||||
../common/custom_widgets.h \
|
||||
../common/qnaturalsorting.h \
|
||||
../common/yacreader_global.h \
|
||||
../common/yacreader_global_gui.h \
|
||||
../common/onstart_flow_selection_dialog.h \
|
||||
../common/pdf_comic.h \
|
||||
no_libraries_widget.h \
|
||||
import_widget.h \
|
||||
yacreader_local_server.h \
|
||||
yacreader_main_toolbar.h \
|
||||
comics_remover.h \
|
||||
../common/http_worker.h \
|
||||
yacreader_libraries.h \
|
||||
../common/exit_check.h \
|
||||
comics_view.h \
|
||||
classic_comics_view.h \
|
||||
empty_folder_widget.h \
|
||||
no_search_results_widget.h \
|
||||
comic_files_manager.h \
|
||||
db/reading_list_model.h \
|
||||
db/reading_list_item.h \
|
||||
yacreader_folders_view.h \
|
||||
yacreader_reading_lists_view.h \
|
||||
add_label_dialog.h \
|
||||
yacreader_history_controller.h \
|
||||
yacreader_navigation_controller.h \
|
||||
empty_label_widget.h \
|
||||
empty_container_info.h \
|
||||
empty_special_list.h \
|
||||
empty_reading_list_widget.h \
|
||||
../common/scroll_management.h \
|
||||
../common/opengl_checker.h \
|
||||
yacreader_comics_views_manager.h \
|
||||
info_comics_view.h \
|
||||
yacreader_comics_selection_helper.h \
|
||||
yacreader_comic_info_helper.h \
|
||||
db/reading_list.h
|
||||
|
||||
!CONFIG(no_opengl) {
|
||||
HEADERS += ../common/gl/yacreader_flow_gl.h
|
||||
}
|
||||
|
||||
SOURCES += comic_flow.cpp \
|
||||
create_library_dialog.cpp \
|
||||
library_creator.cpp \
|
||||
library_window.cpp \
|
||||
main.cpp \
|
||||
add_library_dialog.cpp \
|
||||
rename_library_dialog.cpp \
|
||||
properties_dialog.cpp \
|
||||
options_dialog.cpp \
|
||||
export_library_dialog.cpp \
|
||||
import_library_dialog.cpp \
|
||||
package_manager.cpp \
|
||||
bundle_creator.cpp \
|
||||
export_comics_info_dialog.cpp \
|
||||
import_comics_info_dialog.cpp \
|
||||
server_config_dialog.cpp \
|
||||
comic_flow_widget.cpp \
|
||||
db_helper.cpp \
|
||||
./db/data_base_management.cpp \
|
||||
./db/folder_item.cpp \
|
||||
./db/folder_model.cpp \
|
||||
./db/comic_model.cpp \
|
||||
./db/comic_item.cpp \
|
||||
../common/comic_db.cpp \
|
||||
../common/folder.cpp \
|
||||
../common/library_item.cpp \
|
||||
../common/comic.cpp \
|
||||
../common/bookmarks.cpp \
|
||||
../common/pictureflow.cpp \
|
||||
../common/custom_widgets.cpp \
|
||||
../common/qnaturalsorting.cpp \
|
||||
../common/onstart_flow_selection_dialog.cpp \
|
||||
no_libraries_widget.cpp \
|
||||
import_widget.cpp \
|
||||
yacreader_local_server.cpp \
|
||||
yacreader_main_toolbar.cpp \
|
||||
comics_remover.cpp \
|
||||
../common/http_worker.cpp \
|
||||
../common/yacreader_global.cpp \
|
||||
../common/yacreader_global_gui.cpp \
|
||||
yacreader_libraries.cpp \
|
||||
../common/exit_check.cpp \
|
||||
comics_view.cpp \
|
||||
classic_comics_view.cpp \
|
||||
empty_folder_widget.cpp \
|
||||
no_search_results_widget.cpp \
|
||||
comic_files_manager.cpp \
|
||||
db/reading_list_model.cpp \
|
||||
db/reading_list_item.cpp \
|
||||
yacreader_folders_view.cpp \
|
||||
yacreader_reading_lists_view.cpp \
|
||||
add_label_dialog.cpp \
|
||||
yacreader_history_controller.cpp \
|
||||
yacreader_navigation_controller.cpp \
|
||||
empty_label_widget.cpp \
|
||||
empty_container_info.cpp \
|
||||
empty_special_list.cpp \
|
||||
empty_reading_list_widget.cpp \
|
||||
../common/scroll_management.cpp \
|
||||
../common/opengl_checker.cpp \
|
||||
yacreader_comics_views_manager.cpp \
|
||||
info_comics_view.cpp \
|
||||
yacreader_comics_selection_helper.cpp \
|
||||
yacreader_comic_info_helper.cpp\
|
||||
db/reading_list.cpp
|
||||
|
||||
!CONFIG(no_opengl) {
|
||||
SOURCES += ../common/gl/yacreader_flow_gl.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)
|
||||
|
||||
RESOURCES += images.qrc files.qrc
|
||||
win32:RESOURCES += images_win.qrc
|
||||
unix:!macx:RESOURCES += images_win.qrc
|
||||
macx:RESOURCES += images_osx.qrc
|
||||
|
||||
RC_FILE = icon.rc
|
||||
|
||||
macx {
|
||||
ICON = YACReaderLibrary.icns
|
||||
}
|
||||
|
||||
TRANSLATIONS = yacreaderlibrary_es.ts \
|
||||
yacreaderlibrary_ru.ts \
|
||||
yacreaderlibrary_pt.ts \
|
||||
yacreaderlibrary_fr.ts \
|
||||
yacreaderlibrary_nl.ts \
|
||||
yacreaderlibrary_tr.ts \
|
||||
yacreaderlibrary_de.ts \
|
||||
yacreaderlibrary_source.ts
|
||||
|
||||
#QML/GridView
|
||||
QT += quick qml
|
||||
|
||||
HEADERS += grid_comics_view.h \
|
||||
comics_view_transition.h
|
||||
|
||||
SOURCES += grid_comics_view.cpp \
|
||||
comics_view_transition.cpp
|
||||
|
||||
RESOURCES += qml.qrc
|
||||
win32:RESOURCES += qml_win.qrc
|
||||
unix:!macx:RESOURCES += qml_win.qrc
|
||||
macx:RESOURCES += qml_osx.qrc
|
||||
|
||||
unix:!macx {
|
||||
#set install prefix if it's empty
|
||||
isEmpty(PREFIX) {
|
||||
PREFIX = /usr
|
||||
}
|
||||
isEmpty(BINDIR) {
|
||||
BINDIR = $$PREFIX/bin
|
||||
}
|
||||
isEmpty(LIBDIR) {
|
||||
LIBDIR = $$PREFIX/lib
|
||||
}
|
||||
isEmpty(DATADIR) {
|
||||
DATADIR = $$PREFIX/share
|
||||
}
|
||||
|
||||
DEFINES += "LIBDIR=\\\"$$LIBDIR\\\"" "DATADIR=\\\"$$DATADIR\\\""
|
||||
|
||||
DEFINES += "LIBDIR=\\\"$$LIBDIR\\\"" "DATADIR=\\\"$$DATADIR\\\"" "BINDIR=\\\"$$BINDIR\\\""
|
||||
|
||||
#MAKE INSTALL
|
||||
INSTALLS += bin icon desktop server translation manpage
|
||||
|
||||
bin.path = $$BINDIR
|
||||
isEmpty(DESTDIR) {
|
||||
bin.files = YACReaderLibrary
|
||||
} else {
|
||||
bin.files = $$DESTDIR/YACReaderLibrary
|
||||
}
|
||||
|
||||
server.path = $$DATADIR/yacreader
|
||||
server.files = ../release/server
|
||||
|
||||
icon.path = $$DATADIR/icons/hicolor/scalable/apps
|
||||
icon.files = ../YACReaderLibrary.svg
|
||||
|
||||
desktop.path = $$DATADIR/applications
|
||||
desktop.files = ../YACReaderLibrary.desktop
|
||||
|
||||
translation.path = $$DATADIR/yacreader/languages
|
||||
translation.files = ../release/languages/yacreaderlibrary_*
|
||||
|
||||
manpage.path = $$DATADIR/man/man1
|
||||
manpage.files = ../YACReaderLibrary.1
|
||||
}
|
@ -5,8 +5,8 @@
|
||||
|
||||
#include "QsLog.h"
|
||||
|
||||
ComicsRemover::ComicsRemover(QModelIndexList & il, QList<QString> & ps, QObject *parent)
|
||||
:QObject(parent),indexList(il), paths(ps)
|
||||
ComicsRemover::ComicsRemover(QModelIndexList & il, QList<QString> & ps, qulonglong parentId, QObject *parent)
|
||||
:QObject(parent),indexList(il), paths(ps), parentId(parentId)
|
||||
{
|
||||
}
|
||||
|
||||
@ -29,6 +29,7 @@ void ComicsRemover::process()
|
||||
}
|
||||
|
||||
emit finished();
|
||||
emit removedItemsFromFolder(parentId);
|
||||
}
|
||||
|
||||
|
||||
|
@ -10,12 +10,13 @@ class ComicsRemover : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit ComicsRemover(QModelIndexList & indexList, QList<QString> & paths, QObject *parent = 0);
|
||||
explicit ComicsRemover(QModelIndexList & indexList, QList<QString> & paths, qulonglong parentId, QObject *parent = 0);
|
||||
|
||||
signals:
|
||||
void remove(int);
|
||||
void removeError();
|
||||
void finished();
|
||||
void removedItemsFromFolder(qulonglong);
|
||||
|
||||
public slots:
|
||||
void process();
|
||||
@ -23,6 +24,7 @@ public slots:
|
||||
private:
|
||||
QModelIndexList indexList;
|
||||
QList<QString> paths;
|
||||
qulonglong parentId;
|
||||
};
|
||||
|
||||
class FoldersRemover : public QObject
|
||||
|
@ -582,7 +582,7 @@ void ComicModel::setupFavoritesModelData(const QString &databasePath)
|
||||
"ORDER BY cdrl.ordering");
|
||||
selectQuery.bindValue(":parentDefaultListId", 1);
|
||||
selectQuery.exec();
|
||||
setupModelData(selectQuery);
|
||||
setupModelDataForList(selectQuery);
|
||||
}
|
||||
db.close();
|
||||
QSqlDatabase::removeDatabase(_databasePath);
|
||||
@ -607,9 +607,11 @@ void ComicModel::setupReadingModelData(const QString &databasePath)
|
||||
QSqlQuery selectQuery(db);
|
||||
selectQuery.prepare("SELECT ci.number,ci.title,c.fileName,ci.numPages,c.id,c.parentId,c.path,ci.hash,ci.read,ci.isBis,ci.currentPage,ci.rating,ci.hasBeenOpened "
|
||||
"FROM comic c INNER JOIN comic_info ci ON (c.comicInfoId = ci.id) "
|
||||
"WHERE ci.hasBeenOpened = 1 AND ci.read = 0 AND ci.currentPage != ci.numPages AND ci.currentPage != 1");
|
||||
"WHERE ci.hasBeenOpened = 1 AND ci.read = 0 AND ci.currentPage != ci.numPages AND ci.currentPage != 1 "
|
||||
"ORDER BY ci.lastTimeOpened DESC");
|
||||
selectQuery.exec();
|
||||
setupModelData(selectQuery);
|
||||
|
||||
setupModelDataForList(selectQuery);
|
||||
}
|
||||
db.close();
|
||||
QSqlDatabase::removeDatabase(_databasePath);
|
||||
@ -928,7 +930,7 @@ void ComicModel::removeInTransaction(int row)
|
||||
|
||||
endRemoveRows();
|
||||
}
|
||||
|
||||
/*
|
||||
void ComicModel::remove(ComicDB * comic, int row)
|
||||
{
|
||||
beginRemoveRows(QModelIndex(),row,row);
|
||||
@ -944,7 +946,7 @@ void ComicModel::remove(ComicDB * comic, int row)
|
||||
QSqlDatabase::removeDatabase(_databasePath);
|
||||
endRemoveRows();
|
||||
}
|
||||
|
||||
*/
|
||||
/*ComicDB TableModel::getComic(int row)
|
||||
{
|
||||
return getComic(index(row,0));
|
||||
|
@ -65,7 +65,7 @@ public:
|
||||
//setComicInfoForSelectedComis(QList<QModelIndex> list); -->inserta la información común para los comics seleccionados
|
||||
QVector<YACReaderComicReadStatus> setComicsRead(QList<QModelIndex> list,YACReaderComicReadStatus read);
|
||||
qint64 asignNumbers(QList<QModelIndex> list,int startingNumber);
|
||||
void remove(ComicDB * comic, int row);
|
||||
//void remove(ComicDB * comic, int row);
|
||||
void removeInTransaction(int row);
|
||||
void reload(const ComicDB & comic);
|
||||
void resetComicRating(const QModelIndex & mi);
|
||||
|
@ -3,7 +3,9 @@
|
||||
#include <QtCore>
|
||||
#include "library_creator.h"
|
||||
#include "check_new_version.h"
|
||||
#include "db_helper.h"
|
||||
|
||||
#include "QsLog.h"
|
||||
|
||||
static QString fields = "title ,"
|
||||
|
||||
@ -124,99 +126,105 @@ QSqlDatabase DataBaseManagement::loadDatabaseFromFile(QString filePath)
|
||||
|
||||
bool DataBaseManagement::createTables(QSqlDatabase & database)
|
||||
{
|
||||
bool success = true;
|
||||
bool success = true;
|
||||
|
||||
//FOLDER (representa una carpeta en disco)
|
||||
{
|
||||
QSqlQuery queryFolder(database);
|
||||
queryFolder.prepare("CREATE TABLE folder ("
|
||||
"id INTEGER PRIMARY KEY,"
|
||||
"parentId INTEGER NOT NULL,"
|
||||
"name TEXT NOT NULL,"
|
||||
"path TEXT NOT NULL,"
|
||||
//new 7.1 fields
|
||||
"finished BOOLEAN DEFAULT 0," //reading
|
||||
"completed BOOLEAN DEFAULT 1," //collecting
|
||||
//--
|
||||
"FOREIGN KEY(parentId) REFERENCES folder(id) ON DELETE CASCADE)");
|
||||
success = success && queryFolder.exec();
|
||||
{
|
||||
//COMIC INFO (representa la información de un cómic, cada cómic tendrá un idéntificador único formado por un hash sha1'de los primeros 512kb' + su tamaño en bytes)
|
||||
QSqlQuery queryComicInfo(database);
|
||||
queryComicInfo.prepare("CREATE TABLE comic_info ("
|
||||
"id INTEGER PRIMARY KEY,"
|
||||
"title TEXT,"
|
||||
|
||||
//COMIC INFO (representa la información de un cómic, cada cómic tendrá un idéntificador único formado por un hash sha1'de los primeros 512kb' + su tamaño en bytes)
|
||||
QSqlQuery queryComicInfo(database);
|
||||
queryComicInfo.prepare("CREATE TABLE comic_info ("
|
||||
"id INTEGER PRIMARY KEY,"
|
||||
"title TEXT,"
|
||||
"coverPage INTEGER DEFAULT 1,"
|
||||
"numPages INTEGER,"
|
||||
|
||||
"coverPage INTEGER DEFAULT 1,"
|
||||
"numPages INTEGER,"
|
||||
"number INTEGER,"
|
||||
"isBis BOOLEAN,"
|
||||
"count INTEGER,"
|
||||
|
||||
"number INTEGER,"
|
||||
"isBis BOOLEAN,"
|
||||
"count INTEGER,"
|
||||
"volume TEXT,"
|
||||
"storyArc TEXT,"
|
||||
"arcNumber INTEGER,"
|
||||
"arcCount INTEGER,"
|
||||
|
||||
"volume TEXT,"
|
||||
"storyArc TEXT,"
|
||||
"arcNumber INTEGER,"
|
||||
"arcCount INTEGER,"
|
||||
"genere TEXT,"
|
||||
|
||||
"genere TEXT,"
|
||||
"writer TEXT,"
|
||||
"penciller TEXT,"
|
||||
"inker TEXT,"
|
||||
"colorist TEXT,"
|
||||
"letterer TEXT,"
|
||||
"coverArtist TEXT,"
|
||||
|
||||
"writer TEXT,"
|
||||
"penciller TEXT,"
|
||||
"inker TEXT,"
|
||||
"colorist TEXT,"
|
||||
"letterer TEXT,"
|
||||
"coverArtist TEXT,"
|
||||
"date TEXT," //dd/mm/yyyy --> se mostrará en 3 campos diferentes
|
||||
"publisher TEXT,"
|
||||
"format TEXT,"
|
||||
"color BOOLEAN,"
|
||||
"ageRating BOOLEAN,"
|
||||
|
||||
"date TEXT," //dd/mm/yyyy --> se mostrará en 3 campos diferentes
|
||||
"publisher TEXT,"
|
||||
"format TEXT,"
|
||||
"color BOOLEAN,"
|
||||
"ageRating BOOLEAN,"
|
||||
"synopsis TEXT,"
|
||||
"characters TEXT,"
|
||||
"notes TEXT,"
|
||||
|
||||
"synopsis TEXT,"
|
||||
"characters TEXT,"
|
||||
"notes TEXT,"
|
||||
"hash TEXT UNIQUE NOT NULL,"
|
||||
"edited BOOLEAN DEFAULT 0,"
|
||||
"read BOOLEAN DEFAULT 0,"
|
||||
//new 7.0 fields
|
||||
|
||||
"hash TEXT UNIQUE NOT NULL,"
|
||||
"edited BOOLEAN DEFAULT 0,"
|
||||
"read BOOLEAN DEFAULT 0,"
|
||||
//new 7.0 fields
|
||||
|
||||
"hasBeenOpened BOOLEAN DEFAULT 0,"
|
||||
"rating INTEGER DEFAULT 0,"
|
||||
"currentPage INTEGER DEFAULT 1, "
|
||||
"bookmark1 INTEGER DEFAULT -1, "
|
||||
"bookmark2 INTEGER DEFAULT -1, "
|
||||
"bookmark3 INTEGER DEFAULT -1, "
|
||||
"brightness INTEGER DEFAULT -1, "
|
||||
"contrast INTEGER DEFAULT -1, "
|
||||
"gamma INTEGER DEFAULT -1, "
|
||||
//new 7.1 fields
|
||||
"comicVineID TEXT"
|
||||
"hasBeenOpened BOOLEAN DEFAULT 0,"
|
||||
"rating INTEGER DEFAULT 0,"
|
||||
"currentPage INTEGER DEFAULT 1, "
|
||||
"bookmark1 INTEGER DEFAULT -1, "
|
||||
"bookmark2 INTEGER DEFAULT -1, "
|
||||
"bookmark3 INTEGER DEFAULT -1, "
|
||||
"brightness INTEGER DEFAULT -1, "
|
||||
"contrast INTEGER DEFAULT -1, "
|
||||
"gamma INTEGER DEFAULT -1, "
|
||||
//new 7.1 fields
|
||||
"comicVineID TEXT,"
|
||||
//new 9.5 fields
|
||||
"lastTimeOpened INTEGER,"
|
||||
"coverSizeRatio REAL,"
|
||||
"originalCoverSize STRING"//h/w
|
||||
|
||||
")");
|
||||
success = success && queryComicInfo.exec();
|
||||
//queryComicInfo.finish();
|
||||
")");
|
||||
success = success && queryComicInfo.exec();
|
||||
//queryComicInfo.finish();
|
||||
|
||||
//COMIC (representa un cómic en disco, contiene el nombre de fichero)
|
||||
QSqlQuery queryComic(database);
|
||||
queryComic.prepare("CREATE TABLE comic (id INTEGER PRIMARY KEY, parentId INTEGER NOT NULL, comicInfoId INTEGER NOT NULL, fileName TEXT NOT NULL, path TEXT, FOREIGN KEY(parentId) REFERENCES folder(id) ON DELETE CASCADE, FOREIGN KEY(comicInfoId) REFERENCES comic_info(id))");
|
||||
success = success && queryComic.exec();
|
||||
//queryComic.finish();
|
||||
//DB INFO
|
||||
QSqlQuery queryDBInfo(database);
|
||||
queryDBInfo.prepare("CREATE TABLE db_info (version TEXT NOT NULL)");
|
||||
success = success && queryDBInfo.exec();
|
||||
//queryDBInfo.finish();
|
||||
//FOLDER (representa una carpeta en disco)
|
||||
QSqlQuery queryFolder(database);
|
||||
queryFolder.prepare("CREATE TABLE folder ("
|
||||
"id INTEGER PRIMARY KEY,"
|
||||
"parentId INTEGER NOT NULL,"
|
||||
"name TEXT NOT NULL,"
|
||||
"path TEXT NOT NULL,"
|
||||
//new 7.1 fields
|
||||
"finished BOOLEAN DEFAULT 0," //reading
|
||||
"completed BOOLEAN DEFAULT 1," //collecting
|
||||
//new 9.5 fields
|
||||
"numChildren INTEGER,"
|
||||
"firstChildHash TEXT,"
|
||||
"customImage TEXT,"
|
||||
"FOREIGN KEY(parentId) REFERENCES folder(id) ON DELETE CASCADE)");
|
||||
success = success && queryFolder.exec();
|
||||
|
||||
QSqlQuery query("INSERT INTO db_info (version) "
|
||||
"VALUES ('" VERSION "')",database);
|
||||
//query.finish();
|
||||
//COMIC (representa un cómic en disco, contiene el nombre de fichero)
|
||||
QSqlQuery queryComic(database);
|
||||
queryComic.prepare("CREATE TABLE comic (id INTEGER PRIMARY KEY, parentId INTEGER NOT NULL, comicInfoId INTEGER NOT NULL, fileName TEXT NOT NULL, path TEXT, FOREIGN KEY(parentId) REFERENCES folder(id) ON DELETE CASCADE, FOREIGN KEY(comicInfoId) REFERENCES comic_info(id))");
|
||||
success = success && queryComic.exec();
|
||||
//queryComic.finish();
|
||||
//DB INFO
|
||||
QSqlQuery queryDBInfo(database);
|
||||
queryDBInfo.prepare("CREATE TABLE db_info (version TEXT NOT NULL)");
|
||||
success = success && queryDBInfo.exec();
|
||||
//queryDBInfo.finish();
|
||||
|
||||
//8.0> tables
|
||||
success = success && DataBaseManagement::createV8Tables(database);
|
||||
QSqlQuery query("INSERT INTO db_info (version) "
|
||||
"VALUES ('" VERSION "')",database);
|
||||
//query.finish();
|
||||
|
||||
//8.0> tables
|
||||
success = success && DataBaseManagement::createV8Tables(database);
|
||||
}
|
||||
|
||||
return success;
|
||||
@ -317,7 +325,7 @@ void DataBaseManagement::exportComicsInfo(QString source, QString dest)
|
||||
//QSqlDatabase sourceDB = loadDatabase(source);
|
||||
QSqlDatabase destDB = loadDatabaseFromFile(dest);
|
||||
//sourceDB.open();
|
||||
{
|
||||
{
|
||||
QSqlQuery attach(destDB);
|
||||
attach.prepare("ATTACH DATABASE '"+QDir().toNativeSeparators(dest) +"' AS dest;");
|
||||
//attach.bindValue(":dest",QDir().toNativeSeparators(dest));
|
||||
@ -415,7 +423,12 @@ bool DataBaseManagement::importComicsInfo(QString source, QString dest)
|
||||
|
||||
"edited = :edited,"
|
||||
|
||||
"comicVineID = :comicVineID"
|
||||
"comicVineID = :comicVineID,"
|
||||
|
||||
"lastTimeOpened = :lastTimeOpened,"
|
||||
|
||||
"coverSizeRatio = :coverSizeRatio,"
|
||||
"originalCoverSize = :originalCoverSize"
|
||||
|
||||
" WHERE hash = :hash ");
|
||||
|
||||
@ -449,6 +462,8 @@ bool DataBaseManagement::importComicsInfo(QString source, QString dest)
|
||||
"read,"
|
||||
"edited,"
|
||||
"comicVineID,"
|
||||
"lastTimeOpened,"
|
||||
"coverSizeRatio,"
|
||||
"hash)"
|
||||
|
||||
"VALUES (:title,"
|
||||
@ -486,6 +501,11 @@ bool DataBaseManagement::importComicsInfo(QString source, QString dest)
|
||||
":edited,"
|
||||
":comicVineID,"
|
||||
|
||||
":lastTimeOpened,"
|
||||
|
||||
":coverSizeRatio,"
|
||||
":originalCoverSize,"
|
||||
|
||||
":hash )");
|
||||
|
||||
QSqlRecord record = newInfo.record();
|
||||
@ -596,6 +616,11 @@ void DataBaseManagement::bindValuesFromRecord(const QSqlRecord & record, QSqlQue
|
||||
|
||||
bindString("comicVineID",record,query);
|
||||
|
||||
bindString("lastTimeOpened",record,query);
|
||||
|
||||
bindDouble("coverSizeRatio",record,query);
|
||||
bindString("originalCoverSize",record,query);
|
||||
|
||||
bindString("hash",record,query);
|
||||
}
|
||||
|
||||
@ -609,13 +634,30 @@ bool DataBaseManagement::addColumns(const QString &tableName, const QStringList
|
||||
QSqlQuery alterTable(db);
|
||||
alterTable.prepare(sql.arg(tableName).arg(columnDef));
|
||||
//alterTableComicInfo.bindValue(":column_def",columnDef);
|
||||
alterTable.exec();
|
||||
returnValue = returnValue && (alterTable.numRowsAffected() > 0);
|
||||
bool exec = alterTable.exec();
|
||||
returnValue = returnValue && exec;
|
||||
if (!exec) {
|
||||
QLOG_ERROR() << alterTable.lastError().text();
|
||||
}
|
||||
//returnValue = returnValue && (alterTable.numRowsAffected() > 0);
|
||||
}
|
||||
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
bool DataBaseManagement::addConstraint(const QString &tableName, const QString &constraint, const QSqlDatabase &db)
|
||||
{
|
||||
QString sql = "ALTER TABLE %1 ADD %2";
|
||||
bool returnValue = true;
|
||||
|
||||
QSqlQuery alterTable(db);
|
||||
alterTable.prepare(sql.arg(tableName).arg(constraint));
|
||||
alterTable.exec();
|
||||
returnValue = returnValue && (alterTable.numRowsAffected() > 0);
|
||||
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
void DataBaseManagement::bindString(const QString & name, const QSqlRecord & record, QSqlQuery & query)
|
||||
{
|
||||
if(!record.value(name).isNull())
|
||||
@ -631,6 +673,14 @@ void DataBaseManagement::bindInt(const QString & name, const QSqlRecord & record
|
||||
}
|
||||
}
|
||||
|
||||
void DataBaseManagement::bindDouble(const QString & name, const QSqlRecord & record, QSqlQuery & query)
|
||||
{
|
||||
if(!record.value(name).isNull())
|
||||
{
|
||||
query.bindValue(":"+name,record.value(name).toDouble());
|
||||
}
|
||||
}
|
||||
|
||||
QString DataBaseManagement::checkValidDB(const QString & fullPath)
|
||||
{
|
||||
QSqlDatabase db = loadDatabaseFromFile(fullPath);
|
||||
@ -681,11 +731,14 @@ int DataBaseManagement::compareVersions(const QString & v1, const QString v2)
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool DataBaseManagement::updateToCurrentVersion(const QString & fullPath)
|
||||
bool DataBaseManagement::updateToCurrentVersion(const QString & path)
|
||||
{
|
||||
bool pre7 = false;
|
||||
bool pre7_1 = false;
|
||||
bool pre8 = false;
|
||||
bool pre9_5 = false;
|
||||
|
||||
QString fullPath = path + "/library.ydb";
|
||||
|
||||
if(compareVersions(DataBaseManagement::checkValidDB(fullPath),"7.0.0")<0)
|
||||
pre7 = true;
|
||||
@ -693,6 +746,8 @@ bool DataBaseManagement::updateToCurrentVersion(const QString & fullPath)
|
||||
pre7_1 = true;
|
||||
if(compareVersions(DataBaseManagement::checkValidDB(fullPath),"8.0.0")<0)
|
||||
pre8 = true;
|
||||
if(compareVersions(DataBaseManagement::checkValidDB(fullPath),"9.5.0")<0)
|
||||
pre9_5 = true;
|
||||
|
||||
QSqlDatabase db = loadDatabaseFromFile(fullPath);
|
||||
bool returnValue = false;
|
||||
@ -704,7 +759,7 @@ bool DataBaseManagement::updateToCurrentVersion(const QString & fullPath)
|
||||
updateVersion.bindValue(":version",VERSION);
|
||||
updateVersion.exec();
|
||||
|
||||
if(updateVersion.numRowsAffected() > 0)
|
||||
if(updateVersion.numRowsAffected() > 0)
|
||||
returnValue = true;
|
||||
|
||||
if(pre7) //TODO: execute only if previous version was < 7.0
|
||||
@ -721,7 +776,8 @@ bool DataBaseManagement::updateToCurrentVersion(const QString & fullPath)
|
||||
<< "contrast INTEGER DEFAULT -1"
|
||||
<< "gamma INTEGER DEFAULT -1";
|
||||
|
||||
returnValue = returnValue && addColumns("comic_info", columnDefs, db);
|
||||
bool successAddingColumns = addColumns("comic_info", columnDefs, db);
|
||||
returnValue = returnValue && successAddingColumns;
|
||||
}
|
||||
//TODO update hasBeenOpened value
|
||||
|
||||
@ -731,19 +787,78 @@ bool DataBaseManagement::updateToCurrentVersion(const QString & fullPath)
|
||||
QStringList columnDefs;
|
||||
columnDefs << "finished BOOLEAN DEFAULT 0"
|
||||
<< "completed BOOLEAN DEFAULT 1";
|
||||
returnValue = returnValue && addColumns("folder", columnDefs, db);
|
||||
bool successAddingColumns = addColumns("folder", columnDefs, db);
|
||||
returnValue = returnValue && successAddingColumns;
|
||||
}
|
||||
|
||||
{//comic_info
|
||||
QStringList columnDefs;
|
||||
columnDefs << "comicVineID TEXT DEFAULT NULL";
|
||||
returnValue = returnValue && addColumns("comic_info", columnDefs, db);
|
||||
bool successAddingColumns = addColumns("comic_info", columnDefs, db);
|
||||
returnValue = returnValue && successAddingColumns;
|
||||
}
|
||||
}
|
||||
|
||||
if(pre8)
|
||||
{
|
||||
returnValue = returnValue && createV8Tables(db);
|
||||
bool successCreatingNewTables = createV8Tables(db);
|
||||
returnValue = returnValue && successCreatingNewTables;
|
||||
}
|
||||
|
||||
if(pre9_5)
|
||||
{
|
||||
{//folder
|
||||
QStringList columnDefs;
|
||||
//a full library update is needed after updating the table
|
||||
columnDefs << "numChildren INTEGER";
|
||||
columnDefs << "firstChildHash TEXT";
|
||||
columnDefs << "customImage TEXT";
|
||||
bool successAddingColumns = addColumns("folder", columnDefs, db);
|
||||
returnValue = returnValue && successAddingColumns;
|
||||
}
|
||||
|
||||
{//comic_info
|
||||
QStringList columnDefs;
|
||||
columnDefs << "lastTimeOpened INTEGER";
|
||||
columnDefs << "coverSizeRatio REAL";
|
||||
columnDefs << "originalCoverSize TEXT";
|
||||
bool successAddingColumns = addColumns("comic_info", columnDefs, db);
|
||||
returnValue = returnValue && successAddingColumns;
|
||||
|
||||
QSqlQuery queryIndexLastTimeOpened(db);
|
||||
bool successCreatingIndex = queryIndexLastTimeOpened.exec("CREATE INDEX last_time_opened_index ON comic_info (lastTimeOpened)");
|
||||
returnValue = returnValue && successCreatingIndex;
|
||||
}
|
||||
|
||||
//update folders info
|
||||
{
|
||||
DBHelper::updateChildrenInfo(db);
|
||||
}
|
||||
|
||||
{
|
||||
QSqlQuery selectQuery(db);
|
||||
selectQuery.prepare("SELECT id, hash FROM comic_info");
|
||||
selectQuery.exec();
|
||||
|
||||
db.transaction();
|
||||
|
||||
QSqlQuery updateCoverInfo(db);
|
||||
updateCoverInfo.prepare("UPDATE comic_info SET coverSizeRatio = :coverSizeRatio WHERE id = :id");
|
||||
|
||||
QImageReader thumbnail;
|
||||
while (selectQuery.next())
|
||||
{
|
||||
thumbnail.setFileName(path % "/covers/" % selectQuery.value(1).toString() % ".jpg");
|
||||
|
||||
float coverSizeRatio = static_cast<float>(thumbnail.size().width()) / thumbnail.size().height();
|
||||
updateCoverInfo.bindValue(":coverSizeRatio", coverSizeRatio);
|
||||
updateCoverInfo.bindValue(":id", selectQuery.value(0));
|
||||
|
||||
updateCoverInfo.exec();
|
||||
}
|
||||
|
||||
db.commit();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -35,9 +35,11 @@ private:
|
||||
QList<QString> dataBasesList;
|
||||
static void bindString(const QString & name, const QSqlRecord & record, QSqlQuery & query);
|
||||
static void bindInt(const QString & name, const QSqlRecord & record, QSqlQuery & query);
|
||||
static void bindDouble(const QString & name, const QSqlRecord & record, QSqlQuery & query);
|
||||
static void bindValuesFromRecord(const QSqlRecord & record, QSqlQuery & query);
|
||||
|
||||
static bool addColumns(const QString & tableName, const QStringList & columnDefs, const QSqlDatabase & db);
|
||||
static bool addConstraint(const QString &tableName, const QString & constraint, const QSqlDatabase & db);
|
||||
|
||||
public:
|
||||
DataBaseManagement();
|
||||
|
@ -184,6 +184,9 @@ QVariant FolderModel::data(const QModelIndex &index, int role) const
|
||||
if(role == FolderModel::FinishedRole)
|
||||
return item->data(FolderModel::Finished);
|
||||
|
||||
if(role == FolderModel::IdRole)
|
||||
return item->id;
|
||||
|
||||
if (role != Qt::DisplayRole)
|
||||
return QVariant();
|
||||
|
||||
@ -315,7 +318,7 @@ void FolderModel::setupModelData(QSqlQuery &sqlquery, FolderItem *parent)
|
||||
//el diccionario permitir<69> encontrar cualquier nodo del <20>rbol r<>pidamente, de forma que a<>adir un hijo a un padre sea O(1)
|
||||
items.clear();
|
||||
//se a<>ade el nodo 0
|
||||
items.insert(parent->id,parent);
|
||||
items.insert(parent->id,parent);
|
||||
|
||||
QSqlRecord record = sqlquery.record();
|
||||
|
||||
@ -562,6 +565,7 @@ QModelIndex FolderModel::addFolderAtParent(const QString &folderName, const QMod
|
||||
|
||||
QSqlDatabase db = DataBaseManagement::loadDatabase(_databasePath);
|
||||
newFolder.id = DBHelper::insert(&newFolder, db);
|
||||
DBHelper::updateChildrenInfo(parentItem->id, db);
|
||||
QSqlDatabase::removeDatabase(_databasePath);
|
||||
|
||||
int destRow = 0;
|
||||
@ -600,11 +604,18 @@ void FolderModel::deleteFolder(const QModelIndex &mi)
|
||||
|
||||
QSqlDatabase db = DataBaseManagement::loadDatabase(_databasePath);
|
||||
DBHelper::removeFromDB(&f,db);
|
||||
DBHelper::updateChildrenInfo(item->parent()->id, db);
|
||||
QSqlDatabase::removeDatabase(_databasePath);
|
||||
|
||||
endRemoveRows();
|
||||
}
|
||||
|
||||
void FolderModel::updateFolderChildrenInfo(qulonglong folderId)
|
||||
{
|
||||
QSqlDatabase db = DataBaseManagement::loadDatabase(_databasePath);
|
||||
DBHelper::updateChildrenInfo(folderId, db);
|
||||
QSqlDatabase::removeDatabase(_databasePath);
|
||||
}
|
||||
|
||||
//PROXY
|
||||
|
||||
|
@ -127,11 +127,13 @@ public:
|
||||
|
||||
enum Roles {
|
||||
FinishedRole = Qt::UserRole + 1,
|
||||
CompletedRole
|
||||
CompletedRole,
|
||||
IdRole
|
||||
};
|
||||
|
||||
public slots:
|
||||
void deleteFolder(const QModelIndex & mi);
|
||||
void updateFolderChildrenInfo(qulonglong folderId);
|
||||
|
||||
private:
|
||||
void setupModelData( QSqlQuery &sqlquery, FolderItem *parent);
|
||||
|
44
YACReaderLibrary/db/reading_list.cpp
Normal file
44
YACReaderLibrary/db/reading_list.cpp
Normal file
@ -0,0 +1,44 @@
|
||||
#include "reading_list.h"
|
||||
|
||||
ReadingList::ReadingList(const QString &name, qulonglong id, int ordering)
|
||||
:name(name), id(id), ordering(ordering)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
qulonglong ReadingList::getId() const
|
||||
{
|
||||
return id;
|
||||
}
|
||||
|
||||
QString ReadingList::getName() const
|
||||
{
|
||||
return name;
|
||||
}
|
||||
|
||||
int ReadingList::getOrdering() const
|
||||
{
|
||||
return ordering;
|
||||
}
|
||||
|
||||
|
||||
Label::Label(const QString &name, qulonglong id, YACReader::LabelColors colorid)
|
||||
:name(name), id(id), colorid(colorid)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
YACReader::LabelColors Label::getColorID() const
|
||||
{
|
||||
return colorid;
|
||||
}
|
||||
|
||||
QString Label::getName() const
|
||||
{
|
||||
return name;
|
||||
}
|
||||
|
||||
qulonglong Label::getId() const
|
||||
{
|
||||
return id;
|
||||
}
|
36
YACReaderLibrary/db/reading_list.h
Normal file
36
YACReaderLibrary/db/reading_list.h
Normal file
@ -0,0 +1,36 @@
|
||||
#ifndef READING_LIST_H
|
||||
#define READING_LIST_H
|
||||
|
||||
#include "yacreader_global.h"
|
||||
|
||||
class ReadingList
|
||||
{
|
||||
public:
|
||||
ReadingList(const QString &name, qulonglong id, int ordering);
|
||||
|
||||
qulonglong getId() const;
|
||||
QString getName() const;
|
||||
int getOrdering() const;
|
||||
private:
|
||||
QString name;
|
||||
qulonglong id;
|
||||
int ordering;
|
||||
};
|
||||
|
||||
class Label
|
||||
{
|
||||
public:
|
||||
Label(const QString &name, qulonglong id, YACReader::LabelColors colorid);
|
||||
|
||||
YACReader::LabelColors getColorID() const;
|
||||
QString getName() const;
|
||||
qulonglong getId() const;
|
||||
|
||||
private:
|
||||
QString name;
|
||||
qulonglong id;
|
||||
YACReader::LabelColors colorid;
|
||||
|
||||
};
|
||||
|
||||
#endif // READING_LIST_H
|
@ -14,6 +14,7 @@
|
||||
|
||||
#include <limits>
|
||||
|
||||
#include "reading_list.h"
|
||||
#include "library_item.h"
|
||||
#include "comic_db.h"
|
||||
#include "data_base_management.h"
|
||||
@ -58,6 +59,38 @@ QList<LibraryItem *> DBHelper::getFolderComicsFromLibrary(qulonglong libraryId,
|
||||
QSqlDatabase::removeDatabase(libraryPath);
|
||||
return list;
|
||||
}
|
||||
|
||||
quint32 DBHelper::getNumChildrenFromFolder(qulonglong libraryId, qulonglong folderId)
|
||||
{
|
||||
QString libraryPath = DBHelper::getLibraries().getPath(libraryId);
|
||||
QSqlDatabase db = DataBaseManagement::loadDatabase(libraryPath+"/.yacreaderlibrary");
|
||||
|
||||
quint32 result = 0;
|
||||
|
||||
{
|
||||
QSqlQuery selectQuery(db);
|
||||
selectQuery.prepare("SELECT count(*) FROM folder WHERE parentId = :parentId and id <> 1");
|
||||
selectQuery.bindValue(":parentId", folderId);
|
||||
selectQuery.exec();
|
||||
|
||||
result += selectQuery.record().value(0).toULongLong();
|
||||
}
|
||||
|
||||
{
|
||||
QSqlQuery selectQuery(db);
|
||||
selectQuery.prepare("SELECT count(*) FROM comic c WHERE c.parentId = :parentId");
|
||||
selectQuery.bindValue(":parentId", folderId);
|
||||
selectQuery.exec();
|
||||
|
||||
result += selectQuery.record().value(0).toULongLong();
|
||||
}
|
||||
|
||||
db.close();
|
||||
QSqlDatabase::removeDatabase(libraryPath);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
qulonglong DBHelper::getParentFromComicFolderId(qulonglong libraryId, qulonglong id)
|
||||
{
|
||||
QString libraryPath = DBHelper::getLibraries().getPath(libraryId);
|
||||
@ -107,8 +140,7 @@ QString DBHelper::getFolderName(qulonglong libraryId, qulonglong id)
|
||||
|
||||
if(selectQuery.next())
|
||||
{
|
||||
QSqlRecord record = selectQuery.record();
|
||||
name = record.value(0).toString();
|
||||
name = selectQuery.value(0).toString();
|
||||
}
|
||||
}
|
||||
|
||||
@ -126,14 +158,223 @@ QString DBHelper::getLibraryName(int id)
|
||||
{
|
||||
return getLibraries().getName(id);
|
||||
}
|
||||
|
||||
QList<ComicDB> DBHelper::getLabelComics(qulonglong libraryId, qulonglong labelId)
|
||||
{
|
||||
QString libraryPath = DBHelper::getLibraries().getPath(libraryId);
|
||||
QSqlDatabase db = DataBaseManagement::loadDatabase(libraryPath+"/.yacreaderlibrary");
|
||||
|
||||
QList<ComicDB> list;
|
||||
|
||||
{
|
||||
QSqlQuery selectQuery(db);
|
||||
selectQuery.prepare("SELECT c.id,c.fileName,ci.title,ci.currentPage,ci.numPages,ci.hash,ci.read "
|
||||
"FROM comic c INNER JOIN comic_info ci ON (c.comicInfoId = ci.id) "
|
||||
"INNER JOIN comic_label cl ON (c.id == cl.comic_id) "
|
||||
"WHERE cl.label_id = :parentLabelId "
|
||||
"ORDER BY cl.ordering");
|
||||
selectQuery.bindValue(":parentLabelId", labelId);
|
||||
selectQuery.exec();
|
||||
|
||||
while (selectQuery.next())
|
||||
{
|
||||
ComicDB comic;
|
||||
|
||||
comic.id = selectQuery.value(0).toULongLong();
|
||||
comic.parentId = labelId;
|
||||
comic.name = selectQuery.value(1).toString();
|
||||
comic.info.title = selectQuery.value(2).toString();
|
||||
comic.info.currentPage = selectQuery.value(3).toInt();
|
||||
comic.info.numPages = selectQuery.value(4).toInt();
|
||||
comic.info.hash = selectQuery.value(5).toString();
|
||||
comic.info.read = selectQuery.value(6).toBool();
|
||||
|
||||
list.append(comic);
|
||||
}
|
||||
|
||||
db.close();
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
QList<ComicDB> DBHelper::getFavorites(qulonglong libraryId)
|
||||
{
|
||||
QString libraryPath = DBHelper::getLibraries().getPath(libraryId);
|
||||
QSqlDatabase db = DataBaseManagement::loadDatabase(libraryPath+"/.yacreaderlibrary");
|
||||
|
||||
QList<ComicDB> list;
|
||||
|
||||
const int FAV_ID = 1;
|
||||
|
||||
{
|
||||
QSqlQuery selectQuery(db);
|
||||
selectQuery.prepare("SELECT c.id,c.fileName,ci.title,ci.currentPage,ci.numPages,ci.hash,ci.read "
|
||||
"FROM comic c INNER JOIN comic_info ci ON (c.comicInfoId = ci.id) "
|
||||
"INNER JOIN comic_default_reading_list cdrl ON (c.id == cdrl.comic_id) "
|
||||
"WHERE cdrl.default_reading_list_id = :parentDefaultListId "
|
||||
"ORDER BY cdrl.ordering");
|
||||
selectQuery.bindValue(":parentDefaultListId", FAV_ID);
|
||||
selectQuery.exec();
|
||||
|
||||
while (selectQuery.next())
|
||||
{
|
||||
ComicDB comic;
|
||||
|
||||
comic.id = selectQuery.value(0).toULongLong();
|
||||
comic.parentId = FAV_ID;
|
||||
comic.name = selectQuery.value(1).toString();
|
||||
comic.info.title = selectQuery.value(2).toString();
|
||||
comic.info.currentPage = selectQuery.value(3).toInt();
|
||||
comic.info.numPages = selectQuery.value(4).toInt();
|
||||
comic.info.hash = selectQuery.value(5).toString();
|
||||
comic.info.read = selectQuery.value(6).toBool();
|
||||
|
||||
list.append(comic);
|
||||
}
|
||||
|
||||
db.close();
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
QList<ComicDB> DBHelper::getReading(qulonglong libraryId)
|
||||
{
|
||||
QString libraryPath = DBHelper::getLibraries().getPath(libraryId);
|
||||
QSqlDatabase db = DataBaseManagement::loadDatabase(libraryPath+"/.yacreaderlibrary");
|
||||
|
||||
QList<ComicDB> list;
|
||||
|
||||
{
|
||||
QSqlQuery selectQuery(db);
|
||||
selectQuery.prepare("SELECT c.id,c.parentId,c.fileName,ci.title,ci.currentPage,ci.numPages,ci.hash,ci.read,ci.coverSizeRatio "
|
||||
"FROM comic c INNER JOIN comic_info ci ON (c.comicInfoId = ci.id) "
|
||||
"WHERE ci.hasBeenOpened = 1 AND ci.read = 0 AND ci.currentPage != ci.numPages AND ci.currentPage != 1 "
|
||||
"ORDER BY ci.lastTimeOpened DESC");
|
||||
selectQuery.exec();
|
||||
|
||||
while (selectQuery.next())
|
||||
{
|
||||
ComicDB comic;
|
||||
|
||||
comic.id = selectQuery.value(0).toULongLong();
|
||||
comic.parentId = selectQuery.value(1).toULongLong();
|
||||
comic.name = selectQuery.value(2).toString();
|
||||
comic.info.title = selectQuery.value(3).toString();
|
||||
comic.info.currentPage = selectQuery.value(4).toInt();
|
||||
comic.info.numPages = selectQuery.value(5).toInt();
|
||||
comic.info.hash = selectQuery.value(6).toString();
|
||||
comic.info.read = selectQuery.value(7).toBool();
|
||||
comic.info.coverSizeRatio = selectQuery.value(8).toFloat();
|
||||
|
||||
list.append(comic);
|
||||
}
|
||||
|
||||
db.close();
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
QList<ReadingList> DBHelper::getReadingLists(qulonglong libraryId)
|
||||
{
|
||||
QString libraryPath = DBHelper::getLibraries().getPath(libraryId);
|
||||
QSqlDatabase db = DataBaseManagement::loadDatabase(libraryPath+"/.yacreaderlibrary");
|
||||
|
||||
QList<ReadingList> list;
|
||||
|
||||
QSqlQuery selectQuery("SELECT * from reading_list WHERE parentId IS NULL ORDER BY name DESC",db);
|
||||
|
||||
selectQuery.exec();
|
||||
|
||||
QSqlRecord record = selectQuery.record();
|
||||
|
||||
int name = record.indexOf("name");
|
||||
int id = record.indexOf("id");
|
||||
int ordering = record.indexOf("ordering");
|
||||
|
||||
while (selectQuery.next())
|
||||
{
|
||||
ReadingList item(selectQuery.value(name).toString(), selectQuery.value(id).toLongLong(),selectQuery.value(ordering).toInt());
|
||||
|
||||
if(list.isEmpty())
|
||||
{
|
||||
list.append(item);
|
||||
}
|
||||
else
|
||||
{
|
||||
int i= 0;
|
||||
while(i<list.length() && naturalSortLessThanCI(list.at(i).getName(),item.getName()))
|
||||
i++;
|
||||
list.insert(i,item);
|
||||
}
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
QList<ComicDB> DBHelper::getReadingListFullContent(qulonglong libraryId, qulonglong readingListId)
|
||||
{
|
||||
QString libraryPath = DBHelper::getLibraries().getPath(libraryId);
|
||||
QSqlDatabase db = DataBaseManagement::loadDatabase(libraryPath+"/.yacreaderlibrary");
|
||||
|
||||
QList<ComicDB> list;
|
||||
|
||||
{
|
||||
QList<qulonglong> ids;
|
||||
ids << readingListId;
|
||||
|
||||
QSqlQuery subfolders(db);
|
||||
subfolders.prepare("SELECT id "
|
||||
"FROM reading_list "
|
||||
"WHERE parentId = :parentId "
|
||||
"ORDER BY ordering ASC");
|
||||
subfolders.bindValue(":parentId", readingListId);
|
||||
subfolders.exec();
|
||||
while(subfolders.next())
|
||||
ids << subfolders.value(0).toULongLong();
|
||||
|
||||
foreach(qulonglong id, ids)
|
||||
{
|
||||
QSqlQuery selectQuery(db);
|
||||
selectQuery.prepare("SELECT c.id,c.parentId,c.fileName,ci.title,ci.currentPage,ci.numPages,ci.hash,ci.read "
|
||||
"FROM comic c INNER JOIN comic_info ci ON (c.comicInfoId = ci.id) "
|
||||
"INNER JOIN comic_reading_list crl ON (c.id == crl.comic_id) "
|
||||
"WHERE crl.reading_list_id = :parentReadingList "
|
||||
"ORDER BY crl.ordering");
|
||||
selectQuery.bindValue(":parentReadingList", id);
|
||||
selectQuery.exec();
|
||||
|
||||
while (selectQuery.next())
|
||||
{
|
||||
ComicDB comic;
|
||||
|
||||
comic.id = selectQuery.value(0).toULongLong();
|
||||
comic.parentId = selectQuery.value(1).toULongLong();
|
||||
comic.name = selectQuery.value(2).toString();
|
||||
comic.info.title = selectQuery.value(3).toString();
|
||||
comic.info.currentPage = selectQuery.value(4).toInt();
|
||||
comic.info.numPages = selectQuery.value(5).toInt();
|
||||
comic.info.hash = selectQuery.value(6).toString();
|
||||
comic.info.read = selectQuery.value(7).toBool();
|
||||
|
||||
list.append(comic);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
//objects management
|
||||
//deletes
|
||||
void DBHelper::removeFromDB(LibraryItem * item, QSqlDatabase & db)
|
||||
{
|
||||
if(item->isDir())
|
||||
DBHelper::removeFromDB(dynamic_cast<Folder *>(item),db);
|
||||
DBHelper::removeFromDB(dynamic_cast<Folder *>(item),db);
|
||||
else
|
||||
DBHelper::removeFromDB(dynamic_cast<ComicDB *>(item),db);
|
||||
DBHelper::removeFromDB(dynamic_cast<ComicDB *>(item),db);
|
||||
}
|
||||
void DBHelper::removeFromDB(Folder * folder, QSqlDatabase & db)
|
||||
{
|
||||
@ -296,7 +537,13 @@ void DBHelper::update(ComicInfo * comicInfo, QSqlDatabase & db)
|
||||
"rating = :rating,"
|
||||
|
||||
//new 7.1 fields
|
||||
"comicVineID = :comicVineID"
|
||||
"comicVineID = :comicVineID,"
|
||||
|
||||
//new 9.5 fields
|
||||
"lastTimeOpened = :lastTimeOpened,"
|
||||
|
||||
"coverSizeRatio = :coverSizeRatio,"
|
||||
"originalCoverSize = :originalCoverSize"
|
||||
//--
|
||||
" WHERE id = :id ");
|
||||
|
||||
@ -351,6 +598,11 @@ void DBHelper::update(ComicInfo * comicInfo, QSqlDatabase & db)
|
||||
|
||||
updateComicInfo.bindValue(":comicVineID", comicInfo->comicVineID);
|
||||
|
||||
updateComicInfo.bindValue(":lastTimeOpened", comicInfo->lastTimeOpened);
|
||||
|
||||
updateComicInfo.bindValue(":coverSizeRatio", comicInfo->coverSizeRatio);
|
||||
updateComicInfo.bindValue(":originalCoverSize", comicInfo->originalCoverSize);
|
||||
|
||||
updateComicInfo.exec();
|
||||
}
|
||||
|
||||
@ -379,6 +631,51 @@ void DBHelper::update(const Folder & folder, QSqlDatabase &db)
|
||||
updateFolderInfo.exec();
|
||||
}
|
||||
|
||||
void DBHelper::updateChildrenInfo(const Folder & folder, QSqlDatabase & db)
|
||||
{
|
||||
QSqlQuery updateFolderInfo(db);
|
||||
updateFolderInfo.prepare("UPDATE folder SET "
|
||||
"numChildren = :numChildren, "
|
||||
"firstChildHash = :firstChildHash "
|
||||
"WHERE id = :id ");
|
||||
updateFolderInfo.bindValue(":numChildren", folder.getNumChildren());
|
||||
updateFolderInfo.bindValue(":firstChildHash", folder.getFirstChildHash());
|
||||
updateFolderInfo.bindValue(":id", folder.id);
|
||||
updateFolderInfo.exec();
|
||||
}
|
||||
|
||||
void DBHelper::updateChildrenInfo(qulonglong folderId, QSqlDatabase & db)
|
||||
{
|
||||
QList<LibraryItem *> subfolders = DBHelper::getFoldersFromParent(folderId,db,false);
|
||||
QList<LibraryItem *> comics = DBHelper::getComicsFromParent(folderId,db,true);
|
||||
|
||||
ComicDB * firstComic = NULL;
|
||||
if(comics.count() > 0)
|
||||
firstComic = static_cast<ComicDB *>(comics.first());
|
||||
|
||||
QSqlQuery updateFolderInfo(db);
|
||||
updateFolderInfo.prepare("UPDATE folder SET "
|
||||
"numChildren = :numChildren, "
|
||||
"firstChildHash = :firstChildHash "
|
||||
"WHERE id = :id ");
|
||||
updateFolderInfo.bindValue(":numChildren", subfolders.count() + comics.count());
|
||||
updateFolderInfo.bindValue(":firstChildHash", firstComic != NULL ? firstComic->info.hash : "");
|
||||
updateFolderInfo.bindValue(":id", folderId);
|
||||
updateFolderInfo.exec();
|
||||
}
|
||||
|
||||
void DBHelper::updateChildrenInfo(QSqlDatabase & db)
|
||||
{
|
||||
QSqlQuery selectQuery(db); //TODO check
|
||||
selectQuery.prepare("SELECT id FROM folder");
|
||||
selectQuery.exec();
|
||||
|
||||
while (selectQuery.next())
|
||||
{
|
||||
DBHelper::updateChildrenInfo(selectQuery.value(0).toULongLong(), db);
|
||||
}
|
||||
}
|
||||
|
||||
void DBHelper::updateProgress(qulonglong libraryId, const ComicInfo &comicInfo)
|
||||
{
|
||||
QString libraryPath = DBHelper::getLibraries().getPath(libraryId);
|
||||
@ -402,12 +699,14 @@ void DBHelper::updateReadingRemoteProgress(const ComicInfo &comicInfo, QSqlDatab
|
||||
"read = :read, "
|
||||
"currentPage = :currentPage, "
|
||||
"hasBeenOpened = :hasBeenOpened, "
|
||||
"lastTimeOpened = :lastTimeOpened, "
|
||||
"rating = :rating"
|
||||
" WHERE id = :id ");
|
||||
|
||||
updateComicInfo.bindValue(":read", comicInfo.read?1:0);
|
||||
updateComicInfo.bindValue(":currentPage", comicInfo.currentPage);
|
||||
updateComicInfo.bindValue(":hasBeenOpened", comicInfo.hasBeenOpened?1:0);
|
||||
updateComicInfo.bindValue(":lastTimeOpened", QDateTime::currentSecsSinceEpoch());
|
||||
updateComicInfo.bindValue(":id", comicInfo.id);
|
||||
updateComicInfo.bindValue(":rating", comicInfo.rating);
|
||||
updateComicInfo.exec();
|
||||
@ -492,7 +791,7 @@ void DBHelper::reasignOrderToComicsInFavorites(QList<qulonglong> comicIds, QSqlD
|
||||
QSqlQuery updateOrdering(db);
|
||||
updateOrdering.prepare("UPDATE comic_default_reading_list SET "
|
||||
"ordering = :ordering "
|
||||
"WHERE comic_id = :comic_id AND default_reading_list_id = 0");
|
||||
"WHERE comic_id = :comic_id AND default_reading_list_id = 1");
|
||||
db.transaction();
|
||||
int order = 0;
|
||||
foreach(qulonglong id, comicIds)
|
||||
@ -554,6 +853,7 @@ qulonglong DBHelper::insert(Folder * folder, QSqlDatabase & db)
|
||||
query.bindValue(":name", folder->name);
|
||||
query.bindValue(":path", folder->path);
|
||||
query.exec();
|
||||
|
||||
return query.lastInsertId().toULongLong();
|
||||
}
|
||||
|
||||
@ -562,10 +862,12 @@ qulonglong DBHelper::insert(ComicDB * comic, QSqlDatabase & db)
|
||||
if(!comic->info.existOnDb)
|
||||
{
|
||||
QSqlQuery comicInfoInsert(db);
|
||||
comicInfoInsert.prepare("INSERT INTO comic_info (hash,numPages) "
|
||||
"VALUES (:hash,:numPages)");
|
||||
comicInfoInsert.prepare("INSERT INTO comic_info (hash,numPages,coverSizeRatio,originalCoverSize) "
|
||||
"VALUES (:hash,:numPages,:coverSizeRatio,:originalCoverSize)");
|
||||
comicInfoInsert.bindValue(":hash", comic->info.hash);
|
||||
comicInfoInsert.bindValue(":numPages", comic->info.numPages);
|
||||
comicInfoInsert.bindValue(":coverSizeRatio", comic->info.coverSizeRatio);
|
||||
comicInfoInsert.bindValue(":originalCoverSize", comic->info.originalCoverSize);
|
||||
comicInfoInsert.exec();
|
||||
comic->info.id =comicInfoInsert.lastInsertId().toULongLong();
|
||||
comic->_hasCover = false;
|
||||
@ -581,6 +883,7 @@ qulonglong DBHelper::insert(ComicDB * comic, QSqlDatabase & db)
|
||||
query.bindValue(":name", comic->name);
|
||||
query.bindValue(":path", comic->path);
|
||||
query.exec();
|
||||
|
||||
return query.lastInsertId().toULongLong();
|
||||
}
|
||||
|
||||
@ -703,13 +1006,22 @@ QList<LibraryItem *> DBHelper::getFoldersFromParent(qulonglong parentId, QSqlDat
|
||||
int name = record.indexOf("name");
|
||||
int path = record.indexOf("path");
|
||||
int id = record.indexOf("id");
|
||||
int numChildren = record.indexOf("numChildren");
|
||||
int firstChildHash = record.indexOf("firstChildHash");
|
||||
int customImage = record.indexOf("customImage");
|
||||
|
||||
Folder * currentItem;
|
||||
while (selectQuery.next())
|
||||
{
|
||||
//TODO sort by sort indicator and name
|
||||
currentItem = new Folder(selectQuery.value(id).toULongLong(),parentId,selectQuery.value(name).toString(),selectQuery.value(path).toString());
|
||||
int lessThan = 0;
|
||||
currentItem = new Folder(selectQuery.value(id).toULongLong(),parentId,selectQuery.value(name).toString(),selectQuery.value(path).toString());
|
||||
|
||||
if(!selectQuery.value(numChildren).isNull() && selectQuery.value(numChildren).isValid())
|
||||
currentItem->setNumChildren(selectQuery.value(numChildren).toInt());
|
||||
currentItem->setFirstChildHash(selectQuery.value(firstChildHash).toString());
|
||||
currentItem->setCustomImage(selectQuery.value(customImage).toString());
|
||||
|
||||
int lessThan = 0;
|
||||
|
||||
if(list.isEmpty() || !sort)
|
||||
list.append(currentItem);
|
||||
@ -721,7 +1033,7 @@ QList<LibraryItem *> DBHelper::getFoldersFromParent(qulonglong parentId, QSqlDat
|
||||
QList<LibraryItem *>::iterator i;
|
||||
i = list.end();
|
||||
i--;
|
||||
while ((0 > (lessThan = naturalSortLessThanCI(nameCurrent,nameLast))) && i != list.begin())
|
||||
while ((0 > (lessThan = naturalCompare(nameCurrent,nameLast,Qt::CaseInsensitive))) && i != list.begin())
|
||||
{
|
||||
i--;
|
||||
nameLast = (*i)->name;
|
||||
@ -929,6 +1241,63 @@ QList<LibraryItem *> DBHelper::getComicsFromParent(qulonglong parentId, QSqlData
|
||||
return list;
|
||||
}
|
||||
|
||||
QList<Label> DBHelper::getLabels(qulonglong libraryId)
|
||||
{
|
||||
QString libraryPath = DBHelper::getLibraries().getPath(libraryId);
|
||||
QSqlDatabase db = DataBaseManagement::loadDatabase(libraryPath+"/.yacreaderlibrary");
|
||||
|
||||
QSqlQuery selectQuery("SELECT * FROM label ORDER BY ordering,name",db); //TODO add some kind of
|
||||
QList<Label> labels;
|
||||
|
||||
QSqlRecord record = selectQuery.record();
|
||||
|
||||
int name = record.indexOf("name");
|
||||
int color = record.indexOf("color");
|
||||
int id = record.indexOf("id");
|
||||
int ordering = record.indexOf("ordering");
|
||||
|
||||
while(selectQuery.next())
|
||||
{
|
||||
Label item(selectQuery.value(name).toString(),
|
||||
selectQuery.value(id).toLongLong(),
|
||||
static_cast<YACReader::LabelColors>(selectQuery.value(color).toInt()));
|
||||
|
||||
if(labels.isEmpty())
|
||||
{
|
||||
labels << item;
|
||||
}
|
||||
else
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
while (i < labels.count() && (labels.at(i).getColorID() < item.getColorID()) )
|
||||
i++;
|
||||
|
||||
if(i < labels.count())
|
||||
{
|
||||
if(labels.at(i).getColorID() == item.getColorID()) //sort by name
|
||||
{
|
||||
while( i < labels.count() && labels.at(i).getColorID() == item.getColorID() && naturalSortLessThanCI(labels.at(i).getName(),item.getName()))
|
||||
i++;
|
||||
}
|
||||
}
|
||||
if(i >= labels.count())
|
||||
{
|
||||
labels << item;
|
||||
}
|
||||
else
|
||||
{
|
||||
labels.insert(i,item);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
db.close();
|
||||
QSqlDatabase::removeDatabase(libraryPath);
|
||||
|
||||
return labels;
|
||||
}
|
||||
|
||||
//loads
|
||||
Folder DBHelper::loadFolder(qulonglong id, QSqlDatabase & db)
|
||||
{
|
||||
@ -948,6 +1317,9 @@ Folder DBHelper::loadFolder(qulonglong id, QSqlDatabase & db)
|
||||
int path = record.indexOf("path");
|
||||
int finished = record.indexOf("finished");
|
||||
int completed = record.indexOf("completed");
|
||||
int numChildren = record.indexOf("numChildren");
|
||||
int firstChildHash = record.indexOf("firstChildHash");
|
||||
int customImage = record.indexOf("customImage");
|
||||
|
||||
if(query.next())
|
||||
{
|
||||
@ -955,9 +1327,16 @@ Folder DBHelper::loadFolder(qulonglong id, QSqlDatabase & db)
|
||||
folder.name = query.value(name).toString();
|
||||
folder.path = query.value(path).toString();
|
||||
folder.knownId = true;
|
||||
|
||||
//new 7.1
|
||||
folder.setFinished(query.value(finished).toBool());
|
||||
folder.setCompleted(query.value(completed).toBool());
|
||||
|
||||
//new 9.5
|
||||
if(!query.value(numChildren).isNull() && query.value(numChildren).isValid())
|
||||
folder.setNumChildren(query.value(numChildren).toInt());
|
||||
folder.setFirstChildHash(query.value(firstChildHash).toString());
|
||||
folder.setCustomImage(query.value(customImage).toString());
|
||||
}
|
||||
|
||||
return folder;
|
||||
@ -980,6 +1359,9 @@ Folder DBHelper::loadFolder(const QString &folderName, qulonglong parentId, QSql
|
||||
int path = record.indexOf("path");
|
||||
int finished = record.indexOf("finished");
|
||||
int completed = record.indexOf("completed");
|
||||
int numChildren = record.indexOf("numChildren");
|
||||
int firstChildHash = record.indexOf("firstChildHash");
|
||||
int customImage = record.indexOf("customImage");
|
||||
|
||||
folder.parentId = parentId;
|
||||
if(query.next())
|
||||
@ -988,9 +1370,16 @@ Folder DBHelper::loadFolder(const QString &folderName, qulonglong parentId, QSql
|
||||
folder.name = query.value(name).toString();
|
||||
folder.path = query.value(path).toString();
|
||||
folder.knownId = true;
|
||||
|
||||
//new 7.1
|
||||
folder.setFinished(query.value(finished).toBool());
|
||||
folder.setCompleted(query.value(completed).toBool());
|
||||
|
||||
//new 9.5
|
||||
if(!query.value(numChildren).isNull() && query.value(numChildren).isValid())
|
||||
folder.setNumChildren(query.value(numChildren).toInt());
|
||||
folder.setFirstChildHash(query.value(firstChildHash).toString());
|
||||
folder.setCustomImage(query.value(customImage).toString());
|
||||
}
|
||||
|
||||
return folder;
|
||||
@ -1108,6 +1497,11 @@ ComicInfo DBHelper::loadComicInfo(QString hash, QSqlDatabase & db)
|
||||
|
||||
int comicVineID = record.indexOf("comicVineID");
|
||||
|
||||
int lastTimeOpened = record.indexOf("lastTimeOpened");
|
||||
|
||||
int coverSizeRatio = record.indexOf("coverSizeRatio");
|
||||
int originalCoverSize = record.indexOf("originalCoverSize");
|
||||
|
||||
if(findComicInfo.next())
|
||||
{
|
||||
comicInfo.hash = hash;
|
||||
@ -1126,7 +1520,6 @@ ComicInfo DBHelper::loadComicInfo(QString hash, QSqlDatabase & db)
|
||||
comicInfo.gamma = findComicInfo.value(gamma).toInt();
|
||||
comicInfo.rating = findComicInfo.value(rating).toInt();
|
||||
//--
|
||||
|
||||
comicInfo.title = findComicInfo.value(title);
|
||||
comicInfo.numPages = findComicInfo.value(numPages);
|
||||
|
||||
@ -1162,6 +1555,13 @@ ComicInfo DBHelper::loadComicInfo(QString hash, QSqlDatabase & db)
|
||||
|
||||
comicInfo.comicVineID = findComicInfo.value(comicVineID);
|
||||
|
||||
//new 9.5 fields
|
||||
comicInfo.lastTimeOpened = findComicInfo.value(lastTimeOpened);
|
||||
|
||||
comicInfo.coverSizeRatio = findComicInfo.value(coverSizeRatio);
|
||||
comicInfo.originalCoverSize = findComicInfo.value(originalCoverSize);
|
||||
//--
|
||||
|
||||
comicInfo.existOnDb = true;
|
||||
}
|
||||
else
|
||||
|
@ -9,11 +9,13 @@ class QString;
|
||||
class ComicDB;
|
||||
class Folder;
|
||||
class LibraryItem;
|
||||
class Label;
|
||||
class QSqlDatabase;
|
||||
class ComicInfo;
|
||||
class QSqlRecord;
|
||||
class QSqlQuery;
|
||||
class YACReaderLibraries;
|
||||
class ReadingList;
|
||||
|
||||
class DBHelper
|
||||
{
|
||||
@ -23,18 +25,24 @@ public:
|
||||
static QList<LibraryItem *> getFolderSubfoldersFromLibrary(qulonglong libraryId, qulonglong folderId);
|
||||
static QList<LibraryItem *> getFolderComicsFromLibrary(qulonglong libraryId, qulonglong folderId);
|
||||
static QList<LibraryItem *> getFolderComicsFromLibrary(qulonglong libraryId, qulonglong folderId, bool sort);
|
||||
static quint32 getNumChildrenFromFolder(qulonglong libraryId, qulonglong folderId);
|
||||
static qulonglong getParentFromComicFolderId(qulonglong libraryId, qulonglong id);
|
||||
static ComicDB getComicInfo(qulonglong libraryId, qulonglong id);
|
||||
static QList<ComicDB> getSiblings(qulonglong libraryId, qulonglong parentId);
|
||||
static QString getFolderName(qulonglong libraryId, qulonglong id);
|
||||
static QList<QString> getLibrariesNames();
|
||||
static QString getLibraryName(int id);
|
||||
static QList<ComicDB> getLabelComics(qulonglong libraryId, qulonglong labelId);
|
||||
static QList<ComicDB> getFavorites(qulonglong libraryId);
|
||||
static QList<ComicDB> getReading(qulonglong libraryId);
|
||||
static QList<ReadingList> getReadingLists(qulonglong libraryId);
|
||||
static QList<ComicDB> getReadingListFullContent(qulonglong libraryId, qulonglong readingListId);
|
||||
|
||||
//objects management
|
||||
//deletes
|
||||
static void removeFromDB(LibraryItem * item, QSqlDatabase & db);
|
||||
static void removeFromDB(Folder * folder, QSqlDatabase & db);
|
||||
static void removeFromDB(ComicDB * comic, QSqlDatabase & db);
|
||||
static void removeFromDB(LibraryItem * item, QSqlDatabase & db);
|
||||
static void removeFromDB(Folder * folder, QSqlDatabase & db);
|
||||
static void removeFromDB(ComicDB * comic, QSqlDatabase & db);
|
||||
static void removeLabelFromDB(qulonglong id, QSqlDatabase & db);
|
||||
static void removeListFromDB(qulonglong id, QSqlDatabase & db);
|
||||
//logic deletes
|
||||
@ -42,8 +50,8 @@ public:
|
||||
static void deleteComicsFromLabel(const QList<ComicDB> & comicsList, qulonglong labelId, QSqlDatabase & db);
|
||||
static void deleteComicsFromReadingList(const QList<ComicDB> & comicsList, qulonglong readingListId, QSqlDatabase & db);
|
||||
//inserts
|
||||
static qulonglong insert(Folder * folder, QSqlDatabase & db);
|
||||
static qulonglong insert(ComicDB * comic, QSqlDatabase & db);
|
||||
static qulonglong insert(Folder * folder, QSqlDatabase & db);
|
||||
static qulonglong insert(ComicDB * comic, QSqlDatabase & db);
|
||||
static qulonglong insertLabel(const QString & name, YACReader::LabelColors color , QSqlDatabase & db);
|
||||
static qulonglong insertReadingList(const QString & name, QSqlDatabase & db);
|
||||
static qulonglong insertReadingSubList(const QString & name, qulonglong parentId, int ordering, QSqlDatabase & db);
|
||||
@ -56,6 +64,9 @@ public:
|
||||
static void update(ComicInfo * comicInfo, QSqlDatabase & db);
|
||||
static void updateRead(ComicInfo * comicInfo, QSqlDatabase & db);
|
||||
static void update(const Folder & folder, QSqlDatabase & db);
|
||||
static void updateChildrenInfo(const Folder & folder, QSqlDatabase & db);
|
||||
static void updateChildrenInfo(qulonglong folderId, QSqlDatabase & db);
|
||||
static void updateChildrenInfo(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);
|
||||
@ -69,7 +80,9 @@ public:
|
||||
static QList<LibraryItem *> getFoldersFromParent(qulonglong parentId, QSqlDatabase & db, bool sort = true);
|
||||
static QList<ComicDB> getSortedComicsFromParent(qulonglong parentId, QSqlDatabase & db);
|
||||
static QList<LibraryItem *> getComicsFromParent(qulonglong parentId, QSqlDatabase & db, bool sort = true);
|
||||
//load
|
||||
static QList<Label> getLabels(qulonglong libraryId);
|
||||
|
||||
//load
|
||||
static Folder loadFolder(qulonglong id, QSqlDatabase & db);
|
||||
static Folder loadFolder(const QString & folderName, qulonglong parentId, QSqlDatabase & db);
|
||||
static ComicDB loadComic(qulonglong id, QSqlDatabase & db);
|
||||
|
@ -42,8 +42,6 @@ YACReaderActivityIndicatorWidget::YACReaderActivityIndicatorWidget(QWidget * par
|
||||
normal->setPixmap(line);
|
||||
glow->setPixmap(glowLine);
|
||||
|
||||
|
||||
|
||||
QHBoxLayout * layout = new QHBoxLayout();
|
||||
|
||||
layout->addWidget(normal,0,Qt::AlignVCenter);
|
||||
@ -155,6 +153,7 @@ ImportWidget::ImportWidget(QWidget *parent) :
|
||||
|
||||
QPushButton * stop = new QPushButton(tr("stop"));
|
||||
stop->setSizePolicy(QSizePolicy::Maximum,QSizePolicy::Maximum);
|
||||
stopButton = stop;
|
||||
|
||||
QVBoxLayout * layout = new QVBoxLayout(this);
|
||||
QHBoxLayout * buttonLayout = new QHBoxLayout();
|
||||
@ -192,7 +191,7 @@ ImportWidget::ImportWidget(QWidget *parent) :
|
||||
layout->addLayout(buttonLayout,0);
|
||||
layout->addSpacing(10);
|
||||
layout->addStretch();
|
||||
portadasLabel = new QLabel("<font color=\"#565959\">"+tr("Some of the comics being added...")+"</font>");
|
||||
coversLabel = new QLabel("<font color=\"#565959\">"+tr("Some of the comics being added...")+"</font>");
|
||||
|
||||
hideButton = new QToolButton(this);
|
||||
hideButton->setFixedSize(25,18);
|
||||
@ -202,7 +201,7 @@ ImportWidget::ImportWidget(QWidget *parent) :
|
||||
|
||||
connect(hideButton,SIGNAL(toggled(bool)),this,SLOT(showCovers(bool)));
|
||||
|
||||
layout->addWidget(portadasLabel,0,Qt::AlignHCenter);
|
||||
layout->addWidget(coversLabel,0,Qt::AlignHCenter);
|
||||
layout->addWidget(coversViewContainer);
|
||||
//layout->addStretch();
|
||||
layout->addWidget(currentComicLabel,0,Qt::AlignHCenter);
|
||||
@ -346,6 +345,11 @@ void ImportWidget::setImportLook()
|
||||
iconLabel->setPixmap(QPixmap(":/images/importingIcon.png"));
|
||||
text->setText("<font color=\"#495252\">"+tr("Importing comics")+"</font>");
|
||||
textDescription->setText("<font color=\"#565959\">"+tr("<p>YACReaderLibrary is now creating a new library.</p><p>Create a library could take several minutes. You can stop the process and update the library later for completing the task.</p>")+"</font>");
|
||||
|
||||
stopButton->setVisible(true);
|
||||
coversLabel->setVisible(true);
|
||||
coversViewContainer->setVisible(true);
|
||||
hideButton->setVisible(true);
|
||||
}
|
||||
|
||||
void ImportWidget::setUpdateLook()
|
||||
@ -353,6 +357,23 @@ void ImportWidget::setUpdateLook()
|
||||
iconLabel->setPixmap(QPixmap(":/images/updatingIcon.png"));
|
||||
text->setText("<font color=\"#495252\">"+tr("Updating the library")+"</font>");
|
||||
textDescription->setText("<font color=\"#565959\">"+tr("<p>The current library is being updated. For faster updates, please, update your libraries frequently.</p><p>You can stop the process and continue updating this library later.</p>")+"</font>");
|
||||
|
||||
stopButton->setVisible(true);
|
||||
coversLabel->setVisible(true);
|
||||
coversViewContainer->setVisible(true);
|
||||
hideButton->setVisible(true);
|
||||
}
|
||||
|
||||
void ImportWidget::setUpgradeLook()
|
||||
{
|
||||
iconLabel->setPixmap(QPixmap(":/images/updatingIcon.png"));
|
||||
text->setText("<font color=\"#495252\">"+tr("Upgrading the library")+"</font>");
|
||||
textDescription->setText("<font color=\"#565959\">"+tr("<p>The current library is being upgraded, please wait.</p>")+"</font>");
|
||||
|
||||
stopButton->setVisible(false);
|
||||
coversLabel->setVisible(false);
|
||||
coversViewContainer->setVisible(false);
|
||||
hideButton->setVisible(false);
|
||||
}
|
||||
|
||||
void ImportWidget::clearScene()
|
||||
@ -363,7 +384,7 @@ void ImportWidget::clearScene()
|
||||
|
||||
void ImportWidget::showCovers(bool hide)
|
||||
{
|
||||
portadasLabel->setHidden(hide);
|
||||
coversLabel->setHidden(hide);
|
||||
coversViewContainer->setHidden(hide);
|
||||
}
|
||||
|
||||
|
@ -1,16 +1,9 @@
|
||||
#ifndef IMPORT_WIDGET_H
|
||||
#define IMPORT_WIDGET_H
|
||||
|
||||
#include <QWidget>
|
||||
|
||||
class QLabel;
|
||||
class QGraphicsView;
|
||||
class QGraphicsScene;
|
||||
class QElapsedTimer;
|
||||
class QVBoxLayout;
|
||||
class QToolButton;
|
||||
class QResizeEvent;
|
||||
class QPropertyAnimation;
|
||||
#include <QtWidgets>
|
||||
|
||||
|
||||
class ImportWidget : public QWidget
|
||||
{
|
||||
@ -28,11 +21,12 @@ public slots:
|
||||
void clearScene();
|
||||
void setImportLook();
|
||||
void setUpdateLook();
|
||||
void setUpgradeLook();
|
||||
void showCovers(bool hide);
|
||||
|
||||
private:
|
||||
QLabel * currentComicLabel;
|
||||
QLabel * portadasLabel;
|
||||
QLabel * coversLabel;
|
||||
QLabel * iconLabel;
|
||||
QLabel * text;
|
||||
QLabel * textDescription;
|
||||
@ -40,6 +34,7 @@ private:
|
||||
QGraphicsView * coversView;
|
||||
QGraphicsScene * coversScene;
|
||||
QPropertyAnimation * scrollAnimation;
|
||||
QPushButton * stopButton;
|
||||
|
||||
int previousWidth;
|
||||
bool updatingCovers;
|
||||
|
@ -150,6 +150,9 @@ void LibraryCreator::run()
|
||||
_database.transaction();
|
||||
//se crea la librería
|
||||
create(QDir(_source));
|
||||
|
||||
DBHelper::updateChildrenInfo(_database);
|
||||
|
||||
_database.commit();
|
||||
_database.close();
|
||||
QSqlDatabase::removeDatabase(_database.connectionName());
|
||||
@ -187,6 +190,12 @@ void LibraryCreator::run()
|
||||
{
|
||||
update(QDir(_source));
|
||||
}
|
||||
|
||||
if(partialUpdate)
|
||||
DBHelper::updateChildrenInfo(folderDestinationModelIndex.data(FolderModel::IdRole).toULongLong(),_database);
|
||||
else
|
||||
DBHelper::updateChildrenInfo(_database);
|
||||
|
||||
_database.commit();
|
||||
_database.close();
|
||||
QSqlDatabase::removeDatabase(_target);
|
||||
@ -231,7 +240,7 @@ qulonglong LibraryCreator::insertFolders()
|
||||
if(!(i->knownId))
|
||||
{
|
||||
i->setFather(currentId);
|
||||
currentId = DBHelper::insert(&(*i),_database);//insertFolder(currentId,*i);
|
||||
currentId = DBHelper::insert(&(*i),_database);//insertFolder(currentId,*i);
|
||||
i->setId(currentId);
|
||||
}
|
||||
else
|
||||
@ -300,12 +309,14 @@ void LibraryCreator::insertComic(const QString & relativePath,const QFileInfo &
|
||||
QString hash = QString(crypto.result().toHex().constData()) + QString::number(fileInfo.size());
|
||||
ComicDB comic = DBHelper::loadComic(fileInfo.fileName(),relativePath,hash,_database);
|
||||
int numPages = 0;
|
||||
QPair<int,int> originalCoverSize = {0,0};
|
||||
bool exists = checkCover(hash);
|
||||
if(! ( comic.hasCover() && exists))
|
||||
{
|
||||
ThumbnailCreator tc(QDir::cleanPath(fileInfo.absoluteFilePath()),_target+"/covers/"+hash+".jpg",comic.info.coverPage.toInt());
|
||||
tc.create();
|
||||
numPages = tc.getNumPages();
|
||||
originalCoverSize = tc.getOriginalCoverSize();
|
||||
if (numPages > 0)
|
||||
{
|
||||
emit(comicAdded(relativePath,_target+"/covers/"+hash+".jpg"));
|
||||
@ -317,6 +328,12 @@ void LibraryCreator::insertComic(const QString & relativePath,const QFileInfo &
|
||||
//en este punto sabemos que todos los folders que hay en _currentPath, deberían estar añadidos a la base de datos
|
||||
insertFolders();
|
||||
comic.info.numPages = numPages;
|
||||
if(originalCoverSize.second > 0)
|
||||
{
|
||||
comic.info.originalCoverSize = QString("%1x%2").arg(originalCoverSize.first).arg(originalCoverSize.second);
|
||||
comic.info.coverSizeRatio = static_cast<float>(originalCoverSize.first) / originalCoverSize.second;
|
||||
}
|
||||
|
||||
comic.parentId = _currentPathFolders.last().id;
|
||||
DBHelper::insert(&comic,_database);
|
||||
}
|
||||
@ -631,6 +648,7 @@ void ThumbnailCreator::create()
|
||||
QImage p = pdfComic->page(_coverPage-1)->renderToImage(72,72);
|
||||
#endif //
|
||||
_cover = p;
|
||||
_coverSize = QPair<int,int>(p.width(), p.height());
|
||||
if(_target!="")
|
||||
{
|
||||
QImage scaled;
|
||||
@ -642,7 +660,7 @@ void ThumbnailCreator::create()
|
||||
{
|
||||
scaled = p.scaledToWidth(480,Qt::SmoothTransformation);
|
||||
}
|
||||
scaled.save(_target,0,75);
|
||||
scaled.save(_target,0,75);
|
||||
}
|
||||
else if(_target!="")
|
||||
{
|
||||
@ -708,6 +726,7 @@ void ThumbnailCreator::create()
|
||||
QImage p;
|
||||
if(p.loadFromData(archive.getRawDataAtIndex(index)))
|
||||
{
|
||||
_coverSize = QPair<int,int>(p.width(), p.height());
|
||||
QImage scaled;
|
||||
if(p.width()>p.height()) //landscape??
|
||||
{
|
||||
|
@ -78,6 +78,7 @@
|
||||
QString _target;
|
||||
QString _currentName;
|
||||
int _numPages;
|
||||
QPair<int,int> _coverSize;
|
||||
QImage _cover;
|
||||
int _coverPage;
|
||||
static bool crash;
|
||||
@ -86,6 +87,7 @@
|
||||
void create();
|
||||
int getNumPages(){return _numPages;}
|
||||
QPixmap getCover(){return QPixmap::fromImage(_cover);}
|
||||
QPair<int,int> getOriginalCoverSize(){return _coverSize;}
|
||||
signals:
|
||||
void openingError(QProcess::ProcessError error);
|
||||
|
||||
|
@ -19,6 +19,8 @@
|
||||
|
||||
#include <iterator>
|
||||
#include <typeinfo>
|
||||
#include <thread>
|
||||
#include <future>
|
||||
|
||||
#include "data_base_management.h"
|
||||
#include "yacreader_global.h"
|
||||
@ -1124,6 +1126,15 @@ void LibraryWindow::createConnections()
|
||||
|
||||
//save covers
|
||||
connect(saveCoversToAction,SIGNAL(triggered()),this,SLOT(saveSelectedCoversTo()));
|
||||
|
||||
//upgrade library
|
||||
connect(this, SIGNAL(libraryUpgraded(QString)), this, SLOT(loadLibrary(QString)), Qt::QueuedConnection);
|
||||
connect(this, SIGNAL(errorUpgradingLibrary(QString)), this, SLOT(showErrorUpgradingLibrary(QString)), Qt::QueuedConnection);
|
||||
}
|
||||
|
||||
void LibraryWindow::showErrorUpgradingLibrary(const QString & path)
|
||||
{
|
||||
QMessageBox::critical(this,tr("Upgrade failed"), tr("There were errors during library upgrade in: ") + path+"/library.ydb");
|
||||
}
|
||||
|
||||
void LibraryWindow::loadLibrary(const QString & name)
|
||||
@ -1139,29 +1150,39 @@ void LibraryWindow::loadLibrary(const QString & name)
|
||||
if(d.exists(path) && d.exists(path+"/library.ydb") && (dbVersion = DataBaseManagement::checkValidDB(path+"/library.ydb")) != "") //si existe en disco la biblioteca seleccionada, y es válida..
|
||||
{
|
||||
int comparation = DataBaseManagement::compareVersions(dbVersion,VERSION);
|
||||
bool updated = false;
|
||||
if(comparation < 0)
|
||||
{
|
||||
int ret = QMessageBox::question(this,tr("Update needed"),tr("This library was created with a previous version of YACReaderLibrary. It needs to be updated. Update now?"),QMessageBox::Yes,QMessageBox::No);
|
||||
if(ret == QMessageBox::Yes)
|
||||
{
|
||||
updated = DataBaseManagement::updateToCurrentVersion(path+"/library.ydb");
|
||||
if(!updated)
|
||||
QMessageBox::critical(this,tr("Update failed"), tr("The current library can't be udpated. Check for write write permissions on: ") + path+"/library.ydb");
|
||||
}
|
||||
else
|
||||
{
|
||||
comicsViewsManager->comicsView->setModel(NULL);
|
||||
foldersView->setModel(NULL);
|
||||
listsView->setModel(NULL);
|
||||
disableAllActions();//TODO comprobar que se deben deshabilitar
|
||||
//será possible renombrar y borrar estas bibliotecas
|
||||
renameLibraryAction->setEnabled(true);
|
||||
removeLibraryAction->setEnabled(true);
|
||||
}
|
||||
}
|
||||
|
||||
if(comparation == 0 || updated) //en caso de que la versión se igual que la actual
|
||||
if(comparation < 0)
|
||||
{
|
||||
int ret = QMessageBox::question(this,tr("Update needed"),tr("This library was created with a previous version of YACReaderLibrary. It needs to be updated. Update now?"),QMessageBox::Yes,QMessageBox::No);
|
||||
if(ret == QMessageBox::Yes)
|
||||
{
|
||||
importWidget->setUpgradeLook();
|
||||
showImportingWidget();
|
||||
|
||||
upgradeLibraryFuture = std::async(std::launch::async, [this, name, path] {
|
||||
bool updated = DataBaseManagement::updateToCurrentVersion(path);
|
||||
|
||||
if(!updated)
|
||||
emit errorUpgradingLibrary(path);
|
||||
|
||||
emit libraryUpgraded(name);
|
||||
});
|
||||
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
comicsViewsManager->comicsView->setModel(NULL);
|
||||
foldersView->setModel(NULL);
|
||||
listsView->setModel(NULL);
|
||||
disableAllActions();//TODO comprobar que se deben deshabilitar
|
||||
//será possible renombrar y borrar estas bibliotecas
|
||||
renameLibraryAction->setEnabled(true);
|
||||
removeLibraryAction->setEnabled(true);
|
||||
}
|
||||
}
|
||||
|
||||
if(comparation == 0) //en caso de que la versión se igual que la actual
|
||||
{
|
||||
foldersModel->setupModelData(path);
|
||||
foldersModelProxy->setSourceModel(foldersModel);
|
||||
@ -1242,7 +1263,7 @@ void LibraryWindow::loadLibrary(const QString & name)
|
||||
|
||||
if(d.exists(path+"/library.ydb"))
|
||||
{
|
||||
QSqlDatabase db = DataBaseManagement::loadDatabase(path);
|
||||
QSqlDatabase db = DataBaseManagement::loadDatabase(path);
|
||||
manageOpeningLibraryError(db.lastError().databaseText() + "-" + db.lastError().driverText());
|
||||
//será possible renombrar y borrar estas bibliotecas
|
||||
renameLibraryAction->setEnabled(true);
|
||||
@ -2487,7 +2508,7 @@ void LibraryWindow::deleteComicsFromDisk()
|
||||
QLOG_TRACE() << comic.parentId;
|
||||
}
|
||||
|
||||
ComicsRemover * remover = new ComicsRemover(indexList,paths);
|
||||
ComicsRemover * remover = new ComicsRemover(indexList,paths,comics.at(0).parentId);
|
||||
QThread * thread = NULL;
|
||||
|
||||
thread = new QThread(this);
|
||||
@ -2500,6 +2521,8 @@ void LibraryWindow::deleteComicsFromDisk()
|
||||
connect(remover, SIGNAL(remove(int)), comicsModel, SLOT(remove(int)));
|
||||
connect(remover, SIGNAL(removeError()),this,SLOT(setRemoveError()));
|
||||
connect(remover, SIGNAL(finished()), comicsModel, SLOT(finishTransaction()));
|
||||
connect(remover, SIGNAL(finished()), comicsModel, SLOT(finishTransaction()));
|
||||
connect(remover, SIGNAL(removedItemsFromFolder(qulonglong)), foldersModel, SLOT(updateFolderChildrenInfo(qulonglong)));
|
||||
|
||||
connect(remover, SIGNAL(finished()),this,SLOT(checkEmptyFolder()));
|
||||
connect(remover, SIGNAL(finished()),this,SLOT(checkRemoveError()));
|
||||
|
@ -12,6 +12,8 @@
|
||||
|
||||
#include "yacreader_navigation_controller.h"
|
||||
|
||||
#include <future>
|
||||
|
||||
#ifdef Q_OS_MAC
|
||||
#include "yacreader_macosx_toolbar.h"
|
||||
#endif
|
||||
@ -286,6 +288,9 @@ protected:
|
||||
public:
|
||||
LibraryWindow();
|
||||
|
||||
signals:
|
||||
void libraryUpgraded(const QString & libraryName);
|
||||
void errorUpgradingLibrary(const QString & path);
|
||||
public slots:
|
||||
void loadLibrary(const QString & path);
|
||||
void selectSubfolder(const QModelIndex & mi, int child);
|
||||
@ -377,6 +382,7 @@ public slots:
|
||||
void setToolbarTitle(const QModelIndex & modelIndex);
|
||||
void saveSelectedCoversTo();
|
||||
void checkMaxNumLibraries();
|
||||
void showErrorUpgradingLibrary(const QString & path);
|
||||
|
||||
void changeEvent(QEvent *event);
|
||||
|
||||
@ -385,10 +391,11 @@ private:
|
||||
Qt::WindowFlags previousWindowFlags;
|
||||
QPoint previousPos;
|
||||
QSize previousSize;
|
||||
std::future<void> upgradeLibraryFuture;
|
||||
QSystemTrayIcon trayIcon;
|
||||
|
||||
private slots:
|
||||
void trayActivation(QSystemTrayIcon::ActivationReason reason);
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -757,15 +757,24 @@ void PropertiesDialog::save()
|
||||
|
||||
itr->info.edited = edited;
|
||||
}
|
||||
updateComics();
|
||||
|
||||
if(comics.count() == 1)
|
||||
{
|
||||
if(coverChanged)// && coverPageEdit->text().toInt() != *comics[0].info.coverPage)
|
||||
{
|
||||
ThumbnailCreator tc(basePath+comics[0].path,basePath+"/.yacreaderlibrary/covers/"+comics[0].info.hash+".jpg", comics[0].info.coverPage.toInt());
|
||||
tc.create();
|
||||
|
||||
if(tc.getOriginalCoverSize().second > 0)
|
||||
{
|
||||
comics[0].info.originalCoverSize = QString("%1x%2").arg(tc.getOriginalCoverSize().first).arg(tc.getOriginalCoverSize().second);
|
||||
comics[0].info.coverSizeRatio = static_cast<float>(tc.getOriginalCoverSize().first) / tc.getOriginalCoverSize().second;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
updateComics();
|
||||
|
||||
close();
|
||||
emit(accepted());
|
||||
}
|
||||
|
@ -114,6 +114,8 @@ class QToolButton;
|
||||
void updateCoverPageNumberLabel(int n);
|
||||
|
||||
bool coverChanged;
|
||||
float coverSizeRatio;
|
||||
QString originalCoverSize;
|
||||
|
||||
public:
|
||||
PropertiesDialog(QWidget * parent = 0);
|
||||
|
@ -1,62 +0,0 @@
|
||||
/**
|
||||
@file
|
||||
@author Stefan Frings
|
||||
*/
|
||||
|
||||
#include "dumpcontroller.h"
|
||||
#include <QVariant>
|
||||
#include <QDateTime>
|
||||
|
||||
DumpController::DumpController(){}
|
||||
|
||||
void DumpController::service(HttpRequest& request, HttpResponse& response) {
|
||||
|
||||
response.setHeader("Content-Type", "text/html; charset=ISO-8859-1");
|
||||
response.setCookie(HttpCookie("firstCookie","hello",600));
|
||||
response.setCookie(HttpCookie("secondCookie","world",600));
|
||||
|
||||
QByteArray body("<html><body>");
|
||||
body.append("<b>Request:</b>");
|
||||
body.append("<br>Method: ");
|
||||
body.append(request.getMethod());
|
||||
body.append("<br>Path: ");
|
||||
body.append(request.getPath());
|
||||
body.append("<br>Version: ");
|
||||
body.append(request.getVersion());
|
||||
|
||||
body.append("<p><b>Headers:</b>");
|
||||
QMapIterator<QByteArray,QByteArray> i(request.getHeaderMap());
|
||||
while (i.hasNext()) {
|
||||
i.next();
|
||||
body.append("<br>");
|
||||
body.append(i.key());
|
||||
body.append("=");
|
||||
body.append(i.value());
|
||||
}
|
||||
|
||||
body.append("<p><b>Parameters:</b>");
|
||||
i=QMapIterator<QByteArray,QByteArray>(request.getParameterMap());
|
||||
while (i.hasNext()) {
|
||||
i.next();
|
||||
body.append("<br>");
|
||||
body.append(i.key());
|
||||
body.append("=");
|
||||
body.append(i.value());
|
||||
}
|
||||
|
||||
body.append("<p><b>Cookies:</b>");
|
||||
i=QMapIterator<QByteArray,QByteArray>(request.getCookieMap());
|
||||
while (i.hasNext()) {
|
||||
i.next();
|
||||
body.append("<br>");
|
||||
body.append(i.key());
|
||||
body.append("=");
|
||||
body.append(i.value());
|
||||
}
|
||||
|
||||
body.append("<p><b>Body:</b><br>");
|
||||
body.append(request.getBody());
|
||||
|
||||
body.append("</body></html>");
|
||||
response.write(body,true);
|
||||
}
|
@ -1,29 +0,0 @@
|
||||
/**
|
||||
@file
|
||||
@author Stefan Frings
|
||||
*/
|
||||
|
||||
#ifndef DUMPCONTROLLER_H
|
||||
#define DUMPCONTROLLER_H
|
||||
|
||||
#include "httprequest.h"
|
||||
#include "httpresponse.h"
|
||||
#include "httprequesthandler.h"
|
||||
|
||||
/**
|
||||
This controller dumps the received HTTP request in the response.
|
||||
*/
|
||||
|
||||
class DumpController : public HttpRequestHandler {
|
||||
Q_OBJECT
|
||||
Q_DISABLE_COPY(DumpController);
|
||||
public:
|
||||
|
||||
/** Constructor */
|
||||
DumpController();
|
||||
|
||||
/** Generates the response */
|
||||
void service(HttpRequest& request, HttpResponse& response);
|
||||
};
|
||||
|
||||
#endif // DUMPCONTROLLER_H
|
@ -1,38 +0,0 @@
|
||||
/**
|
||||
@file
|
||||
@author Stefan Frings
|
||||
*/
|
||||
|
||||
#include "fileuploadcontroller.h"
|
||||
|
||||
FileUploadController::FileUploadController() {}
|
||||
|
||||
void FileUploadController::service(HttpRequest& request, HttpResponse& response) {
|
||||
|
||||
if (request.getParameter("action")=="show") {
|
||||
response.setHeader("Content-Type", "image/jpeg");
|
||||
QTemporaryFile* file=request.getUploadedFile("file1");
|
||||
if (file) {
|
||||
while (!file->atEnd() && !file->error()) {
|
||||
QByteArray buffer=file->read(65536);
|
||||
response.write(buffer);
|
||||
}
|
||||
}
|
||||
else {
|
||||
response.write("upload failed");
|
||||
}
|
||||
}
|
||||
|
||||
else {
|
||||
response.setHeader("Content-Type", "text/html; charset=ISO-8859-1");
|
||||
response.write("<html><body>");
|
||||
response.write("Upload a JPEG image file<p>");
|
||||
response.write("<form method=\"post\" enctype=\"multipart/form-data\">");
|
||||
response.write(" <input type=\"hidden\" name=\"action\" value=\"show\">");
|
||||
response.write(" File: <input type=\"file\" name=\"file1\"><br>");
|
||||
response.write(" <input type=\"submit\">");
|
||||
response.write("</form>");
|
||||
response.write("</body></html>",true);
|
||||
}
|
||||
}
|
||||
|
@ -1,30 +0,0 @@
|
||||
/**
|
||||
@file
|
||||
@author Stefan Frings
|
||||
*/
|
||||
|
||||
#ifndef FILEUPLOADCONTROLLER_H
|
||||
#define FILEUPLOADCONTROLLER_H
|
||||
|
||||
#include "httprequest.h"
|
||||
#include "httpresponse.h"
|
||||
#include "httprequesthandler.h"
|
||||
|
||||
/**
|
||||
This controller displays a HTML form for file upload and recieved the file.
|
||||
*/
|
||||
|
||||
|
||||
class FileUploadController : public HttpRequestHandler {
|
||||
Q_OBJECT
|
||||
Q_DISABLE_COPY(FileUploadController);
|
||||
public:
|
||||
|
||||
/** Constructor */
|
||||
FileUploadController();
|
||||
|
||||
/** Generates the response */
|
||||
void service(HttpRequest& request, HttpResponse& response);
|
||||
};
|
||||
|
||||
#endif // FILEUPLOADCONTROLLER_H
|
@ -1,64 +0,0 @@
|
||||
/**
|
||||
@file
|
||||
@author Stefan Frings
|
||||
*/
|
||||
|
||||
#include "formcontroller.h"
|
||||
#include <QStringList>
|
||||
|
||||
FormController::FormController() {}
|
||||
|
||||
void FormController::service(HttpRequest& request, HttpResponse& response) {
|
||||
|
||||
response.setHeader("Content-Type", "text/html; charset=utf-8");
|
||||
|
||||
QString data(request.getBody());
|
||||
|
||||
QStringList list = data.split("\n");
|
||||
|
||||
response.write("<html><body>");
|
||||
response.writeText("á é í ó ú ñ -> \\ /Device type: "+list.first());
|
||||
|
||||
//test background proccesing
|
||||
/*int i=0;
|
||||
int j=0;
|
||||
while(i<1000000000)
|
||||
{
|
||||
if(request.getBody().length()>1)
|
||||
j++;
|
||||
else
|
||||
i++;
|
||||
if(i%1000000 == 0)
|
||||
response.write("<p> lista </p>");
|
||||
}*/
|
||||
|
||||
response.write("<p> lista </p>");
|
||||
|
||||
response.write("<ul>");
|
||||
|
||||
for(int i=1;i<list.length();i++)
|
||||
{
|
||||
response.writeText("<li>"+list.at(i)+"</li>");
|
||||
}
|
||||
response.write("</ul></body></html>",true);
|
||||
|
||||
/*if (request.getParameter("action")=="show") {
|
||||
response.write("<html><body>");
|
||||
response.write("Name = ");
|
||||
response.write(request.getParameter("name"));
|
||||
response.write("<br>City = ");
|
||||
response.write(request.getParameter("city"));
|
||||
response.write("</body></html>",true);
|
||||
}
|
||||
else {
|
||||
response.write("<html><body>");
|
||||
response.write("<form method=\"post\">");
|
||||
response.write(" <input type=\"hidden\" name=\"action\" value=\"show\">");
|
||||
response.write(" Name: <input type=\"text\" name=\"name\"><br>");
|
||||
response.write(" City: <input type=\"text\" name=\"city\"><br>");
|
||||
response.write(" <input type=\"submit\">");
|
||||
response.write("</form>");
|
||||
response.write("</body></html>",true);
|
||||
}*/
|
||||
}
|
||||
|
@ -1,40 +0,0 @@
|
||||
#include "librariescontroller.h"
|
||||
#include "db_helper.h" //get libraries
|
||||
#include "yacreader_libraries.h"
|
||||
|
||||
#include "template.h"
|
||||
#include "../static.h"
|
||||
|
||||
#include "QsLog.h"
|
||||
|
||||
LibrariesController::LibrariesController() {}
|
||||
|
||||
void LibrariesController::service(HttpRequest& request, HttpResponse& response)
|
||||
{
|
||||
HttpSession session=Static::sessionStore->getSession(request,response,false);
|
||||
|
||||
response.setHeader("Content-Type", "text/html; charset=utf-8");
|
||||
response.setHeader("Connection","close");
|
||||
|
||||
session.clearNavigationPath();
|
||||
|
||||
Template t=Static::templateLoader->getTemplate("libraries_"+session.getDeviceType(),request.getHeader("Accept-Language"));
|
||||
t.enableWarnings();
|
||||
|
||||
YACReaderLibraries libraries = DBHelper::getLibraries();
|
||||
QList<QString> names = DBHelper::getLibrariesNames();
|
||||
|
||||
t.loop("library",names.length());
|
||||
|
||||
int currentId = 0;
|
||||
int i = 0;
|
||||
foreach (QString name,names) {
|
||||
currentId = libraries.getId(name);
|
||||
t.setVariable(QString("library%1.name").arg(i),QString::number(currentId));
|
||||
t.setVariable(QString("library%1.label").arg(i),name);
|
||||
i++;
|
||||
}
|
||||
|
||||
response.setStatus(200,"OK");
|
||||
response.writeText(t,true);
|
||||
}
|
@ -1,29 +0,0 @@
|
||||
/**
|
||||
@file
|
||||
@author Stefan Frings
|
||||
*/
|
||||
|
||||
#ifndef SESSIONCONTROLLER_H
|
||||
#define SESSIONCONTROLLER_H
|
||||
|
||||
#include "httprequest.h"
|
||||
#include "httpresponse.h"
|
||||
#include "httprequesthandler.h"
|
||||
|
||||
/**
|
||||
This controller demonstrates how to use sessions.
|
||||
*/
|
||||
|
||||
class SessionController : public HttpRequestHandler {
|
||||
Q_OBJECT
|
||||
Q_DISABLE_COPY(SessionController);
|
||||
public:
|
||||
|
||||
/** Constructor */
|
||||
SessionController();
|
||||
|
||||
/** Generates the response */
|
||||
void service(HttpRequest& request, HttpResponse& response);
|
||||
};
|
||||
|
||||
#endif // SESSIONCONTROLLER_H
|
@ -1,31 +0,0 @@
|
||||
/**
|
||||
@file
|
||||
@author Stefan Frings
|
||||
*/
|
||||
|
||||
#include "templatecontroller.h"
|
||||
#include "template.h"
|
||||
#include "../static.h"
|
||||
|
||||
TemplateController::TemplateController(){}
|
||||
|
||||
void TemplateController::service(HttpRequest& request, HttpResponse& response) {
|
||||
|
||||
response.setHeader("Content-Type", "text/html; charset=ISO-8859-1");
|
||||
|
||||
Template t=Static::templateLoader->getTemplate("demo",request.getHeader("Accept-Language"));
|
||||
t.enableWarnings();
|
||||
t.setVariable("path",request.getPath());
|
||||
QMap<QByteArray,QByteArray> headers=request.getHeaderMap();
|
||||
QMapIterator<QByteArray,QByteArray> iterator(headers);
|
||||
t.loop("header",headers.size());
|
||||
int i=0;
|
||||
while (iterator.hasNext()) {
|
||||
iterator.next();
|
||||
t.setVariable(QString("header%1.name").arg(i),QString(iterator.key()));
|
||||
t.setVariable(QString("header%1.value").arg(i),QString(iterator.value()));
|
||||
++i;
|
||||
}
|
||||
|
||||
response.write(t.toLatin1(),true);
|
||||
}
|
@ -1,30 +0,0 @@
|
||||
/**
|
||||
@file
|
||||
@author Stefan Frings
|
||||
*/
|
||||
|
||||
#ifndef TEMPLATECONTROLLER_H
|
||||
#define TEMPLATECONTROLLER_H
|
||||
|
||||
#include "httprequest.h"
|
||||
#include "httpresponse.h"
|
||||
#include "httprequesthandler.h"
|
||||
|
||||
/**
|
||||
This controller generates a website using the template engine.
|
||||
It generates a Latin1 (ISO-8859-1) encoded website from a UTF-8 encoded template file.
|
||||
*/
|
||||
|
||||
class TemplateController : public HttpRequestHandler {
|
||||
Q_OBJECT
|
||||
Q_DISABLE_COPY(TemplateController);
|
||||
public:
|
||||
|
||||
/** Constructor */
|
||||
TemplateController();
|
||||
|
||||
/** Generates the response */
|
||||
void service(HttpRequest& request, HttpResponse& response);
|
||||
};
|
||||
|
||||
#endif // TEMPLATECONTROLLER_H
|
124
YACReaderLibrary/server/controllers/v1/comiccontroller.cpp
Normal file
124
YACReaderLibrary/server/controllers/v1/comiccontroller.cpp
Normal file
@ -0,0 +1,124 @@
|
||||
#include "comiccontroller.h"
|
||||
|
||||
#include "db_helper.h"
|
||||
#include "yacreader_libraries.h"
|
||||
#include "yacreader_http_session.h"
|
||||
|
||||
#include "template.h"
|
||||
#include "../static.h"
|
||||
|
||||
#include "comic_db.h"
|
||||
#include "comic.h"
|
||||
|
||||
#include "QsLog.h"
|
||||
|
||||
#include <typeinfo>
|
||||
|
||||
ComicController::ComicController() {}
|
||||
|
||||
void ComicController::service(HttpRequest& request, HttpResponse& response)
|
||||
{
|
||||
HttpSession session=Static::sessionStore->getSession(request,response,false);
|
||||
YACReaderHttpSession *ySession = Static::yacreaderSessionStore->getYACReaderSessionHttpSession(session.getId());
|
||||
|
||||
QString path = QUrl::fromPercentEncoding(request.getPath()).toUtf8();
|
||||
QStringList pathElements = path.split('/');
|
||||
qulonglong libraryId = pathElements.at(2).toLongLong();
|
||||
QString libraryName = DBHelper::getLibraryName(libraryId);
|
||||
qulonglong comicId = pathElements.at(4).toULongLong();
|
||||
|
||||
bool remoteComic = path.endsWith("remote");
|
||||
|
||||
//TODO
|
||||
//if(pathElements.size() == 6)
|
||||
//{
|
||||
// QString action = pathElements.at(5);
|
||||
// if(!action.isEmpty() && (action == "close"))
|
||||
// {
|
||||
// session.dismissCurrentComic();
|
||||
// response.write("",true);
|
||||
// return;
|
||||
// }
|
||||
//}
|
||||
|
||||
YACReaderLibraries libraries = DBHelper::getLibraries();
|
||||
|
||||
ComicDB comic = DBHelper::getComicInfo(libraryId, comicId);
|
||||
|
||||
if(!remoteComic)
|
||||
ySession->setDownloadedComic(comic.info.hash);
|
||||
|
||||
Comic * comicFile = FactoryComic::newComic(libraries.getPath(libraryId)+comic.path);
|
||||
|
||||
if(comicFile != NULL)
|
||||
{
|
||||
QThread * thread = NULL;
|
||||
|
||||
thread = new QThread();
|
||||
|
||||
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()));
|
||||
|
||||
comicFile->load(libraries.getPath(libraryId)+comic.path);
|
||||
|
||||
if(thread != NULL)
|
||||
thread->start();
|
||||
|
||||
if(remoteComic)
|
||||
{
|
||||
QLOG_TRACE() << "remote comic requested";
|
||||
ySession->setCurrentRemoteComic(comic.id, comicFile);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
QLOG_TRACE() << "comic requested";
|
||||
ySession->setCurrentComic(comic.id, comicFile);
|
||||
}
|
||||
|
||||
response.setHeader("Content-Type", "text/plain; charset=utf-8");
|
||||
//TODO this field is not used by the client!
|
||||
response.write(QString("library:%1\r\n").arg(libraryName).toUtf8());
|
||||
response.write(QString("libraryId:%1\r\n").arg(libraryId).toUtf8());
|
||||
if(remoteComic) //send previous and next comics id
|
||||
{
|
||||
QList<LibraryItem *> siblings = DBHelper::getFolderComicsFromLibrary(libraryId, comic.parentId, true);
|
||||
bool found = false;
|
||||
int i;
|
||||
for(i = 0; i < siblings.length(); i++)
|
||||
{
|
||||
if (siblings.at(i)->id == comic.id)
|
||||
{
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(found)
|
||||
{
|
||||
if(i>0)
|
||||
response.write(QString("previousComic:%1\r\n").arg(siblings.at(i-1)->id).toUtf8());
|
||||
if(i<siblings.length()-1)
|
||||
response.write(QString("nextComic:%1\r\n").arg(siblings.at(i+1)->id).toUtf8());
|
||||
}
|
||||
else
|
||||
{
|
||||
//ERROR
|
||||
}
|
||||
qDeleteAll(siblings);
|
||||
}
|
||||
response.write(comic.toTXT().toUtf8(),true);
|
||||
}
|
||||
else
|
||||
{
|
||||
//delete comicFile;
|
||||
response.setStatus(404,"not found");
|
||||
response.write("404 not found",true);
|
||||
}
|
||||
//response.write(t.toLatin1(),true);
|
||||
|
||||
}
|
@ -10,7 +10,7 @@ ComicDownloadInfoController::ComicDownloadInfoController() {}
|
||||
|
||||
void ComicDownloadInfoController::service(HttpRequest& request, HttpResponse& response)
|
||||
{
|
||||
response.setHeader("Content-Type", "plain/text; charset=utf-8");
|
||||
response.setHeader("Content-Type", "text/plain; charset=utf-8");
|
||||
|
||||
QString path = QUrl::fromPercentEncoding(request.getPath()).toUtf8();
|
||||
QStringList pathElements = path.split('/');
|
||||
@ -21,6 +21,6 @@ void ComicDownloadInfoController::service(HttpRequest& request, HttpResponse& re
|
||||
ComicDB comic = DBHelper::getComicInfo(libraryId, comicId);
|
||||
|
||||
//TODO: check if the comic wasn't found;
|
||||
response.writeText(QString("fileName:%1\r\n").arg(comic.getFileName()));
|
||||
response.writeText(QString("fileSize:%1\r\n").arg(comic.getFileSize()),true);
|
||||
response.write(QString("fileName:%1\r\n").arg(comic.getFileName()).toUtf8());
|
||||
response.write(QString("fileSize:%1\r\n").arg(comic.getFileSize()).toUtf8(),true);
|
||||
}
|
89
YACReaderLibrary/server/controllers/v1/covercontroller.cpp
Normal file
89
YACReaderLibrary/server/controllers/v1/covercontroller.cpp
Normal file
@ -0,0 +1,89 @@
|
||||
#include "covercontroller.h"
|
||||
#include "db_helper.h" //get libraries
|
||||
#include "yacreader_libraries.h"
|
||||
#include "yacreader_http_session.h"
|
||||
|
||||
#include "template.h"
|
||||
#include "../static.h"
|
||||
|
||||
CoverController::CoverController() {}
|
||||
|
||||
void CoverController::service(HttpRequest& request, HttpResponse& response)
|
||||
{
|
||||
HttpSession session=Static::sessionStore->getSession(request,response,false);
|
||||
YACReaderHttpSession *ySession = Static::yacreaderSessionStore->getYACReaderSessionHttpSession(session.getId());
|
||||
|
||||
response.setHeader("Content-Type", "image/jpeg");
|
||||
response.setHeader("Connection","close");
|
||||
//response.setHeader("Content-Type", "plain/text; charset=ISO-8859-1");
|
||||
|
||||
YACReaderLibraries libraries = DBHelper::getLibraries();
|
||||
|
||||
QString path = QUrl::fromPercentEncoding(request.getPath()).toUtf8();
|
||||
QStringList pathElements = path.split('/');
|
||||
QString libraryName = DBHelper::getLibraryName(pathElements.at(2).toInt());
|
||||
QString fileName = pathElements.at(4);
|
||||
|
||||
bool folderCover = request.getParameter("folderCover").length()>0;
|
||||
|
||||
//response.writeText(path+"<br/>");
|
||||
//response.writeText(libraryName+"<br/>");
|
||||
//response.writeText(libraries.value(libraryName)+"/.yacreaderlibrary/covers/"+fileName+"<br/>");
|
||||
|
||||
//QFile file(libraries.value(libraryName)+"/.yacreaderlibrary/covers/"+fileName);
|
||||
//if (file.exists()) {
|
||||
// if (file.open(QIODevice::ReadOnly))
|
||||
// {
|
||||
// qDebug("StaticFileController: Open file %s",qPrintable(file.fileName()));
|
||||
// // Return the file content, do not store in cache
|
||||
// while (!file.atEnd() && !file.error()) {
|
||||
// response.write(file.read(131072));
|
||||
// }
|
||||
// }
|
||||
|
||||
// file.close();
|
||||
//}
|
||||
|
||||
QImage img(libraries.getPath(libraryName)+"/.yacreaderlibrary/covers/"+fileName);
|
||||
if (!img.isNull()) {
|
||||
|
||||
int width = 80, height = 120;
|
||||
if(ySession->getDisplayType()=="@2x")
|
||||
{
|
||||
width = 160;
|
||||
height = 240;
|
||||
}
|
||||
|
||||
if(float(img.width())/img.height() < 0.66666)
|
||||
img = img.scaledToWidth(width,Qt::SmoothTransformation);
|
||||
else
|
||||
img = img.scaledToHeight(height,Qt::SmoothTransformation);
|
||||
|
||||
QImage destImg(width,height,QImage::Format_RGB32);
|
||||
destImg.fill(Qt::black);
|
||||
QPainter p(&destImg);
|
||||
|
||||
p.drawImage((width-img.width())/2,(height-img.height())/2,img);
|
||||
|
||||
if(folderCover)
|
||||
{
|
||||
if(ySession->getDisplayType()=="@2x")
|
||||
p.drawImage(0,0,QImage(":/images/f_overlayed_retina.png"));
|
||||
else
|
||||
p.drawImage(0,0,QImage(":/images/f_overlayed.png"));
|
||||
}
|
||||
|
||||
QByteArray ba;
|
||||
QBuffer buffer(&ba);
|
||||
buffer.open(QIODevice::WriteOnly);
|
||||
destImg.save(&buffer, "JPG");
|
||||
response.write(ba,true);
|
||||
}
|
||||
//DONE else, hay que devolver un 404
|
||||
else
|
||||
{
|
||||
response.setStatus(404,"not found");
|
||||
response.write("404 not found",true);
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,7 @@
|
||||
#include "foldercontroller.h"
|
||||
#include "controllers/errorcontroller.h"
|
||||
#include "controllers/v1/errorcontroller.h"
|
||||
|
||||
#include "yacreader_http_session.h"
|
||||
|
||||
#include "db_helper.h" //get libraries
|
||||
#include "comic_db.h"
|
||||
@ -32,6 +34,7 @@ void FolderController::service(HttpRequest& request, HttpResponse& response)
|
||||
bool showlessInfoPerFolder = settings->value(REMOTE_BROWSE_PERFORMANCE_WORKAROUND,false).toBool();
|
||||
|
||||
HttpSession session=Static::sessionStore->getSession(request,response,false);
|
||||
YACReaderHttpSession *ySession = Static::yacreaderSessionStore->getYACReaderSessionHttpSession(session.getId());
|
||||
|
||||
response.setHeader("Content-Type", "text/html; charset=utf-8");
|
||||
response.setHeader("Connection","close");
|
||||
@ -39,7 +42,7 @@ void FolderController::service(HttpRequest& request, HttpResponse& response)
|
||||
//QString y = session.get("xxx").toString();
|
||||
//response.writeText(QString("session xxx : %1 <br/>").arg(y));
|
||||
|
||||
Template t=Static::templateLoader->getTemplate("folder_"+session.getDeviceType(),request.getHeader("Accept-Language"));
|
||||
Template t=Static::templateLoader->getTemplate("folder_"+ySession->getDeviceType(),request.getHeader("Accept-Language"));
|
||||
t.enableWarnings();
|
||||
QString path = QUrl::fromPercentEncoding(request.getPath()).toUtf8();
|
||||
QStringList pathElements = path.split('/');
|
||||
@ -91,17 +94,17 @@ void FolderController::service(HttpRequest& request, HttpResponse& response)
|
||||
|
||||
if(folderId == 1)
|
||||
{
|
||||
session.clearNavigationPath();
|
||||
session.pushNavigationItem(QPair<qulonglong,quint32>(folderId,page));
|
||||
ySession->clearNavigationPath();
|
||||
ySession->pushNavigationItem(QPair<qulonglong,quint32>(folderId,page));
|
||||
t.setVariable(QString("upurl"),"/");
|
||||
}
|
||||
else
|
||||
{
|
||||
if(fromUp)
|
||||
session.popNavigationItem();
|
||||
ySession->popNavigationItem();
|
||||
else //drill down or direct access
|
||||
{
|
||||
QStack<QPair<qulonglong, quint32> > path = session.getNavigationPath();
|
||||
QStack<QPair<qulonglong, quint32> > path = ySession->getNavigationPath();
|
||||
bool found=false;
|
||||
for(QStack<QPair<qulonglong, quint32> >::const_iterator itr = path.begin(); itr!=path.end(); itr++)
|
||||
if(itr->first == folderId)
|
||||
@ -112,16 +115,16 @@ void FolderController::service(HttpRequest& request, HttpResponse& response)
|
||||
|
||||
if(found)
|
||||
{
|
||||
while(session.topNavigationItem().first != folderId)
|
||||
session.popNavigationItem();
|
||||
while(ySession->topNavigationItem().first != folderId)
|
||||
ySession->popNavigationItem();
|
||||
|
||||
session.updateTopItem(QPair<qulonglong,quint32>(folderId,page));
|
||||
ySession->updateTopItem(QPair<qulonglong,quint32>(folderId,page));
|
||||
}
|
||||
else
|
||||
session.pushNavigationItem(QPair<qulonglong,quint32>(folderId,page));
|
||||
ySession->pushNavigationItem(QPair<qulonglong,quint32>(folderId,page));
|
||||
}
|
||||
|
||||
QStack<QPair<qulonglong, quint32> > path = session.getNavigationPath();
|
||||
QStack<QPair<qulonglong, quint32> > path = ySession->getNavigationPath();
|
||||
if(path.count()>1)
|
||||
{
|
||||
QPair<qulonglong, quint32> parentItem = path.at(path.count()-2);
|
||||
@ -152,7 +155,7 @@ void FolderController::service(HttpRequest& request, HttpResponse& response)
|
||||
int numFoldersAtCurrentPage = qMax(0,qMin(numFolders - indexCurrentPage, elementsPerPage));
|
||||
|
||||
//PATH
|
||||
QStack<QPair<qulonglong,quint32> > foldersPath = session.getNavigationPath();
|
||||
QStack<QPair<qulonglong,quint32> > foldersPath = ySession->getNavigationPath();
|
||||
t.setVariable(QString("library.name"),libraryName);
|
||||
t.setVariable(QString("library.url"),QString("/library/%1/folder/1").arg(libraryId));
|
||||
t.loop("path",foldersPath.count()-1);
|
||||
@ -208,9 +211,9 @@ void FolderController::service(HttpRequest& request, HttpResponse& response)
|
||||
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))
|
||||
if(!ySession->isComicOnDevice(comic->info.hash) && !ySession->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))
|
||||
else if (ySession->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>"));
|
||||
@ -329,6 +332,6 @@ void FolderController::service(HttpRequest& request, HttpResponse& response)
|
||||
t.setVariable("page",QString("%1").arg(page+1));
|
||||
t.setVariable("pages",QString("%1").arg(numPages));
|
||||
|
||||
response.writeText(t, true);
|
||||
response.write(t.toUtf8(), true);
|
||||
|
||||
}
|
@ -12,17 +12,17 @@ FolderInfoController::FolderInfoController() {}
|
||||
|
||||
void FolderInfoController::service(HttpRequest& request, HttpResponse& response)
|
||||
{
|
||||
response.setHeader("Content-Type", "plain/text; charset=utf-8");
|
||||
response.setHeader("Content-Type", "text/plain; charset=utf-8");
|
||||
|
||||
QString path = QUrl::fromPercentEncoding(request.getPath()).toUtf8();
|
||||
QStringList pathElements = path.split('/');
|
||||
int libraryId = pathElements.at(2).toInt();
|
||||
QString libraryName = DBHelper::getLibraryName(libraryId);
|
||||
qulonglong parentId = pathElements.at(4).toULongLong();
|
||||
QStringList pathElements = path.split('/');
|
||||
int libraryId = pathElements.at(2).toInt();
|
||||
QString libraryName = DBHelper::getLibraryName(libraryId);
|
||||
qulonglong parentId = pathElements.at(4).toULongLong();
|
||||
|
||||
serviceComics(libraryId, parentId, response);
|
||||
|
||||
response.writeText("",true);
|
||||
response.write("",true);
|
||||
}
|
||||
|
||||
void FolderInfoController::serviceComics(const int &library, const qulonglong &folderId, HttpResponse &response)
|
||||
@ -34,7 +34,7 @@ void FolderInfoController::serviceComics(const int &library, const qulonglong &f
|
||||
for(QList<LibraryItem *>::const_iterator itr = folderComics.constBegin();itr!=folderComics.constEnd();itr++)
|
||||
{
|
||||
currentComic = (ComicDB *)(*itr);
|
||||
response.writeText(QString("/library/%1/comic/%2:%3:%4\r\n").arg(library).arg(currentComic->id).arg(currentComic->getFileName()).arg(currentComic->getFileSize()));
|
||||
response.write(QString("/library/%1/comic/%2:%3:%4\r\n").arg(library).arg(currentComic->id).arg(currentComic->getFileName()).arg(currentComic->getFileSize()).toUtf8());
|
||||
delete currentComic;
|
||||
}
|
||||
|
@ -0,0 +1,42 @@
|
||||
#include "librariescontroller.h"
|
||||
#include "db_helper.h" //get libraries
|
||||
#include "yacreader_libraries.h"
|
||||
#include "yacreader_http_session.h"
|
||||
|
||||
#include "template.h"
|
||||
#include "../static.h"
|
||||
|
||||
#include "QsLog.h"
|
||||
|
||||
LibrariesController::LibrariesController() {}
|
||||
|
||||
void LibrariesController::service(HttpRequest& request, HttpResponse& response)
|
||||
{
|
||||
HttpSession session=Static::sessionStore->getSession(request,response,false);
|
||||
YACReaderHttpSession *ySession = Static::yacreaderSessionStore->getYACReaderSessionHttpSession(session.getId());
|
||||
|
||||
response.setHeader("Content-Type", "text/html; charset=utf-8");
|
||||
response.setHeader("Connection","close");
|
||||
|
||||
ySession->clearNavigationPath();
|
||||
|
||||
Template t=Static::templateLoader->getTemplate("libraries_"+ySession->getDeviceType(),request.getHeader("Accept-Language"));
|
||||
t.enableWarnings();
|
||||
|
||||
YACReaderLibraries libraries = DBHelper::getLibraries();
|
||||
QList<QString> names = DBHelper::getLibrariesNames();
|
||||
|
||||
t.loop("library",names.length());
|
||||
|
||||
int currentId = 0;
|
||||
int i = 0;
|
||||
foreach (QString name,names) {
|
||||
currentId = libraries.getId(name);
|
||||
t.setVariable(QString("library%1.name").arg(i),QString::number(currentId));
|
||||
t.setVariable(QString("library%1.label").arg(i),name);
|
||||
i++;
|
||||
}
|
||||
|
||||
response.setStatus(200,"OK");
|
||||
response.write(t.toUtf8(),true);
|
||||
}
|
99
YACReaderLibrary/server/controllers/v1/pagecontroller.cpp
Normal file
99
YACReaderLibrary/server/controllers/v1/pagecontroller.cpp
Normal file
@ -0,0 +1,99 @@
|
||||
#include "pagecontroller.h"
|
||||
|
||||
#include "../static.h"
|
||||
|
||||
#include "comic.h"
|
||||
#include "comiccontroller.h"
|
||||
#include "yacreader_http_session.h"
|
||||
|
||||
#include <QDataStream>
|
||||
#include <QPointer>
|
||||
|
||||
#include <QsLog.h>
|
||||
|
||||
#include "db_helper.h"
|
||||
|
||||
PageController::PageController() {}
|
||||
|
||||
void PageController::service(HttpRequest& request, HttpResponse& response)
|
||||
{
|
||||
HttpSession session=Static::sessionStore->getSession(request,response,false);
|
||||
YACReaderHttpSession *ySession = Static::yacreaderSessionStore->getYACReaderSessionHttpSession(session.getId());
|
||||
|
||||
QString path = QUrl::fromPercentEncoding(request.getPath()).toUtf8();
|
||||
bool remote = path.endsWith("remote");
|
||||
|
||||
//QByteArray path2=request.getPath();
|
||||
//qDebug("PageController: request to -> %s ",path2.data());
|
||||
|
||||
QStringList pathElements = path.split('/');
|
||||
QString libraryName = DBHelper::getLibraryName(pathElements.at(2).toInt());
|
||||
qulonglong comicId = pathElements.at(4).toULongLong();
|
||||
unsigned int page = pathElements.at(6).toUInt();
|
||||
|
||||
//qDebug("lib name : %s",pathElements.at(2).data());
|
||||
|
||||
Comic * comicFile;
|
||||
qulonglong currentComicId;
|
||||
if(remote)
|
||||
{
|
||||
QLOG_TRACE() << "se recupera comic remoto para servir páginas";
|
||||
comicFile = ySession->getCurrentRemoteComic();
|
||||
currentComicId = ySession->getCurrentRemoteComicId();
|
||||
}
|
||||
else
|
||||
{
|
||||
QLOG_TRACE() << "se recupera comic para servir páginas";
|
||||
comicFile = ySession->getCurrentComic();
|
||||
currentComicId = ySession->getCurrentComicId();
|
||||
}
|
||||
|
||||
if(currentComicId != 0 && !QPointer<Comic>(comicFile).isNull())
|
||||
{
|
||||
if(comicId == currentComicId && page < comicFile->numPages())
|
||||
{
|
||||
if(comicFile->pageIsLoaded(page))
|
||||
{
|
||||
//qDebug("PageController: La página estaba cargada -> %s ",path.data());
|
||||
response.setHeader("Content-Type", "image/jpeg");
|
||||
response.setHeader("Transfer-Encoding","chunked");
|
||||
QByteArray pageData = comicFile->getRawPage(page);
|
||||
QDataStream data(pageData);
|
||||
char buffer[4096];
|
||||
while (!data.atEnd()) {
|
||||
int len = data.readRawData(buffer,4096);
|
||||
response.write(QByteArray(buffer,len));
|
||||
}
|
||||
//response.write(pageData,true);
|
||||
response.write(QByteArray(),true);
|
||||
}
|
||||
else
|
||||
{
|
||||
//qDebug("PageController: La página NO estaba cargada 404 -> %s ",path.data());
|
||||
response.setStatus(404,"not found"); //TODO qué mensaje enviar
|
||||
response.write("404 not found",true);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(comicId != currentComicId)
|
||||
{
|
||||
//delete comicFile;
|
||||
if(remote)
|
||||
ySession->dismissCurrentRemoteComic();
|
||||
else
|
||||
ySession->dismissCurrentComic();
|
||||
}
|
||||
response.setStatus(404,"not found"); //TODO qué mensaje enviar
|
||||
response.write("404 not found",true);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
response.setStatus(404,"not found");
|
||||
response.write("404 not found",true);
|
||||
}
|
||||
|
||||
//response.write(t.toLatin1(),true);
|
||||
|
||||
}
|
@ -55,7 +55,7 @@ void SyncController::service(HttpRequest &request, HttpResponse &response)
|
||||
else
|
||||
{
|
||||
response.setStatus(412,"No comic info received");
|
||||
response.writeText("",true);
|
||||
response.write("",true);
|
||||
return;
|
||||
}
|
||||
|
@ -9,7 +9,7 @@
|
||||
|
||||
class SyncController : public HttpRequestHandler {
|
||||
Q_OBJECT
|
||||
Q_DISABLE_COPY(SyncController);
|
||||
Q_DISABLE_COPY(SyncController)
|
||||
public:
|
||||
/** Constructor */
|
||||
SyncController();
|
@ -38,7 +38,7 @@ void UpdateComicController::service(HttpRequest &request, HttpResponse &response
|
||||
else
|
||||
{
|
||||
response.setStatus(412,"No comic info received");
|
||||
response.writeText("",true);
|
||||
response.write("",true);
|
||||
return;
|
||||
}
|
||||
|
@ -1,7 +1,8 @@
|
||||
#include "comiccontroller.h"
|
||||
#include "comiccontroller_v2.h"
|
||||
|
||||
#include "db_helper.h"
|
||||
#include "yacreader_libraries.h"
|
||||
#include "yacreader_http_session.h"
|
||||
|
||||
#include "template.h"
|
||||
#include "../static.h"
|
||||
@ -13,17 +14,18 @@
|
||||
|
||||
#include <typeinfo>
|
||||
|
||||
ComicController::ComicController() {}
|
||||
ComicControllerV2::ComicControllerV2() {}
|
||||
|
||||
void ComicController::service(HttpRequest& request, HttpResponse& response)
|
||||
void ComicControllerV2::service(HttpRequest& request, HttpResponse& response)
|
||||
{
|
||||
HttpSession session=Static::sessionStore->getSession(request,response,false);
|
||||
YACReaderHttpSession *ySession = Static::yacreaderSessionStore->getYACReaderSessionHttpSession(session.getId());
|
||||
|
||||
QString path = QUrl::fromPercentEncoding(request.getPath()).toUtf8();
|
||||
QStringList pathElements = path.split('/');
|
||||
qulonglong libraryId = pathElements.at(2).toLongLong();
|
||||
qulonglong libraryId = pathElements.at(3).toLongLong();
|
||||
QString libraryName = DBHelper::getLibraryName(libraryId);
|
||||
qulonglong comicId = pathElements.at(4).toULongLong();
|
||||
qulonglong comicId = pathElements.at(5).toULongLong();
|
||||
|
||||
bool remoteComic = path.endsWith("remote");
|
||||
|
||||
@ -44,7 +46,7 @@ void ComicController::service(HttpRequest& request, HttpResponse& response)
|
||||
ComicDB comic = DBHelper::getComicInfo(libraryId, comicId);
|
||||
|
||||
if(!remoteComic)
|
||||
session.setDownloadedComic(comic.info.hash);
|
||||
ySession->setDownloadedComic(comic.info.hash);
|
||||
|
||||
Comic * comicFile = FactoryComic::newComic(libraries.getPath(libraryId)+comic.path);
|
||||
|
||||
@ -70,19 +72,19 @@ void ComicController::service(HttpRequest& request, HttpResponse& response)
|
||||
if(remoteComic)
|
||||
{
|
||||
QLOG_TRACE() << "remote comic requested";
|
||||
session.setCurrentRemoteComic(comic.id, comicFile);
|
||||
ySession->setCurrentRemoteComic(comic.id, comicFile);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
QLOG_TRACE() << "comic requested";
|
||||
session.setCurrentComic(comic.id, comicFile);
|
||||
ySession->setCurrentComic(comic.id, comicFile);
|
||||
}
|
||||
|
||||
response.setHeader("Content-Type", "plain/text; charset=utf-8");
|
||||
response.setHeader("Content-Type", "text/plain; charset=utf-8");
|
||||
//TODO this field is not used by the client!
|
||||
response.writeText(QString("library:%1\r\n").arg(libraryName));
|
||||
response.writeText(QString("libraryId:%1\r\n").arg(libraryId));
|
||||
response.write(QString("library:%1\r\n").arg(libraryName).toUtf8());
|
||||
response.write(QString("libraryId:%1\r\n").arg(libraryId).toUtf8());
|
||||
if(remoteComic) //send previous and next comics id
|
||||
{
|
||||
QList<LibraryItem *> siblings = DBHelper::getFolderComicsFromLibrary(libraryId, comic.parentId, true);
|
||||
@ -99,9 +101,9 @@ void ComicController::service(HttpRequest& request, HttpResponse& response)
|
||||
if(found)
|
||||
{
|
||||
if(i>0)
|
||||
response.writeText(QString("previousComic:%1\r\n").arg(siblings.at(i-1)->id));
|
||||
response.write(QString("previousComic:%1\r\n").arg(siblings.at(i-1)->id).toUtf8());
|
||||
if(i<siblings.length()-1)
|
||||
response.writeText(QString("nextComic:%1\r\n").arg(siblings.at(i+1)->id));
|
||||
response.write(QString("nextComic:%1\r\n").arg(siblings.at(i+1)->id).toUtf8());
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -109,7 +111,7 @@ void ComicController::service(HttpRequest& request, HttpResponse& response)
|
||||
}
|
||||
qDeleteAll(siblings);
|
||||
}
|
||||
response.writeText(comic.toTXT(),true);
|
||||
response.write(comic.toTXT().toUtf8(),true);
|
||||
}
|
||||
else
|
||||
{
|
23
YACReaderLibrary/server/controllers/v2/comiccontroller_v2.h
Normal file
23
YACReaderLibrary/server/controllers/v2/comiccontroller_v2.h
Normal file
@ -0,0 +1,23 @@
|
||||
#ifndef COMICCONTROLLER_V2_H
|
||||
#define COMICCONTROLLER_V2_H
|
||||
|
||||
#include "httprequest.h"
|
||||
#include "httpresponse.h"
|
||||
#include "httprequesthandler.h"
|
||||
|
||||
#include <QThread>
|
||||
class Comic;
|
||||
class QString;
|
||||
|
||||
class ComicControllerV2 : public HttpRequestHandler {
|
||||
Q_OBJECT
|
||||
Q_DISABLE_COPY(ComicControllerV2)
|
||||
public:
|
||||
/** Constructor */
|
||||
ComicControllerV2();
|
||||
|
||||
/** Generates the response */
|
||||
void service(HttpRequest& request, HttpResponse& response);
|
||||
};
|
||||
|
||||
#endif // COMICCONTROLLER_H
|
@ -0,0 +1,27 @@
|
||||
#include "comicdownloadinfocontroller_v2.h"
|
||||
|
||||
#include "db_helper.h"
|
||||
#include "yacreader_libraries.h"
|
||||
|
||||
#include "comic_db.h"
|
||||
|
||||
ComicDownloadInfoControllerV2::ComicDownloadInfoControllerV2() {}
|
||||
|
||||
|
||||
void ComicDownloadInfoControllerV2::service(HttpRequest& request, HttpResponse& response)
|
||||
{
|
||||
response.setHeader("Content-Type", "text/plain; charset=utf-8");
|
||||
|
||||
QString path = QUrl::fromPercentEncoding(request.getPath()).toUtf8();
|
||||
QStringList pathElements = path.split('/');
|
||||
|
||||
qulonglong libraryId = pathElements.at(3).toLongLong();
|
||||
qulonglong comicId = pathElements.at(5).toULongLong();
|
||||
|
||||
ComicDB comic = DBHelper::getComicInfo(libraryId, comicId);
|
||||
|
||||
//TODO: check if the comic wasn't found;
|
||||
response.write(QString("fileName:%1\r\n").arg(comic.getFileName()).toUtf8());
|
||||
response.write(QString("fileSize:%1\r\n").arg(comic.getFileSize()).toUtf8());
|
||||
response.write(QString("hash:%1\r\n").arg(comic.info.hash).toUtf8(),true);
|
||||
}
|
@ -0,0 +1,19 @@
|
||||
#ifndef COMICDOWNLOADINFOCONTROLLER_V2_H
|
||||
#define COMICDOWNLOADINFOCONTROLLER_V2_H
|
||||
|
||||
#include "httprequest.h"
|
||||
#include "httpresponse.h"
|
||||
#include "httprequesthandler.h"
|
||||
|
||||
class ComicDownloadInfoControllerV2 : public HttpRequestHandler {
|
||||
Q_OBJECT
|
||||
Q_DISABLE_COPY(ComicDownloadInfoControllerV2)
|
||||
public:
|
||||
/** Constructor **/
|
||||
ComicDownloadInfoControllerV2();
|
||||
|
||||
/** Generates the response */
|
||||
void service(HttpRequest& request, HttpResponse& response);
|
||||
};
|
||||
|
||||
#endif // COMICDOWNLOADINFOCONTROLLER_H
|
@ -1,16 +1,17 @@
|
||||
#include "covercontroller.h"
|
||||
#include "covercontroller_v2.h"
|
||||
#include "db_helper.h" //get libraries
|
||||
#include "yacreader_libraries.h"
|
||||
#include "yacreader_http_session.h"
|
||||
|
||||
#include "template.h"
|
||||
#include "../static.h"
|
||||
|
||||
CoverController::CoverController() {}
|
||||
CoverControllerV2::CoverControllerV2() {}
|
||||
|
||||
void CoverController::service(HttpRequest& request, HttpResponse& response)
|
||||
void CoverControllerV2::service(HttpRequest& request, HttpResponse& response)
|
||||
{
|
||||
|
||||
HttpSession session=Static::sessionStore->getSession(request,response,false);
|
||||
YACReaderHttpSession *ySession = Static::yacreaderSessionStore->getYACReaderSessionHttpSession(session.getId());
|
||||
|
||||
response.setHeader("Content-Type", "image/jpeg");
|
||||
response.setHeader("Connection","close");
|
||||
@ -20,8 +21,8 @@ void CoverController::service(HttpRequest& request, HttpResponse& response)
|
||||
|
||||
QString path = QUrl::fromPercentEncoding(request.getPath()).toUtf8();
|
||||
QStringList pathElements = path.split('/');
|
||||
QString libraryName = DBHelper::getLibraryName(pathElements.at(2).toInt());
|
||||
QString fileName = pathElements.at(4);
|
||||
QString libraryName = DBHelper::getLibraryName(pathElements.at(3).toInt());
|
||||
QString fileName = pathElements.at(5);
|
||||
|
||||
bool folderCover = request.getParameter("folderCover").length()>0;
|
||||
|
||||
@ -46,8 +47,8 @@ void CoverController::service(HttpRequest& request, HttpResponse& response)
|
||||
QImage img(libraries.getPath(libraryName)+"/.yacreaderlibrary/covers/"+fileName);
|
||||
if (!img.isNull()) {
|
||||
|
||||
int width = 80, height = 120;
|
||||
if(session.getDisplayType()=="@2x")
|
||||
/*int width = 80, height = 120;
|
||||
if(ySession->getDisplayType()=="@2x")
|
||||
{
|
||||
width = 160;
|
||||
height = 240;
|
||||
@ -66,16 +67,16 @@ void CoverController::service(HttpRequest& request, HttpResponse& response)
|
||||
|
||||
if(folderCover)
|
||||
{
|
||||
if(session.getDisplayType()=="@2x")
|
||||
if(ySession->getDisplayType()=="@2x")
|
||||
p.drawImage(0,0,QImage(":/images/f_overlayed_retina.png"));
|
||||
else
|
||||
p.drawImage(0,0,QImage(":/images/f_overlayed.png"));
|
||||
}
|
||||
|
||||
*/
|
||||
QByteArray ba;
|
||||
QBuffer buffer(&ba);
|
||||
buffer.open(QIODevice::WriteOnly);
|
||||
destImg.save(&buffer, "JPG");
|
||||
img.save(&buffer, "JPG");
|
||||
response.write(ba,true);
|
||||
}
|
||||
//DONE else, hay que devolver un 404
|
20
YACReaderLibrary/server/controllers/v2/covercontroller_v2.h
Normal file
20
YACReaderLibrary/server/controllers/v2/covercontroller_v2.h
Normal file
@ -0,0 +1,20 @@
|
||||
#ifndef COVERCONTROLLER_V2_H
|
||||
#define COVERCONTROLLER_V2_H
|
||||
|
||||
#include "httprequest.h"
|
||||
#include "httpresponse.h"
|
||||
#include "httprequesthandler.h"
|
||||
|
||||
class CoverControllerV2 : public HttpRequestHandler {
|
||||
Q_OBJECT
|
||||
Q_DISABLE_COPY(CoverControllerV2)
|
||||
public:
|
||||
|
||||
/** Constructor */
|
||||
CoverControllerV2();
|
||||
|
||||
/** Generates the response */
|
||||
void service(HttpRequest& request, HttpResponse& response);
|
||||
};
|
||||
|
||||
#endif // COVERCONTROLLER_H
|
@ -0,0 +1,26 @@
|
||||
#include "errorcontroller_v2.h"
|
||||
|
||||
#include "template.h"
|
||||
#include "../static.h"
|
||||
|
||||
|
||||
ErrorControllerV2::ErrorControllerV2(int errorCode)
|
||||
:error(errorCode)
|
||||
{}
|
||||
|
||||
void ErrorControllerV2::service(HttpRequest& request, HttpResponse& response)
|
||||
{
|
||||
Q_UNUSED(request)
|
||||
switch(error)
|
||||
{
|
||||
case 300:
|
||||
response.setStatus(300,"redirect");
|
||||
response.write("<html> <head> <meta http-equiv=\"refresh\" content=\"0; URL=/\"> </head> <body> </body> </html>", true);
|
||||
break;
|
||||
case 404:
|
||||
response.setStatus(404,"not found");
|
||||
response.write("404 not found",true);
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
22
YACReaderLibrary/server/controllers/v2/errorcontroller_v2.h
Normal file
22
YACReaderLibrary/server/controllers/v2/errorcontroller_v2.h
Normal file
@ -0,0 +1,22 @@
|
||||
#ifndef ERRORCONTROLLER_V2_H
|
||||
#define ERRORCONTROLLER_V2_H
|
||||
|
||||
#include "httprequest.h"
|
||||
#include "httpresponse.h"
|
||||
#include "httprequesthandler.h"
|
||||
|
||||
class ErrorControllerV2 : public HttpRequestHandler {
|
||||
Q_OBJECT
|
||||
Q_DISABLE_COPY(ErrorControllerV2)
|
||||
public:
|
||||
|
||||
/** Constructor */
|
||||
ErrorControllerV2(int errorCode);
|
||||
|
||||
/** Generates the response */
|
||||
void service(HttpRequest& request, HttpResponse& response);
|
||||
private:
|
||||
int error;
|
||||
};
|
||||
|
||||
#endif // ERRORCONTROLLER_H
|
@ -0,0 +1,33 @@
|
||||
#include "favoritescontroller_v2.h"
|
||||
|
||||
#include "db_helper.h"
|
||||
#include "comic_db.h"
|
||||
|
||||
#include "yacreader_server_data_helper.h"
|
||||
|
||||
FavoritesControllerV2::FavoritesControllerV2() {}
|
||||
|
||||
void FavoritesControllerV2::service(HttpRequest &request, HttpResponse &response)
|
||||
{
|
||||
response.setHeader("Content-Type", "text/plain; charset=utf-8");
|
||||
|
||||
QString path = QUrl::fromPercentEncoding(request.getPath()).toUtf8();
|
||||
QStringList pathElements = path.split('/');
|
||||
int libraryId = pathElements.at(3).toInt();
|
||||
|
||||
serviceContent(libraryId, response);
|
||||
|
||||
response.write("",true);
|
||||
}
|
||||
|
||||
void FavoritesControllerV2::serviceContent(const int library, HttpResponse &response)
|
||||
{
|
||||
QList<ComicDB> tagComics = DBHelper::getFavorites(library);
|
||||
|
||||
for(const ComicDB &comic : tagComics)
|
||||
{
|
||||
response.write(YACReaderServerDataHelper::comicToYSFormat(library, comic).toUtf8());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,21 @@
|
||||
#ifndef FAVORITESCONTROLLER_V2_H
|
||||
#define FAVORITESCONTROLLER_V2_H
|
||||
|
||||
#include "httprequest.h"
|
||||
#include "httpresponse.h"
|
||||
#include "httprequesthandler.h"
|
||||
|
||||
class FavoritesControllerV2 : public HttpRequestHandler {
|
||||
Q_OBJECT
|
||||
Q_DISABLE_COPY(FavoritesControllerV2)
|
||||
public:
|
||||
FavoritesControllerV2();
|
||||
|
||||
void service(HttpRequest& request, HttpResponse& response);
|
||||
|
||||
private:
|
||||
void serviceContent(const int library, HttpResponse &response);
|
||||
};
|
||||
|
||||
|
||||
#endif // FAVORITESCONTROLLER_H
|
@ -0,0 +1,72 @@
|
||||
#include "foldercontentcontroller_v2.h"
|
||||
|
||||
#include <QUrl>
|
||||
|
||||
#include "db_helper.h"
|
||||
#include "comic_db.h"
|
||||
#include "folder.h"
|
||||
|
||||
#include "yacreader_server_data_helper.h"
|
||||
|
||||
#include "qnaturalsorting.h"
|
||||
|
||||
#include <ctime>
|
||||
using namespace std;
|
||||
|
||||
struct LibraryItemSorter
|
||||
{
|
||||
bool operator()(const LibraryItem * a,const LibraryItem * b) const
|
||||
{
|
||||
return naturalSortLessThanCI(a->name,b->name);
|
||||
}
|
||||
};
|
||||
|
||||
FolderContentControllerV2::FolderContentControllerV2() {}
|
||||
|
||||
void FolderContentControllerV2::service(HttpRequest& request, HttpResponse& response)
|
||||
{
|
||||
response.setHeader("Content-Type", "application/json");
|
||||
|
||||
QString path = QUrl::fromPercentEncoding(request.getPath()).toUtf8();
|
||||
QStringList pathElements = path.split('/');
|
||||
int libraryId = pathElements.at(3).toInt();
|
||||
qulonglong parentId = pathElements.at(5).toULongLong();
|
||||
|
||||
serviceContent(libraryId, parentId, response);
|
||||
|
||||
response.setStatus(200,"OK");
|
||||
response.write("",true);
|
||||
}
|
||||
|
||||
void FolderContentControllerV2::serviceContent(const int &library, const qulonglong &folderId, HttpResponse &response)
|
||||
{
|
||||
QList<LibraryItem *> folderContent = DBHelper::getFolderSubfoldersFromLibrary(library,folderId);
|
||||
QList<LibraryItem *> folderComics = DBHelper::getFolderComicsFromLibrary(library,folderId);
|
||||
|
||||
folderContent.append(folderComics);
|
||||
qSort(folderContent.begin(),folderContent.end(),LibraryItemSorter());
|
||||
|
||||
folderComics.clear();
|
||||
|
||||
QJsonArray items;
|
||||
|
||||
ComicDB * currentComic;
|
||||
Folder * currentFolder;
|
||||
for(QList<LibraryItem *>::const_iterator itr = folderContent.constBegin();itr!=folderContent.constEnd();itr++)
|
||||
{
|
||||
if((*itr)->isDir())
|
||||
{
|
||||
currentFolder = (Folder *)(*itr);
|
||||
items.append(YACReaderServerDataHelper::folderToJSON(library, *currentFolder));
|
||||
}
|
||||
else
|
||||
{
|
||||
currentComic = (ComicDB *)(*itr);
|
||||
items.append(YACReaderServerDataHelper::comicToJSON(library, *currentComic));
|
||||
}
|
||||
}
|
||||
|
||||
QJsonDocument output(items);
|
||||
|
||||
response.write(output.toJson());
|
||||
}
|
@ -0,0 +1,22 @@
|
||||
#ifndef FOLDERCONTENTCONTROLLER_V2_H
|
||||
#define FOLDERCONTENTCONTROLLER_V2_H
|
||||
|
||||
#include "httprequest.h"
|
||||
#include "httpresponse.h"
|
||||
#include "httprequesthandler.h"
|
||||
|
||||
class FolderContentControllerV2 : public HttpRequestHandler {
|
||||
Q_OBJECT
|
||||
Q_DISABLE_COPY(FolderContentControllerV2)
|
||||
public:
|
||||
/** Constructor */
|
||||
FolderContentControllerV2();
|
||||
|
||||
/** Generates the response */
|
||||
void service(HttpRequest& request, HttpResponse& response);
|
||||
|
||||
private:
|
||||
void serviceContent(const int &library, const qulonglong &folderId, HttpResponse &response);
|
||||
};
|
||||
|
||||
#endif // FOLDERCONTENTCONTROLLER_H
|
@ -0,0 +1,55 @@
|
||||
#include "folderinfocontroller_v2.h"
|
||||
#include "db_helper.h" //get libraries
|
||||
|
||||
#include "folder.h"
|
||||
#include "comic_db.h"
|
||||
|
||||
#include "template.h"
|
||||
#include "../static.h"
|
||||
|
||||
|
||||
FolderInfoControllerV2::FolderInfoControllerV2() {}
|
||||
|
||||
void FolderInfoControllerV2::service(HttpRequest& request, HttpResponse& response)
|
||||
{
|
||||
response.setHeader("Content-Type", "text/plain; charset=utf-8");
|
||||
|
||||
QString path = QUrl::fromPercentEncoding(request.getPath()).toUtf8();
|
||||
QStringList pathElements = path.split('/');
|
||||
int libraryId = pathElements.at(3).toInt();
|
||||
QString libraryName = DBHelper::getLibraryName(libraryId);
|
||||
qulonglong parentId = pathElements.at(5).toULongLong();
|
||||
|
||||
serviceComics(libraryId, parentId, response);
|
||||
|
||||
response.write("",true);
|
||||
}
|
||||
|
||||
void FolderInfoControllerV2::serviceComics(const int &library, const qulonglong &folderId, HttpResponse &response)
|
||||
{
|
||||
QList<LibraryItem *> folderContent = DBHelper::getFolderSubfoldersFromLibrary(library,folderId);
|
||||
QList<LibraryItem *> folderComics = DBHelper::getFolderComicsFromLibrary(library,folderId);
|
||||
|
||||
ComicDB * currentComic;
|
||||
for(QList<LibraryItem *>::const_iterator itr = folderComics.constBegin();itr!=folderComics.constEnd();itr++)
|
||||
{
|
||||
currentComic = (ComicDB *)(*itr);
|
||||
response.write(QString("/library/%1/comic/%2:%3:%4:%5:%6\r\n")
|
||||
.arg(library)
|
||||
.arg(currentComic->id)
|
||||
.arg(currentComic->getFileName())
|
||||
.arg(currentComic->getFileSize())
|
||||
.arg(currentComic->info.read ? 1 : 0)
|
||||
.arg(currentComic->info.hash)
|
||||
.toUtf8());
|
||||
delete currentComic;
|
||||
}
|
||||
|
||||
Folder * currentFolder;
|
||||
for(QList<LibraryItem *>::const_iterator itr = folderContent.constBegin();itr!=folderContent.constEnd();itr++)
|
||||
{
|
||||
currentFolder = (Folder *)(*itr);
|
||||
serviceComics(library, currentFolder->id, response);
|
||||
delete currentFolder;
|
||||
}
|
||||
}
|
@ -0,0 +1,23 @@
|
||||
#ifndef FOLDERINFOCONTROLLER_V2_H
|
||||
#define FOLDERINFOCONTROLLER_V2_H
|
||||
|
||||
#include "httprequest.h"
|
||||
#include "httpresponse.h"
|
||||
#include "httprequesthandler.h"
|
||||
|
||||
class FolderInfoControllerV2 : public HttpRequestHandler {
|
||||
Q_OBJECT
|
||||
Q_DISABLE_COPY(FolderInfoControllerV2)
|
||||
public:
|
||||
|
||||
/** Constructor */
|
||||
FolderInfoControllerV2();
|
||||
|
||||
/** Generates the response */
|
||||
void service(HttpRequest& request, HttpResponse& response);
|
||||
|
||||
private:
|
||||
void serviceComics(const int &library, const qulonglong & folderId, HttpResponse& response);
|
||||
};
|
||||
|
||||
#endif // FOLDERINFOCONTROLLER_H
|
@ -0,0 +1,39 @@
|
||||
#include "librariescontroller_v2.h"
|
||||
#include "db_helper.h" //get libraries
|
||||
#include "yacreader_libraries.h"
|
||||
|
||||
#include "template.h"
|
||||
#include "../static.h"
|
||||
|
||||
#include "QsLog.h"
|
||||
|
||||
LibrariesControllerV2::LibrariesControllerV2() {}
|
||||
|
||||
void LibrariesControllerV2::service(HttpRequest& request, HttpResponse& response)
|
||||
{
|
||||
HttpSession session=Static::sessionStore->getSession(request,response,false);
|
||||
|
||||
response.setHeader("Content-Type", "application/json");
|
||||
response.setHeader("Connection","close");
|
||||
|
||||
YACReaderLibraries libraries = DBHelper::getLibraries();
|
||||
QList<QString> names = DBHelper::getLibrariesNames();
|
||||
|
||||
QJsonArray librariesJson;
|
||||
|
||||
int currentId = 0;
|
||||
foreach (QString name,names) {
|
||||
currentId = libraries.getId(name);
|
||||
QJsonObject library;
|
||||
|
||||
library["name"] = name;
|
||||
library["id"] = currentId;
|
||||
|
||||
librariesJson.append(library);
|
||||
}
|
||||
|
||||
QJsonDocument output(librariesJson);
|
||||
|
||||
response.setStatus(200,"OK");
|
||||
response.write(output.toJson(),true);
|
||||
}
|
@ -1,10 +1,5 @@
|
||||
/**
|
||||
@file
|
||||
@author Stefan Frings
|
||||
*/
|
||||
|
||||
#ifndef FORMCONTROLLER_H
|
||||
#define FORMCONTROLLER_H
|
||||
#ifndef LIBRARIESCONTROLLER_V2_H
|
||||
#define LIBRARIESCONTROLLER_V2_H
|
||||
|
||||
#include "httprequest.h"
|
||||
#include "httpresponse.h"
|
||||
@ -15,16 +10,16 @@
|
||||
*/
|
||||
|
||||
|
||||
class FormController : public HttpRequestHandler {
|
||||
class LibrariesControllerV2 : public HttpRequestHandler {
|
||||
Q_OBJECT
|
||||
Q_DISABLE_COPY(FormController);
|
||||
Q_DISABLE_COPY(LibrariesControllerV2)
|
||||
public:
|
||||
|
||||
/** Constructor */
|
||||
FormController();
|
||||
LibrariesControllerV2();
|
||||
|
||||
/** Generates the response */
|
||||
void service(HttpRequest& request, HttpResponse& response);
|
||||
};
|
||||
|
||||
#endif // FORMCONTROLLER_H
|
||||
#endif // LIBRARIESCONTROLLER_H
|
@ -1,9 +1,11 @@
|
||||
#include "pagecontroller.h"
|
||||
#include "pagecontroller_v2.h"
|
||||
|
||||
#include "../static.h"
|
||||
|
||||
#include "comic.h"
|
||||
#include "comiccontroller.h"
|
||||
#include "yacreader_http_session.h"
|
||||
|
||||
#include <QDataStream>
|
||||
#include <QPointer>
|
||||
|
||||
@ -11,11 +13,12 @@
|
||||
|
||||
#include "db_helper.h"
|
||||
|
||||
PageController::PageController() {}
|
||||
PageControllerV2::PageControllerV2() {}
|
||||
|
||||
void PageController::service(HttpRequest& request, HttpResponse& response)
|
||||
void PageControllerV2::service(HttpRequest& request, HttpResponse& response)
|
||||
{
|
||||
HttpSession session=Static::sessionStore->getSession(request,response,false);
|
||||
YACReaderHttpSession *ySession = Static::yacreaderSessionStore->getYACReaderSessionHttpSession(session.getId());
|
||||
|
||||
QString path = QUrl::fromPercentEncoding(request.getPath()).toUtf8();
|
||||
bool remote = path.endsWith("remote");
|
||||
@ -25,8 +28,8 @@ void PageController::service(HttpRequest& request, HttpResponse& response)
|
||||
|
||||
QStringList pathElements = path.split('/');
|
||||
QString libraryName = DBHelper::getLibraryName(pathElements.at(2).toInt());
|
||||
qulonglong comicId = pathElements.at(4).toULongLong();
|
||||
unsigned int page = pathElements.at(6).toUInt();
|
||||
qulonglong comicId = pathElements.at(5).toULongLong();
|
||||
unsigned int page = pathElements.at(7).toUInt();
|
||||
|
||||
//qDebug("lib name : %s",pathElements.at(2).data());
|
||||
|
||||
@ -35,14 +38,14 @@ void PageController::service(HttpRequest& request, HttpResponse& response)
|
||||
if(remote)
|
||||
{
|
||||
QLOG_TRACE() << "se recupera comic remoto para servir páginas";
|
||||
comicFile = session.getCurrentRemoteComic();
|
||||
currentComicId = session.getCurrentRemoteComicId();
|
||||
comicFile = ySession->getCurrentRemoteComic();
|
||||
currentComicId = ySession->getCurrentRemoteComicId();
|
||||
}
|
||||
else
|
||||
{
|
||||
QLOG_TRACE() << "se recupera comic para servir páginas";
|
||||
comicFile = session.getCurrentComic();
|
||||
currentComicId = session.getCurrentComicId();
|
||||
comicFile = ySession->getCurrentComic();
|
||||
currentComicId = ySession->getCurrentComicId();
|
||||
}
|
||||
|
||||
if(currentComicId != 0 && !QPointer<Comic>(comicFile).isNull())
|
||||
@ -77,9 +80,9 @@ void PageController::service(HttpRequest& request, HttpResponse& response)
|
||||
{
|
||||
//delete comicFile;
|
||||
if(remote)
|
||||
session.dismissCurrentRemoteComic();
|
||||
ySession->dismissCurrentRemoteComic();
|
||||
else
|
||||
session.dismissCurrentComic();
|
||||
ySession->dismissCurrentComic();
|
||||
}
|
||||
response.setStatus(404,"not found"); //TODO qué mensaje enviar
|
||||
response.write("404 not found",true);
|
20
YACReaderLibrary/server/controllers/v2/pagecontroller_v2.h
Normal file
20
YACReaderLibrary/server/controllers/v2/pagecontroller_v2.h
Normal file
@ -0,0 +1,20 @@
|
||||
#ifndef PAGECONTROLLER_V2_H
|
||||
#define PAGECONTROLLER_V2_H
|
||||
|
||||
#include "httprequest.h"
|
||||
#include "httpresponse.h"
|
||||
#include "httprequesthandler.h"
|
||||
|
||||
class PageControllerV2 : public HttpRequestHandler {
|
||||
Q_OBJECT
|
||||
Q_DISABLE_COPY(PageControllerV2)
|
||||
public:
|
||||
|
||||
/** Constructor */
|
||||
PageControllerV2();
|
||||
|
||||
/** Generates the response */
|
||||
void service(HttpRequest& request, HttpResponse& response);
|
||||
};
|
||||
|
||||
#endif // PAGECONTROLLER_H
|
@ -0,0 +1,41 @@
|
||||
#include "readingcomicscontroller_v2.h"
|
||||
|
||||
#include "db_helper.h"
|
||||
#include "comic_db.h"
|
||||
|
||||
#include "yacreader_server_data_helper.h"
|
||||
|
||||
ReadingComicsControllerV2::ReadingComicsControllerV2()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void ReadingComicsControllerV2::service(HttpRequest &request, HttpResponse &response)
|
||||
{
|
||||
response.setHeader("Content-Type", "application/json");
|
||||
|
||||
QString path = QUrl::fromPercentEncoding(request.getPath()).toUtf8();
|
||||
QStringList pathElements = path.split('/');
|
||||
int libraryId = pathElements.at(3).toInt();
|
||||
|
||||
serviceContent(libraryId, response);
|
||||
|
||||
response.setStatus(200,"OK");
|
||||
response.write("",true);
|
||||
}
|
||||
|
||||
void ReadingComicsControllerV2::serviceContent(const int &library, HttpResponse &response)
|
||||
{
|
||||
QList<ComicDB> readingComics = DBHelper::getReading(library);
|
||||
|
||||
QJsonArray comics;
|
||||
|
||||
for(const ComicDB &comic : readingComics)
|
||||
{
|
||||
comics.append(YACReaderServerDataHelper::comicToJSON(library, comic));
|
||||
}
|
||||
|
||||
QJsonDocument output(comics);
|
||||
|
||||
response.write(output.toJson());
|
||||
}
|
@ -0,0 +1,20 @@
|
||||
#ifndef READINGCOMICSCONTROLLER_V2_H
|
||||
#define READINGCOMICSCONTROLLER_V2_H
|
||||
|
||||
#include "httprequest.h"
|
||||
#include "httpresponse.h"
|
||||
#include "httprequesthandler.h"
|
||||
|
||||
class ReadingComicsControllerV2 : public HttpRequestHandler {
|
||||
Q_OBJECT
|
||||
Q_DISABLE_COPY(ReadingComicsControllerV2)
|
||||
public:
|
||||
ReadingComicsControllerV2();
|
||||
|
||||
void service(HttpRequest& request, HttpResponse& response);
|
||||
|
||||
private:
|
||||
void serviceContent(const int &library, HttpResponse &response);
|
||||
};
|
||||
|
||||
#endif // READINGCOMICSCONTROLLER_H
|
@ -0,0 +1,35 @@
|
||||
#include "readinglistcontentcontroller_v2.h"
|
||||
|
||||
#include "db_helper.h"
|
||||
#include "comic_db.h"
|
||||
|
||||
#include "yacreader_server_data_helper.h"
|
||||
|
||||
ReadingListContentControllerV2::ReadingListContentControllerV2()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void ReadingListContentControllerV2::service(HttpRequest &request, HttpResponse &response)
|
||||
{
|
||||
response.setHeader("Content-Type", "text/plain; charset=utf-8");
|
||||
|
||||
QString path = QUrl::fromPercentEncoding(request.getPath()).toUtf8();
|
||||
QStringList pathElements = path.split('/');
|
||||
int libraryId = pathElements.at(3).toInt();
|
||||
qulonglong readingListId = pathElements.at(5).toULongLong();
|
||||
|
||||
serviceContent(libraryId, readingListId, response);
|
||||
|
||||
response.write("",true);
|
||||
}
|
||||
|
||||
void ReadingListContentControllerV2::serviceContent(const int &library, const qulonglong &readingListId, HttpResponse &response)
|
||||
{
|
||||
QList<ComicDB> comics = DBHelper::getReadingListFullContent(library, readingListId);
|
||||
|
||||
for(const ComicDB &comic : comics)
|
||||
{
|
||||
response.write(YACReaderServerDataHelper::comicToYSFormat(library, comic).toUtf8());
|
||||
}
|
||||
}
|
@ -0,0 +1,20 @@
|
||||
#ifndef READINGLISTCONTENTCONTROLLER_V2_H
|
||||
#define READINGLISTCONTENTCONTROLLER_V2_H
|
||||
|
||||
#include "httprequest.h"
|
||||
#include "httpresponse.h"
|
||||
#include "httprequesthandler.h"
|
||||
|
||||
class ReadingListContentControllerV2 : public HttpRequestHandler {
|
||||
Q_OBJECT
|
||||
Q_DISABLE_COPY(ReadingListContentControllerV2)
|
||||
public:
|
||||
ReadingListContentControllerV2();
|
||||
|
||||
void service(HttpRequest& request, HttpResponse& response);
|
||||
|
||||
private:
|
||||
void serviceContent(const int &library, const qulonglong &readingListId, HttpResponse &response);
|
||||
};
|
||||
|
||||
#endif // READINGLISTCONTENTCONTROLLER_H
|
@ -0,0 +1,32 @@
|
||||
#include "readinglistscontroller_v2.h"
|
||||
|
||||
#include "db_helper.h"
|
||||
#include "reading_list.h"
|
||||
|
||||
ReadingListsControllerV2::ReadingListsControllerV2()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void ReadingListsControllerV2::service(HttpRequest &request, HttpResponse &response)
|
||||
{
|
||||
response.setHeader("Content-Type", "text/plain; charset=utf-8");
|
||||
|
||||
QString path = QUrl::fromPercentEncoding(request.getPath()).toUtf8();
|
||||
QStringList pathElements = path.split('/');
|
||||
int libraryId = pathElements.at(3).toInt();
|
||||
|
||||
serviceContent(libraryId, response);
|
||||
|
||||
response.write("",true);
|
||||
}
|
||||
|
||||
void ReadingListsControllerV2::serviceContent(const int library, HttpResponse &response)
|
||||
{
|
||||
QList<ReadingList> readingLists = DBHelper::getReadingLists(library);
|
||||
|
||||
foreach(const ReadingList &item, readingLists)
|
||||
{
|
||||
response.write(QString("%1\t%2\t%3\r\n").arg(library).arg(item.getId()).arg(item.getName()).toUtf8());
|
||||
}
|
||||
}
|
@ -0,0 +1,20 @@
|
||||
#ifndef READINGLISTSCONTROLLER_V2_H
|
||||
#define READINGLISTSCONTROLLER_V2_H
|
||||
|
||||
#include "httprequest.h"
|
||||
#include "httpresponse.h"
|
||||
#include "httprequesthandler.h"
|
||||
|
||||
class ReadingListsControllerV2 : public HttpRequestHandler {
|
||||
Q_OBJECT
|
||||
Q_DISABLE_COPY(ReadingListsControllerV2)
|
||||
public:
|
||||
ReadingListsControllerV2();
|
||||
|
||||
void service(HttpRequest& request, HttpResponse& response);
|
||||
|
||||
private:
|
||||
void serviceContent(const int library, HttpResponse &response);
|
||||
};
|
||||
|
||||
#endif // READINGLISTSCONTROLLER_H
|
64
YACReaderLibrary/server/controllers/v2/synccontroller_v2.cpp
Normal file
64
YACReaderLibrary/server/controllers/v2/synccontroller_v2.cpp
Normal file
@ -0,0 +1,64 @@
|
||||
#include "synccontroller_v2.h"
|
||||
|
||||
#include "QsLog.h"
|
||||
#include <QUrl>
|
||||
|
||||
#include "comic_db.h"
|
||||
#include "db_helper.h"
|
||||
|
||||
SyncControllerV2::SyncControllerV2()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void SyncControllerV2::service(HttpRequest &request, HttpResponse &response)
|
||||
{
|
||||
QString postData = QString::fromUtf8(request.getBody());
|
||||
|
||||
QLOG_TRACE() << "POST DATA: " << postData;
|
||||
|
||||
if(postData.length()>0) {
|
||||
QList<QString> data = postData.split("\n");
|
||||
|
||||
qulonglong libraryId;
|
||||
qulonglong comicId;
|
||||
int currentPage;
|
||||
int currentRating;
|
||||
QString hash;
|
||||
foreach(QString comicInfo, data)
|
||||
{
|
||||
QList<QString> comicInfoProgress = comicInfo.split("\t");
|
||||
|
||||
if(comicInfoProgress.length() == 4 || comicInfoProgress.length() == 5)
|
||||
{
|
||||
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;
|
||||
|
||||
//Client 2.1+ version
|
||||
if(comicInfoProgress.length() > 4)
|
||||
{
|
||||
currentRating = comicInfoProgress.at(4).toInt();
|
||||
info.rating = currentRating;
|
||||
}
|
||||
|
||||
DBHelper::updateFromRemoteClient(libraryId,info);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
response.setStatus(412,"No comic info received");
|
||||
response.write("",true);
|
||||
return;
|
||||
}
|
||||
|
||||
response.write("OK",true);
|
||||
}
|
||||
|
21
YACReaderLibrary/server/controllers/v2/synccontroller_v2.h
Normal file
21
YACReaderLibrary/server/controllers/v2/synccontroller_v2.h
Normal file
@ -0,0 +1,21 @@
|
||||
#ifndef SYNCCONTROLLER_V2_H
|
||||
#define SYNCCONTROLLER_V2_H
|
||||
|
||||
#include <QObject>
|
||||
|
||||
#include "httprequest.h"
|
||||
#include "httpresponse.h"
|
||||
#include "httprequesthandler.h"
|
||||
|
||||
class SyncControllerV2 : public HttpRequestHandler {
|
||||
Q_OBJECT
|
||||
Q_DISABLE_COPY(SyncControllerV2)
|
||||
public:
|
||||
/** Constructor */
|
||||
SyncControllerV2();
|
||||
|
||||
/** Generates the response */
|
||||
void service(HttpRequest& request, HttpResponse& response);
|
||||
};
|
||||
|
||||
#endif // SYNCCONTROLLER_H
|
@ -0,0 +1,37 @@
|
||||
#include "tagcontentcontroller_v2.h"
|
||||
|
||||
#include "db_helper.h"
|
||||
#include "comic_db.h"
|
||||
|
||||
#include "yacreader_server_data_helper.h"
|
||||
|
||||
#include <QUrl>
|
||||
|
||||
TagContentControllerV2::TagContentControllerV2()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void TagContentControllerV2::service(HttpRequest &request, HttpResponse &response)
|
||||
{
|
||||
response.setHeader("Content-Type", "text/plain; charset=utf-8");
|
||||
|
||||
QString path = QUrl::fromPercentEncoding(request.getPath()).toUtf8();
|
||||
QStringList pathElements = path.split('/');
|
||||
int libraryId = pathElements.at(3).toInt();
|
||||
qulonglong tagId = pathElements.at(5).toULongLong();
|
||||
|
||||
serviceContent(libraryId, tagId, response);
|
||||
|
||||
response.write("",true);
|
||||
}
|
||||
|
||||
void TagContentControllerV2::serviceContent(const int &library, const qulonglong &tagId, HttpResponse &response)
|
||||
{
|
||||
QList<ComicDB> tagComics = DBHelper::getLabelComics(library, tagId);
|
||||
|
||||
for(const ComicDB &comic : tagComics)
|
||||
{
|
||||
response.write(YACReaderServerDataHelper::comicToYSFormat(library, comic).toUtf8());
|
||||
}
|
||||
}
|
@ -0,0 +1,22 @@
|
||||
#ifndef TAGCONTENTCONTROLLER_V2_H
|
||||
#define TAGCONTENTCONTROLLER_V2_H
|
||||
|
||||
#include "httprequest.h"
|
||||
#include "httpresponse.h"
|
||||
#include "httprequesthandler.h"
|
||||
|
||||
class TagContentControllerV2 : public HttpRequestHandler {
|
||||
Q_OBJECT
|
||||
Q_DISABLE_COPY(TagContentControllerV2)
|
||||
public:
|
||||
/** Constructor */
|
||||
TagContentControllerV2();
|
||||
|
||||
/** Generates the response */
|
||||
void service(HttpRequest& request, HttpResponse& response);
|
||||
|
||||
private:
|
||||
void serviceContent(const int &library, const qulonglong &tagId, HttpResponse &response);
|
||||
};
|
||||
|
||||
#endif // TAGCONTENTCONTROLLER_H
|
30
YACReaderLibrary/server/controllers/v2/tagscontroller_v2.cpp
Normal file
30
YACReaderLibrary/server/controllers/v2/tagscontroller_v2.cpp
Normal file
@ -0,0 +1,30 @@
|
||||
#include "tagscontroller_v2.h"
|
||||
|
||||
#include "db_helper.h"
|
||||
#include "yacreader_libraries.h"
|
||||
|
||||
#include "reading_list.h"
|
||||
#include "../static.h"
|
||||
#include "yacreader_global.h"
|
||||
|
||||
#include "QsLog.h"
|
||||
|
||||
TagsControllerV2::TagsControllerV2() {}
|
||||
|
||||
void TagsControllerV2::service(HttpRequest& request, HttpResponse& response)
|
||||
{
|
||||
response.setHeader("Content-Type", "text/plain; charset=utf-8");
|
||||
|
||||
QString path = QUrl::fromPercentEncoding(request.getPath()).toUtf8();
|
||||
QStringList pathElements = path.split('/');
|
||||
int libraryId = pathElements.at(3).toInt();
|
||||
|
||||
QList<Label> tags = DBHelper::getLabels(libraryId);
|
||||
|
||||
foreach(const Label &tag, tags)
|
||||
{
|
||||
response.write(QString("%1\t%2\t%3\t%4\r\n").arg(libraryId).arg(tag.getId()).arg(tag.getName()).arg(labelColorToRGBString(tag.getColorID())).toUtf8());
|
||||
}
|
||||
|
||||
response.write("",true);
|
||||
}
|
22
YACReaderLibrary/server/controllers/v2/tagscontroller_v2.h
Normal file
22
YACReaderLibrary/server/controllers/v2/tagscontroller_v2.h
Normal file
@ -0,0 +1,22 @@
|
||||
#ifndef TAGSCONTROLLER_V2_H
|
||||
#define TAGSCONTROLLER_V2_H
|
||||
|
||||
#include "httprequest.h"
|
||||
#include "httpresponse.h"
|
||||
#include "httprequesthandler.h"
|
||||
|
||||
|
||||
|
||||
class TagsControllerV2 : public HttpRequestHandler {
|
||||
Q_OBJECT
|
||||
Q_DISABLE_COPY(TagsControllerV2)
|
||||
public:
|
||||
|
||||
/** Constructor */
|
||||
TagsControllerV2();
|
||||
|
||||
/** Generates the response */
|
||||
void service(HttpRequest& request, HttpResponse& response);
|
||||
};
|
||||
|
||||
#endif // TAGSCONTROLLER_H
|
@ -0,0 +1,46 @@
|
||||
#include "updatecomiccontroller_v2.h"
|
||||
|
||||
#include "db_helper.h"
|
||||
#include "yacreader_libraries.h"
|
||||
|
||||
#include "template.h"
|
||||
#include "../static.h"
|
||||
|
||||
#include "comic_db.h"
|
||||
#include "comic.h"
|
||||
|
||||
#include "QsLog.h"
|
||||
|
||||
UpdateComicControllerV2::UpdateComicControllerV2(){}
|
||||
|
||||
void UpdateComicControllerV2::service(HttpRequest &request, HttpResponse &response)
|
||||
{
|
||||
HttpSession session=Static::sessionStore->getSession(request,response,false);
|
||||
|
||||
QString path = QUrl::fromPercentEncoding(request.getPath()).toUtf8();
|
||||
QStringList pathElements = path.split('/');
|
||||
qulonglong libraryId = pathElements.at(3).toULongLong();
|
||||
QString libraryName = DBHelper::getLibraryName(libraryId);
|
||||
qulonglong comicId = pathElements.at(5).toULongLong();
|
||||
|
||||
QString postData = QString::fromUtf8(request.getBody());
|
||||
|
||||
QLOG_TRACE() << "POST DATA: " << postData;
|
||||
|
||||
if(postData.length()>0) {
|
||||
QList<QString> data = postData.split("\n");
|
||||
int currentPage = data.at(0).split(":").at(1).toInt();
|
||||
ComicInfo info;
|
||||
info.currentPage = currentPage;
|
||||
info.id = comicId;
|
||||
DBHelper::updateProgress(libraryId,info);
|
||||
}
|
||||
else
|
||||
{
|
||||
response.setStatus(412,"No comic info received");
|
||||
response.write("",true);
|
||||
return;
|
||||
}
|
||||
|
||||
response.write("OK",true);
|
||||
}
|
@ -0,0 +1,22 @@
|
||||
#ifndef UPDATECOMICCONTROLLER_V2_H
|
||||
#define UPDATECOMICCONTROLLER_V2_H
|
||||
|
||||
|
||||
#include "httprequest.h"
|
||||
#include "httpresponse.h"
|
||||
#include "httprequesthandler.h"
|
||||
|
||||
|
||||
class UpdateComicControllerV2 : public HttpRequestHandler
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_DISABLE_COPY(UpdateComicControllerV2)
|
||||
|
||||
public:
|
||||
UpdateComicControllerV2();
|
||||
|
||||
/** Generates the response */
|
||||
void service(HttpRequest& request, HttpResponse& response);
|
||||
};
|
||||
|
||||
#endif // UPDATECOMICCONTROLLER_H
|
10
YACReaderLibrary/server/controllers/versioncontroller.cpp
Normal file
10
YACReaderLibrary/server/controllers/versioncontroller.cpp
Normal file
@ -0,0 +1,10 @@
|
||||
#include "versioncontroller.h"
|
||||
|
||||
VersionController::VersionController() {}
|
||||
|
||||
void VersionController::service(HttpRequest& request, HttpResponse& response)
|
||||
{
|
||||
Q_UNUSED(request);
|
||||
|
||||
response.write(SERVER_VERSION_NUMBER,true);
|
||||
}
|
21
YACReaderLibrary/server/controllers/versioncontroller.h
Normal file
21
YACReaderLibrary/server/controllers/versioncontroller.h
Normal file
@ -0,0 +1,21 @@
|
||||
#ifndef VERSIONCONTROLLER_H
|
||||
#define VERSIONCONTROLLER_H
|
||||
|
||||
#include "httprequest.h"
|
||||
#include "httpresponse.h"
|
||||
#include "httprequesthandler.h"
|
||||
|
||||
#include <QThread>
|
||||
|
||||
class VersionController : public HttpRequestHandler {
|
||||
Q_OBJECT
|
||||
Q_DISABLE_COPY(VersionController);
|
||||
public:
|
||||
/** Constructor */
|
||||
VersionController();
|
||||
|
||||
/** Generates the response */
|
||||
void service(HttpRequest& request, HttpResponse& response);
|
||||
};
|
||||
|
||||
#endif // VERSIONCONTROLLER_H
|
@ -1,12 +0,0 @@
|
||||
INCLUDEPATH += $$PWD
|
||||
DEPENDPATH += $$PWD
|
||||
|
||||
HEADERS += $$PWD/httplistener.h $$PWD/httpconnectionhandler.h $$PWD/httpconnectionhandlerpool.h $$PWD/httprequest.h $$PWD/httpresponse.h $$PWD/httpcookie.h $$PWD/httprequesthandler.h
|
||||
HEADERS += $$PWD/httpsession.h $$PWD/httpsessionstore.h
|
||||
HEADERS += $$PWD/staticfilecontroller.h
|
||||
|
||||
SOURCES += $$PWD/httplistener.cpp $$PWD/httpconnectionhandler.cpp $$PWD/httpconnectionhandlerpool.cpp $$PWD/httprequest.cpp $$PWD/httpresponse.cpp $$PWD/httpcookie.cpp $$PWD/httprequesthandler.cpp
|
||||
SOURCES += $$PWD/httpsession.cpp $$PWD/httpsessionstore.cpp
|
||||
SOURCES += $$PWD/staticfilecontroller.cpp
|
||||
|
||||
OTHER_FILES += $$PWD/../doc/readme.txt
|
@ -1,170 +0,0 @@
|
||||
/**
|
||||
@file
|
||||
@author Stefan Frings
|
||||
*/
|
||||
|
||||
#include "httpconnectionhandler.h"
|
||||
#include "httpresponse.h"
|
||||
#include <QTimer>
|
||||
#include <QCoreApplication>
|
||||
|
||||
HttpConnectionHandler::HttpConnectionHandler(QSettings* settings, HttpRequestHandler* requestHandler)
|
||||
: QThread()
|
||||
{
|
||||
Q_ASSERT(settings!=0);
|
||||
Q_ASSERT(requestHandler!=0);
|
||||
this->settings=settings;
|
||||
this->requestHandler=requestHandler;
|
||||
currentRequest=0;
|
||||
busy = false;
|
||||
// execute signals in my own thread
|
||||
moveToThread(this);
|
||||
socket.moveToThread(this);
|
||||
readTimer.moveToThread(this);
|
||||
connect(&socket, SIGNAL(readyRead()), SLOT(read()));
|
||||
connect(&socket, SIGNAL(disconnected()), SLOT(disconnected()));
|
||||
connect(&readTimer, SIGNAL(timeout()), SLOT(readTimeout()));
|
||||
readTimer.setSingleShot(true);
|
||||
qDebug("HttpConnectionHandler (%p): constructed", this);
|
||||
this->start();
|
||||
}
|
||||
|
||||
|
||||
HttpConnectionHandler::~HttpConnectionHandler() {
|
||||
socket.close();
|
||||
quit();
|
||||
wait();
|
||||
qDebug("HttpConnectionHandler (%p): destroyed", this);
|
||||
}
|
||||
|
||||
|
||||
void HttpConnectionHandler::run() {
|
||||
qDebug("HttpConnectionHandler (%p): thread started", this);
|
||||
try {
|
||||
exec();
|
||||
}
|
||||
catch (...) {
|
||||
qCritical("HttpConnectionHandler (%p): an uncatched exception occured in the thread",this);
|
||||
}
|
||||
qDebug("HttpConnectionHandler (%p): thread stopped", this);
|
||||
// Change to the main thread, otherwise deleteLater() would not work
|
||||
moveToThread(QCoreApplication::instance()->thread());
|
||||
}
|
||||
|
||||
|
||||
void HttpConnectionHandler::handleConnection(tSocketDescriptor socketDescriptor) {
|
||||
qDebug("HttpConnectionHandler (%p): handle new connection", this);
|
||||
busy = true;
|
||||
Q_ASSERT(socket.isOpen()==false); // if not, then the handler is already busy
|
||||
|
||||
if (!socket.setSocketDescriptor(socketDescriptor)) {
|
||||
qCritical("HttpConnectionHandler (%p): cannot initialize socket: %s", this,qPrintable(socket.errorString()));
|
||||
return;
|
||||
}
|
||||
// Start timer for read timeout
|
||||
int readTimeout=settings->value("readTimeout",10000).toInt();
|
||||
readTimer.start(readTimeout);
|
||||
// delete previous request
|
||||
delete currentRequest;
|
||||
currentRequest=0;
|
||||
}
|
||||
|
||||
|
||||
bool HttpConnectionHandler::isBusy() {
|
||||
return busy;
|
||||
}
|
||||
|
||||
void HttpConnectionHandler::setBusy() {
|
||||
this->busy = true;
|
||||
}
|
||||
|
||||
|
||||
void HttpConnectionHandler::readTimeout() {
|
||||
qDebug("HttpConnectionHandler (%p): read timeout occured",this);
|
||||
|
||||
//Commented out because QWebView cannot handle this.
|
||||
//socket.write("HTTP/1.1 408 request timeout\r\nConnection: close\r\n\r\n408 request timeout\r\n");
|
||||
|
||||
socket.disconnectFromHost();
|
||||
delete currentRequest;
|
||||
currentRequest=0;
|
||||
}
|
||||
|
||||
|
||||
void HttpConnectionHandler::disconnected() {
|
||||
qDebug("HttpConnectionHandler (%p): disconnected", this);
|
||||
socket.close();
|
||||
readTimer.stop();
|
||||
busy = false;
|
||||
}
|
||||
|
||||
void HttpConnectionHandler::read() {
|
||||
while (socket.bytesAvailable()) {
|
||||
#ifdef SUPERVERBOSE
|
||||
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);
|
||||
}
|
||||
|
||||
// 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);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,64 +0,0 @@
|
||||
#include "httpconnectionhandlerpool.h"
|
||||
|
||||
HttpConnectionHandlerPool::HttpConnectionHandlerPool(QSettings* settings, HttpRequestHandler* requestHandler)
|
||||
: QObject()
|
||||
{
|
||||
Q_ASSERT(settings!=0);
|
||||
this->settings=settings;
|
||||
this->requestHandler=requestHandler;
|
||||
cleanupTimer.start(settings->value("cleanupInterval",10000).toInt());
|
||||
connect(&cleanupTimer, SIGNAL(timeout()), SLOT(cleanup()));
|
||||
}
|
||||
|
||||
|
||||
HttpConnectionHandlerPool::~HttpConnectionHandlerPool() {
|
||||
foreach(HttpConnectionHandler* handler, pool) {
|
||||
connect(handler,SIGNAL(finished()),handler,SLOT(deleteLater()));
|
||||
handler->quit();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
HttpConnectionHandler* HttpConnectionHandlerPool::getConnectionHandler() {
|
||||
HttpConnectionHandler* freeHandler=0;
|
||||
mutex.lock();
|
||||
// find a free handler in pool
|
||||
foreach(HttpConnectionHandler* handler, pool) {
|
||||
if (!handler->isBusy()) {
|
||||
freeHandler=handler;
|
||||
freeHandler->setBusy();
|
||||
break;
|
||||
}
|
||||
}
|
||||
// create a new handler, if necessary
|
||||
if (!freeHandler) {
|
||||
int maxConnectionHandlers=settings->value("maxThreads",1000).toInt();
|
||||
if (pool.count()<maxConnectionHandlers) {
|
||||
freeHandler=new HttpConnectionHandler(settings,requestHandler);
|
||||
freeHandler->setBusy();
|
||||
pool.append(freeHandler);
|
||||
}
|
||||
}
|
||||
mutex.unlock();
|
||||
return freeHandler;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void HttpConnectionHandlerPool::cleanup() {
|
||||
int maxIdleHandlers=settings->value("minThreads",50).toInt();
|
||||
int idleCounter=0;
|
||||
mutex.lock();
|
||||
foreach(HttpConnectionHandler* handler, pool) {
|
||||
if (!handler->isBusy()) {
|
||||
if (++idleCounter > maxIdleHandlers) {
|
||||
pool.removeOne(handler);
|
||||
qDebug("HttpConnectionHandlerPool: Removed connection handler (%p), pool size is now %i",handler,pool.size());
|
||||
connect(handler,SIGNAL(finished()),handler,SLOT(deleteLater()));
|
||||
handler->quit();
|
||||
break; // remove only one handler in each interval
|
||||
}
|
||||
}
|
||||
}
|
||||
mutex.unlock();
|
||||
}
|
@ -1,132 +0,0 @@
|
||||
/**
|
||||
@file
|
||||
@author Stefan Frings
|
||||
*/
|
||||
|
||||
#include "httpresponse.h"
|
||||
|
||||
HttpResponse::HttpResponse(QTcpSocket* socket) {
|
||||
this->socket=socket;
|
||||
statusCode=200;
|
||||
statusText="OK";
|
||||
sentHeaders=false;
|
||||
sentLastPart=false;
|
||||
}
|
||||
|
||||
void HttpResponse::setHeader(QByteArray name, QByteArray value) {
|
||||
//Q_ASSERT(sentHeaders==false);
|
||||
headers.insert(name,value);
|
||||
}
|
||||
|
||||
void HttpResponse::setHeader(QByteArray name, int value) {
|
||||
//Q_ASSERT(sentHeaders==false);
|
||||
headers.insert(name,QByteArray::number(value));
|
||||
}
|
||||
|
||||
QMap<QByteArray,QByteArray>& HttpResponse::getHeaders() {
|
||||
return headers;
|
||||
}
|
||||
|
||||
void HttpResponse::setStatus(int statusCode, QByteArray description) {
|
||||
this->statusCode=statusCode;
|
||||
statusText=description;
|
||||
}
|
||||
|
||||
void HttpResponse::writeHeaders() {
|
||||
//Q_ASSERT(sentHeaders==false);
|
||||
QByteArray buffer;
|
||||
buffer.append("HTTP/1.1 ");
|
||||
buffer.append(QByteArray::number(statusCode));
|
||||
buffer.append(' ');
|
||||
buffer.append(statusText);
|
||||
buffer.append("\r\n");
|
||||
foreach(QByteArray name, headers.keys()) {
|
||||
buffer.append(name);
|
||||
buffer.append(": ");
|
||||
buffer.append(headers.value(name));
|
||||
buffer.append("\r\n");
|
||||
}
|
||||
foreach(HttpCookie cookie,cookies.values()) {
|
||||
buffer.append("Set-Cookie: ");
|
||||
buffer.append(cookie.toByteArray());
|
||||
buffer.append("\r\n");
|
||||
}
|
||||
buffer.append("\r\n");
|
||||
writeToSocket(buffer);
|
||||
sentHeaders=true;
|
||||
}
|
||||
|
||||
bool HttpResponse::writeToSocket(QByteArray data) {
|
||||
int remaining=data.size();
|
||||
char* ptr=data.data();
|
||||
while (socket->isOpen() && remaining>0) {
|
||||
// Wait until the previous buffer content is written out, otherwise it could become very large
|
||||
socket->waitForBytesWritten(-1);
|
||||
int written=socket->write(ptr,remaining);
|
||||
if (written==-1) {
|
||||
return false;
|
||||
}
|
||||
ptr+=written;
|
||||
remaining-=written;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void HttpResponse::write(QByteArray data, bool lastPart) {
|
||||
//Q_ASSERT(sentLastPart==false);
|
||||
if (sentHeaders==false) {
|
||||
QByteArray connectionMode=headers.value("Connection");
|
||||
if (!headers.contains("Content-Length") && !headers.contains("Transfer-Encoding") && connectionMode!="close" && connectionMode!="Close") {
|
||||
if (!lastPart) {
|
||||
headers.insert("Transfer-Encoding","chunked");
|
||||
}
|
||||
else {
|
||||
headers.insert("Content-Length",QByteArray::number(data.size()));
|
||||
}
|
||||
}
|
||||
writeHeaders();
|
||||
}
|
||||
bool chunked=headers.value("Transfer-Encoding")=="chunked" || headers.value("Transfer-Encoding")=="Chunked";
|
||||
if (chunked) {
|
||||
if (data.size()>0) {
|
||||
QByteArray buffer=QByteArray::number(data.size(),16);
|
||||
buffer.append("\r\n");
|
||||
writeToSocket(buffer);
|
||||
writeToSocket(data);
|
||||
writeToSocket("\r\n");
|
||||
}
|
||||
}
|
||||
else {
|
||||
writeToSocket(data);
|
||||
}
|
||||
if (lastPart) {
|
||||
if (chunked) {
|
||||
writeToSocket("0\r\n\r\n");
|
||||
}
|
||||
else if (!headers.contains("Content-Length")) {
|
||||
socket->disconnectFromHost();
|
||||
}
|
||||
sentLastPart=true;
|
||||
}
|
||||
}
|
||||
|
||||
void HttpResponse::writeText(QString text, bool lastPart)
|
||||
{
|
||||
write(QByteArray(text.toUtf8()),lastPart);
|
||||
}
|
||||
|
||||
bool HttpResponse::hasSentLastPart() const {
|
||||
return sentLastPart;
|
||||
}
|
||||
|
||||
|
||||
void HttpResponse::setCookie(const HttpCookie& cookie) {
|
||||
//Q_ASSERT(sentHeaders==false);
|
||||
if (!cookie.getName().isEmpty()) {
|
||||
cookies.insert(cookie.getName(),cookie);
|
||||
}
|
||||
}
|
||||
|
||||
QMap<QByteArray,HttpCookie>& HttpResponse::getCookies() {
|
||||
return cookies;
|
||||
}
|
@ -1,135 +0,0 @@
|
||||
/**
|
||||
@file
|
||||
@author Stefan Frings
|
||||
*/
|
||||
|
||||
#ifndef HTTPRESPONSE_H
|
||||
#define HTTPRESPONSE_H
|
||||
|
||||
#include <QMap>
|
||||
#include <QString>
|
||||
#include <QTcpSocket>
|
||||
#include "httpcookie.h"
|
||||
|
||||
/**
|
||||
This object represents a HTTP response, in particular the response headers.
|
||||
<p>
|
||||
Example code for proper response generation:
|
||||
<code><pre>
|
||||
response.setStatus(200,"OK"); // optional, because this is the default
|
||||
response.writeBody("Hello");
|
||||
response.writeBody("World!",true);
|
||||
</pre></code>
|
||||
<p>
|
||||
Example how to return an error:
|
||||
<code><pre>
|
||||
response.setStatus(500,"server error");
|
||||
response.write("The request cannot be processed because the servers is broken",true);
|
||||
</pre></code>
|
||||
<p>
|
||||
For performance reason, writing a single or few large packets is better than writing
|
||||
many small packets. In case of large responses (e.g. file downloads), a Content-Length
|
||||
header should be set before calling write(). Web Browsers use that information to display
|
||||
a progress bar.
|
||||
*/
|
||||
|
||||
class HttpResponse {
|
||||
Q_DISABLE_COPY(HttpResponse)
|
||||
public:
|
||||
|
||||
/**
|
||||
Constructor.
|
||||
@param socket used to write the response
|
||||
*/
|
||||
HttpResponse(QTcpSocket* socket);
|
||||
|
||||
/**
|
||||
Set a HTTP response header
|
||||
@param name name of the header
|
||||
@param value value of the header
|
||||
*/
|
||||
void setHeader(QByteArray name, QByteArray value);
|
||||
|
||||
/**
|
||||
Set a HTTP response header
|
||||
@param name name of the header
|
||||
@param value value of the header
|
||||
*/
|
||||
void setHeader(QByteArray name, int value);
|
||||
|
||||
/** Get the map of HTTP response headers */
|
||||
QMap<QByteArray,QByteArray>& getHeaders();
|
||||
|
||||
/** Get the map of cookies */
|
||||
QMap<QByteArray,HttpCookie>& getCookies();
|
||||
|
||||
/**
|
||||
Set status code and description. The default is 200,OK.
|
||||
*/
|
||||
void setStatus(int statusCode, QByteArray description=QByteArray());
|
||||
|
||||
/**
|
||||
Write body data to the socket.
|
||||
<p>
|
||||
The HTTP status line and headers are sent automatically before the first
|
||||
byte of the body gets sent.
|
||||
<p>
|
||||
If the response contains only a single chunk (indicated by lastPart=true),
|
||||
the response is transferred in traditional mode with a Content-Length
|
||||
header, which is automatically added if not already set before.
|
||||
<p>
|
||||
Otherwise, each part is transferred in chunked mode.
|
||||
@param data Data bytes of the body
|
||||
@param lastPart Indicator, if this is the last part of the response.
|
||||
*/
|
||||
void write(QByteArray data, bool lastPart=false);
|
||||
void writeText(QString text, bool lastPart=false);
|
||||
|
||||
/**
|
||||
Indicates wheter the body has been sent completely. Used by the connection
|
||||
handler to terminate the body automatically when necessary.
|
||||
*/
|
||||
bool hasSentLastPart() const;
|
||||
|
||||
/**
|
||||
Set a cookie. Cookies are sent together with the headers when the first
|
||||
call to write() occurs.
|
||||
*/
|
||||
void setCookie(const HttpCookie& cookie);
|
||||
|
||||
private:
|
||||
|
||||
/** Request headers */
|
||||
QMap<QByteArray,QByteArray> headers;
|
||||
|
||||
/** Socket for writing output */
|
||||
QTcpSocket* socket;
|
||||
|
||||
/** HTTP status code*/
|
||||
int statusCode;
|
||||
|
||||
/** HTTP status code description */
|
||||
QByteArray statusText;
|
||||
|
||||
/** Indicator whether headers have been sent */
|
||||
bool sentHeaders;
|
||||
|
||||
/** Indicator whether the body has been sent completely */
|
||||
bool sentLastPart;
|
||||
|
||||
/** Cookies */
|
||||
QMap<QByteArray,HttpCookie> cookies;
|
||||
|
||||
/** Write raw data to the socket. This method blocks until all bytes have been passed to the TCP buffer */
|
||||
bool writeToSocket(QByteArray data);
|
||||
|
||||
/**
|
||||
Write the response HTTP status and headers to the socket.
|
||||
Calling this method is optional, because writeBody() calls
|
||||
it automatically when required.
|
||||
*/
|
||||
void writeHeaders();
|
||||
|
||||
};
|
||||
|
||||
#endif // HTTPRESPONSE_H
|
@ -1,383 +0,0 @@
|
||||
/**
|
||||
@file
|
||||
@author Stefan Frings
|
||||
*/
|
||||
|
||||
#include "httpsession.h"
|
||||
#include <QDateTime>
|
||||
#include <QUuid>
|
||||
|
||||
|
||||
HttpSession::HttpSession(bool canStore) {
|
||||
if (canStore) {
|
||||
dataPtr=new HttpSessionData();
|
||||
dataPtr->refCount=1;
|
||||
dataPtr->lastAccess=QDateTime::currentMSecsSinceEpoch();
|
||||
dataPtr->id=QUuid::createUuid().toString().toLatin1();
|
||||
dataPtr->yacreaderSessionData.comic = 0;
|
||||
dataPtr->yacreaderSessionData.comicId = 0;
|
||||
dataPtr->yacreaderSessionData.remoteComic = 0;
|
||||
dataPtr->yacreaderSessionData.remoteComicId = 0;
|
||||
#ifdef SUPERVERBOSE
|
||||
qDebug("HttpSession: created new session data with id %s",dataPtr->id.data());
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
dataPtr=0;
|
||||
}
|
||||
}
|
||||
|
||||
HttpSession::HttpSession(const HttpSession& other) {
|
||||
dataPtr=other.dataPtr;
|
||||
if (dataPtr) {
|
||||
dataPtr->lock.lockForWrite();
|
||||
dataPtr->refCount++;
|
||||
#ifdef SUPERVERBOSE
|
||||
qDebug("HttpSession: refCount of %s is %i",dataPtr->id.data(),dataPtr->refCount);
|
||||
#endif
|
||||
dataPtr->lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
HttpSession& HttpSession::operator= (const HttpSession& other) {
|
||||
HttpSessionData* oldPtr=dataPtr;
|
||||
dataPtr=other.dataPtr;
|
||||
if (dataPtr) {
|
||||
dataPtr->lock.lockForWrite();
|
||||
dataPtr->refCount++;
|
||||
#ifdef SUPERVERBOSE
|
||||
qDebug("HttpSession: refCount of %s is %i",dataPtr->id.data(),dataPtr->refCount);
|
||||
#endif
|
||||
dataPtr->lastAccess=QDateTime::currentMSecsSinceEpoch();
|
||||
dataPtr->lock.unlock();
|
||||
}
|
||||
if (oldPtr) {
|
||||
int refCount;
|
||||
oldPtr->lock.lockForRead();
|
||||
refCount=oldPtr->refCount--;
|
||||
#ifdef SUPERVERBOSE
|
||||
qDebug("HttpSession: refCount of %s is %i",oldPtr->id.data(),oldPtr->refCount);
|
||||
#endif
|
||||
oldPtr->lock.unlock();
|
||||
if (refCount==0) {
|
||||
delete oldPtr;
|
||||
}
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
HttpSession::~HttpSession() {
|
||||
if (dataPtr) {
|
||||
int refCount;
|
||||
dataPtr->lock.lockForRead();
|
||||
refCount=--dataPtr->refCount;
|
||||
#ifdef SUPERVERBOSE
|
||||
qDebug("HttpSession: refCount of %s is %i",dataPtr->id.data(),dataPtr->refCount);
|
||||
#endif
|
||||
dataPtr->lock.unlock();
|
||||
if (refCount==0) {
|
||||
qDebug("HttpSession: deleting data");
|
||||
delete dataPtr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
QByteArray HttpSession::getId() const {
|
||||
if (dataPtr) {
|
||||
return dataPtr->id;
|
||||
}
|
||||
else {
|
||||
return QByteArray();
|
||||
}
|
||||
}
|
||||
|
||||
bool HttpSession::isNull() const {
|
||||
return dataPtr==0;
|
||||
}
|
||||
|
||||
void HttpSession::set(const QByteArray& key, const QVariant& value) {
|
||||
if (dataPtr) {
|
||||
dataPtr->lock.lockForWrite();
|
||||
dataPtr->values.insert(key,value);
|
||||
dataPtr->lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
void HttpSession::remove(const QByteArray& key) {
|
||||
if (dataPtr) {
|
||||
dataPtr->lock.lockForWrite();
|
||||
dataPtr->values.remove(key);
|
||||
dataPtr->lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
QVariant HttpSession::get(const QByteArray& key) const {
|
||||
QVariant value;
|
||||
if (dataPtr) {
|
||||
dataPtr->lock.lockForRead();
|
||||
value=dataPtr->values.value(key);
|
||||
dataPtr->lock.unlock();
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
bool HttpSession::contains(const QByteArray& key) const {
|
||||
bool found=false;
|
||||
if (dataPtr) {
|
||||
dataPtr->lock.lockForRead();
|
||||
found=dataPtr->values.contains(key);
|
||||
dataPtr->lock.unlock();
|
||||
}
|
||||
return found;
|
||||
}
|
||||
|
||||
QMap<QByteArray,QVariant> HttpSession::getAll() const {
|
||||
QMap<QByteArray,QVariant> values;
|
||||
if (dataPtr) {
|
||||
dataPtr->lock.lockForRead();
|
||||
values=dataPtr->values;
|
||||
dataPtr->lock.unlock();
|
||||
}
|
||||
return values;
|
||||
}
|
||||
|
||||
qint64 HttpSession::getLastAccess() const {
|
||||
qint64 value=0;
|
||||
if (dataPtr) {
|
||||
dataPtr->lock.lockForRead();
|
||||
value=dataPtr->lastAccess;
|
||||
dataPtr->lock.unlock();
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
|
||||
void HttpSession::setLastAccess() {
|
||||
if (dataPtr) {
|
||||
dataPtr->lock.lockForRead();
|
||||
dataPtr->lastAccess=QDateTime::currentMSecsSinceEpoch();
|
||||
dataPtr->lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
//AÑADIDO
|
||||
//sets
|
||||
bool HttpSession::isComicOnDevice(const QString & hash)
|
||||
{
|
||||
if(dataPtr)
|
||||
return dataPtr->yacreaderSessionData.comicsOnDevice.contains(hash);
|
||||
else
|
||||
return false;
|
||||
}
|
||||
bool HttpSession::isComicDownloaded(const QString & hash)
|
||||
{
|
||||
if(dataPtr)
|
||||
return dataPtr->yacreaderSessionData.downloadedComics.contains(hash);
|
||||
else
|
||||
return false;
|
||||
}
|
||||
void HttpSession::setComicOnDevice(const QString & hash)
|
||||
{
|
||||
if(dataPtr)
|
||||
{
|
||||
dataPtr->yacreaderSessionData.comicsOnDevice.insert(hash);
|
||||
}
|
||||
}
|
||||
void HttpSession::setComicsOnDevice(const QSet<QString> & set)
|
||||
{
|
||||
if(dataPtr)
|
||||
{
|
||||
dataPtr->yacreaderSessionData.comicsOnDevice = set;
|
||||
}
|
||||
}
|
||||
void HttpSession::setDownloadedComic(const QString & hash)
|
||||
{
|
||||
if(dataPtr)
|
||||
{
|
||||
dataPtr->yacreaderSessionData.downloadedComics.insert(hash);
|
||||
}
|
||||
}
|
||||
QSet<QString> HttpSession::getComicsOnDevice()
|
||||
{
|
||||
if(dataPtr)
|
||||
return dataPtr->yacreaderSessionData.comicsOnDevice ;
|
||||
else
|
||||
return QSet<QString>();
|
||||
}
|
||||
QSet<QString> HttpSession::getDownloadedComics()
|
||||
{
|
||||
if(dataPtr)
|
||||
return dataPtr->yacreaderSessionData.downloadedComics ;
|
||||
else
|
||||
return QSet<QString>();
|
||||
}
|
||||
|
||||
void HttpSession::clearComics()
|
||||
{
|
||||
if(dataPtr)
|
||||
{
|
||||
dataPtr->yacreaderSessionData.comicsOnDevice.clear();
|
||||
dataPtr->yacreaderSessionData.downloadedComics.clear();
|
||||
}
|
||||
}
|
||||
//current comic (import)
|
||||
qulonglong HttpSession::getCurrentComicId()
|
||||
{
|
||||
if(dataPtr)
|
||||
return dataPtr->yacreaderSessionData.comicId ;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
Comic* HttpSession::getCurrentComic()
|
||||
{
|
||||
if(dataPtr)
|
||||
{
|
||||
return dataPtr->yacreaderSessionData.comic ;
|
||||
}
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
void HttpSession::dismissCurrentComic()
|
||||
{
|
||||
if(dataPtr)
|
||||
{
|
||||
if(dataPtr->yacreaderSessionData.comic != 0)
|
||||
{
|
||||
dataPtr->yacreaderSessionData.comic->invalidate();
|
||||
dataPtr->yacreaderSessionData.comic->deleteLater();
|
||||
dataPtr->yacreaderSessionData.comic = 0;
|
||||
}
|
||||
dataPtr->yacreaderSessionData.comicId = 0;
|
||||
}
|
||||
}
|
||||
void HttpSession::setCurrentComic(qulonglong id, Comic * comic)
|
||||
{
|
||||
if(dataPtr)
|
||||
{
|
||||
dismissCurrentComic();
|
||||
dataPtr->yacreaderSessionData.comicId = id;
|
||||
dataPtr->yacreaderSessionData.comic = comic;
|
||||
}
|
||||
}
|
||||
|
||||
//current comic (read)
|
||||
qulonglong HttpSession::getCurrentRemoteComicId()
|
||||
{
|
||||
if(dataPtr)
|
||||
return dataPtr->yacreaderSessionData.remoteComicId ;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
Comic* HttpSession::getCurrentRemoteComic()
|
||||
{
|
||||
if(dataPtr)
|
||||
{
|
||||
return dataPtr->yacreaderSessionData.remoteComic ;
|
||||
}
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
void HttpSession::dismissCurrentRemoteComic()
|
||||
{
|
||||
if(dataPtr)
|
||||
{
|
||||
if(dataPtr->yacreaderSessionData.remoteComic != 0)
|
||||
{
|
||||
dataPtr->yacreaderSessionData.remoteComic->invalidate();
|
||||
dataPtr->yacreaderSessionData.remoteComic->deleteLater();
|
||||
dataPtr->yacreaderSessionData.remoteComic = 0;
|
||||
}
|
||||
dataPtr->yacreaderSessionData.remoteComicId = 0;
|
||||
}
|
||||
}
|
||||
void HttpSession::setCurrentRemoteComic(qulonglong id, Comic * comic)
|
||||
{
|
||||
if(dataPtr)
|
||||
{
|
||||
dismissCurrentRemoteComic();
|
||||
dataPtr->yacreaderSessionData.remoteComicId = id;
|
||||
dataPtr->yacreaderSessionData.remoteComic = comic;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
QString HttpSession::getDeviceType()
|
||||
{
|
||||
if(dataPtr)
|
||||
{
|
||||
return dataPtr->yacreaderSessionData.device;
|
||||
}
|
||||
return "";
|
||||
}
|
||||
QString HttpSession::getDisplayType()
|
||||
{
|
||||
if(dataPtr)
|
||||
{
|
||||
return dataPtr->yacreaderSessionData.display;
|
||||
}
|
||||
return "";
|
||||
}
|
||||
void HttpSession::setDeviceType(const QString & device)
|
||||
{
|
||||
if(dataPtr)
|
||||
{
|
||||
//dataPtr->yacreaderSessionData.comicsOnDevice.clear(); //TODO crear un método clear que limpie la sesión completamente
|
||||
//dataPtr->yacreaderSessionData.downloadedComics.clear();
|
||||
dataPtr->yacreaderSessionData.device = device;
|
||||
}
|
||||
}
|
||||
void HttpSession::setDisplayType(const QString & display)
|
||||
{
|
||||
if(dataPtr)
|
||||
{
|
||||
dataPtr->yacreaderSessionData.display = display;
|
||||
}
|
||||
}
|
||||
|
||||
void HttpSession::clearNavigationPath()
|
||||
{
|
||||
if(dataPtr)
|
||||
dataPtr->yacreaderSessionData.navigationPath.clear();
|
||||
}
|
||||
|
||||
QPair<qulonglong, quint32> HttpSession::popNavigationItem()
|
||||
{
|
||||
if(dataPtr && !(dataPtr->yacreaderSessionData.navigationPath.isEmpty()))
|
||||
return dataPtr->yacreaderSessionData.navigationPath.pop();
|
||||
return QPair<qulonglong, quint32>();
|
||||
}
|
||||
|
||||
QPair<qulonglong, quint32> HttpSession::topNavigationItem()
|
||||
{
|
||||
if(dataPtr && !(dataPtr->yacreaderSessionData.navigationPath.isEmpty()))
|
||||
return dataPtr->yacreaderSessionData.navigationPath.top();
|
||||
return QPair<qulonglong, quint32>();
|
||||
}
|
||||
|
||||
void HttpSession::pushNavigationItem(const QPair<qulonglong, quint32> &item)
|
||||
{
|
||||
if(dataPtr)
|
||||
dataPtr->yacreaderSessionData.navigationPath.push(item);
|
||||
}
|
||||
|
||||
void HttpSession::updateTopItem(const QPair<qulonglong, quint32> &item)
|
||||
{
|
||||
if(dataPtr && !(dataPtr->yacreaderSessionData.navigationPath.isEmpty()))
|
||||
{
|
||||
dataPtr->yacreaderSessionData.navigationPath.pop();
|
||||
dataPtr->yacreaderSessionData.navigationPath.push(item);
|
||||
} else if(dataPtr)
|
||||
{
|
||||
dataPtr->yacreaderSessionData.navigationPath.push(item);
|
||||
}
|
||||
}
|
||||
|
||||
QStack<QPair<qulonglong, quint32> > HttpSession::getNavigationPath()
|
||||
{
|
||||
if(dataPtr)
|
||||
return dataPtr->yacreaderSessionData.navigationPath;
|
||||
else
|
||||
return QStack<QPair<qulonglong, quint32> >();
|
||||
}
|
||||
|
@ -1,193 +0,0 @@
|
||||
/**
|
||||
@file
|
||||
@author Stefan Frings
|
||||
*/
|
||||
|
||||
#ifndef HTTPSESSION_H
|
||||
#define HTTPSESSION_H
|
||||
|
||||
#include <QByteArray>
|
||||
#include <QVariant>
|
||||
#include <QReadWriteLock>
|
||||
|
||||
#include <QSet>
|
||||
#include <QString>
|
||||
#include "comic.h"
|
||||
|
||||
/**
|
||||
This class stores data for a single HTTP session.
|
||||
A session can store any number of key/value pairs. This class uses implicit
|
||||
sharing for read and write access. This class is thread safe.
|
||||
@see HttpSessionStore should be used to create and get instances of this class.
|
||||
*/
|
||||
|
||||
class HttpSession {
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
Constructor.
|
||||
@param canStore The session can store data, if this parameter is true.
|
||||
Otherwise all calls to set() and remove() do not have any effect.
|
||||
*/
|
||||
HttpSession(bool canStore=false);
|
||||
|
||||
/**
|
||||
Copy constructor. Creates another HttpSession object that shares the
|
||||
data of the other object.
|
||||
*/
|
||||
HttpSession(const HttpSession& other);
|
||||
|
||||
/**
|
||||
Copy operator. Detaches from the current shared data and attaches to
|
||||
the data of the other object.
|
||||
*/
|
||||
HttpSession& operator= (const HttpSession& other);
|
||||
|
||||
|
||||
/**
|
||||
Destructor. Detaches from the shared data.
|
||||
*/
|
||||
virtual ~HttpSession();
|
||||
|
||||
/** Get the unique ID of this session. This method is thread safe. */
|
||||
QByteArray getId() const;
|
||||
|
||||
/**
|
||||
Null sessions cannot store data. All calls to set() and remove()
|
||||
do not have any effect.This method is thread safe.
|
||||
*/
|
||||
bool isNull() const;
|
||||
|
||||
/** Set a value. This method is thread safe. */
|
||||
void set(const QByteArray& key, const QVariant& value);
|
||||
|
||||
/** Remove a value. This method is thread safe. */
|
||||
void remove(const QByteArray& key);
|
||||
|
||||
/** Get a value. This method is thread safe. */
|
||||
QVariant get(const QByteArray& key) const;
|
||||
|
||||
/** Check if a key exists. This method is thread safe. */
|
||||
bool contains(const QByteArray& key) const;
|
||||
|
||||
/**
|
||||
Get a copy of all data stored in this session.
|
||||
Changes to the session do not affect the copy and vice versa.
|
||||
This method is thread safe.
|
||||
*/
|
||||
QMap<QByteArray,QVariant> getAll() const;
|
||||
|
||||
/**
|
||||
Get the timestamp of last access. That is the time when the last
|
||||
HttpSessionStore::getSession() has been called.
|
||||
This method is thread safe.
|
||||
*/
|
||||
qint64 getLastAccess() const;
|
||||
|
||||
/**
|
||||
Set the timestamp of last access, to renew the timeout period.
|
||||
Called by HttpSessionStore::getSession().
|
||||
This method is thread safe.
|
||||
*/
|
||||
void setLastAccess();
|
||||
|
||||
//AÑADIDO
|
||||
//sets
|
||||
void setComicsOnDevice(const QSet<QString> & set);
|
||||
void setComicOnDevice(const QString & hash);
|
||||
void setDownloadedComic(const QString & hash);
|
||||
bool isComicOnDevice(const QString & hash);
|
||||
bool isComicDownloaded(const QString & hash);
|
||||
QSet<QString> getComicsOnDevice();
|
||||
QSet<QString> getDownloadedComics();
|
||||
void clearComics();
|
||||
|
||||
//current comic (import)
|
||||
qulonglong getCurrentComicId();
|
||||
Comic * getCurrentComic();
|
||||
void dismissCurrentComic();
|
||||
void setCurrentComic(qulonglong id, Comic * comic);
|
||||
|
||||
//current comic (read)
|
||||
qulonglong getCurrentRemoteComicId();
|
||||
Comic * getCurrentRemoteComic();
|
||||
void dismissCurrentRemoteComic();
|
||||
void setCurrentRemoteComic(qulonglong id, Comic * comic);
|
||||
|
||||
//device identification
|
||||
QString getDeviceType();
|
||||
QString getDisplayType();
|
||||
void setDeviceType(const QString & device);
|
||||
void setDisplayType(const QString & display);
|
||||
|
||||
|
||||
/*int popPage();
|
||||
void pushPage(int page);
|
||||
int topPage();
|
||||
|
||||
void clearFoldersPath();
|
||||
int popFolder();
|
||||
void pushFolder(int page);
|
||||
int topFolder();
|
||||
QStack<int> getFoldersPath();*/
|
||||
|
||||
void clearNavigationPath();
|
||||
QPair<qulonglong, quint32> popNavigationItem();
|
||||
QPair<qulonglong, quint32> topNavigationItem();
|
||||
void pushNavigationItem(const QPair<qulonglong, quint32> & item);
|
||||
void updateTopItem(const QPair<qulonglong, quint32> & item);
|
||||
|
||||
//TODO replace QPair by a custom class for storing folderId, page and folderName(save some DB accesses)
|
||||
QStack<QPair<qulonglong, quint32> > getNavigationPath();
|
||||
|
||||
|
||||
|
||||
|
||||
private:
|
||||
|
||||
struct YACReaderSessionData {
|
||||
//cómics disponibles en dispositivo
|
||||
QSet<QString> comicsOnDevice;
|
||||
//cómics que han sido descargados o están siendo descargados en esta sesión
|
||||
QSet<QString> downloadedComics;
|
||||
//cómic actual que está siendo descargado
|
||||
QString device;
|
||||
QString display;
|
||||
qulonglong comicId;
|
||||
qulonglong remoteComicId;
|
||||
|
||||
//folder_id, page_number
|
||||
QStack<QPair<qulonglong, quint32> > navigationPath;
|
||||
|
||||
Comic * comic;
|
||||
Comic * remoteComic;
|
||||
};
|
||||
|
||||
struct HttpSessionData {
|
||||
|
||||
/** Unique ID */
|
||||
QByteArray id;
|
||||
|
||||
/** Timestamp of last access, set by the HttpSessionStore */
|
||||
qint64 lastAccess;
|
||||
|
||||
/** Reference counter */
|
||||
int refCount;
|
||||
|
||||
/** Used to synchronize threads */
|
||||
QReadWriteLock lock;
|
||||
|
||||
/** Storage for the key/value pairs; */
|
||||
QMap<QByteArray,QVariant> values;
|
||||
|
||||
YACReaderSessionData yacreaderSessionData;
|
||||
|
||||
};
|
||||
|
||||
/** Pointer to the shared data. */
|
||||
HttpSessionData* dataPtr;
|
||||
|
||||
};
|
||||
|
||||
#endif // HTTPSESSION_H
|
@ -1,235 +0,0 @@
|
||||
/**
|
||||
@file
|
||||
@author Stefan Frings
|
||||
*/
|
||||
|
||||
#include "staticfilecontroller.h"
|
||||
#include <QFileInfo>
|
||||
#include <QDir>
|
||||
#include <QDateTime>
|
||||
#include "httpsession.h"
|
||||
#include "static.h"
|
||||
#include <QCoreApplication>
|
||||
|
||||
|
||||
StaticFileController::StaticFileController(QSettings* settings, QObject* parent)
|
||||
:HttpRequestHandler(parent)
|
||||
{
|
||||
maxAge=settings->value("maxAge","60000").toInt();
|
||||
encoding=settings->value("encoding","UTF-8").toString();
|
||||
docroot=settings->value("path","./server/docroot").toString();
|
||||
// Convert relative path to absolute, based on the directory of the config file.
|
||||
#ifdef Q_OS_WIN32
|
||||
if (QDir::isRelativePath(docroot) && settings->format()!=QSettings::NativeFormat)
|
||||
#else
|
||||
if (QDir::isRelativePath(docroot))
|
||||
#endif
|
||||
{
|
||||
#if defined Q_OS_UNIX && ! defined Q_OS_MAC
|
||||
QFileInfo configFile(QString(DATADIR)+"/yacreader");
|
||||
docroot=QFileInfo(QString(DATADIR)+"/yacreader",docroot).absoluteFilePath();
|
||||
#else
|
||||
QFileInfo configFile(QCoreApplication::applicationDirPath());
|
||||
docroot=QFileInfo(QCoreApplication::applicationDirPath(),docroot).absoluteFilePath();
|
||||
#endif
|
||||
}
|
||||
qDebug("StaticFileController: docroot=%s, encoding=%s, maxAge=%i",qPrintable(docroot),qPrintable(encoding),maxAge);
|
||||
maxCachedFileSize=settings->value("maxCachedFileSize","65536").toInt();
|
||||
cache.setMaxCost(settings->value("cacheSize","1000000").toInt());
|
||||
cacheTimeout=settings->value("cacheTime","60000").toInt();
|
||||
qDebug("StaticFileController: cache timeout=%i, size=%i",cacheTimeout,cache.maxCost());
|
||||
}
|
||||
|
||||
|
||||
void StaticFileController::service(HttpRequest& request, HttpResponse& response) {
|
||||
QByteArray path=request.getPath();
|
||||
// Forbid access to files outside the docroot directory
|
||||
if (path.startsWith("/..")) {
|
||||
qWarning("StaticFileController: somebody attempted to access a file outside the docroot directory");
|
||||
response.setStatus(403,"forbidden");
|
||||
response.write("403 forbidden",true);
|
||||
}
|
||||
|
||||
//TODO(DONE) carga sensible al dispositivo y a la localización
|
||||
QString stringPath = path;
|
||||
QStringList paths = QString(path).split('/');
|
||||
QString fileName = paths.last();
|
||||
stringPath.remove(fileName);
|
||||
HttpSession session=Static::sessionStore->getSession(request,response,false);
|
||||
QString device = session.getDeviceType();
|
||||
QString display = session.getDisplayType();
|
||||
if(fileName.endsWith(".png"))
|
||||
fileName = getDeviceAwareFileName(fileName, device, display, request.getHeader("Accept-Language"), stringPath);
|
||||
else
|
||||
fileName = getDeviceAwareFileName(fileName, device, request.getHeader("Accept-Language"), stringPath);
|
||||
QString newPath = stringPath.append(fileName);
|
||||
path = newPath.toLocal8Bit();
|
||||
|
||||
//CAMBIADO
|
||||
response.setHeader("Connection","close");
|
||||
//END_TODO
|
||||
|
||||
// Check if we have the file in cache
|
||||
//qint64 now=QDateTime::currentMSecsSinceEpoch();
|
||||
// mutex.lock();
|
||||
// CacheEntry* entry=cache.object(path);
|
||||
//if (entry && (cacheTimeout==0 || entry->created>now-cacheTimeout)) {
|
||||
// QByteArray document=entry->document; //copy the cached document, because other threads may destroy the cached entry immediately after mutex unlock.
|
||||
// mutex.unlock();
|
||||
// qDebug("StaticFileController: Cache hit for %s",path.data());
|
||||
// setContentType(path,response);
|
||||
// response.setHeader("Cache-Control","max-age="+QByteArray::number(maxAge/1000));
|
||||
// response.write(document);
|
||||
//}
|
||||
//else {
|
||||
|
||||
// mutex.unlock();
|
||||
//qDebug("StaticFileController: Cache miss for %s",path.data());
|
||||
// The file is not in cache.
|
||||
// If the filename is a directory, append index.html.
|
||||
if (QFileInfo(docroot+path).isDir()) {
|
||||
path+="/index.html";
|
||||
}
|
||||
|
||||
|
||||
QFile file(docroot+path);
|
||||
if (file.exists()) {
|
||||
qDebug("StaticFileController: Open file %s",qPrintable(file.fileName()));
|
||||
if (file.open(QIODevice::ReadOnly)) {
|
||||
setContentType(path,response);
|
||||
//response.setHeader("Cache-Control","max-age="+QByteArray::number(maxAge/1000));
|
||||
//if (file.size()<=maxCachedFileSize) {
|
||||
// // Return the file content and store it also in the cache
|
||||
// entry=new CacheEntry();
|
||||
// while (!file.atEnd() && !file.error()) {
|
||||
// QByteArray buffer=file.read(65536);
|
||||
// response.write(buffer);
|
||||
// entry->document.append(buffer);
|
||||
// }
|
||||
// entry->created=now;
|
||||
// mutex.lock();
|
||||
// cache.insert(request.getPath(),entry,entry->document.size());
|
||||
// mutex.unlock();
|
||||
//}
|
||||
//else {
|
||||
// Return the file content, do not store in cache*/
|
||||
while (!file.atEnd() && !file.error()) {
|
||||
response.write(file.read(131072));
|
||||
//}
|
||||
}
|
||||
file.close();
|
||||
}
|
||||
else {
|
||||
qWarning("StaticFileController: Cannot open existing file %s for reading",qPrintable(file.fileName()));
|
||||
response.setStatus(403,"forbidden");
|
||||
response.write("403 forbidden",true);
|
||||
}
|
||||
}
|
||||
else {
|
||||
response.setStatus(404,"not found");
|
||||
response.write("404 not found",true);
|
||||
}
|
||||
//}
|
||||
}
|
||||
|
||||
void StaticFileController::setContentType(QString fileName, HttpResponse& response) const {
|
||||
if (fileName.endsWith(".png")) {
|
||||
response.setHeader("Content-Type", "image/png");
|
||||
}
|
||||
else if (fileName.endsWith(".jpg")) {
|
||||
response.setHeader("Content-Type", "image/jpeg");
|
||||
}
|
||||
else if (fileName.endsWith(".gif")) {
|
||||
response.setHeader("Content-Type", "image/gif");
|
||||
}
|
||||
else if (fileName.endsWith(".pdf")) {
|
||||
response.setHeader("Content-Type", "application/pdf");
|
||||
}
|
||||
else if (fileName.endsWith(".txt")) {
|
||||
response.setHeader("Content-Type", qPrintable("text/plain; charset="+encoding));
|
||||
}
|
||||
else if (fileName.endsWith(".html") || fileName.endsWith(".htm")) {
|
||||
response.setHeader("Content-Type", qPrintable("text/html; charset="+encoding));
|
||||
}
|
||||
else if (fileName.endsWith(".css")) {
|
||||
response.setHeader("Content-Type", "text/css");
|
||||
}
|
||||
else if (fileName.endsWith(".js")) {
|
||||
response.setHeader("Content-Type", "text/javascript");
|
||||
}
|
||||
// Todo: add all of your content types
|
||||
}
|
||||
|
||||
bool StaticFileController::exists(QString localizedName, QString path) const
|
||||
{
|
||||
QString fileName=docroot+"/"+path + localizedName;
|
||||
QFile file(fileName);
|
||||
return file.exists();
|
||||
}
|
||||
|
||||
//retorna fileName si no se encontró alternativa traducida ó fileName-locale.extensión si se encontró
|
||||
QString StaticFileController::getLocalizedFileName(QString fileName, QString locales, QString path) const
|
||||
{
|
||||
QSet<QString> tried; // used to suppress duplicate attempts
|
||||
QStringList locs=locales.split(',',QString::SkipEmptyParts);
|
||||
QStringList fileNameParts = fileName.split('.');
|
||||
QString file = fileNameParts.first();
|
||||
QString extension = fileNameParts.last();
|
||||
// Search for exact match
|
||||
foreach (QString loc,locs) {
|
||||
loc.replace(QRegExp(";.*"),"");
|
||||
loc.replace('-','_');
|
||||
QString localizedName=file+"-"+loc.trimmed()+"."+extension;
|
||||
if (!tried.contains(localizedName)) {
|
||||
if(exists(localizedName, path))
|
||||
return localizedName;
|
||||
tried.insert(localizedName);
|
||||
}
|
||||
}
|
||||
|
||||
// Search for correct language but any country
|
||||
foreach (QString loc,locs) {
|
||||
loc.replace(QRegExp("[;_-].*"),"");
|
||||
QString localizedName=file+"-"+loc.trimmed()+"."+extension;
|
||||
if (!tried.contains(localizedName)) {
|
||||
if(exists(localizedName, path))
|
||||
return localizedName;
|
||||
tried.insert(localizedName);
|
||||
}
|
||||
}
|
||||
|
||||
return fileName;
|
||||
}
|
||||
|
||||
QString StaticFileController::getDeviceAwareFileName(QString fileName, QString device, QString locales, QString path) const
|
||||
{
|
||||
QFileInfo fi(fileName);
|
||||
QString baseName = fi.baseName();
|
||||
QString extension = fi.completeSuffix();
|
||||
|
||||
QString completeFileName = getLocalizedFileName(baseName+"_"+device+"."+extension,locales,path);
|
||||
|
||||
if(QFile(docroot+"/"+path+completeFileName).exists())
|
||||
return completeFileName; //existe un archivo específico para este dispositivo y locales
|
||||
else
|
||||
return getLocalizedFileName(fileName,locales,path); //no hay archivo específico para el dispositivo, pero puede haberlo para estas locales
|
||||
}
|
||||
|
||||
QString StaticFileController::getDeviceAwareFileName(QString fileName, QString device, QString display, QString locales, QString path) const
|
||||
{
|
||||
QFileInfo fi(fileName);
|
||||
QString baseName = fi.baseName();
|
||||
QString extension = fi.completeSuffix();
|
||||
|
||||
QString completeFileName = baseName+display+"."+extension;
|
||||
if(QFile(docroot+"/"+path+completeFileName).exists())
|
||||
return completeFileName;
|
||||
else
|
||||
{
|
||||
completeFileName = baseName+"_"+device+display+"."+extension;
|
||||
if((QFile(docroot+"/"+path+completeFileName).exists()))
|
||||
return completeFileName;
|
||||
}
|
||||
|
||||
return fileName;
|
||||
}
|
@ -1,92 +0,0 @@
|
||||
/**
|
||||
@file
|
||||
@author Stefan Frings
|
||||
*/
|
||||
|
||||
#ifndef STATICFILECONTROLLER_H
|
||||
#define STATICFILECONTROLLER_H
|
||||
|
||||
#include "httprequest.h"
|
||||
#include "httpresponse.h"
|
||||
#include "httprequesthandler.h"
|
||||
#include <QCache>
|
||||
#include <QMutex>
|
||||
|
||||
/**
|
||||
Delivers static files. It is usually called by the applications main request handler when
|
||||
the caller request a path that is mapped to static files.
|
||||
<p>
|
||||
The following settings are required in the config file:
|
||||
<code><pre>
|
||||
path=docroot
|
||||
encoding=UTF-8
|
||||
maxAge=60000
|
||||
cacheTime=60000
|
||||
cacheSize=1000000
|
||||
maxCachedFileSize=65536
|
||||
</pre></code>
|
||||
The path is relative to the directory of the config file. In case of windows, if the
|
||||
settings are in the registry, the path is relative to the current working directory.
|
||||
<p>
|
||||
The encoding is sent to the web browser in case of text and html files.
|
||||
<p>
|
||||
The cache improves performance of small files when loaded from a network
|
||||
drive. Large files are not cached. Files are cached as long as possible,
|
||||
when cacheTime=0. The maxAge value (in msec!) controls the remote browsers cache.
|
||||
<p>
|
||||
Do not instantiate this class in each request, because this would make the file cache
|
||||
useless. Better create one instance during start-up and call it when the application
|
||||
received a related HTTP request.
|
||||
*/
|
||||
|
||||
class StaticFileController : public HttpRequestHandler {
|
||||
Q_OBJECT
|
||||
Q_DISABLE_COPY(StaticFileController);
|
||||
public:
|
||||
|
||||
/** Constructor */
|
||||
StaticFileController(QSettings* settings, QObject* parent = 0);
|
||||
|
||||
/** Generates the response */
|
||||
void service(HttpRequest& request, HttpResponse& response);
|
||||
|
||||
private:
|
||||
|
||||
/** Encoding of text files */
|
||||
QString encoding;
|
||||
|
||||
/** Root directory of documents */
|
||||
QString docroot;
|
||||
|
||||
/** Maximum age of files in the browser cache */
|
||||
int maxAge;
|
||||
|
||||
struct CacheEntry {
|
||||
QByteArray document;
|
||||
qint64 created;
|
||||
};
|
||||
|
||||
/** Timeout for each cached file */
|
||||
int cacheTimeout;
|
||||
|
||||
|
||||
/** Maximum size of files in cache, larger files are not cached */
|
||||
int maxCachedFileSize;
|
||||
|
||||
/** Cache storage */
|
||||
QCache<QString,CacheEntry> cache;
|
||||
|
||||
/** Used to synchronize cache access for threads */
|
||||
QMutex mutex;
|
||||
|
||||
/** Set a content-type header in the response depending on the ending of the filename */
|
||||
void setContentType(QString file, HttpResponse& response) const;
|
||||
|
||||
QString getLocalizedFileName(QString fileName, QString locales, QString path) const;
|
||||
QString getDeviceAwareFileName(QString fileName, QString device, QString locales, QString path) const;
|
||||
QString getDeviceAwareFileName(QString fileName, QString device, QString display, QString locales, QString path) const;
|
||||
|
||||
bool exists(QString localizedName, QString path) const;
|
||||
};
|
||||
|
||||
#endif // STATICFILECONTROLLER_H
|
@ -1,5 +0,0 @@
|
||||
INCLUDEPATH += $$PWD
|
||||
DEPENDPATH += $$PWD
|
||||
|
||||
HEADERS += $$PWD/logmessage.h $$PWD/logger.h $$PWD/filelogger.h $$PWD/dualfilelogger.h
|
||||
SOURCES += $$PWD/logmessage.cpp $$PWD/logger.cpp $$PWD/filelogger.cpp $$PWD/dualfilelogger.cpp
|
@ -1,7 +0,0 @@
|
||||
INCLUDEPATH += $$PWD
|
||||
DEPENDPATH += $$PWD
|
||||
|
||||
HEADERS += $$PWD/template.h $$PWD/templateloader.h $$PWD/templatecache.h
|
||||
SOURCES += $$PWD/template.cpp $$PWD/templateloader.cpp $$PWD/templatecache.cpp
|
||||
|
||||
OTHER_FILES += $$PWD/../doc/readme.txt
|
275
YACReaderLibrary/server/lib/httpserver/httpconnectionhandler.cpp
Normal file
275
YACReaderLibrary/server/lib/httpserver/httpconnectionhandler.cpp
Normal file
@ -0,0 +1,275 @@
|
||||
/**
|
||||
@file
|
||||
@author Stefan Frings
|
||||
*/
|
||||
|
||||
#include "httpconnectionhandler.h"
|
||||
#include "httpresponse.h"
|
||||
|
||||
HttpConnectionHandler::HttpConnectionHandler(QSettings* settings, HttpRequestHandler* requestHandler, QSslConfiguration* sslConfiguration)
|
||||
: QThread()
|
||||
{
|
||||
Q_ASSERT(settings!=0);
|
||||
Q_ASSERT(requestHandler!=0);
|
||||
this->settings=settings;
|
||||
this->requestHandler=requestHandler;
|
||||
this->sslConfiguration=sslConfiguration;
|
||||
currentRequest=0;
|
||||
busy=false;
|
||||
|
||||
// Create TCP or SSL socket
|
||||
createSocket();
|
||||
|
||||
// execute signals in my own thread
|
||||
moveToThread(this);
|
||||
socket->moveToThread(this);
|
||||
readTimer.moveToThread(this);
|
||||
|
||||
// Connect signals
|
||||
connect(socket, SIGNAL(readyRead()), SLOT(read()));
|
||||
connect(socket, SIGNAL(disconnected()), SLOT(disconnected()));
|
||||
connect(&readTimer, SIGNAL(timeout()), SLOT(readTimeout()));
|
||||
readTimer.setSingleShot(true);
|
||||
|
||||
qDebug("HttpConnectionHandler (%p): constructed", this);
|
||||
this->start();
|
||||
}
|
||||
|
||||
|
||||
HttpConnectionHandler::~HttpConnectionHandler()
|
||||
{
|
||||
quit();
|
||||
wait();
|
||||
qDebug("HttpConnectionHandler (%p): destroyed", this);
|
||||
}
|
||||
|
||||
|
||||
void HttpConnectionHandler::createSocket()
|
||||
{
|
||||
// If SSL is supported and configured, then create an instance of QSslSocket
|
||||
#ifndef QT_NO_OPENSSL
|
||||
if (sslConfiguration)
|
||||
{
|
||||
QSslSocket* sslSocket=new QSslSocket();
|
||||
sslSocket->setSslConfiguration(*sslConfiguration);
|
||||
socket=sslSocket;
|
||||
qDebug("HttpConnectionHandler (%p): SSL is enabled", this);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
// else create an instance of QTcpSocket
|
||||
socket=new QTcpSocket();
|
||||
}
|
||||
|
||||
|
||||
void HttpConnectionHandler::run()
|
||||
{
|
||||
qDebug("HttpConnectionHandler (%p): thread started", this);
|
||||
try
|
||||
{
|
||||
exec();
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
qCritical("HttpConnectionHandler (%p): an uncatched exception occured in the thread",this);
|
||||
}
|
||||
socket->close();
|
||||
delete socket;
|
||||
readTimer.stop();
|
||||
qDebug("HttpConnectionHandler (%p): thread stopped", this);
|
||||
}
|
||||
|
||||
|
||||
void HttpConnectionHandler::handleConnection(tSocketDescriptor socketDescriptor)
|
||||
{
|
||||
qDebug("HttpConnectionHandler (%p): handle new connection", this);
|
||||
busy = true;
|
||||
Q_ASSERT(socket->isOpen()==false); // if not, then the handler is already busy
|
||||
|
||||
//UGLY workaround - we need to clear writebuffer before reusing this socket
|
||||
//https://bugreports.qt-project.org/browse/QTBUG-28914
|
||||
socket->connectToHost("",0);
|
||||
socket->abort();
|
||||
|
||||
if (!socket->setSocketDescriptor(socketDescriptor))
|
||||
{
|
||||
qCritical("HttpConnectionHandler (%p): cannot initialize socket: %s", this,qPrintable(socket->errorString()));
|
||||
return;
|
||||
}
|
||||
|
||||
#ifndef QT_NO_OPENSSL
|
||||
// Switch on encryption, if SSL is configured
|
||||
if (sslConfiguration)
|
||||
{
|
||||
qDebug("HttpConnectionHandler (%p): Starting encryption", this);
|
||||
((QSslSocket*)socket)->startServerEncryption();
|
||||
}
|
||||
#endif
|
||||
|
||||
// Start timer for read timeout
|
||||
int readTimeout=settings->value("readTimeout",10000).toInt();
|
||||
readTimer.start(readTimeout);
|
||||
// delete previous request
|
||||
delete currentRequest;
|
||||
currentRequest=0;
|
||||
}
|
||||
|
||||
|
||||
bool HttpConnectionHandler::isBusy()
|
||||
{
|
||||
return busy;
|
||||
}
|
||||
|
||||
void HttpConnectionHandler::setBusy()
|
||||
{
|
||||
this->busy = true;
|
||||
}
|
||||
|
||||
|
||||
void HttpConnectionHandler::readTimeout()
|
||||
{
|
||||
qDebug("HttpConnectionHandler (%p): read timeout occured",this);
|
||||
|
||||
//Commented out because QWebView cannot handle this.
|
||||
//socket->write("HTTP/1.1 408 request timeout\r\nConnection: close\r\n\r\n408 request timeout\r\n");
|
||||
|
||||
socket->flush();
|
||||
socket->disconnectFromHost();
|
||||
delete currentRequest;
|
||||
currentRequest=0;
|
||||
}
|
||||
|
||||
|
||||
void HttpConnectionHandler::disconnected()
|
||||
{
|
||||
qDebug("HttpConnectionHandler (%p): disconnected", this);
|
||||
socket->close();
|
||||
readTimer.stop();
|
||||
busy = false;
|
||||
}
|
||||
|
||||
void HttpConnectionHandler::read()
|
||||
{
|
||||
// The loop adds support for HTTP pipelinig
|
||||
while (socket->bytesAvailable())
|
||||
{
|
||||
#ifdef SUPERVERBOSE
|
||||
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->flush();
|
||||
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);
|
||||
|
||||
// Copy the Connection:close header to the response
|
||||
HttpResponse response(socket);
|
||||
bool closeConnection=QString::compare(currentRequest->getHeader("Connection"),"close",Qt::CaseInsensitive)==0;
|
||||
if (closeConnection)
|
||||
{
|
||||
response.setHeader("Connection","close");
|
||||
}
|
||||
|
||||
// In case of HTTP 1.0 protocol add the Connection:close header.
|
||||
// This ensures that the HttpResponse does not activate chunked mode, which is not spported by HTTP 1.0.
|
||||
else
|
||||
{
|
||||
bool http1_0=QString::compare(currentRequest->getVersion(),"HTTP/1.0",Qt::CaseInsensitive)==0;
|
||||
if (http1_0)
|
||||
{
|
||||
closeConnection=true;
|
||||
response.setHeader("Connection","close");
|
||||
}
|
||||
}
|
||||
|
||||
// Call the request mapper
|
||||
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);
|
||||
}
|
||||
|
||||
qDebug("HttpConnectionHandler (%p): finished request",this);
|
||||
|
||||
// Find out whether the connection must be closed
|
||||
if (!closeConnection)
|
||||
{
|
||||
// Maybe the request handler or mapper added a Connection:close header in the meantime
|
||||
bool closeResponse=QString::compare(response.getHeaders().value("Connection"),"close",Qt::CaseInsensitive)==0;
|
||||
if (closeResponse==true)
|
||||
{
|
||||
closeConnection=true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// If we have no Content-Length header and did not use chunked mode, then we have to close the
|
||||
// connection to tell the HTTP client that the end of the response has been reached.
|
||||
bool hasContentLength=response.getHeaders().contains("Content-Length");
|
||||
if (!hasContentLength)
|
||||
{
|
||||
bool hasChunkedMode=QString::compare(response.getHeaders().value("Transfer-Encoding"),"chunked",Qt::CaseInsensitive)==0;
|
||||
if (!hasChunkedMode)
|
||||
{
|
||||
closeConnection=true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Close the connection or prepare for the next request on the same connection.
|
||||
if (closeConnection)
|
||||
{
|
||||
socket->flush();
|
||||
socket->disconnectFromHost();
|
||||
}
|
||||
else
|
||||
{
|
||||
// Start timer for next request
|
||||
int readTimeout=settings->value("readTimeout",10000).toInt();
|
||||
readTimer.start(readTimeout);
|
||||
}
|
||||
delete currentRequest;
|
||||
currentRequest=0;
|
||||
}
|
||||
}
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user